mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-05 19:31:57 -04:00
usb: Undo qcom damage
Revert "reverting all USB patches" This reverts commit365834436c. Conflicts: drivers/usb/core/quirks.c drivers/usb/dwc3/dwc3-qcom.c drivers/usb/host/xhci-plat.c drivers/usb/serial/option.c Partially revert "reverting enum-conversion, Handle CPU state and all USB patches" This partially reverts commit2c3bda25f8. Conflicts: drivers/usb/core/quirks.c drivers/usb/dwc3/gadget.c drivers/usb/gadget/function/f_fs.c drivers/usb/serial/option.c Change-Id: I89f5ca04b3306fddb8b9ebd5382ec495ff9e1030
This commit is contained in:
parent
9f0d3e60bc
commit
af92965dcb
73 changed files with 900 additions and 393 deletions
|
|
@ -197,7 +197,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
|||
if (!input_device->hid_desc)
|
||||
goto cleanup;
|
||||
|
||||
input_device->report_desc_size = desc->desc[0].wDescriptorLength;
|
||||
input_device->report_desc_size = le16_to_cpu(
|
||||
desc->rpt_desc.wDescriptorLength);
|
||||
if (input_device->report_desc_size == 0) {
|
||||
input_device->dev_info_status = -EINVAL;
|
||||
goto cleanup;
|
||||
|
|
@ -213,7 +214,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
|||
|
||||
memcpy(input_device->report_desc,
|
||||
((unsigned char *)desc) + desc->bLength,
|
||||
desc->desc[0].wDescriptorLength);
|
||||
le16_to_cpu(desc->rpt_desc.wDescriptorLength));
|
||||
|
||||
/* Send the ack */
|
||||
memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
|
||||
|
|
|
|||
|
|
@ -984,12 +984,11 @@ static int usbhid_parse(struct hid_device *hid)
|
|||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
struct usb_device *dev = interface_to_usbdev (intf);
|
||||
struct hid_descriptor *hdesc;
|
||||
struct hid_class_descriptor *hcdesc;
|
||||
u32 quirks = 0;
|
||||
unsigned int rsize = 0;
|
||||
char *rdesc;
|
||||
int ret, n;
|
||||
int num_descriptors;
|
||||
size_t offset = offsetof(struct hid_descriptor, desc);
|
||||
int ret;
|
||||
|
||||
quirks = hid_lookup_quirk(hid);
|
||||
|
||||
|
|
@ -1011,20 +1010,19 @@ static int usbhid_parse(struct hid_device *hid)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (hdesc->bLength < sizeof(struct hid_descriptor)) {
|
||||
dbg_hid("hid descriptor is too short\n");
|
||||
if (!hdesc->bNumDescriptors ||
|
||||
hdesc->bLength != sizeof(*hdesc) +
|
||||
(hdesc->bNumDescriptors - 1) * sizeof(*hcdesc)) {
|
||||
dbg_hid("hid descriptor invalid, bLen=%hhu bNum=%hhu\n",
|
||||
hdesc->bLength, hdesc->bNumDescriptors);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hid->version = le16_to_cpu(hdesc->bcdHID);
|
||||
hid->country = hdesc->bCountryCode;
|
||||
|
||||
num_descriptors = min_t(int, hdesc->bNumDescriptors,
|
||||
(hdesc->bLength - offset) / sizeof(struct hid_class_descriptor));
|
||||
|
||||
for (n = 0; n < num_descriptors; n++)
|
||||
if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
|
||||
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
|
||||
if (hdesc->rpt_desc.bDescriptorType == HID_DT_REPORT)
|
||||
rsize = le16_to_cpu(hdesc->rpt_desc.wDescriptorLength);
|
||||
|
||||
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
|
||||
dbg_hid("weird size of report descriptor (%u)\n", rsize);
|
||||
|
|
@ -1052,6 +1050,11 @@ static int usbhid_parse(struct hid_device *hid)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (hdesc->bNumDescriptors > 1)
|
||||
hid_warn(intf,
|
||||
"%u unsupported optional hid class descriptors\n",
|
||||
(int)(hdesc->bNumDescriptors - 1));
|
||||
|
||||
hid->quirks |= quirks;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -984,94 +984,6 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void cxacru_upload_firmware(struct cxacru_data *instance,
|
||||
const struct firmware *fw,
|
||||
const struct firmware *bp)
|
||||
{
|
||||
int ret;
|
||||
struct usbatm_data *usbatm = instance->usbatm;
|
||||
struct usb_device *usb_dev = usbatm->usb_dev;
|
||||
__le16 signature[] = { usb_dev->descriptor.idVendor,
|
||||
usb_dev->descriptor.idProduct };
|
||||
__le32 val;
|
||||
|
||||
usb_dbg(usbatm, "%s\n", __func__);
|
||||
|
||||
/* FirmwarePllFClkValue */
|
||||
val = cpu_to_le32(instance->modem_type->pll_f_clk);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FirmwarePllBClkValue */
|
||||
val = cpu_to_le32(instance->modem_type->pll_b_clk);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable SDRAM */
|
||||
val = cpu_to_le32(SDRAM_ENA);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Firmware */
|
||||
usb_info(usbatm, "loading firmware\n");
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Firmware upload failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Boot ROM patch */
|
||||
if (instance->modem_type->boot_rom_patch) {
|
||||
usb_info(usbatm, "loading boot ROM patch\n");
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Signature */
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Signature storing failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
usb_info(usbatm, "starting device\n");
|
||||
if (instance->modem_type->boot_rom_patch) {
|
||||
val = cpu_to_le32(BR_ADDR);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
|
||||
} else {
|
||||
ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
|
||||
}
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Delay to allow firmware to start up. */
|
||||
msleep_interruptible(1000);
|
||||
|
||||
usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD));
|
||||
usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD));
|
||||
usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA));
|
||||
usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA));
|
||||
|
||||
ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
|
||||
if (ret < 0) {
|
||||
usb_err(usbatm, "modem failed to initialize: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int cxacru_find_firmware(struct cxacru_data *instance,
|
||||
char *phase, const struct firmware **fw_p)
|
||||
|
|
@ -1098,8 +1010,14 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
|
|||
{
|
||||
const struct firmware *fw, *bp;
|
||||
struct cxacru_data *instance = usbatm_instance->driver_data;
|
||||
int ret = cxacru_find_firmware(instance, "fw", &fw);
|
||||
struct usbatm_data *usbatm = instance->usbatm;
|
||||
struct usb_device *usb_dev = usbatm->usb_dev;
|
||||
__le16 signature[] = { usb_dev->descriptor.idVendor,
|
||||
usb_dev->descriptor.idProduct };
|
||||
__le32 val;
|
||||
int ret;
|
||||
|
||||
ret = cxacru_find_firmware(instance, "fw", &fw);
|
||||
if (ret) {
|
||||
usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
|
||||
return ret;
|
||||
|
|
@ -1114,8 +1032,82 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
|
|||
}
|
||||
}
|
||||
|
||||
cxacru_upload_firmware(instance, fw, bp);
|
||||
/* FirmwarePllFClkValue */
|
||||
val = cpu_to_le32(instance->modem_type->pll_f_clk);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* FirmwarePllBClkValue */
|
||||
val = cpu_to_le32(instance->modem_type->pll_b_clk);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Enable SDRAM */
|
||||
val = cpu_to_le32(SDRAM_ENA);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Firmware */
|
||||
usb_info(usbatm, "loading firmware\n");
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Firmware upload failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Boot ROM patch */
|
||||
if (instance->modem_type->boot_rom_patch) {
|
||||
usb_info(usbatm, "loading boot ROM patch\n");
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Signature */
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Signature storing failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
usb_info(usbatm, "starting device\n");
|
||||
if (instance->modem_type->boot_rom_patch) {
|
||||
val = cpu_to_le32(BR_ADDR);
|
||||
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
|
||||
} else {
|
||||
ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
|
||||
}
|
||||
if (ret) {
|
||||
usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Delay to allow firmware to start up. */
|
||||
msleep_interruptible(1000);
|
||||
|
||||
usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD));
|
||||
usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD));
|
||||
usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA));
|
||||
usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA));
|
||||
|
||||
ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
|
||||
if (ret < 0) {
|
||||
usb_err(usbatm, "modem failed to initialize: %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (instance->modem_type->boot_rom_patch)
|
||||
release_firmware(bp);
|
||||
release_firmware(fw);
|
||||
|
|
@ -1135,7 +1127,10 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
|
|||
struct cxacru_data *instance;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(intf);
|
||||
struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD];
|
||||
struct usb_endpoint_descriptor *in, *out;
|
||||
static const u8 ep_addrs[] = {
|
||||
CXACRU_EP_CMD + USB_DIR_IN,
|
||||
CXACRU_EP_CMD + USB_DIR_OUT,
|
||||
0};
|
||||
int ret;
|
||||
|
||||
/* instance init */
|
||||
|
|
@ -1183,13 +1178,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
|
|||
}
|
||||
|
||||
if (usb_endpoint_xfer_int(&cmd_ep->desc))
|
||||
ret = usb_find_common_endpoints(intf->cur_altsetting,
|
||||
NULL, NULL, &in, &out);
|
||||
ret = usb_check_int_endpoints(intf, ep_addrs);
|
||||
else
|
||||
ret = usb_find_common_endpoints(intf->cur_altsetting,
|
||||
&in, &out, NULL, NULL);
|
||||
ret = usb_check_bulk_endpoints(intf, ep_addrs);
|
||||
|
||||
if (ret) {
|
||||
if (!ret) {
|
||||
usb_err(usbatm_instance, "cxacru_bind: interface has incorrect endpoints\n");
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -1920,6 +1920,7 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep)
|
|||
"%s is already disabled\n", priv_ep->name))
|
||||
return 0;
|
||||
|
||||
local_bh_disable();
|
||||
spin_lock_irqsave(&priv_dev->lock, flags);
|
||||
|
||||
trace_cdns3_gadget_ep_disable(priv_ep);
|
||||
|
|
@ -1976,6 +1977,7 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep)
|
|||
priv_ep->flags &= ~EP_ENABLED;
|
||||
|
||||
spin_unlock_irqrestore(&priv_dev->lock, flags);
|
||||
local_bh_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,8 +277,19 @@ static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role)
|
|||
return -ENXIO;
|
||||
|
||||
ret = ci->roles[role]->start(ci);
|
||||
if (!ret)
|
||||
ci->role = role;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ci->role = role;
|
||||
|
||||
if (ci->usb_phy) {
|
||||
if (role == CI_ROLE_HOST)
|
||||
usb_phy_set_event(ci->usb_phy, USB_EVENT_ID);
|
||||
else
|
||||
/* in device mode but vbus is invalid*/
|
||||
usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -292,6 +303,9 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
|
|||
ci->role = CI_ROLE_END;
|
||||
|
||||
ci->roles[role]->stop(ci);
|
||||
|
||||
if (ci->usb_phy)
|
||||
usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
|
||||
}
|
||||
|
||||
static inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci)
|
||||
|
|
|
|||
|
|
@ -340,11 +340,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
pdata.flags |= CI_HDRC_IMX_IS_HSIC;
|
||||
data->usbmisc_data->hsic = 1;
|
||||
data->pinctrl = devm_pinctrl_get(dev);
|
||||
if (IS_ERR(data->pinctrl)) {
|
||||
dev_err(dev, "pinctrl get failed, err=%ld\n",
|
||||
PTR_ERR(data->pinctrl));
|
||||
return PTR_ERR(data->pinctrl);
|
||||
}
|
||||
if (PTR_ERR(data->pinctrl) == -ENODEV)
|
||||
data->pinctrl = NULL;
|
||||
else if (IS_ERR(data->pinctrl))
|
||||
return dev_err_probe(dev, PTR_ERR(data->pinctrl),
|
||||
"pinctrl get failed\n");
|
||||
|
||||
pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle");
|
||||
if (IS_ERR(pinctrl_hsic_idle)) {
|
||||
|
|
@ -369,17 +369,14 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(data->pinctrl_hsic_active);
|
||||
}
|
||||
|
||||
data->hsic_pad_regulator = devm_regulator_get(dev, "hsic");
|
||||
if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) {
|
||||
return -EPROBE_DEFER;
|
||||
} else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
|
||||
data->hsic_pad_regulator =
|
||||
devm_regulator_get_optional(dev, "hsic");
|
||||
if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
|
||||
/* no pad regualator is needed */
|
||||
data->hsic_pad_regulator = NULL;
|
||||
} else if (IS_ERR(data->hsic_pad_regulator)) {
|
||||
dev_err(dev, "Get HSIC pad regulator error: %ld\n",
|
||||
PTR_ERR(data->hsic_pad_regulator));
|
||||
return PTR_ERR(data->hsic_pad_regulator);
|
||||
}
|
||||
} else if (IS_ERR(data->hsic_pad_regulator))
|
||||
return dev_err_probe(dev, PTR_ERR(data->hsic_pad_regulator),
|
||||
"Get HSIC pad regulator error\n");
|
||||
|
||||
if (data->hsic_pad_regulator) {
|
||||
ret = regulator_enable(data->hsic_pad_regulator);
|
||||
|
|
@ -420,7 +417,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) {
|
||||
pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL;
|
||||
data->override_phy_control = true;
|
||||
usb_phy_init(pdata.usb_phy);
|
||||
ret = usb_phy_init(pdata.usb_phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init phy\n");
|
||||
goto err_clk;
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
|
||||
|
|
@ -429,7 +430,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
ret = imx_usbmisc_init(data->usbmisc_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
|
||||
goto err_clk;
|
||||
goto phy_shutdown;
|
||||
}
|
||||
|
||||
data->ci_pdev = ci_hdrc_add_device(dev,
|
||||
|
|
@ -437,10 +438,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
&pdata);
|
||||
if (IS_ERR(data->ci_pdev)) {
|
||||
ret = PTR_ERR(data->ci_pdev);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "ci_hdrc_add_device failed, err=%d\n",
|
||||
ret);
|
||||
goto err_clk;
|
||||
dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n");
|
||||
goto phy_shutdown;
|
||||
}
|
||||
|
||||
ret = imx_usbmisc_init_post(data->usbmisc_data);
|
||||
|
|
@ -460,6 +459,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|||
|
||||
disable_device:
|
||||
ci_hdrc_remove_device(data->ci_pdev);
|
||||
phy_shutdown:
|
||||
if (data->override_phy_control)
|
||||
usb_phy_shutdown(data->phy);
|
||||
err_clk:
|
||||
imx_disable_unprepare_clks(dev);
|
||||
disable_hsic_regulator:
|
||||
|
|
|
|||
|
|
@ -1533,44 +1533,68 @@ static const struct usb_ep_ops usb_ep_ops = {
|
|||
/******************************************************************************
|
||||
* GADGET block
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* ci_hdrc_gadget_connect: caller makes sure gadget driver is binded
|
||||
*/
|
||||
static void ci_hdrc_gadget_connect(struct usb_gadget *_gadget, int is_active)
|
||||
{
|
||||
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
|
||||
|
||||
if (is_active) {
|
||||
pm_runtime_get_sync(&_gadget->dev);
|
||||
hw_device_reset(ci);
|
||||
spin_lock_irq(&ci->lock);
|
||||
if (ci->driver) {
|
||||
hw_device_state(ci, ci->ep0out->qh.dma);
|
||||
usb_gadget_set_state(_gadget, USB_STATE_POWERED);
|
||||
spin_unlock_irq(&ci->lock);
|
||||
usb_udc_vbus_handler(_gadget, true);
|
||||
} else {
|
||||
spin_unlock_irq(&ci->lock);
|
||||
}
|
||||
} else {
|
||||
usb_udc_vbus_handler(_gadget, false);
|
||||
if (ci->driver)
|
||||
ci->driver->disconnect(&ci->gadget);
|
||||
hw_device_state(ci, 0);
|
||||
if (ci->platdata->notify_event)
|
||||
ci->platdata->notify_event(ci,
|
||||
CI_HDRC_CONTROLLER_STOPPED_EVENT);
|
||||
_gadget_stop_activity(&ci->gadget);
|
||||
pm_runtime_put_sync(&_gadget->dev);
|
||||
usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
|
||||
}
|
||||
}
|
||||
|
||||
static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
|
||||
{
|
||||
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
|
||||
unsigned long flags;
|
||||
int gadget_ready = 0;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&ci->lock, flags);
|
||||
ci->vbus_active = is_active;
|
||||
if (ci->driver)
|
||||
gadget_ready = 1;
|
||||
spin_unlock_irqrestore(&ci->lock, flags);
|
||||
|
||||
if (ci->usb_phy)
|
||||
usb_phy_set_charger_state(ci->usb_phy, is_active ?
|
||||
USB_CHARGER_PRESENT : USB_CHARGER_ABSENT);
|
||||
|
||||
if (gadget_ready) {
|
||||
if (is_active) {
|
||||
pm_runtime_get_sync(&_gadget->dev);
|
||||
hw_device_reset(ci);
|
||||
hw_device_state(ci, ci->ep0out->qh.dma);
|
||||
usb_gadget_set_state(_gadget, USB_STATE_POWERED);
|
||||
usb_udc_vbus_handler(_gadget, true);
|
||||
} else {
|
||||
usb_udc_vbus_handler(_gadget, false);
|
||||
if (ci->driver)
|
||||
ci->driver->disconnect(&ci->gadget);
|
||||
hw_device_state(ci, 0);
|
||||
if (ci->platdata->notify_event)
|
||||
ci->platdata->notify_event(ci,
|
||||
CI_HDRC_CONTROLLER_STOPPED_EVENT);
|
||||
_gadget_stop_activity(&ci->gadget);
|
||||
pm_runtime_put_sync(&_gadget->dev);
|
||||
usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
|
||||
}
|
||||
if (ci->platdata->notify_event)
|
||||
ret = ci->platdata->notify_event(ci,
|
||||
CI_HDRC_CONTROLLER_VBUS_EVENT);
|
||||
|
||||
if (ci->usb_phy) {
|
||||
if (is_active)
|
||||
usb_phy_set_event(ci->usb_phy, USB_EVENT_VBUS);
|
||||
else
|
||||
usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (ci->driver)
|
||||
ci_hdrc_gadget_connect(_gadget, is_active);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ci_udc_wakeup(struct usb_gadget *_gadget)
|
||||
|
|
@ -1794,18 +1818,10 @@ static int ci_udc_start(struct usb_gadget *gadget,
|
|||
return retval;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(&ci->gadget.dev);
|
||||
if (ci->vbus_active) {
|
||||
hw_device_reset(ci);
|
||||
} else {
|
||||
if (ci->vbus_active)
|
||||
ci_hdrc_gadget_connect(gadget, 1);
|
||||
else
|
||||
usb_udc_vbus_handler(&ci->gadget, false);
|
||||
pm_runtime_put_sync(&ci->gadget.dev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = hw_device_state(ci, ci->ep0out->qh.dma);
|
||||
if (retval)
|
||||
pm_runtime_put_sync(&ci->gadget.dev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -1835,6 +1851,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ci->lock, flags);
|
||||
ci->driver = NULL;
|
||||
|
||||
if (ci->vbus_active) {
|
||||
hw_device_state(ci, 0);
|
||||
|
|
@ -1847,7 +1864,6 @@ static int ci_udc_stop(struct usb_gadget *gadget)
|
|||
pm_runtime_put(&ci->gadget.dev);
|
||||
}
|
||||
|
||||
ci->driver = NULL;
|
||||
spin_unlock_irqrestore(&ci->lock, flags);
|
||||
|
||||
ci_udc_stop_for_otg_fsm(ci);
|
||||
|
|
@ -1890,6 +1906,9 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
|
|||
if (USBi_PCI & intr) {
|
||||
ci->gadget.speed = hw_port_is_high_speed(ci) ?
|
||||
USB_SPEED_HIGH : USB_SPEED_FULL;
|
||||
if (ci->usb_phy)
|
||||
usb_phy_set_event(ci->usb_phy,
|
||||
USB_EVENT_ENUMERATED);
|
||||
if (ci->suspended) {
|
||||
if (ci->driver->resume) {
|
||||
spin_unlock(&ci->lock);
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
|
|||
static void acm_ctrl_irq(struct urb *urb)
|
||||
{
|
||||
struct acm *acm = urb->context;
|
||||
struct usb_cdc_notification *dr = urb->transfer_buffer;
|
||||
struct usb_cdc_notification *dr;
|
||||
unsigned int current_size = urb->actual_length;
|
||||
unsigned int expected_size, copy_size, alloc_size;
|
||||
int retval;
|
||||
|
|
@ -386,14 +386,25 @@ static void acm_ctrl_irq(struct urb *urb)
|
|||
|
||||
usb_mark_last_busy(acm->dev);
|
||||
|
||||
if (acm->nb_index)
|
||||
if (acm->nb_index == 0) {
|
||||
/*
|
||||
* The first chunk of a message must contain at least the
|
||||
* notification header with the length field, otherwise we
|
||||
* can't get an expected_size.
|
||||
*/
|
||||
if (current_size < sizeof(struct usb_cdc_notification)) {
|
||||
dev_dbg(&acm->control->dev, "urb too short\n");
|
||||
goto exit;
|
||||
}
|
||||
dr = urb->transfer_buffer;
|
||||
} else {
|
||||
dr = (struct usb_cdc_notification *)acm->notification_buffer;
|
||||
|
||||
}
|
||||
/* size = notification-header + (optional) data */
|
||||
expected_size = sizeof(struct usb_cdc_notification) +
|
||||
le16_to_cpu(dr->wLength);
|
||||
|
||||
if (current_size < expected_size) {
|
||||
if (acm->nb_index != 0 || current_size < expected_size) {
|
||||
/* notification is transmitted fragmented, reassemble */
|
||||
if (acm->nb_size < expected_size) {
|
||||
u8 *new_buffer;
|
||||
|
|
@ -1509,8 +1520,6 @@ skip_countries:
|
|||
acm->nb_index = 0;
|
||||
acm->nb_size = 0;
|
||||
|
||||
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
|
||||
|
||||
acm->line.dwDTERate = cpu_to_le32(9600);
|
||||
acm->line.bDataBits = 8;
|
||||
acm_set_line(acm, &acm->line);
|
||||
|
|
@ -1518,6 +1527,12 @@ skip_countries:
|
|||
usb_driver_claim_interface(&acm_driver, data_interface, acm);
|
||||
usb_set_intfdata(data_interface, acm);
|
||||
|
||||
if (quirks & CLEAR_HALT_CONDITIONS) {
|
||||
/* errors intentionally ignored */
|
||||
usb_clear_halt(usb_dev, acm->in);
|
||||
usb_clear_halt(usb_dev, acm->out);
|
||||
}
|
||||
|
||||
tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
|
||||
&control_interface->dev);
|
||||
if (IS_ERR(tty_dev)) {
|
||||
|
|
@ -1525,10 +1540,7 @@ skip_countries:
|
|||
goto alloc_fail6;
|
||||
}
|
||||
|
||||
if (quirks & CLEAR_HALT_CONDITIONS) {
|
||||
usb_clear_halt(usb_dev, acm->in);
|
||||
usb_clear_halt(usb_dev, acm->out);
|
||||
}
|
||||
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
|
||||
|
||||
return 0;
|
||||
alloc_fail6:
|
||||
|
|
@ -1733,13 +1745,16 @@ static const struct usb_device_id acm_ids[] = {
|
|||
{ USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
|
||||
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */
|
||||
{ USB_DEVICE(0x045b, 0x023c), /* Renesas R-Car H3 USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */
|
||||
{ USB_DEVICE(0x045b, 0x0247), /* Renesas R-Car D3 USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */
|
||||
{ USB_DEVICE(0x045b, 0x0248), /* Renesas R-Car M3-N USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x024D), /* Renesas R-Car E3 USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ struct wdm_device {
|
|||
u16 wMaxCommand;
|
||||
u16 wMaxPacketSize;
|
||||
__le16 inum;
|
||||
int reslength;
|
||||
int length;
|
||||
int read;
|
||||
int count;
|
||||
|
|
@ -201,6 +200,11 @@ static void wdm_in_callback(struct urb *urb)
|
|||
if (desc->rerr == 0 && status != -EPIPE)
|
||||
desc->rerr = status;
|
||||
|
||||
if (length == 0) {
|
||||
dev_dbg(&desc->intf->dev, "received ZLP\n");
|
||||
goto skip_zlp;
|
||||
}
|
||||
|
||||
if (length + desc->length > desc->wMaxCommand) {
|
||||
/* The buffer would overflow */
|
||||
set_bit(WDM_OVERFLOW, &desc->flags);
|
||||
|
|
@ -209,18 +213,18 @@ static void wdm_in_callback(struct urb *urb)
|
|||
if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
|
||||
memmove(desc->ubuf + desc->length, desc->inbuf, length);
|
||||
desc->length += length;
|
||||
desc->reslength = length;
|
||||
}
|
||||
}
|
||||
skip_error:
|
||||
|
||||
if (desc->rerr) {
|
||||
/*
|
||||
* Since there was an error, userspace may decide to not read
|
||||
* any data after poll'ing.
|
||||
* If there was a ZLP or an error, userspace may decide to not
|
||||
* read any data after poll'ing.
|
||||
* We should respond to further attempts from the device to send
|
||||
* data, so that we can get unstuck.
|
||||
*/
|
||||
skip_zlp:
|
||||
schedule_work(&desc->service_outs_intr);
|
||||
} else {
|
||||
set_bit(WDM_READ, &desc->flags);
|
||||
|
|
@ -571,15 +575,6 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
if (!desc->reslength) { /* zero length read */
|
||||
dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n");
|
||||
clear_bit(WDM_READ, &desc->flags);
|
||||
rv = service_outstanding_interrupt(desc);
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
if (rv < 0)
|
||||
goto err;
|
||||
goto retry;
|
||||
}
|
||||
cntr = desc->length;
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
}
|
||||
|
|
@ -839,7 +834,7 @@ static void service_interrupt_work(struct work_struct *work)
|
|||
|
||||
spin_lock_irq(&desc->iuspin);
|
||||
service_outstanding_interrupt(desc);
|
||||
if (!desc->resp_count) {
|
||||
if (!desc->resp_count && (desc->length || desc->rerr)) {
|
||||
set_bit(WDM_READ, &desc->flags);
|
||||
wake_up(&desc->wait);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1337,11 +1337,12 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
|
|||
if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
|
||||
return -EINVAL;
|
||||
|
||||
alts = usblp->protocol[protocol].alt_setting;
|
||||
if (alts < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't unnecessarily set the interface if there's a single alt. */
|
||||
if (usblp->intf->num_altsetting > 1) {
|
||||
alts = usblp->protocol[protocol].alt_setting;
|
||||
if (alts < 0)
|
||||
return -EINVAL;
|
||||
r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
|
||||
if (r < 0) {
|
||||
printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n",
|
||||
|
|
|
|||
|
|
@ -485,6 +485,8 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
|
|||
u8 tag;
|
||||
__u8 stb;
|
||||
int rv;
|
||||
long wait_rv;
|
||||
unsigned long expire;
|
||||
|
||||
dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n",
|
||||
data->iin_ep_present);
|
||||
|
|
@ -527,16 +529,18 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
|
|||
}
|
||||
|
||||
if (data->iin_ep_present) {
|
||||
rv = wait_event_interruptible_timeout(
|
||||
expire = msecs_to_jiffies(file_data->timeout);
|
||||
wait_rv = wait_event_interruptible_timeout(
|
||||
data->waitq,
|
||||
atomic_read(&data->iin_data_valid) != 0,
|
||||
file_data->timeout);
|
||||
if (rv < 0) {
|
||||
dev_dbg(dev, "wait interrupted %d\n", rv);
|
||||
expire);
|
||||
if (wait_rv < 0) {
|
||||
dev_dbg(dev, "wait interrupted %ld\n", wait_rv);
|
||||
rv = wait_rv;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
if (wait_rv == 0) {
|
||||
dev_dbg(dev, "wait timed out\n");
|
||||
rv = -ETIMEDOUT;
|
||||
goto exit;
|
||||
|
|
@ -556,6 +560,8 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
|
|||
rv = put_user(stb, (__u8 __user *)arg);
|
||||
dev_dbg(dev, "stb:0x%02x received %d\n", (unsigned int)stb, rv);
|
||||
|
||||
rv = 0;
|
||||
|
||||
exit:
|
||||
/* bump interrupt bTag */
|
||||
data->iin_bTag += 1;
|
||||
|
|
@ -572,9 +578,9 @@ static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
|
|||
{
|
||||
struct usbtmc_device_data *data = file_data->data;
|
||||
struct device *dev = &data->intf->dev;
|
||||
int rv;
|
||||
u32 timeout;
|
||||
unsigned long expire;
|
||||
long wait_rv;
|
||||
|
||||
if (!data->iin_ep_present) {
|
||||
dev_dbg(dev, "no interrupt endpoint present\n");
|
||||
|
|
@ -588,25 +594,24 @@ static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
|
|||
|
||||
mutex_unlock(&data->io_mutex);
|
||||
|
||||
rv = wait_event_interruptible_timeout(
|
||||
data->waitq,
|
||||
atomic_read(&file_data->srq_asserted) != 0 ||
|
||||
atomic_read(&file_data->closing),
|
||||
expire);
|
||||
wait_rv = wait_event_interruptible_timeout(
|
||||
data->waitq,
|
||||
atomic_read(&file_data->srq_asserted) != 0 ||
|
||||
atomic_read(&file_data->closing),
|
||||
expire);
|
||||
|
||||
mutex_lock(&data->io_mutex);
|
||||
|
||||
/* Note! disconnect or close could be called in the meantime */
|
||||
if (atomic_read(&file_data->closing) || data->zombie)
|
||||
rv = -ENODEV;
|
||||
return -ENODEV;
|
||||
|
||||
if (rv < 0) {
|
||||
/* dev can be invalid now! */
|
||||
pr_debug("%s - wait interrupted %d\n", __func__, rv);
|
||||
return rv;
|
||||
if (wait_rv < 0) {
|
||||
dev_dbg(dev, "%s - wait interrupted %ld\n", __func__, wait_rv);
|
||||
return wait_rv;
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
if (wait_rv == 0) {
|
||||
dev_dbg(dev, "%s - wait timed out\n", __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
|
@ -800,6 +805,7 @@ static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data,
|
|||
unsigned long expire;
|
||||
int bufcount = 1;
|
||||
int again = 0;
|
||||
long wait_rv;
|
||||
|
||||
/* mutex already locked */
|
||||
|
||||
|
|
@ -912,19 +918,24 @@ static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data,
|
|||
if (!(flags & USBTMC_FLAG_ASYNC)) {
|
||||
dev_dbg(dev, "%s: before wait time %lu\n",
|
||||
__func__, expire);
|
||||
retval = wait_event_interruptible_timeout(
|
||||
wait_rv = wait_event_interruptible_timeout(
|
||||
file_data->wait_bulk_in,
|
||||
usbtmc_do_transfer(file_data),
|
||||
expire);
|
||||
|
||||
dev_dbg(dev, "%s: wait returned %d\n",
|
||||
__func__, retval);
|
||||
dev_dbg(dev, "%s: wait returned %ld\n",
|
||||
__func__, wait_rv);
|
||||
|
||||
if (retval <= 0) {
|
||||
if (retval == 0)
|
||||
retval = -ETIMEDOUT;
|
||||
if (wait_rv < 0) {
|
||||
retval = wait_rv;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (wait_rv == 0) {
|
||||
retval = -ETIMEDOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
urb = usb_get_from_anchor(&file_data->in_anchor);
|
||||
|
|
@ -1350,7 +1361,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&data->io_mutex);
|
||||
retval = mutex_lock_interruptible(&data->io_mutex);
|
||||
if (retval < 0)
|
||||
goto exit_nolock;
|
||||
|
||||
if (data->zombie) {
|
||||
retval = -ENODEV;
|
||||
goto exit;
|
||||
|
|
@ -1473,6 +1487,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
|
|||
|
||||
exit:
|
||||
mutex_unlock(&data->io_mutex);
|
||||
exit_nolock:
|
||||
kfree(buffer);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,12 @@
|
|||
#define USB_TP_TRANSMISSION_DELAY_MAX 65535 /* ns */
|
||||
#define USB_PING_RESPONSE_TIME 400 /* ns */
|
||||
|
||||
/*
|
||||
* Give SS hubs 200ms time after wake to train downstream links before
|
||||
* assuming no port activity and allowing hub to runtime suspend back.
|
||||
*/
|
||||
#define USB_SS_PORT_U0_WAKE_TIME 200 /* ms */
|
||||
|
||||
/* Protect struct usb_device->state and ->children members
|
||||
* Note: Both are also protected by ->dev.sem, except that ->state can
|
||||
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
|
||||
|
|
@ -1055,6 +1061,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
|||
goto init2;
|
||||
goto init3;
|
||||
}
|
||||
|
||||
kref_get(&hub->kref);
|
||||
|
||||
/* The superspeed hub except for root hub has to use Hub Depth
|
||||
|
|
@ -1303,6 +1310,17 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
|||
device_unlock(&hdev->dev);
|
||||
}
|
||||
|
||||
if (type == HUB_RESUME && hub_is_superspeed(hub->hdev)) {
|
||||
/* give usb3 downstream links training time after hub resume */
|
||||
usb_autopm_get_interface_no_resume(
|
||||
to_usb_interface(hub->intfdev));
|
||||
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->post_resume_work,
|
||||
msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME));
|
||||
return;
|
||||
}
|
||||
|
||||
kref_put(&hub->kref, hub_release);
|
||||
}
|
||||
|
||||
|
|
@ -1321,6 +1339,14 @@ static void hub_init_func3(struct work_struct *ws)
|
|||
hub_activate(hub, HUB_INIT3);
|
||||
}
|
||||
|
||||
static void hub_post_resume(struct work_struct *ws)
|
||||
{
|
||||
struct usb_hub *hub = container_of(ws, struct usb_hub, post_resume_work.work);
|
||||
|
||||
usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
|
||||
kref_put(&hub->kref, hub_release);
|
||||
}
|
||||
|
||||
enum hub_quiescing_type {
|
||||
HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
|
||||
};
|
||||
|
|
@ -1346,6 +1372,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
|
|||
|
||||
/* Stop hub_wq and related activity */
|
||||
del_timer_sync(&hub->irq_urb_retry);
|
||||
flush_delayed_work(&hub->post_resume_work);
|
||||
usb_kill_urb(hub->urb);
|
||||
if (hub->has_indicators)
|
||||
cancel_delayed_work_sync(&hub->leds);
|
||||
|
|
@ -1796,6 +1823,17 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
desc = intf->cur_altsetting;
|
||||
hdev = interface_to_usbdev(intf);
|
||||
|
||||
/*
|
||||
* The USB 2.0 spec prohibits hubs from having more than one
|
||||
* configuration or interface, and we rely on this prohibition.
|
||||
* Refuse to accept a device that violates it.
|
||||
*/
|
||||
if (hdev->descriptor.bNumConfigurations > 1 ||
|
||||
hdev->actconfig->desc.bNumInterfaces > 1) {
|
||||
dev_err(&intf->dev, "Invalid hub with more than one config or interface\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default autosuspend delay as 0 to speedup bus suspend,
|
||||
* based on the below considerations:
|
||||
|
|
@ -1881,6 +1919,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
hub->hdev = hdev;
|
||||
INIT_DELAYED_WORK(&hub->leds, led_work);
|
||||
INIT_DELAYED_WORK(&hub->init_work, NULL);
|
||||
INIT_DELAYED_WORK(&hub->post_resume_work, hub_post_resume);
|
||||
INIT_WORK(&hub->events, hub_event);
|
||||
spin_lock_init(&hub->irq_urb_lock);
|
||||
timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0);
|
||||
|
|
@ -2596,13 +2635,13 @@ int usb_new_device(struct usb_device *udev)
|
|||
err = sysfs_create_link(&udev->dev.kobj,
|
||||
&port_dev->dev.kobj, "port");
|
||||
if (err)
|
||||
goto fail;
|
||||
goto out_del_dev;
|
||||
|
||||
err = sysfs_create_link(&port_dev->dev.kobj,
|
||||
&udev->dev.kobj, "device");
|
||||
if (err) {
|
||||
sysfs_remove_link(&udev->dev.kobj, "port");
|
||||
goto fail;
|
||||
goto out_del_dev;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(port1, hub->child_usage_bits))
|
||||
|
|
@ -2614,6 +2653,8 @@ int usb_new_device(struct usb_device *udev)
|
|||
pm_runtime_put_sync_autosuspend(&udev->dev);
|
||||
return err;
|
||||
|
||||
out_del_dev:
|
||||
device_del(&udev->dev);
|
||||
fail:
|
||||
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
|
||||
pm_runtime_disable(&udev->dev);
|
||||
|
|
@ -2746,6 +2787,8 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
|
|||
#define SET_CONFIG_TRIES (2 * (use_both_schemes + 1))
|
||||
#define USE_NEW_SCHEME(i, scheme) ((i) / 2 == (int)(scheme))
|
||||
|
||||
#define DETECT_DISCONNECT_TRIES 5
|
||||
|
||||
#define HUB_ROOT_RESET_TIME 60 /* times are in msec */
|
||||
#define HUB_SHORT_RESET_TIME 10
|
||||
#define HUB_BH_RESET_TIME 50
|
||||
|
|
@ -5381,6 +5424,8 @@ static void port_event(struct usb_hub *hub, int port1)
|
|||
struct usb_device *udev = port_dev->child;
|
||||
struct usb_device *hdev = hub->hdev;
|
||||
u16 portstatus, portchange;
|
||||
int i = 0;
|
||||
int err;
|
||||
|
||||
connect_change = test_bit(port1, hub->change_bits);
|
||||
clear_bit(port1, hub->event_bits);
|
||||
|
|
@ -5457,17 +5502,30 @@ static void port_event(struct usb_hub *hub, int port1)
|
|||
connect_change = 1;
|
||||
|
||||
/*
|
||||
* Warm reset a USB3 protocol port if it's in
|
||||
* SS.Inactive state.
|
||||
* Avoid trying to recover a USB3 SS.Inactive port with a warm reset if
|
||||
* the device was disconnected. A 12ms disconnect detect timer in
|
||||
* SS.Inactive state transitions the port to RxDetect automatically.
|
||||
* SS.Inactive link error state is common during device disconnect.
|
||||
*/
|
||||
if (hub_port_warm_reset_required(hub, port1, portstatus)) {
|
||||
dev_dbg(&port_dev->dev, "do warm reset\n");
|
||||
if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
|
||||
while (hub_port_warm_reset_required(hub, port1, portstatus)) {
|
||||
if ((i++ < DETECT_DISCONNECT_TRIES) && udev) {
|
||||
u16 unused;
|
||||
|
||||
msleep(20);
|
||||
hub_port_status(hub, port1, &portstatus, &unused);
|
||||
dev_dbg(&port_dev->dev, "Wait for inactive link disconnect detect\n");
|
||||
continue;
|
||||
} else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
|
||||
|| udev->state == USB_STATE_NOTATTACHED) {
|
||||
if (hub_port_reset(hub, port1, NULL,
|
||||
HUB_BH_RESET_TIME, true) < 0)
|
||||
dev_dbg(&port_dev->dev, "do warm reset, port only\n");
|
||||
err = hub_port_reset(hub, port1, NULL,
|
||||
HUB_BH_RESET_TIME, true);
|
||||
if (!udev && err == -ENOTCONN)
|
||||
connect_change = 0;
|
||||
else if (err < 0)
|
||||
hub_port_disable(hub, port1, 1);
|
||||
} else {
|
||||
dev_dbg(&port_dev->dev, "do warm reset, full device\n");
|
||||
usb_unlock_port(port_dev);
|
||||
usb_lock_device(udev);
|
||||
usb_reset_device(udev);
|
||||
|
|
@ -5475,6 +5533,7 @@ static void port_event(struct usb_hub *hub, int port1)
|
|||
usb_lock_port(port_dev);
|
||||
connect_change = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (connect_change)
|
||||
|
|
@ -5822,6 +5881,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
struct usb_hub *parent_hub;
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct usb_device_descriptor descriptor = udev->descriptor;
|
||||
struct usb_interface *intf;
|
||||
struct usb_host_bos *bos;
|
||||
char buf[50];
|
||||
int i, j, ret = 0;
|
||||
|
|
@ -5884,6 +5944,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
if (!udev->actconfig)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Some devices can't handle setting default altsetting 0 with a
|
||||
* Set-Interface request. Disable host-side endpoints of those
|
||||
* interfaces here. Enable and reset them back after host has set
|
||||
* its internal endpoint structures during usb_hcd_alloc_bandwith()
|
||||
*/
|
||||
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
|
||||
intf = udev->actconfig->interface[i];
|
||||
if (intf->cur_altsetting->desc.bAlternateSetting == 0)
|
||||
usb_disable_interface(udev, intf, true);
|
||||
}
|
||||
|
||||
mutex_lock(hcd->bandwidth_mutex);
|
||||
ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
|
|
@ -5927,12 +5999,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
*/
|
||||
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
|
||||
struct usb_host_config *config = udev->actconfig;
|
||||
struct usb_interface *intf = config->interface[i];
|
||||
struct usb_interface_descriptor *desc;
|
||||
|
||||
intf = config->interface[i];
|
||||
desc = &intf->cur_altsetting->desc;
|
||||
if (desc->bAlternateSetting == 0) {
|
||||
usb_disable_interface(udev, intf, true);
|
||||
usb_enable_interface(udev, intf, true);
|
||||
ret = 0;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ struct usb_hub {
|
|||
u8 indicator[USB_MAXCHILDREN];
|
||||
struct delayed_work leds;
|
||||
struct delayed_work init_work;
|
||||
struct delayed_work post_resume_work;
|
||||
struct work_struct events;
|
||||
spinlock_t irq_urb_lock;
|
||||
struct timer_list irq_urb_retry;
|
||||
|
|
|
|||
|
|
@ -294,10 +294,11 @@ static int usb_port_runtime_suspend(struct device *dev)
|
|||
static void usb_port_shutdown(struct device *dev)
|
||||
{
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
struct usb_device *udev = port_dev->child;
|
||||
|
||||
if (port_dev->child) {
|
||||
usb_disable_usb2_hardware_lpm(port_dev->child);
|
||||
usb_unlocked_disable_lpm(port_dev->child);
|
||||
if (udev && !udev->port_is_suspended) {
|
||||
usb_disable_usb2_hardware_lpm(udev);
|
||||
usb_unlocked_disable_lpm(udev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* Logitech HD Webcam C270 */
|
||||
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME |
|
||||
USB_QUIRK_NO_LPM},
|
||||
|
||||
/* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */
|
||||
{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||
|
|
@ -338,6 +339,10 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
|
||||
USB_QUIRK_STRING_FETCH_255 },
|
||||
|
||||
/* Prolific Single-LUN Mass Storage Card Reader */
|
||||
{ USB_DEVICE(0x067b, 0x2731), .driver_info = USB_QUIRK_DELAY_INIT |
|
||||
USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Saitek Cyborg Gold Joystick */
|
||||
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
|
||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||
|
|
@ -362,6 +367,13 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
{ USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM },
|
||||
{ USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* SanDisk Corp. SanDisk 3.2Gen1 */
|
||||
{ USB_DEVICE(0x0781, 0x5596), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||
{ USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||
|
||||
/* SanDisk Extreme 55AE */
|
||||
{ USB_DEVICE(0x0781, 0x55ae), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Realforce 87U Keyboard */
|
||||
{ USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
|
|
@ -434,6 +446,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
{ USB_DEVICE(0x0c45, 0x7056), .driver_info =
|
||||
USB_QUIRK_IGNORE_REMOTE_WAKEUP },
|
||||
|
||||
/* Sony Xperia XZ1 Compact (lilac) smartphone in fastboot mode */
|
||||
{ USB_DEVICE(0x0fce, 0x0dde), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Action Semiconductor flash disk */
|
||||
{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
|
||||
USB_QUIRK_STRING_FETCH_255 },
|
||||
|
|
@ -448,6 +463,8 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
/* Huawei 4G LTE module */
|
||||
{ USB_DEVICE(0x12d1, 0x15bb), .driver_info =
|
||||
USB_QUIRK_DISCONNECT_SUSPEND },
|
||||
{ USB_DEVICE(0x12d1, 0x15c1), .driver_info =
|
||||
USB_QUIRK_DISCONNECT_SUSPEND },
|
||||
{ USB_DEVICE(0x12d1, 0x15c3), .driver_info =
|
||||
USB_QUIRK_DISCONNECT_SUSPEND },
|
||||
|
||||
|
|
@ -524,10 +541,16 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||
/* Blackmagic Design UltraStudio SDI */
|
||||
{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Teclast disk */
|
||||
{ USB_DEVICE(0x1f75, 0x0917), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Hauppauge HVR-950q */
|
||||
{ USB_DEVICE(0x2040, 0x7200), .driver_info =
|
||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||
|
||||
/* VLI disk */
|
||||
{ USB_DEVICE(0x2109, 0x0711), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Raydium Touchscreen */
|
||||
{ USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
|
|
@ -708,7 +731,7 @@ void usb_detect_quirks(struct usb_device *udev)
|
|||
udev->quirks ^= usb_detect_dynamic_quirks(udev);
|
||||
|
||||
if (udev->quirks)
|
||||
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
|
||||
dev_dbg(&udev->dev, "USB quirks for this device: 0x%x\n",
|
||||
udev->quirks);
|
||||
|
||||
#ifdef CONFIG_USB_DEFAULT_PERSIST
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||
|
||||
/* Check that the pipe's type matches the endpoint's type */
|
||||
if (usb_pipe_type_check(urb->dev, urb->pipe))
|
||||
dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
|
||||
dev_warn_once(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
|
||||
usb_pipetype(urb->pipe), pipetypes[xfertype]);
|
||||
|
||||
/* Check against a simple/standard policy */
|
||||
|
|
|
|||
|
|
@ -717,15 +717,16 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
|||
dev_set_name(&dev->dev, "usb%d", bus->busnum);
|
||||
root_hub = 1;
|
||||
} else {
|
||||
int n;
|
||||
|
||||
/* match any labeling on the hubs; it's one-based */
|
||||
if (parent->devpath[0] == '0') {
|
||||
snprintf(dev->devpath, sizeof dev->devpath,
|
||||
"%d", port1);
|
||||
n = snprintf(dev->devpath, sizeof(dev->devpath), "%d", port1);
|
||||
/* Root ports are not counted in route string */
|
||||
dev->route = 0;
|
||||
} else {
|
||||
snprintf(dev->devpath, sizeof dev->devpath,
|
||||
"%s.%d", parent->devpath, port1);
|
||||
n = snprintf(dev->devpath, sizeof(dev->devpath), "%s.%d",
|
||||
parent->devpath, port1);
|
||||
/* Route string assumes hubs have less than 16 ports */
|
||||
if (port1 < 15)
|
||||
dev->route = parent->route +
|
||||
|
|
@ -734,6 +735,11 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
|||
dev->route = parent->route +
|
||||
(15 << ((parent->level - 1)*4));
|
||||
}
|
||||
if (n >= sizeof(dev->devpath)) {
|
||||
usb_put_hcd(bus_to_hcd(bus));
|
||||
usb_put_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->dev.parent = &parent->dev;
|
||||
dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
|
||||
|
|
|
|||
|
|
@ -4548,6 +4548,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
|
|||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
|
||||
hsotg->driver = NULL;
|
||||
hsotg->gadget.dev.of_node = NULL;
|
||||
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
hsotg->enabled = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -120,17 +120,19 @@ static void __dwc3_set_mode(struct work_struct *work)
|
|||
if (dwc->dr_mode != USB_DR_MODE_OTG)
|
||||
return;
|
||||
|
||||
pm_runtime_get_sync(dwc->dev);
|
||||
|
||||
if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG)
|
||||
dwc3_otg_update(dwc, 0);
|
||||
|
||||
if (!dwc->desired_dr_role)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
if (dwc->desired_dr_role == dwc->current_dr_role)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
switch (dwc->current_dr_role) {
|
||||
case DWC3_GCTL_PRTCAP_HOST:
|
||||
|
|
@ -194,6 +196,9 @@ static void __dwc3_set_mode(struct work_struct *work)
|
|||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(dwc->dev);
|
||||
pm_runtime_put_autosuspend(dwc->dev);
|
||||
}
|
||||
|
||||
void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
|
||||
|
|
|
|||
|
|
@ -529,6 +529,9 @@ static int dwc3_meson_g12a_remove(struct platform_device *pdev)
|
|||
|
||||
usb_role_switch_unregister(priv->role_switch);
|
||||
|
||||
put_device(priv->switch_desc.udc);
|
||||
put_device(priv->switch_desc.usb2_port);
|
||||
|
||||
of_platform_depopulate(dev);
|
||||
|
||||
for (i = 0 ; i < PHY_COUNT ; ++i) {
|
||||
|
|
|
|||
|
|
@ -641,13 +641,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
|
|||
ret = reset_control_deassert(qcom->resets);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret);
|
||||
goto reset_assert;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np));
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clocks\n");
|
||||
goto reset_assert;
|
||||
return ret;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
|
@ -729,8 +729,6 @@ clk_disable:
|
|||
if (qcom->gdsc)
|
||||
if (regulator_disable(qcom->gdsc))
|
||||
dev_err(qcom->dev, "unable to disable usb3 gdsc\n");
|
||||
reset_assert:
|
||||
reset_control_assert(qcom->resets);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -754,8 +752,6 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
|
|||
}
|
||||
qcom->num_clocks = 0;
|
||||
|
||||
reset_control_assert(qcom->resets);
|
||||
|
||||
pm_runtime_allow(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -3535,6 +3535,15 @@ out:
|
|||
static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep,
|
||||
const struct dwc3_event_depevt *event)
|
||||
{
|
||||
/*
|
||||
* During a device-initiated disconnect, a late xferNotReady event can
|
||||
* be generated after the End Transfer command resets the event filter,
|
||||
* but before the controller is halted. Ignore it to prevent a new
|
||||
* transfer from starting.
|
||||
*/
|
||||
if (!dep->dwc->connected)
|
||||
return;
|
||||
|
||||
dwc3_gadget_endpoint_frame_from_event(dep, event);
|
||||
(void) __dwc3_gadget_start_isoc(dep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,6 +678,10 @@ int __init early_xdbc_setup_hardware(void)
|
|||
|
||||
xdbc.table_base = NULL;
|
||||
xdbc.out_buf = NULL;
|
||||
|
||||
early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
|
||||
xdbc.xhci_base = NULL;
|
||||
xdbc.xhci_length = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -970,10 +970,11 @@ static int set_config(struct usb_composite_dev *cdev,
|
|||
else
|
||||
power = min(power, 900U);
|
||||
done:
|
||||
if (power <= USB_SELF_POWER_VBUS_MAX_DRAW)
|
||||
usb_gadget_set_selfpowered(gadget);
|
||||
else
|
||||
if (power > USB_SELF_POWER_VBUS_MAX_DRAW ||
|
||||
(c && !(c->bmAttributes & USB_CONFIG_ATT_SELFPOWER)))
|
||||
usb_gadget_clear_selfpowered(gadget);
|
||||
else
|
||||
usb_gadget_set_selfpowered(gadget);
|
||||
|
||||
usb_gadget_vbus_draw(gadget, power);
|
||||
if (result >= 0 && cdev->delayed_status)
|
||||
|
|
@ -2321,6 +2322,11 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
|
|||
if (!cdev->os_desc_req->buf) {
|
||||
ret = -ENOMEM;
|
||||
usb_ep_free_request(ep0, cdev->os_desc_req);
|
||||
/*
|
||||
* Set os_desc_req to NULL so that composite_dev_cleanup()
|
||||
* will not try to free it again.
|
||||
*/
|
||||
cdev->os_desc_req = NULL;
|
||||
goto end;
|
||||
}
|
||||
cdev->os_desc_req->context = cdev;
|
||||
|
|
@ -2446,7 +2452,10 @@ void composite_suspend(struct usb_gadget *gadget)
|
|||
|
||||
cdev->suspended = 1;
|
||||
|
||||
usb_gadget_set_selfpowered(gadget);
|
||||
if (cdev->config &&
|
||||
cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER)
|
||||
usb_gadget_set_selfpowered(gadget);
|
||||
|
||||
usb_gadget_vbus_draw(gadget, 2);
|
||||
}
|
||||
|
||||
|
|
@ -2478,8 +2487,11 @@ void composite_resume(struct usb_gadget *gadget)
|
|||
else
|
||||
maxpower = min(maxpower, 900U);
|
||||
|
||||
if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW)
|
||||
if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW ||
|
||||
!(cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER))
|
||||
usb_gadget_clear_selfpowered(gadget);
|
||||
else
|
||||
usb_gadget_set_selfpowered(gadget);
|
||||
|
||||
usb_gadget_vbus_draw(gadget, maxpower);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -938,6 +938,8 @@ static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
|
|||
struct gadget_info *gi = os_desc_item_to_gadget_info(item);
|
||||
int res, l;
|
||||
|
||||
if (!len)
|
||||
return len;
|
||||
l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
|
||||
if (page[l - 1] == '\n')
|
||||
--l;
|
||||
|
|
@ -1439,6 +1441,8 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
|
|||
cdev->use_os_string = true;
|
||||
cdev->b_vendor_code = gi->b_vendor_code;
|
||||
memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
|
||||
} else {
|
||||
cdev->use_os_string = false;
|
||||
}
|
||||
|
||||
if (gadget_is_otg(gadget) && !otg_desc[0]) {
|
||||
|
|
|
|||
|
|
@ -2254,7 +2254,12 @@ static int ffs_func_eps_enable(struct ffs_function *func)
|
|||
ep = func->eps;
|
||||
epfile = ffs->epfiles;
|
||||
count = ffs->eps_count;
|
||||
while(count--) {
|
||||
if (!epfile) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (count--) {
|
||||
ep->ep->driver_data = ep;
|
||||
|
||||
ret = config_ep_by_speed(func->gadget, &func->function, ep->ep);
|
||||
|
|
@ -2280,6 +2285,7 @@ static int ffs_func_eps_enable(struct ffs_function *func)
|
|||
}
|
||||
|
||||
wake_up_interruptible(&ffs->wait);
|
||||
done:
|
||||
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ static struct hid_descriptor hidg_desc = {
|
|||
.bcdHID = cpu_to_le16(0x0101),
|
||||
.bCountryCode = 0x00,
|
||||
.bNumDescriptors = 0x1,
|
||||
/*.desc[0].bDescriptorType = DYNAMIC */
|
||||
/*.desc[0].wDescriptorLenght = DYNAMIC */
|
||||
/*.rpt_desc.bDescriptorType = DYNAMIC */
|
||||
/*.rpt_desc.wDescriptorLength = DYNAMIC */
|
||||
};
|
||||
|
||||
/* Super-Speed Support */
|
||||
|
|
@ -496,7 +496,7 @@ try_again:
|
|||
}
|
||||
|
||||
req->status = 0;
|
||||
req->zero = 0;
|
||||
req->zero = 1;
|
||||
req->length = count;
|
||||
req->complete = f_hidg_req_complete;
|
||||
req->context = hidg;
|
||||
|
|
@ -730,8 +730,8 @@ static int hidg_setup(struct usb_function *f,
|
|||
struct hid_descriptor hidg_desc_copy = hidg_desc;
|
||||
|
||||
VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: HID\n");
|
||||
hidg_desc_copy.desc[0].bDescriptorType = HID_DT_REPORT;
|
||||
hidg_desc_copy.desc[0].wDescriptorLength =
|
||||
hidg_desc_copy.rpt_desc.bDescriptorType = HID_DT_REPORT;
|
||||
hidg_desc_copy.rpt_desc.wDescriptorLength =
|
||||
cpu_to_le16(hidg->report_desc_length);
|
||||
|
||||
length = min_t(unsigned short, length,
|
||||
|
|
@ -767,7 +767,7 @@ stall:
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
respond:
|
||||
req->zero = 0;
|
||||
req->zero = 1;
|
||||
req->length = length;
|
||||
status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
|
||||
if (status < 0)
|
||||
|
|
@ -972,8 +972,8 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
* We can use hidg_desc struct here but we should not relay
|
||||
* that its content won't change after returning from this function.
|
||||
*/
|
||||
hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
|
||||
hidg_desc.desc[0].wDescriptorLength =
|
||||
hidg_desc.rpt_desc.bDescriptorType = HID_DT_REPORT;
|
||||
hidg_desc.rpt_desc.wDescriptorLength =
|
||||
cpu_to_le16(hidg->report_desc_length);
|
||||
|
||||
hidg_hs_in_ep_desc.bEndpointAddress =
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ struct f_midi {
|
|||
struct snd_rawmidi_substream *out_substream[MAX_PORTS];
|
||||
|
||||
unsigned long out_triggered;
|
||||
struct tasklet_struct tasklet;
|
||||
struct work_struct work;
|
||||
unsigned int in_ports;
|
||||
unsigned int out_ports;
|
||||
int index;
|
||||
|
|
@ -282,7 +282,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
/* Our transmit completed. See if there's more to go.
|
||||
* f_midi_transmit eats req, don't queue it again. */
|
||||
req->length = 0;
|
||||
f_midi_transmit(midi);
|
||||
queue_work(system_highpri_wq, &midi->work);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
|
@ -698,9 +698,11 @@ drop_out:
|
|||
f_midi_drop_out_substreams(midi);
|
||||
}
|
||||
|
||||
static void f_midi_in_tasklet(unsigned long data)
|
||||
static void f_midi_in_work(struct work_struct *work)
|
||||
{
|
||||
struct f_midi *midi = (struct f_midi *) data;
|
||||
struct f_midi *midi;
|
||||
|
||||
midi = container_of(work, struct f_midi, work);
|
||||
f_midi_transmit(midi);
|
||||
}
|
||||
|
||||
|
|
@ -737,7 +739,7 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up)
|
|||
VDBG(midi, "%s() %d\n", __func__, up);
|
||||
midi->in_ports_array[substream->number].active = up;
|
||||
if (up)
|
||||
tasklet_hi_schedule(&midi->tasklet);
|
||||
queue_work(system_highpri_wq, &midi->work);
|
||||
}
|
||||
|
||||
static int f_midi_out_open(struct snd_rawmidi_substream *substream)
|
||||
|
|
@ -875,7 +877,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
|
||||
|
||||
midi->gadget = cdev->gadget;
|
||||
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
|
||||
INIT_WORK(&midi->work, f_midi_in_work);
|
||||
status = f_midi_register_card(midi);
|
||||
if (status < 0)
|
||||
goto fail_register;
|
||||
|
|
@ -997,11 +999,11 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
}
|
||||
|
||||
/* configure the endpoint descriptors ... */
|
||||
ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
|
||||
ms_out_desc.bNumEmbMIDIJack = midi->in_ports;
|
||||
ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
|
||||
ms_out_desc.bNumEmbMIDIJack = midi->out_ports;
|
||||
|
||||
ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
|
||||
ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
|
||||
ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
|
||||
ms_in_desc.bNumEmbMIDIJack = midi->in_ports;
|
||||
|
||||
/* ... and add them to the list */
|
||||
endpoint_descriptor_index = i;
|
||||
|
|
|
|||
|
|
@ -245,7 +245,6 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
|
|||
{
|
||||
struct f_uas *fu = cmd->fu;
|
||||
struct se_cmd *se_cmd = &cmd->se_cmd;
|
||||
struct usb_gadget *gadget = fuas_to_gadget(fu);
|
||||
int ret;
|
||||
|
||||
init_completion(&cmd->write_complete);
|
||||
|
|
@ -256,22 +255,6 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!gadget->sg_supported) {
|
||||
cmd->data_buf = kmalloc(se_cmd->data_length, GFP_KERNEL);
|
||||
if (!cmd->data_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
fu->bot_req_out->buf = cmd->data_buf;
|
||||
} else {
|
||||
fu->bot_req_out->buf = NULL;
|
||||
fu->bot_req_out->num_sgs = se_cmd->t_data_nents;
|
||||
fu->bot_req_out->sg = se_cmd->t_data_sg;
|
||||
}
|
||||
|
||||
fu->bot_req_out->complete = usbg_data_write_cmpl;
|
||||
fu->bot_req_out->length = se_cmd->data_length;
|
||||
fu->bot_req_out->context = cmd;
|
||||
|
||||
ret = usbg_prepare_w_request(cmd, fu->bot_req_out);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
|
@ -971,6 +954,7 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
|
|||
return;
|
||||
|
||||
cleanup:
|
||||
target_put_sess_cmd(se_cmd);
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1063,8 +1047,7 @@ static void usbg_cmd_work(struct work_struct *work)
|
|||
|
||||
out:
|
||||
transport_send_check_condition_and_sense(se_cmd,
|
||||
TCM_UNSUPPORTED_SCSI_OPCODE, 1);
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 0);
|
||||
TCM_UNSUPPORTED_SCSI_OPCODE, 0);
|
||||
}
|
||||
|
||||
static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
|
||||
|
|
@ -1193,8 +1176,7 @@ static void bot_cmd_work(struct work_struct *work)
|
|||
|
||||
out:
|
||||
transport_send_check_condition_and_sense(se_cmd,
|
||||
TCM_UNSUPPORTED_SCSI_OPCODE, 1);
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 0);
|
||||
TCM_UNSUPPORTED_SCSI_OPCODE, 0);
|
||||
}
|
||||
|
||||
static int bot_submit_command(struct f_uas *fu,
|
||||
|
|
@ -1338,14 +1320,14 @@ static struct se_portal_group *usbg_make_tpg(struct se_wwn *wwn,
|
|||
struct usbg_tport *tport = container_of(wwn, struct usbg_tport,
|
||||
tport_wwn);
|
||||
struct usbg_tpg *tpg;
|
||||
unsigned long tpgt;
|
||||
u16 tpgt;
|
||||
int ret;
|
||||
struct f_tcm_opts *opts;
|
||||
unsigned i;
|
||||
|
||||
if (strstr(name, "tpgt_") != name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX)
|
||||
if (kstrtou16(name + 5, 0, &tpgt))
|
||||
return ERR_PTR(-EINVAL);
|
||||
ret = -ENODEV;
|
||||
mutex_lock(&tpg_instances_lock);
|
||||
|
|
@ -2017,43 +1999,39 @@ static int tcm_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
bot_intf_desc.bInterfaceNumber = iface;
|
||||
uasp_intf_desc.bInterfaceNumber = iface;
|
||||
fu->iface = iface;
|
||||
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bi_desc,
|
||||
&uasp_bi_ep_comp_desc);
|
||||
ep = usb_ep_autoconfig(gadget, &uasp_fs_bi_desc);
|
||||
if (!ep)
|
||||
goto ep_fail;
|
||||
|
||||
fu->ep_in = ep;
|
||||
|
||||
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
|
||||
&uasp_bo_ep_comp_desc);
|
||||
ep = usb_ep_autoconfig(gadget, &uasp_fs_bo_desc);
|
||||
if (!ep)
|
||||
goto ep_fail;
|
||||
fu->ep_out = ep;
|
||||
|
||||
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
|
||||
&uasp_status_in_ep_comp_desc);
|
||||
ep = usb_ep_autoconfig(gadget, &uasp_fs_status_desc);
|
||||
if (!ep)
|
||||
goto ep_fail;
|
||||
fu->ep_status = ep;
|
||||
|
||||
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
|
||||
&uasp_cmd_comp_desc);
|
||||
ep = usb_ep_autoconfig(gadget, &uasp_fs_cmd_desc);
|
||||
if (!ep)
|
||||
goto ep_fail;
|
||||
fu->ep_cmd = ep;
|
||||
|
||||
/* Assume endpoint addresses are the same for both speeds */
|
||||
uasp_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
|
||||
uasp_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
|
||||
uasp_bi_desc.bEndpointAddress = uasp_fs_bi_desc.bEndpointAddress;
|
||||
uasp_bo_desc.bEndpointAddress = uasp_fs_bo_desc.bEndpointAddress;
|
||||
uasp_status_desc.bEndpointAddress =
|
||||
uasp_ss_status_desc.bEndpointAddress;
|
||||
uasp_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
|
||||
uasp_fs_status_desc.bEndpointAddress;
|
||||
uasp_cmd_desc.bEndpointAddress = uasp_fs_cmd_desc.bEndpointAddress;
|
||||
|
||||
uasp_fs_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
|
||||
uasp_fs_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
|
||||
uasp_fs_status_desc.bEndpointAddress =
|
||||
uasp_ss_status_desc.bEndpointAddress;
|
||||
uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
|
||||
uasp_ss_bi_desc.bEndpointAddress = uasp_fs_bi_desc.bEndpointAddress;
|
||||
uasp_ss_bo_desc.bEndpointAddress = uasp_fs_bo_desc.bEndpointAddress;
|
||||
uasp_ss_status_desc.bEndpointAddress =
|
||||
uasp_fs_status_desc.bEndpointAddress;
|
||||
uasp_ss_cmd_desc.bEndpointAddress = uasp_fs_cmd_desc.bEndpointAddress;
|
||||
|
||||
ret = usb_assign_descriptors(f, uasp_fs_function_desc,
|
||||
uasp_hs_function_desc, uasp_ss_function_desc,
|
||||
|
|
|
|||
|
|
@ -286,8 +286,8 @@ __acquires(&port->port_lock)
|
|||
break;
|
||||
}
|
||||
|
||||
if (do_tty_wake && port->port.tty)
|
||||
tty_wakeup(port->port.tty);
|
||||
if (do_tty_wake)
|
||||
tty_port_tty_wakeup(&port->port);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +564,7 @@ static int gs_start_io(struct gs_port *port)
|
|||
gs_start_tx(port);
|
||||
/* Unblock any pending writes into our circular buffer, in case
|
||||
* we didn't in gs_start_tx() */
|
||||
tty_wakeup(port->port.tty);
|
||||
tty_port_tty_wakeup(&port->port);
|
||||
} else {
|
||||
/* Free reqs only if we are still connected */
|
||||
if (port->port_usb) {
|
||||
|
|
|
|||
|
|
@ -542,6 +542,9 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
|
|||
d->vhub = vhub;
|
||||
d->index = idx;
|
||||
d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1);
|
||||
if (!d->name)
|
||||
return -ENOMEM;
|
||||
|
||||
d->regs = vhub->regs + 0x100 + 0x10 * idx;
|
||||
|
||||
ast_vhub_init_ep0(vhub, &d->ep0, d);
|
||||
|
|
|
|||
|
|
@ -748,7 +748,7 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
|
|||
struct dummy *dum;
|
||||
int retval = -EINVAL;
|
||||
unsigned long flags;
|
||||
struct dummy_request *req = NULL;
|
||||
struct dummy_request *req = NULL, *iter;
|
||||
|
||||
if (!_ep || !_req)
|
||||
return retval;
|
||||
|
|
@ -758,25 +758,26 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
|
|||
if (!dum->driver)
|
||||
return -ESHUTDOWN;
|
||||
|
||||
local_irq_save(flags);
|
||||
spin_lock(&dum->lock);
|
||||
list_for_each_entry(req, &ep->queue, queue) {
|
||||
if (&req->req == _req) {
|
||||
list_del_init(&req->queue);
|
||||
_req->status = -ECONNRESET;
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
spin_lock_irqsave(&dum->lock, flags);
|
||||
list_for_each_entry(iter, &ep->queue, queue) {
|
||||
if (&iter->req != _req)
|
||||
continue;
|
||||
list_del_init(&iter->queue);
|
||||
_req->status = -ECONNRESET;
|
||||
req = iter;
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
spin_unlock(&dum->lock);
|
||||
|
||||
if (retval == 0) {
|
||||
dev_dbg(udc_dev(dum),
|
||||
"dequeued req %p from %s, len %d buf %p\n",
|
||||
req, _ep->name, _req->length, _req->buf);
|
||||
spin_unlock(&dum->lock);
|
||||
usb_gadget_giveback_request(_ep, _req);
|
||||
spin_lock(&dum->lock);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_irqrestore(&dum->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ struct renesas_usb3_request {
|
|||
struct list_head queue;
|
||||
};
|
||||
|
||||
#define USB3_EP_NAME_SIZE 8
|
||||
#define USB3_EP_NAME_SIZE 16
|
||||
struct renesas_usb3_ep {
|
||||
struct usb_ep ep;
|
||||
struct renesas_usb3 *usb3;
|
||||
|
|
@ -2551,6 +2551,7 @@ static int renesas_usb3_remove(struct platform_device *pdev)
|
|||
struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
|
||||
|
||||
debugfs_remove_recursive(usb3->dentry);
|
||||
put_device(usb3->host_dev);
|
||||
device_remove_file(&pdev->dev, &dev_attr_role);
|
||||
|
||||
cancel_work_sync(&usb3->role_work);
|
||||
|
|
|
|||
|
|
@ -1925,7 +1925,7 @@ error:
|
|||
if (hcd) {
|
||||
kfree(max3421_hcd->tx);
|
||||
kfree(max3421_hcd->rx);
|
||||
if (max3421_hcd->spi_thread)
|
||||
if (!IS_ERR_OR_NULL(max3421_hcd->spi_thread))
|
||||
kthread_stop(max3421_hcd->spi_thread);
|
||||
usb_put_hcd(hcd);
|
||||
}
|
||||
|
|
@ -1956,6 +1956,12 @@ max3421_remove(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id max3421_spi_ids[] = {
|
||||
{ "max3421" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, max3421_spi_ids);
|
||||
|
||||
static const struct of_device_id max3421_of_match_table[] = {
|
||||
{ .compatible = "maxim,max3421", },
|
||||
{},
|
||||
|
|
@ -1965,6 +1971,7 @@ MODULE_DEVICE_TABLE(of, max3421_of_match_table);
|
|||
static struct spi_driver max3421_driver = {
|
||||
.probe = max3421_probe,
|
||||
.remove = max3421_remove,
|
||||
.id_table = max3421_spi_ids,
|
||||
.driver = {
|
||||
.name = "max3421-hcd",
|
||||
.of_match_table = of_match_ptr(max3421_of_match_table),
|
||||
|
|
|
|||
|
|
@ -165,6 +165,25 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ohci_quirk_loongson(struct usb_hcd *hcd)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||
|
||||
/*
|
||||
* Loongson's LS7A OHCI controller (rev 0x02) has a
|
||||
* flaw. MMIO register with offset 0x60/64 is treated
|
||||
* as legacy PS2-compatible keyboard/mouse interface.
|
||||
* Since OHCI only use 4KB BAR resource, LS7A OHCI's
|
||||
* 32KB BAR is wrapped around (the 2nd 4KB BAR space
|
||||
* is the same as the 1st 4KB internally). So add 4KB
|
||||
* offset (0x1000) to the OHCI registers as a quirk.
|
||||
*/
|
||||
if (pdev->revision == 0x2)
|
||||
hcd->regs += SZ_4K; /* SZ_4K = 0x1000 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ohci_quirk_qemu(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
|
|
@ -224,6 +243,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
|
|||
PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
|
||||
.driver_data = (unsigned long)ohci_quirk_amd700,
|
||||
},
|
||||
{
|
||||
PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a24),
|
||||
.driver_data = (unsigned long)ohci_quirk_loongson,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_APPLE,
|
||||
.device = 0x003f,
|
||||
|
|
|
|||
|
|
@ -945,6 +945,15 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev)
|
|||
* booting from USB disk or using a usb keyboard
|
||||
*/
|
||||
hcc_params = readl(base + EHCI_HCC_PARAMS);
|
||||
|
||||
/* LS7A EHCI controller doesn't have extended capabilities, the
|
||||
* EECP (EHCI Extended Capabilities Pointer) field of HCCPARAMS
|
||||
* register should be 0x0 but it reads as 0xa0. So clear it to
|
||||
* avoid error messages on boot.
|
||||
*/
|
||||
if (pdev->vendor == PCI_VENDOR_ID_LOONGSON && pdev->device == 0x7a14)
|
||||
hcc_params &= ~(0xffL << 8);
|
||||
|
||||
offset = (hcc_params >> 8) & 0xff;
|
||||
while (offset && --count) {
|
||||
pci_read_config_dword(pdev, offset, &cap);
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Get and enable clock if any specified */
|
||||
uhci->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
uhci->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
if (IS_ERR(uhci->clk)) {
|
||||
ret = PTR_ERR(uhci->clk);
|
||||
goto err_rmr;
|
||||
|
|
|
|||
|
|
@ -975,8 +975,15 @@ int xhci_dbc_suspend(struct xhci_hcd *xhci)
|
|||
if (!dbc)
|
||||
return 0;
|
||||
|
||||
if (dbc->state == DS_CONFIGURED)
|
||||
switch (dbc->state) {
|
||||
case DS_ENABLED:
|
||||
case DS_CONNECTED:
|
||||
case DS_CONFIGURED:
|
||||
dbc->resume_required = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
xhci_dbc_stop(xhci);
|
||||
|
||||
|
|
|
|||
|
|
@ -629,8 +629,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci,
|
|||
if (!xhci->devs[i])
|
||||
continue;
|
||||
|
||||
retval = xhci_disable_slot(xhci, i);
|
||||
xhci_free_virt_device(xhci, i);
|
||||
retval = xhci_disable_and_free_slot(xhci, i);
|
||||
if (retval)
|
||||
xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
|
||||
i, retval);
|
||||
|
|
|
|||
|
|
@ -879,21 +879,20 @@ free_tts:
|
|||
* will be manipulated by the configure endpoint, allocate device, or update
|
||||
* hub functions while this function is removing the TT entries from the list.
|
||||
*/
|
||||
void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
||||
void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev,
|
||||
int slot_id)
|
||||
{
|
||||
struct xhci_virt_device *dev;
|
||||
int i;
|
||||
int old_active_eps = 0;
|
||||
|
||||
/* Slot ID 0 is reserved */
|
||||
if (slot_id == 0 || !xhci->devs[slot_id])
|
||||
if (slot_id == 0 || !dev)
|
||||
return;
|
||||
|
||||
dev = xhci->devs[slot_id];
|
||||
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
if (!dev)
|
||||
return;
|
||||
/* If device ctx array still points to _this_ device, clear it */
|
||||
if (dev->out_ctx &&
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] == cpu_to_le64(dev->out_ctx->dma))
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
|
||||
trace_xhci_free_virt_device(dev);
|
||||
|
||||
|
|
@ -932,8 +931,9 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
|||
|
||||
if (dev->udev && dev->udev->slot_id)
|
||||
dev->udev->slot_id = 0;
|
||||
kfree(xhci->devs[slot_id]);
|
||||
xhci->devs[slot_id] = NULL;
|
||||
if (xhci->devs[slot_id] == dev)
|
||||
xhci->devs[slot_id] = NULL;
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -975,7 +975,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i
|
|||
out:
|
||||
/* we are now at a leaf device */
|
||||
xhci_debugfs_remove_slot(xhci, slot_id);
|
||||
xhci_free_virt_device(xhci, slot_id);
|
||||
xhci_free_virt_device(xhci, vdev, slot_id);
|
||||
}
|
||||
|
||||
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
||||
|
|
@ -1214,6 +1214,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma |
|
||||
dev->eps[0].ring->cycle_state);
|
||||
|
||||
ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8));
|
||||
|
||||
trace_xhci_setup_addressable_virt_device(dev);
|
||||
|
||||
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
#define SPARSE_CNTL_ENABLE 0xC12C
|
||||
|
||||
/* Device for a quirk */
|
||||
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
|
||||
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009 0x1009
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 0x1100
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400
|
||||
|
|
@ -36,8 +36,8 @@
|
|||
#define PCI_DEVICE_ID_EJ168 0x7023
|
||||
#define PCI_DEVICE_ID_EJ188 0x7052
|
||||
|
||||
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
|
||||
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
|
||||
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
|
||||
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
|
||||
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI 0x9cb1
|
||||
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
|
||||
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
|
||||
|
|
|
|||
|
|
@ -977,12 +977,15 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
|
|||
*/
|
||||
void xhci_hc_died(struct xhci_hcd *xhci)
|
||||
{
|
||||
bool notify;
|
||||
int i, j;
|
||||
|
||||
if (xhci->xhc_state & XHCI_STATE_DYING)
|
||||
return;
|
||||
|
||||
xhci_err(xhci, "xHCI host controller not responding, assume dead\n");
|
||||
notify = !(xhci->xhc_state & XHCI_STATE_REMOVING);
|
||||
if (notify)
|
||||
xhci_err(xhci, "xHCI host controller not responding, assume dead\n");
|
||||
xhci->xhc_state |= XHCI_STATE_DYING;
|
||||
|
||||
xhci_cleanup_command_queue(xhci);
|
||||
|
|
@ -996,7 +999,7 @@ void xhci_hc_died(struct xhci_hcd *xhci)
|
|||
}
|
||||
|
||||
/* inform usb core hc died if PCI remove isn't already handling it */
|
||||
if (!(xhci->xhc_state & XHCI_STATE_REMOVING))
|
||||
if (notify)
|
||||
usb_hc_died(xhci_to_hcd(xhci));
|
||||
}
|
||||
|
||||
|
|
@ -1259,7 +1262,8 @@ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
|
|||
command->slot_id = 0;
|
||||
}
|
||||
|
||||
static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
|
||||
static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id,
|
||||
u32 cmd_comp_code)
|
||||
{
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
|
|
@ -1274,6 +1278,10 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
|
|||
if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
|
||||
/* Delete default control endpoint resources */
|
||||
xhci_free_device_endpoint_resources(xhci, virt_dev, true);
|
||||
if (cmd_comp_code == COMP_SUCCESS) {
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
xhci->devs[slot_id] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
|
|
@ -1513,7 +1521,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
|||
xhci_handle_cmd_enable_slot(xhci, slot_id, cmd, cmd_comp_code);
|
||||
break;
|
||||
case TRB_DISABLE_SLOT:
|
||||
xhci_handle_cmd_disable_slot(xhci, slot_id);
|
||||
xhci_handle_cmd_disable_slot(xhci, slot_id, cmd_comp_code);
|
||||
break;
|
||||
case TRB_CONFIG_EP:
|
||||
if (!cmd->completion)
|
||||
|
|
@ -4225,7 +4233,8 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
|
|||
|
||||
if ((xhci->xhc_state & XHCI_STATE_DYING) ||
|
||||
(xhci->xhc_state & XHCI_STATE_HALTED)) {
|
||||
xhci_dbg(xhci, "xHCI dying or halted, can't queue_command\n");
|
||||
xhci_dbg(xhci, "xHCI dying or halted, can't queue_command. state: 0x%x\n",
|
||||
xhci->xhc_state);
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ int xhci_halt(struct xhci_hcd *xhci)
|
|||
ret = xhci_handshake(&xhci->op_regs->status,
|
||||
STS_HALT, STS_HALT, 3 * XHCI_MAX_HALT_USEC);
|
||||
if (ret) {
|
||||
xhci_warn(xhci, "Host halt failed, %d\n", ret);
|
||||
if (!(xhci->xhc_state & XHCI_STATE_DYING))
|
||||
xhci_warn(xhci, "Host halt failed, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
xhci->xhc_state |= XHCI_STATE_HALTED;
|
||||
|
|
@ -204,7 +205,8 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
|
|||
state = readl(&xhci->op_regs->status);
|
||||
|
||||
if (state == ~(u32)0) {
|
||||
xhci_warn(xhci, "Host not accessible, reset failed.\n");
|
||||
if (!(xhci->xhc_state & XHCI_STATE_DYING))
|
||||
xhci_warn(xhci, "Host not accessible, reset failed.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -4130,7 +4132,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
xhci_disable_slot(xhci, udev->slot_id);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
xhci_free_virt_device(xhci, udev->slot_id);
|
||||
xhci_free_virt_device(xhci, virt_dev, udev->slot_id);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
}
|
||||
|
|
@ -4179,6 +4181,16 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id)
|
||||
{
|
||||
struct xhci_virt_device *vdev = xhci->devs[slot_id];
|
||||
int ret;
|
||||
|
||||
ret = xhci_disable_slot(xhci, slot_id);
|
||||
xhci_free_virt_device(xhci, vdev, slot_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if we have enough host controller resources for the default control
|
||||
* endpoint.
|
||||
|
|
@ -4284,8 +4296,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
return 1;
|
||||
|
||||
disable_slot:
|
||||
xhci_disable_slot(xhci, udev->slot_id);
|
||||
xhci_free_virt_device(xhci, udev->slot_id);
|
||||
xhci_disable_and_free_slot(xhci, udev->slot_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4414,8 +4425,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
dev_warn(&udev->dev, "Device not responding to setup %s.\n", act);
|
||||
|
||||
mutex_unlock(&xhci->mutex);
|
||||
ret = xhci_disable_slot(xhci, udev->slot_id);
|
||||
xhci_free_virt_device(xhci, udev->slot_id);
|
||||
ret = xhci_disable_and_free_slot(xhci, udev->slot_id);
|
||||
if (!ret) {
|
||||
if (xhci_alloc_dev(hcd, udev) == 1)
|
||||
xhci_setup_addressable_virt_dev(xhci, udev);
|
||||
|
|
|
|||
|
|
@ -2031,7 +2031,7 @@ void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *),
|
|||
/* xHCI memory management */
|
||||
void xhci_mem_cleanup(struct xhci_hcd *xhci);
|
||||
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags);
|
||||
void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);
|
||||
void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, int slot_id);
|
||||
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags);
|
||||
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
|
||||
void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
|
||||
|
|
@ -2123,6 +2123,7 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
|
|||
int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
||||
struct usb_tt *tt, gfp_t mem_flags);
|
||||
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
|
||||
int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id);
|
||||
int xhci_ext_cap_init(struct xhci_hcd *xhci);
|
||||
|
||||
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
|
||||
|
|
|
|||
|
|
@ -68,18 +68,20 @@
|
|||
* The magic limit was calculated so that it allows the monitoring
|
||||
* application to pick data once in two ticks. This way, another application,
|
||||
* which presumably drives the bus, gets to hog CPU, yet we collect our data.
|
||||
* If HZ is 100, a 480 mbit/s bus drives 614 KB every jiffy. USB has an
|
||||
* enormous overhead built into the bus protocol, so we need about 1000 KB.
|
||||
*
|
||||
* Originally, for a 480 Mbit/s bus this required a buffer of about 1 MB. For
|
||||
* modern 20 Gbps buses, this value increases to over 50 MB. The maximum
|
||||
* buffer size is set to 64 MiB to accommodate this.
|
||||
*
|
||||
* This is still too much for most cases, where we just snoop a few
|
||||
* descriptor fetches for enumeration. So, the default is a "reasonable"
|
||||
* amount for systems with HZ=250 and incomplete bus saturation.
|
||||
* amount for typical, low-throughput use cases.
|
||||
*
|
||||
* XXX What about multi-megabyte URBs which take minutes to transfer?
|
||||
*/
|
||||
#define BUFF_MAX CHUNK_ALIGN(1200*1024)
|
||||
#define BUFF_DFL CHUNK_ALIGN(300*1024)
|
||||
#define BUFF_MIN CHUNK_ALIGN(8*1024)
|
||||
#define BUFF_MAX CHUNK_ALIGN(64*1024*1024)
|
||||
#define BUFF_DFL CHUNK_ALIGN(300*1024)
|
||||
#define BUFF_MIN CHUNK_ALIGN(8*1024)
|
||||
|
||||
/*
|
||||
* The per-event API header (2 per URB).
|
||||
|
|
|
|||
|
|
@ -1910,6 +1910,7 @@ static int musb_gadget_stop(struct usb_gadget *g)
|
|||
* gadget driver here and have everything work;
|
||||
* that currently misbehaves.
|
||||
*/
|
||||
usb_gadget_set_state(g, USB_STATE_NOTATTACHED);
|
||||
|
||||
/* Force check of devctl register for PM runtime */
|
||||
schedule_delayed_work(&musb->irq_work, 0);
|
||||
|
|
@ -2018,6 +2019,7 @@ void musb_g_disconnect(struct musb *musb)
|
|||
case OTG_STATE_B_PERIPHERAL:
|
||||
case OTG_STATE_B_IDLE:
|
||||
musb->xceiv->otg->state = OTG_STATE_B_IDLE;
|
||||
usb_gadget_set_state(&musb->g, USB_STATE_NOTATTACHED);
|
||||
break;
|
||||
case OTG_STATE_B_SRP_INIT:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -476,13 +476,13 @@ static int omap2430_probe(struct platform_device *pdev)
|
|||
ARRAY_SIZE(musb_resources));
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add resources\n");
|
||||
goto err2;
|
||||
goto err_put_control_otghs;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add platform_data\n");
|
||||
goto err2;
|
||||
goto err_put_control_otghs;
|
||||
}
|
||||
|
||||
pm_runtime_enable(glue->dev);
|
||||
|
|
@ -497,7 +497,9 @@ static int omap2430_probe(struct platform_device *pdev)
|
|||
|
||||
err3:
|
||||
pm_runtime_disable(glue->dev);
|
||||
|
||||
err_put_control_otghs:
|
||||
if (!IS_ERR(glue->control_otghs))
|
||||
put_device(glue->control_otghs);
|
||||
err2:
|
||||
platform_device_put(musb);
|
||||
|
||||
|
|
@ -511,6 +513,8 @@ static int omap2430_remove(struct platform_device *pdev)
|
|||
|
||||
platform_device_unregister(glue->musb);
|
||||
pm_runtime_disable(glue->dev);
|
||||
if (!IS_ERR(glue->control_otghs))
|
||||
put_device(glue->control_otghs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@ static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
|
|||
static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
|
||||
{
|
||||
bool vbus_is_on = false;
|
||||
enum usb_phy_events last_event = mxs_phy->phy.last_event;
|
||||
|
||||
/* If the SoCs don't need to disconnect line without vbus, quit */
|
||||
if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
|
||||
|
|
@ -405,7 +406,8 @@ static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
|
|||
|
||||
vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
|
||||
|
||||
if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
|
||||
if (on && ((!vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
|
||||
|| (last_event == USB_EVENT_VBUS)))
|
||||
__mxs_phy_disconnect_line(mxs_phy, true);
|
||||
else
|
||||
__mxs_phy_disconnect_line(mxs_phy, false);
|
||||
|
|
|
|||
|
|
@ -328,9 +328,8 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
|
|||
|
||||
static int twl6030_usb_probe(struct platform_device *pdev)
|
||||
{
|
||||
u32 ret;
|
||||
struct twl6030_usb *twl;
|
||||
int status, err;
|
||||
int status, err, ret;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
|
|
|
|||
|
|
@ -313,8 +313,10 @@ static int usbhsc_clk_get(struct device *dev, struct usbhs_priv *priv)
|
|||
priv->clks[1] = of_clk_get(dev_of_node(dev), 1);
|
||||
if (PTR_ERR(priv->clks[1]) == -ENOENT)
|
||||
priv->clks[1] = NULL;
|
||||
else if (IS_ERR(priv->clks[1]))
|
||||
else if (IS_ERR(priv->clks[1])) {
|
||||
clk_put(priv->clks[0]);
|
||||
return PTR_ERR(priv->clks[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -678,10 +680,29 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||
INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
|
||||
spin_lock_init(usbhs_priv_to_lock(priv));
|
||||
|
||||
/*
|
||||
* Acquire clocks and enable power management (PM) early in the
|
||||
* probe process, as the driver accesses registers during
|
||||
* initialization. Ensure the device is active before proceeding.
|
||||
*/
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = usbhsc_clk_get(dev, priv);
|
||||
if (ret)
|
||||
goto probe_pm_disable;
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
goto probe_clk_put;
|
||||
|
||||
ret = usbhsc_clk_prepare_enable(priv);
|
||||
if (ret)
|
||||
goto probe_pm_put;
|
||||
|
||||
/* call pipe and module init */
|
||||
ret = usbhs_pipe_probe(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto probe_clk_dis_unprepare;
|
||||
|
||||
ret = usbhs_fifo_probe(priv);
|
||||
if (ret < 0)
|
||||
|
|
@ -698,10 +719,6 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto probe_fail_rst;
|
||||
|
||||
ret = usbhsc_clk_get(dev, priv);
|
||||
if (ret)
|
||||
goto probe_fail_clks;
|
||||
|
||||
/*
|
||||
* deviece reset here because
|
||||
* USB device might be used in boot loader.
|
||||
|
|
@ -717,7 +734,7 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||
dev_warn(dev, "USB function not selected (GPIO %d)\n",
|
||||
priv->dparam.enable_gpio);
|
||||
ret = -ENOTSUPP;
|
||||
goto probe_end_mod_exit;
|
||||
goto probe_assert_rest;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -731,14 +748,19 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||
ret = usbhs_platform_call(priv, hardware_init, pdev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "platform init failed.\n");
|
||||
goto probe_end_mod_exit;
|
||||
goto probe_assert_rest;
|
||||
}
|
||||
|
||||
/* reset phy for connection */
|
||||
usbhs_platform_call(priv, phy_reset, pdev);
|
||||
|
||||
/* power control */
|
||||
pm_runtime_enable(dev);
|
||||
/*
|
||||
* Disable the clocks that were enabled earlier in the probe path,
|
||||
* and let the driver handle the clocks beyond this point.
|
||||
*/
|
||||
usbhsc_clk_disable_unprepare(priv);
|
||||
pm_runtime_put(dev);
|
||||
|
||||
if (!usbhs_get_dparam(priv, runtime_pwctrl)) {
|
||||
usbhsc_power_ctrl(priv, 1);
|
||||
usbhs_mod_autonomy_mode(priv);
|
||||
|
|
@ -755,9 +777,7 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||
|
||||
return ret;
|
||||
|
||||
probe_end_mod_exit:
|
||||
usbhsc_clk_put(priv);
|
||||
probe_fail_clks:
|
||||
probe_assert_rest:
|
||||
reset_control_assert(priv->rsts);
|
||||
probe_fail_rst:
|
||||
usbhs_mod_remove(priv);
|
||||
|
|
@ -765,6 +785,14 @@ probe_end_fifo_exit:
|
|||
usbhs_fifo_remove(priv);
|
||||
probe_end_pipe_exit:
|
||||
usbhs_pipe_remove(priv);
|
||||
probe_clk_dis_unprepare:
|
||||
usbhsc_clk_disable_unprepare(priv);
|
||||
probe_pm_put:
|
||||
pm_runtime_put(dev);
|
||||
probe_clk_put:
|
||||
usbhsc_clk_put(priv);
|
||||
probe_pm_disable:
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
dev_info(dev, "probe failed (%d)\n", ret);
|
||||
|
||||
|
|
@ -777,6 +805,8 @@ static int usbhs_remove(struct platform_device *pdev)
|
|||
|
||||
dev_dbg(&pdev->dev, "usb remove\n");
|
||||
|
||||
flush_delayed_work(&priv->notify_hotplug_work);
|
||||
|
||||
/* power off */
|
||||
if (!usbhs_get_dparam(priv, runtime_pwctrl))
|
||||
usbhsc_power_ctrl(priv, 0);
|
||||
|
|
|
|||
|
|
@ -1094,7 +1094,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
|
|||
goto usbhs_mod_gadget_probe_err_gpriv;
|
||||
}
|
||||
|
||||
gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
|
||||
gpriv->transceiver = devm_usb_get_phy(dev, USB_PHY_TYPE_UNDEFINED);
|
||||
dev_info(dev, "%stransceiver found\n",
|
||||
!IS_ERR(gpriv->transceiver) ? "" : "no ");
|
||||
|
||||
|
|
|
|||
|
|
@ -317,14 +317,15 @@ usb_role_switch_register(struct device *parent,
|
|||
sw->dev.type = &usb_role_dev_type;
|
||||
dev_set_name(&sw->dev, "%s-role-switch", dev_name(parent));
|
||||
|
||||
sw->registered = true;
|
||||
|
||||
ret = device_register(&sw->dev);
|
||||
if (ret) {
|
||||
sw->registered = false;
|
||||
put_device(&sw->dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
sw->registered = true;
|
||||
|
||||
/* TODO: Symlinks for the host port and the device controller. */
|
||||
|
||||
return sw;
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ static const struct usb_device_id id_table[] = {
|
|||
{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
|
||||
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
|
||||
{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
|
||||
{ USB_DEVICE(0x1B93, 0x1013) }, /* Phoenix Contact UPS Device */
|
||||
{ USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
|
||||
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
|
||||
{ USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */
|
||||
|
|
|
|||
|
|
@ -781,6 +781,8 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(FTDI_NDI_VID, FTDI_NDI_EMGUIDE_GEMINI_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
|
||||
{ USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, RTSYSTEMS_USB_VX8_PID) },
|
||||
|
|
@ -1057,6 +1059,22 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
/* GMC devices */
|
||||
{ USB_DEVICE(GMC_VID, GMC_Z216C_PID) },
|
||||
/* Altera USB Blaster 3 */
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6022_PID, 1) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6025_PID, 2) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6026_PID, 2) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6026_PID, 3) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6029_PID, 2) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602A_PID, 2) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602A_PID, 3) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602C_PID, 1) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602D_PID, 1) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602D_PID, 2) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 1) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 2) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) },
|
||||
/* Abacus Electrics */
|
||||
{ USB_DEVICE(FTDI_VID, ABACUS_OPTICAL_PROBE_PID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -197,6 +197,9 @@
|
|||
#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */
|
||||
#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */
|
||||
|
||||
#define FTDI_NDI_VID 0x23F2
|
||||
#define FTDI_NDI_EMGUIDE_GEMINI_PID 0x0003 /* NDI Emguide Gemini */
|
||||
|
||||
/*
|
||||
* ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs
|
||||
*/
|
||||
|
|
@ -435,6 +438,11 @@
|
|||
#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */
|
||||
#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */
|
||||
|
||||
/*
|
||||
* Abacus Electrics
|
||||
*/
|
||||
#define ABACUS_OPTICAL_PROBE_PID 0xf458 /* ABACUS ELECTRICS Optical Probe */
|
||||
|
||||
/*
|
||||
* Oceanic product ids
|
||||
*/
|
||||
|
|
@ -1605,3 +1613,16 @@
|
|||
*/
|
||||
#define GMC_VID 0x1cd7
|
||||
#define GMC_Z216C_PID 0x0217 /* GMC Z216C Adapter IR-USB */
|
||||
|
||||
/*
|
||||
* Altera USB Blaster 3 (http://www.altera.com).
|
||||
*/
|
||||
#define ALTERA_VID 0x09fb
|
||||
#define ALTERA_UB3_6022_PID 0x6022
|
||||
#define ALTERA_UB3_6025_PID 0x6025
|
||||
#define ALTERA_UB3_6026_PID 0x6026
|
||||
#define ALTERA_UB3_6029_PID 0x6029
|
||||
#define ALTERA_UB3_602A_PID 0x602a
|
||||
#define ALTERA_UB3_602C_PID 0x602c
|
||||
#define ALTERA_UB3_602D_PID 0x602d
|
||||
#define ALTERA_UB3_602E_PID 0x602e
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ static void option_instat_callback(struct urb *urb);
|
|||
#define QUECTEL_PRODUCT_EM05CN 0x0312
|
||||
#define QUECTEL_PRODUCT_EM05G_GR 0x0313
|
||||
#define QUECTEL_PRODUCT_EM05G_RS 0x0314
|
||||
#define QUECTEL_PRODUCT_RG255C 0x0316
|
||||
#define QUECTEL_PRODUCT_EM12 0x0512
|
||||
#define QUECTEL_PRODUCT_RM500Q 0x0800
|
||||
#define QUECTEL_PRODUCT_RM520N 0x0801
|
||||
|
|
@ -611,23 +612,16 @@ static void option_instat_callback(struct urb *urb);
|
|||
/* Sierra Wireless products */
|
||||
#define SIERRA_VENDOR_ID 0x1199
|
||||
#define SIERRA_PRODUCT_EM9191 0x90d3
|
||||
#define SIERRA_PRODUCT_EM9291 0x90e3
|
||||
|
||||
/* UNISOC (Spreadtrum) products */
|
||||
#define UNISOC_VENDOR_ID 0x1782
|
||||
/* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */
|
||||
#define TOZED_PRODUCT_LT70C 0x4055
|
||||
#define UNISOC_PRODUCT_UIS7720 0x4064
|
||||
/* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
|
||||
#define LUAT_PRODUCT_AIR720U 0x4e00
|
||||
|
||||
/* MeiG Smart Technology products */
|
||||
#define MEIGSMART_VENDOR_ID 0x2dee
|
||||
/* MeiG Smart SRM825L based on Qualcomm 315 */
|
||||
#define MEIGSMART_PRODUCT_SRM825L 0x4d22
|
||||
/* MeiG Smart SLM320 based on UNISOC UIS8910 */
|
||||
#define MEIGSMART_PRODUCT_SLM320 0x4d41
|
||||
/* MeiG Smart SLM770A based on ASR1803 */
|
||||
#define MEIGSMART_PRODUCT_SLM770A 0x4d57
|
||||
|
||||
/* Device flags */
|
||||
|
||||
/* Highest interface number which can be used with NCTRL() and RSVD() */
|
||||
|
|
@ -1278,6 +1272,9 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG650V, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG650V, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0xff, 0x40) },
|
||||
|
||||
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
|
||||
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
|
||||
|
|
@ -1330,7 +1327,18 @@ static const struct usb_device_id option_ids[] = {
|
|||
.driver_info = NCTRL(0) | RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */
|
||||
.driver_info = NCTRL(0) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1034, 0xff), /* Telit LE910C4-WWX (rmnet) */
|
||||
.driver_info = RSVD(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1036, 0xff) }, /* Telit LE910C4-WWX */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1037, 0xff), /* Telit LE910C4-WWX (rmnet) */
|
||||
.driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1038, 0xff), /* Telit LE910C4-WWX (rmnet) */
|
||||
.driver_info = NCTRL(0) | RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103b, 0xff), /* Telit LE910C4-WWX */
|
||||
.driver_info = NCTRL(0) | NCTRL(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103c, 0xff), /* Telit LE910C4-WWX */
|
||||
.driver_info = NCTRL(0) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
|
||||
.driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1),
|
||||
|
|
@ -1367,42 +1375,87 @@ static const struct usb_device_id option_ids[] = {
|
|||
.driver_info = NCTRL(2) | RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990A (rmnet) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990A (MBIM) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990A (RNDIS) */
|
||||
.driver_info = NCTRL(2) | RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990A (ECM) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */
|
||||
.driver_info = RSVD(0) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1077, 0xff), /* Telit FN990A (rmnet + audio) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990 (MBIM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1078, 0xff), /* Telit FN990A (MBIM + audio) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990 (RNDIS) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1079, 0xff), /* Telit FN990A (RNDIS + audio) */
|
||||
.driver_info = NCTRL(2) | RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990A (RNDIS) */
|
||||
.driver_info = NCTRL(2) | RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990A (ECM) */
|
||||
.driver_info = NCTRL(0) | RSVD(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff), /* Telit FN920C04 (MBIM) */
|
||||
.driver_info = NCTRL(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a3, 0xff), /* Telit FN920C04 (ECM) */
|
||||
.driver_info = NCTRL(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff), /* Telit FN920C04 (MBIM) */
|
||||
.driver_info = NCTRL(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a8, 0xff), /* Telit FN920C04 (ECM) */
|
||||
.driver_info = NCTRL(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */
|
||||
.driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x30), /* Telit FE990B (rmnet) */
|
||||
.driver_info = NCTRL(5) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x30), /* Telit FE990B (MBIM) */
|
||||
.driver_info = NCTRL(6) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x30), /* Telit FE990B (RNDIS) */
|
||||
.driver_info = NCTRL(6) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x30), /* Telit FE990B (ECM) */
|
||||
.driver_info = NCTRL(6) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c0, 0xff), /* Telit FE910C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c4, 0xff), /* Telit FE910C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x30), /* Telit FN990B (rmnet) */
|
||||
.driver_info = NCTRL(5) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x30), /* Telit FE910C04 (ECM) */
|
||||
.driver_info = NCTRL(4) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x30), /* Telit FN990B (MBIM) */
|
||||
.driver_info = NCTRL(6) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x30), /* Telit FN990B (RNDIS) */
|
||||
.driver_info = NCTRL(6) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x30), /* Telit FN990B (ECM) */
|
||||
.driver_info = NCTRL(6) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
|
||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
|
||||
|
|
@ -2070,6 +2123,12 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9003, 0xff) }, /* Simcom SIM7500/SIM7600 MBIM mode */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9011, 0xff), /* Simcom SIM7500/SIM7600 RNDIS mode */
|
||||
.driver_info = RSVD(7) },
|
||||
{ USB_DEVICE(0x1e0e, 0x9071), /* Simcom SIM8230 RMNET mode */
|
||||
.driver_info = RSVD(3) | RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9078, 0xff), /* Simcom SIM8230 ECM mode */
|
||||
.driver_info = RSVD(5) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x907b, 0xff), /* Simcom SIM8230 RNDIS mode */
|
||||
.driver_info = RSVD(5) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9205, 0xff) }, /* Simcom SIM7070/SIM7080/SIM7090 AT+ECM mode */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9206, 0xff) }, /* Simcom SIM7070/SIM7080/SIM7090 AT-only mode */
|
||||
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
|
||||
|
|
@ -2319,6 +2378,10 @@ static const struct usb_device_id option_ids[] = {
|
|||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe145, 0xff), /* Foxconn T99W651 RNDIS */
|
||||
.driver_info = RSVD(5) | RSVD(6) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe15f, 0xff), /* Foxconn T99W709 */
|
||||
.driver_info = RSVD(5) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe167, 0xff), /* Foxconn T99W640 MBIM */
|
||||
.driver_info = RSVD(3) },
|
||||
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
|
||||
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
|
||||
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
|
||||
|
|
@ -2347,6 +2410,14 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d41, 0xff, 0, 0) }, /* MeiG Smart SLM320 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d57, 0xff, 0, 0) }, /* MeiG Smart SLM770A */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0, 0) }, /* MeiG Smart SRM815 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x02) }, /* MeiG Smart SLM828 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x03) }, /* MeiG Smart SLM828 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x30) }, /* MeiG Smart SRM815 and SRM825L */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x40) }, /* MeiG Smart SRM825L */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x60) }, /* MeiG Smart SRM825L */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
|
||||
|
|
@ -2401,17 +2472,16 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, UNISOC_PRODUCT_UIS7720, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */
|
||||
.driver_info = NCTRL(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */
|
||||
.driver_info = NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2949, 0x8700, 0xff) }, /* Neoway N723-EA */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@ static void qt2_process_read_urb(struct urb *urb)
|
|||
|
||||
newport = *(ch + 3);
|
||||
|
||||
if (newport > serial->num_ports) {
|
||||
if (newport >= serial->num_ports) {
|
||||
dev_err(&port->dev,
|
||||
"%s - port change to invalid port: %i\n",
|
||||
__func__, newport);
|
||||
|
|
|
|||
|
|
@ -101,6 +101,11 @@ DEVICE(nokia, NOKIA_IDS);
|
|||
{ USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */
|
||||
DEVICE_N(novatel_gps, NOVATEL_IDS, 3);
|
||||
|
||||
/* OWON electronic test and measurement equipment driver */
|
||||
#define OWON_IDS() \
|
||||
{ USB_DEVICE(0x5345, 0x1234) } /* HDS200 oscilloscopes and others */
|
||||
DEVICE(owon, OWON_IDS);
|
||||
|
||||
/* Siemens USB/MPI adapter */
|
||||
#define SIEMENS_IDS() \
|
||||
{ USB_DEVICE(0x908, 0x0004) }
|
||||
|
|
@ -135,6 +140,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
|
|||
&motorola_tetra_device,
|
||||
&nokia_device,
|
||||
&novatel_gps_device,
|
||||
&owon_device,
|
||||
&siemens_mpi_device,
|
||||
&suunto_device,
|
||||
&vivopay_device,
|
||||
|
|
@ -154,6 +160,7 @@ static const struct usb_device_id id_table[] = {
|
|||
MOTOROLA_TETRA_IDS(),
|
||||
NOKIA_IDS(),
|
||||
NOVATEL_IDS(),
|
||||
OWON_IDS(),
|
||||
SIEMENS_IDS(),
|
||||
SUUNTO_IDS(),
|
||||
VIVOPAY_IDS(),
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
|
|||
return USB_STOR_TRANSPORT_ERROR;
|
||||
}
|
||||
|
||||
residue = bcs->Residue;
|
||||
residue = le32_to_cpu(bcs->Residue);
|
||||
if (bcs->Tag != us->tag)
|
||||
return USB_STOR_TRANSPORT_ERROR;
|
||||
|
||||
|
|
|
|||
|
|
@ -255,6 +255,13 @@ UNUSUAL_DEV( 0x0421, 0x06aa, 0x1110, 0x1110,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_MAX_SECTORS_64 ),
|
||||
|
||||
/* Added by Lubomir Rintel <lkundrak@v3.sk>, a very fine chap */
|
||||
UNUSUAL_DEV( 0x0421, 0x06c2, 0x0000, 0x0406,
|
||||
"Nokia",
|
||||
"Nokia 208",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_MAX_SECTORS_64 ),
|
||||
|
||||
#ifdef NO_SDDR09
|
||||
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
|
||||
"Microtech",
|
||||
|
|
@ -927,6 +934,13 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_SANE_SENSE ),
|
||||
|
||||
/* Added by Maël GUERIN <mael.guerin@murena.io> */
|
||||
UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff,
|
||||
"Novatek",
|
||||
"NTK96550-based camera",
|
||||
USB_SC_SCSI, USB_PR_BULK, NULL,
|
||||
US_FL_BULK_IGNORE_TAG ),
|
||||
|
||||
/*
|
||||
* Reported by Hanno Boeck <hanno@gmx.de>
|
||||
* Taken from the Lycoris Kernel
|
||||
|
|
@ -1476,6 +1490,28 @@ UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_WP_DETECT ),
|
||||
|
||||
/*
|
||||
* Reported by Zenm Chen <zenmchen@gmail.com>
|
||||
* Ignore driver CD mode, otherwise usb_modeswitch may fail to switch
|
||||
* the device into Wi-Fi mode.
|
||||
*/
|
||||
UNUSUAL_DEV( 0x0bda, 0x1a2b, 0x0000, 0xffff,
|
||||
"Realtek",
|
||||
"DISK",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_DEVICE ),
|
||||
|
||||
/*
|
||||
* Reported by Zenm Chen <zenmchen@gmail.com>
|
||||
* Ignore driver CD mode, otherwise usb_modeswitch may fail to switch
|
||||
* the device into Wi-Fi mode.
|
||||
*/
|
||||
UNUSUAL_DEV( 0x0bda, 0xa192, 0x0000, 0xffff,
|
||||
"Realtek",
|
||||
"DISK",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_DEVICE ),
|
||||
|
||||
UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999,
|
||||
"Maxtor",
|
||||
"USB to SATA",
|
||||
|
|
|
|||
|
|
@ -52,6 +52,13 @@ UNUSUAL_DEV(0x059f, 0x1061, 0x0000, 0x9999,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME),
|
||||
|
||||
/* Reported-by: Zhihong Zhou <zhouzhihong@greatwall.com.cn> */
|
||||
UNUSUAL_DEV(0x0781, 0x55e8, 0x0000, 0x9999,
|
||||
"SanDisk",
|
||||
"",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_UAS),
|
||||
|
||||
/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */
|
||||
UNUSUAL_DEV(0x090c, 0x2000, 0x0000, 0x9999,
|
||||
"Hiksemi",
|
||||
|
|
@ -83,6 +90,13 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_REPORT_LUNS),
|
||||
|
||||
/* Reported-by: Oliver Neukum <oneukum@suse.com> */
|
||||
UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160,
|
||||
"ADATA",
|
||||
"Portable HDD CH94",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_ATA_1X),
|
||||
|
||||
/* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
|
||||
UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
|
||||
"Initio Corporation",
|
||||
|
|
|
|||
|
|
@ -288,6 +288,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
|
|||
break;
|
||||
case CMDT_RSP_NAK:
|
||||
switch (cmd) {
|
||||
case DP_CMD_STATUS_UPDATE:
|
||||
dp->state = DP_STATE_EXIT;
|
||||
break;
|
||||
case DP_CMD_CONFIGURE:
|
||||
dp->data.conf = 0;
|
||||
ret = dp_altmode_configured(dp);
|
||||
|
|
@ -488,7 +491,7 @@ static ssize_t pin_assignment_show(struct device *dev,
|
|||
|
||||
assignments = get_current_pin_assignments(dp);
|
||||
|
||||
for (i = 0; assignments; assignments >>= 1, i++) {
|
||||
for (i = 0; assignments && i < DP_PIN_ASSIGN_MAX; assignments >>= 1, i++) {
|
||||
if (assignments & 1) {
|
||||
if (i == cur)
|
||||
len += sprintf(buf + len, "[%s] ",
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ struct fusb302_chip {
|
|||
bool vconn_on;
|
||||
bool vbus_on;
|
||||
bool charge_on;
|
||||
bool pd_rx_on;
|
||||
bool vbus_present;
|
||||
enum typec_cc_polarity cc_polarity;
|
||||
enum typec_cc_status cc1;
|
||||
|
|
@ -841,6 +842,11 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on)
|
|||
int ret = 0;
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
if (chip->pd_rx_on == on) {
|
||||
fusb302_log(chip, "pd is already %s", on ? "on" : "off");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = fusb302_pd_rx_flush(chip);
|
||||
if (ret < 0) {
|
||||
fusb302_log(chip, "cannot flush pd rx buffer, ret=%d", ret);
|
||||
|
|
@ -863,6 +869,8 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on)
|
|||
on ? "on" : "off", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
chip->pd_rx_on = on;
|
||||
fusb302_log(chip, "pd := %s", on ? "on" : "off");
|
||||
done:
|
||||
mutex_unlock(&chip->lock);
|
||||
|
|
|
|||
|
|
@ -217,6 +217,11 @@ static int rt1711h_probe(struct i2c_client *client,
|
|||
{
|
||||
int ret;
|
||||
struct rt1711h_chip *chip;
|
||||
const u16 alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED |
|
||||
TCPC_ALERT_TX_FAILED | TCPC_ALERT_RX_HARD_RST |
|
||||
TCPC_ALERT_RX_STATUS | TCPC_ALERT_POWER_STATUS |
|
||||
TCPC_ALERT_CC_STATUS | TCPC_ALERT_RX_BUF_OVF |
|
||||
TCPC_ALERT_FAULT;
|
||||
|
||||
ret = rt1711h_check_revision(client);
|
||||
if (ret < 0) {
|
||||
|
|
@ -258,6 +263,12 @@ static int rt1711h_probe(struct i2c_client *client,
|
|||
dev_name(chip->dev), chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable alert interrupts */
|
||||
ret = rt1711h_write16(chip, TCPC_ALERT_MASK, alert_mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
enable_irq_wake(client->irq);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3009,7 +3009,7 @@ static void run_state_machine(struct tcpm_port *port)
|
|||
port->caps_count = 0;
|
||||
port->pd_capable = true;
|
||||
tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
|
||||
PD_T_SEND_SOURCE_CAP);
|
||||
PD_T_SENDER_RESPONSE);
|
||||
}
|
||||
break;
|
||||
case SRC_SEND_CAPABILITIES_TIMEOUT:
|
||||
|
|
@ -3761,7 +3761,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
|||
case SNK_TRY_WAIT_DEBOUNCE:
|
||||
if (!tcpm_port_is_sink(port)) {
|
||||
port->max_wait = 0;
|
||||
tcpm_set_state(port, SRC_TRYWAIT, 0);
|
||||
tcpm_set_state(port, SRC_TRYWAIT, PD_T_PD_DEBOUNCE);
|
||||
}
|
||||
break;
|
||||
case SRC_TRY_WAIT:
|
||||
|
|
|
|||
|
|
@ -270,6 +270,8 @@ void ucsi_displayport_remove_partner(struct typec_altmode *alt)
|
|||
if (!dp)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&dp->work);
|
||||
|
||||
dp->data.conf = 0;
|
||||
dp->data.status = 0;
|
||||
dp->initialized = false;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
* difficult to estimate the time it takes for the system to process the command
|
||||
* before it is actually passed to the PPM.
|
||||
*/
|
||||
#define UCSI_TIMEOUT_MS 5000
|
||||
#define UCSI_TIMEOUT_MS 10000
|
||||
|
||||
/*
|
||||
* UCSI_SWAP_TIMEOUT_MS - Timeout for role swap requests
|
||||
|
|
|
|||
|
|
@ -765,6 +765,17 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
|
|||
ctrlreq->wValue, vdev->rhport);
|
||||
|
||||
vdev->udev = usb_get_dev(urb->dev);
|
||||
/*
|
||||
* NOTE: A similar operation has been done via
|
||||
* USB_REQ_GET_DESCRIPTOR handler below, which is
|
||||
* supposed to always precede USB_REQ_SET_ADDRESS.
|
||||
*
|
||||
* It's not entirely clear if operating on a different
|
||||
* usb_device instance here is a real possibility,
|
||||
* otherwise this call and vdev->udev assignment above
|
||||
* should be dropped.
|
||||
*/
|
||||
dev_pm_syscore_device(&vdev->udev->dev, true);
|
||||
usb_put_dev(old);
|
||||
|
||||
spin_lock(&vdev->ud.lock);
|
||||
|
|
@ -785,6 +796,17 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
|
|||
"Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
|
||||
|
||||
vdev->udev = usb_get_dev(urb->dev);
|
||||
/*
|
||||
* Set syscore PM flag for the virtually attached
|
||||
* devices to ensure they will not enter suspend on
|
||||
* the client side.
|
||||
*
|
||||
* Note this doesn't have any impact on the physical
|
||||
* devices attached to the host system on the server
|
||||
* side, hence there is no need to undo the operation
|
||||
* on disconnect.
|
||||
*/
|
||||
dev_pm_syscore_device(&vdev->udev->dev, true);
|
||||
usb_put_dev(old);
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -671,8 +671,9 @@ struct hid_descriptor {
|
|||
__le16 bcdHID;
|
||||
__u8 bCountryCode;
|
||||
__u8 bNumDescriptors;
|
||||
struct hid_class_descriptor rpt_desc;
|
||||
|
||||
struct hid_class_descriptor desc[1];
|
||||
struct hid_class_descriptor opt_descs[];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define HID_DEVICE(b, g, ven, prod) \
|
||||
|
|
|
|||
|
|
@ -713,13 +713,12 @@ struct usb_device {
|
|||
|
||||
unsigned long active_duration;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned long connect_time;
|
||||
|
||||
unsigned do_remote_wakeup:1;
|
||||
unsigned reset_resume:1;
|
||||
unsigned port_is_suspended:1;
|
||||
#endif
|
||||
|
||||
struct wusb_dev *wusb_dev;
|
||||
int slot_id;
|
||||
enum usb_device_removable removable;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ struct ci_hdrc_platform_data {
|
|||
#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
|
||||
#define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2
|
||||
#define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3
|
||||
#define CI_HDRC_CONTROLLER_VBUS_EVENT 4
|
||||
int (*notify_event) (struct ci_hdrc *ci, unsigned event);
|
||||
struct regulator *reg_vbus;
|
||||
struct usb_otg_caps ci_otg_caps;
|
||||
|
|
|
|||
|
|
@ -498,9 +498,7 @@ extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
|
|||
|
||||
extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
|
||||
#endif
|
||||
#endif /* CONFIG_USB_PCI */
|
||||
|
||||
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ enum {
|
|||
DP_PIN_ASSIGN_D,
|
||||
DP_PIN_ASSIGN_E,
|
||||
DP_PIN_ASSIGN_F, /* Not supported after v1.0b */
|
||||
DP_PIN_ASSIGN_MAX,
|
||||
};
|
||||
|
||||
/* DisplayPort alt mode specific commands */
|
||||
|
|
|
|||
Loading…
Reference in a new issue