提交 e431e0e4 编写于 作者: L Linus Torvalds

Merge tag 'usb-4.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB/PHY fixes from Greg KH:
 "Here are a number of small USB and PHY driver fixes for 4.11-rc4.

  Nothing major here, just an bunch of small fixes, and a handfull of
  good fixes from Johan for devices with crazy descriptors. There are a
  few new device ids in here as well.

  All of these have been in linux-next with no reported issues"

* tag 'usb-4.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits)
  usb: gadget: f_hid: fix: Don't access hidg->req without spinlock held
  usb: gadget: udc: remove pointer dereference after free
  usb: gadget: f_uvc: Sanity check wMaxPacketSize for SuperSpeed
  usb: gadget: f_uvc: Fix SuperSpeed companion descriptor's wBytesPerInterval
  usb: gadget: acm: fix endianness in notifications
  usb: dwc3: gadget: delay unmap of bounced requests
  USB: serial: qcserial: add Dell DW5811e
  usb: hub: Fix crash after failure to read BOS descriptor
  ACM gadget: fix endianness in notifications
  USB: usbtmc: fix probe error path
  USB: usbtmc: add missing endpoint sanity check
  USB: serial: option: add Quectel UC15, UC20, EC21, and EC25 modems
  usb: musb: fix possible spinlock deadlock
  usb: musb: dsps: fix iounmap in error and exit paths
  usb: musb: cppi41: don't check early-TX-interrupt for Isoch transfer
  usb-core: Add LINEAR_FRAME_INTR_BINTERVAL USB quirk
  uwb: i1480-dfu: fix NULL-deref at probe
  uwb: hwa-rc: fix NULL-deref at probe
  USB: wusbcore: fix NULL-deref at probe
  USB: uss720: fix NULL-deref at probe
  ...
Broadcom USB3 phy binding for northstar plus SoC
The USB3 phy is internal to the SoC and is accessed using mdio interface.
Required mdio bus properties:
- reg: Should be 0x0 for SoC internal USB3 phy
- #address-cells: must be 1
- #size-cells: must be 0
Required USB3 PHY properties:
- compatible: should be "brcm,nsp-usb3-phy"
- reg: USB3 Phy address on SoC internal MDIO bus and it should be 0x10.
- usb3-ctrl-syscon: handler of syscon node defining physical address
of usb3 control register.
- #phy-cells: must be 0
Required usb3 control properties:
- compatible: should be "brcm,nsp-usb3-ctrl"
- reg: offset and length of the control registers
Example:
mdio@0 {
reg = <0x0>;
#address-cells = <1>;
#size-cells = <0>;
usb3_phy: usb-phy@10 {
compatible = "brcm,nsp-usb3-phy";
reg = <0x10>;
usb3-ctrl-syscon = <&usb3_ctrl>;
#phy-cells = <0>;
status = "disabled";
};
};
usb3_ctrl: syscon@104408 {
compatible = "brcm,nsp-usb3-ctrl", "syscon";
reg = <0x104408 0x3fc>;
};
......@@ -449,6 +449,7 @@ config PHY_QCOM_UFS
config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
select GENERIC_PHY
help
Support for the USB high-speed ULPI compliant phy on Qualcomm
......@@ -510,12 +511,4 @@ config PHY_MESON8B_USB2
and GXBB SoCs.
If unsure, say N.
config PHY_NSP_USB3
tristate "Broadcom NorthStar plus USB3 PHY driver"
depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
select GENERIC_PHY
default ARCH_BCM_NSP
help
Enable this to support the Broadcom Northstar plus USB3 PHY.
If unsure, say N.
endmenu
......@@ -62,4 +62,3 @@ obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
obj-$(CONFIG_PHY_NSP_USB3) += phy-bcm-nsp-usb3.o
/*
* Copyright (C) 2016 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#define NSP_USB3_RST_CTRL_OFFSET 0x3f8
/* mdio reg access */
#define NSP_USB3_PHY_BASE_ADDR_REG 0x1f
#define NSP_USB3_PHY_PLL30_BLOCK 0x8000
#define NSP_USB3_PLL_CONTROL 0x01
#define NSP_USB3_PLLA_CONTROL0 0x0a
#define NSP_USB3_PLLA_CONTROL1 0x0b
#define NSP_USB3_PHY_TX_PMD_BLOCK 0x8040
#define NSP_USB3_TX_PMD_CONTROL1 0x01
#define NSP_USB3_PHY_PIPE_BLOCK 0x8060
#define NSP_USB3_LFPS_CMP 0x02
#define NSP_USB3_LFPS_DEGLITCH 0x03
struct nsp_usb3_phy {
struct regmap *usb3_ctrl;
struct phy *phy;
struct mdio_device *mdiodev;
};
static int nsp_usb3_phy_init(struct phy *phy)
{
struct nsp_usb3_phy *iphy = phy_get_drvdata(phy);
struct mii_bus *bus = iphy->mdiodev->bus;
int addr = iphy->mdiodev->addr;
u32 data;
int rc;
rc = regmap_read(iphy->usb3_ctrl, 0, &data);
if (rc)
return rc;
data |= 1;
rc = regmap_write(iphy->usb3_ctrl, 0, data);
if (rc)
return rc;
rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 1);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
NSP_USB3_PHY_PLL30_BLOCK);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x1000);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL0, 0x6400);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0xc000);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0x8000);
if (rc)
return rc;
rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 0);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x9000);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
NSP_USB3_PHY_PIPE_BLOCK);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_CMP, 0xf30d);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_DEGLITCH, 0x6302);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
NSP_USB3_PHY_TX_PMD_BLOCK);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_TX_PMD_CONTROL1, 0x1003);
return rc;
}
static struct phy_ops nsp_usb3_phy_ops = {
.init = nsp_usb3_phy_init,
.owner = THIS_MODULE,
};
static int nsp_usb3_phy_probe(struct mdio_device *mdiodev)
{
struct device *dev = &mdiodev->dev;
struct phy_provider *provider;
struct nsp_usb3_phy *iphy;
iphy = devm_kzalloc(dev, sizeof(*iphy), GFP_KERNEL);
if (!iphy)
return -ENOMEM;
iphy->mdiodev = mdiodev;
iphy->usb3_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
"usb3-ctrl-syscon");
if (IS_ERR(iphy->usb3_ctrl))
return PTR_ERR(iphy->usb3_ctrl);
iphy->phy = devm_phy_create(dev, dev->of_node, &nsp_usb3_phy_ops);
if (IS_ERR(iphy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(iphy->phy);
}
phy_set_drvdata(iphy->phy, iphy);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "could not register PHY provider\n");
return PTR_ERR(provider);
}
return 0;
}
static const struct of_device_id nsp_usb3_phy_of_match[] = {
{.compatible = "brcm,nsp-usb3-phy",},
{ /* sentinel */ }
};
static struct mdio_driver nsp_usb3_phy_driver = {
.mdiodrv = {
.driver = {
.name = "nsp-usb3-phy",
.of_match_table = nsp_usb3_phy_of_match,
},
},
.probe = nsp_usb3_phy_probe,
};
mdio_module_driver(nsp_usb3_phy_driver);
MODULE_DESCRIPTION("Broadcom NSP USB3 PHY driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com");
......@@ -254,8 +254,8 @@ static int exynos_pcie_phy_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
exynos_phy->blk_base = devm_ioremap_resource(dev, res);
if (IS_ERR(exynos_phy->phy_base))
return PTR_ERR(exynos_phy->phy_base);
if (IS_ERR(exynos_phy->blk_base))
return PTR_ERR(exynos_phy->blk_base);
exynos_phy->drv_data = drv_data;
......
......@@ -1381,7 +1381,7 @@ static int usbtmc_probe(struct usb_interface *intf,
dev_dbg(&intf->dev, "%s called\n", __func__);
data = kmalloc(sizeof(*data), GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
......@@ -1444,6 +1444,13 @@ static int usbtmc_probe(struct usb_interface *intf,
break;
}
}
if (!data->bulk_out || !data->bulk_in) {
dev_err(&intf->dev, "bulk endpoints not found\n");
retcode = -ENODEV;
goto err_put;
}
/* Find int endpoint */
for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) {
endpoint = &iface_desc->endpoint[n].desc;
......@@ -1469,8 +1476,10 @@ static int usbtmc_probe(struct usb_interface *intf,
if (data->iin_ep_present) {
/* allocate int urb */
data->iin_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!data->iin_urb)
if (!data->iin_urb) {
retcode = -ENOMEM;
goto error_register;
}
/* Protect interrupt in endpoint data until iin_urb is freed */
kref_get(&data->kref);
......@@ -1478,8 +1487,10 @@ static int usbtmc_probe(struct usb_interface *intf,
/* allocate buffer for interrupt in */
data->iin_buffer = kmalloc(data->iin_wMaxPacketSize,
GFP_KERNEL);
if (!data->iin_buffer)
if (!data->iin_buffer) {
retcode = -ENOMEM;
goto error_register;
}
/* fill interrupt urb */
usb_fill_int_urb(data->iin_urb, data->usb_dev,
......@@ -1512,6 +1523,7 @@ static int usbtmc_probe(struct usb_interface *intf,
sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
usbtmc_free_int(data);
err_put:
kref_put(&data->kref, usbtmc_delete);
return retcode;
}
......
......@@ -280,6 +280,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
/*
* Adjust bInterval for quirked devices.
*/
/*
* This quirk fixes bIntervals reported in ms.
*/
if (to_usb_device(ddev)->quirks &
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
n = clamp(fls(d->bInterval) + 3, i, j);
i = j = n;
}
/*
* This quirk fixes bIntervals reported in
* linear microframes.
*/
......
......@@ -4275,7 +4275,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
if (!udev->usb2_hw_lpm_capable)
if (!udev->usb2_hw_lpm_capable || !udev->bos)
return;
if (hub)
......
......@@ -170,6 +170,14 @@ static const struct usb_device_id usb_quirk_list[] = {
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
/* Baum Vario Ultra */
{ USB_DEVICE(0x0904, 0x6101), .driver_info =
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
{ USB_DEVICE(0x0904, 0x6102), .driver_info =
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
{ USB_DEVICE(0x0904, 0x6103), .driver_info =
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
/* Keytouch QWERTY Panel keyboard */
{ USB_DEVICE(0x0926, 0x3333), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
......
......@@ -171,6 +171,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status)
{
struct dwc3 *dwc = dep->dwc;
unsigned int unmap_after_complete = false;
req->started = false;
list_del(&req->list);
......@@ -180,11 +181,19 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
if (req->request.status == -EINPROGRESS)
req->request.status = status;
if (dwc->ep0_bounced && dep->number <= 1)
/*
* NOTICE we don't want to unmap before calling ->complete() if we're
* dealing with a bounced ep0 request. If we unmap it here, we would end
* up overwritting the contents of req->buf and this could confuse the
* gadget driver.
*/
if (dwc->ep0_bounced && dep->number <= 1) {
dwc->ep0_bounced = false;
usb_gadget_unmap_request_by_dev(dwc->sysdev,
&req->request, req->direction);
unmap_after_complete = true;
} else {
usb_gadget_unmap_request_by_dev(dwc->sysdev,
&req->request, req->direction);
}
trace_dwc3_gadget_giveback(req);
......@@ -192,6 +201,10 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
usb_gadget_giveback_request(&dep->endpoint, &req->request);
spin_lock(&dwc->lock);
if (unmap_after_complete)
usb_gadget_unmap_request_by_dev(dwc->sysdev,
&req->request, req->direction);
if (dep->number > 1)
pm_runtime_put(dwc->dev);
}
......
......@@ -535,13 +535,15 @@ static int acm_notify_serial_state(struct f_acm *acm)
{
struct usb_composite_dev *cdev = acm->port.func.config->cdev;
int status;
__le16 serial_state;
spin_lock(&acm->lock);
if (acm->notify_req) {
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n",
acm->port_num, acm->serial_state);
serial_state = cpu_to_le16(acm->serial_state);
status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
0, &acm->serial_state, sizeof(acm->serial_state));
0, &serial_state, sizeof(acm->serial_state));
} else {
acm->pending = true;
status = 0;
......
......@@ -367,7 +367,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
count = min_t(unsigned, count, hidg->report_length);
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
status = copy_from_user(hidg->req->buf, buffer, count);
status = copy_from_user(req->buf, buffer, count);
if (status != 0) {
ERROR(hidg->func.config->cdev,
......@@ -378,9 +378,9 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
spin_lock_irqsave(&hidg->write_spinlock, flags);
/* we our function has been disabled by host */
/* when our function has been disabled by host */
if (!hidg->req) {
free_ep_req(hidg->in_ep, hidg->req);
free_ep_req(hidg->in_ep, req);
/*
* TODO
* Should we fail with error here?
......@@ -394,7 +394,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
req->complete = f_hidg_req_complete;
req->context = hidg;
status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
if (status < 0) {
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
......
......@@ -594,6 +594,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U);
opts->streaming_maxburst = min(opts->streaming_maxburst, 15U);
/* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */
if (opts->streaming_maxburst &&
(opts->streaming_maxpacket % 1024) != 0) {
opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024);
INFO(cdev, "overriding streaming_maxpacket to %d\n",
opts->streaming_maxpacket);
}
/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
* module parameters.
*
......@@ -625,7 +633,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
cpu_to_le16(max_packet_size * max_packet_mult *
opts->streaming_maxburst);
(opts->streaming_maxburst + 1));
/* Allocate endpoints. */
ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
......
......@@ -1523,7 +1523,6 @@ static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
td = phys_to_virt(addr);
addr2 = (dma_addr_t)td->next;
pci_pool_free(dev->data_requests, td, addr);
td->next = 0x00;
addr = addr2;
}
req->chain_len = 1;
......
......@@ -347,6 +347,9 @@ static int idmouse_probe(struct usb_interface *interface,
if (iface_desc->desc.bInterfaceClass != 0x0A)
return -ENODEV;
if (iface_desc->desc.bNumEndpoints < 1)
return -ENODEV;
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
......
......@@ -366,6 +366,10 @@ static int lvs_rh_probe(struct usb_interface *intf,
hdev = interface_to_usbdev(intf);
desc = intf->cur_altsetting;
if (desc->desc.bNumEndpoints < 1)
return -ENODEV;
endpoint = &desc->endpoint[0].desc;
/* valid only for SS root hub */
......
......@@ -709,6 +709,11 @@ static int uss720_probe(struct usb_interface *intf,
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints < 3) {
usb_put_dev(usbdev);
return -ENODEV;
}
/*
* Allocate parport interface
*/
......
......@@ -2490,8 +2490,8 @@ static int musb_remove(struct platform_device *pdev)
musb_host_cleanup(musb);
musb_gadget_cleanup(musb);
spin_lock_irqsave(&musb->lock, flags);
musb_platform_disable(musb);
spin_lock_irqsave(&musb->lock, flags);
musb_disable_interrupts(musb);
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
spin_unlock_irqrestore(&musb->lock, flags);
......
......@@ -238,8 +238,27 @@ static void cppi41_dma_callback(void *private_data,
transferred < cppi41_channel->packet_sz)
cppi41_channel->prog_len = 0;
if (cppi41_channel->is_tx)
empty = musb_is_tx_fifo_empty(hw_ep);
if (cppi41_channel->is_tx) {
u8 type;
if (is_host_active(musb))
type = hw_ep->out_qh->type;
else
type = hw_ep->ep_in.type;
if (type == USB_ENDPOINT_XFER_ISOC)
/*
* Don't use the early-TX-interrupt workaround below
* for Isoch transfter. Since Isoch are periodic
* transfer, by the time the next transfer is
* scheduled, the current one should be done already.
*
* This avoids audio playback underrun issue.
*/
empty = true;
else
empty = musb_is_tx_fifo_empty(hw_ep);
}
if (!cppi41_channel->is_tx || empty) {
cppi41_trans_done(cppi41_channel);
......
......@@ -933,7 +933,7 @@ static int dsps_probe(struct platform_device *pdev)
if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
ret = dsps_setup_optional_vbus_irq(pdev, glue);
if (ret)
return ret;
goto err_iounmap;
}
platform_set_drvdata(pdev, glue);
......@@ -946,6 +946,8 @@ static int dsps_probe(struct platform_device *pdev)
err:
pm_runtime_disable(&pdev->dev);
err_iounmap:
iounmap(glue->usbss_base);
return ret;
}
......@@ -956,6 +958,7 @@ static int dsps_remove(struct platform_device *pdev)
platform_device_unregister(glue->musb);
pm_runtime_disable(&pdev->dev);
iounmap(glue->usbss_base);
return 0;
}
......
......@@ -233,6 +233,14 @@ static void option_instat_callback(struct urb *urb);
#define BANDRICH_PRODUCT_1012 0x1012
#define QUALCOMM_VENDOR_ID 0x05C6
/* These Quectel products use Qualcomm's vendor ID */
#define QUECTEL_PRODUCT_UC20 0x9003
#define QUECTEL_PRODUCT_UC15 0x9090
#define QUECTEL_VENDOR_ID 0x2c7c
/* These Quectel products use Quectel's vendor ID */
#define QUECTEL_PRODUCT_EC21 0x0121
#define QUECTEL_PRODUCT_EC25 0x0125
#define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6001 0x6001
......@@ -1161,7 +1169,14 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
/* Quectel products using Qualcomm vendor ID */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
/* Quectel products using Quectel vendor ID */
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
......
......@@ -169,6 +169,8 @@ static const struct usb_device_id id_table[] = {
{DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81b1)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
{DEVICE_SWI(0x413c, 0x81b5)}, /* Dell Wireless 5811e QDL */
{DEVICE_SWI(0x413c, 0x81b6)}, /* Dell Wireless 5811e QDL */
/* Huawei devices */
{DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
......
......@@ -39,6 +39,9 @@ int wa_create(struct wahc *wa, struct usb_interface *iface,
int result;
struct device *dev = &iface->dev;
if (iface->cur_altsetting->desc.bNumEndpoints < 3)
return -ENODEV;
result = wa_rpipes_create(wa);
if (result < 0)
goto error_rpipes_create;
......
......@@ -823,6 +823,9 @@ static int hwarc_probe(struct usb_interface *iface,
struct hwarc *hwarc;
struct device *dev = &iface->dev;
if (iface->cur_altsetting->desc.bNumEndpoints < 1)
return -ENODEV;
result = -ENOMEM;
uwb_rc = uwb_rc_alloc();
if (uwb_rc == NULL) {
......
......@@ -362,6 +362,9 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
result);
}
if (iface->cur_altsetting->desc.bNumEndpoints < 1)
return -ENODEV;
result = -ENOMEM;
i1480_usb = kzalloc(sizeof(*i1480_usb), GFP_KERNEL);
if (i1480_usb == NULL) {
......
......@@ -50,4 +50,10 @@
/* device can't handle Link Power Management */
#define USB_QUIRK_NO_LPM BIT(10)
/*
* Device reports its bInterval as linear frames instead of the
* USB 2.0 calculation.
*/
#define USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL BIT(11)
#endif /* __LINUX_USB_QUIRKS_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册