USB/Thunderbolt fixes for 5.9-rc5
Here are some small USB and Thunderbolt driver fixes for 5.9-rc5. Nothing huge, just a number of bugfixes and new device ids for problems reported: - new USB serial driver ids - bug fixes for syzbot reported problems - typec driver fixes - thunderbolt driver fixes - revert of reported broken commit All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCX13VNw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylPEwCaA+IjSAIYP4Bm/zqrX1DaFETAY9oAn0m8v0rc 4rL321B83HSHlQ45X1J/ =GIDw -----END PGP SIGNATURE----- Merge tag 'usb-5.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB/Thunderbolt fixes from Greg KH: "Here are some small USB and Thunderbolt driver fixes for 5.9-rc5. Nothing huge, just a number of bugfixes and new device ids for problems reported: - new USB serial driver ids - bug fixes for syzbot reported problems - typec driver fixes - thunderbolt driver fixes - revert of reported broken commit All of these have been in linux-next with no reported issues" * tag 'usb-5.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: typec: intel_pmc_mux: Do not configure SBU and HSL Orientation in Alternate modes usb: typec: intel_pmc_mux: Do not configure Altmode HPD High usb: core: fix slab-out-of-bounds Read in read_descriptors Revert "usb: dwc3: meson-g12a: fix shared reset control use" usb: typec: ucsi: acpi: Check the _DEP dependencies usb: typec: intel_pmc_mux: Un-register the USB role switch usb: Fix out of sync data toggle if a configured device is reconfigured USB: serial: option: support dynamic Quectel USB compositions USB: serial: option: add support for SIM7070/SIM7080/SIM7090 modules thunderbolt: Use maximum USB3 link rate when reclaiming if link is not up thunderbolt: Disable ports that are not implemented USB: serial: ftdi_sio: add IDs for Xsens Mti USB converter
This commit is contained in:
commit
e4c26faa42
@ -684,6 +684,7 @@ static int tb_init_port(struct tb_port *port)
|
||||
if (res == -ENODEV) {
|
||||
tb_dbg(port->sw->tb, " Port %d: not implemented\n",
|
||||
port->port);
|
||||
port->disabled = true;
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
|
@ -186,7 +186,7 @@ struct tb_switch {
|
||||
* @cap_adap: Offset of the adapter specific capability (%0 if not present)
|
||||
* @cap_usb4: Offset to the USB4 port capability (%0 if not present)
|
||||
* @port: Port number on switch
|
||||
* @disabled: Disabled by eeprom
|
||||
* @disabled: Disabled by eeprom or enabled but not implemented
|
||||
* @bonded: true if the port is bonded (two lanes combined as one)
|
||||
* @dual_link_port: If the switch is connected using two ports, points
|
||||
* to the other port.
|
||||
|
@ -951,10 +951,18 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel,
|
||||
int ret, max_rate, allocate_up, allocate_down;
|
||||
|
||||
ret = usb4_usb3_port_actual_link_rate(tunnel->src_port);
|
||||
if (ret <= 0) {
|
||||
tb_tunnel_warn(tunnel, "tunnel is not up\n");
|
||||
if (ret < 0) {
|
||||
tb_tunnel_warn(tunnel, "failed to read actual link rate\n");
|
||||
return;
|
||||
} else if (!ret) {
|
||||
/* Use maximum link rate if the link valid is not set */
|
||||
ret = usb4_usb3_port_max_link_rate(tunnel->src_port);
|
||||
if (ret < 0) {
|
||||
tb_tunnel_warn(tunnel, "failed to read maximum link rate\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 90% of the max rate can be allocated for isochronous
|
||||
* transfers.
|
||||
|
@ -1205,6 +1205,34 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* usb_disable_device_endpoints -- Disable all endpoints for a device
|
||||
* @dev: the device whose endpoints are being disabled
|
||||
* @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
|
||||
*/
|
||||
static void usb_disable_device_endpoints(struct usb_device *dev, int skip_ep0)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(dev->bus);
|
||||
int i;
|
||||
|
||||
if (hcd->driver->check_bandwidth) {
|
||||
/* First pass: Cancel URBs, leave endpoint pointers intact. */
|
||||
for (i = skip_ep0; i < 16; ++i) {
|
||||
usb_disable_endpoint(dev, i, false);
|
||||
usb_disable_endpoint(dev, i + USB_DIR_IN, false);
|
||||
}
|
||||
/* Remove endpoints from the host controller internal state */
|
||||
mutex_lock(hcd->bandwidth_mutex);
|
||||
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
|
||||
mutex_unlock(hcd->bandwidth_mutex);
|
||||
}
|
||||
/* Second pass: remove endpoint pointers */
|
||||
for (i = skip_ep0; i < 16; ++i) {
|
||||
usb_disable_endpoint(dev, i, true);
|
||||
usb_disable_endpoint(dev, i + USB_DIR_IN, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_disable_device - Disable all the endpoints for a USB device
|
||||
* @dev: the device whose endpoints are being disabled
|
||||
@ -1218,7 +1246,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
|
||||
void usb_disable_device(struct usb_device *dev, int skip_ep0)
|
||||
{
|
||||
int i;
|
||||
struct usb_hcd *hcd = bus_to_hcd(dev->bus);
|
||||
|
||||
/* getting rid of interfaces will disconnect
|
||||
* any drivers bound to them (a key side effect)
|
||||
@ -1264,22 +1291,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
|
||||
|
||||
dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
|
||||
skip_ep0 ? "non-ep0" : "all");
|
||||
if (hcd->driver->check_bandwidth) {
|
||||
/* First pass: Cancel URBs, leave endpoint pointers intact. */
|
||||
for (i = skip_ep0; i < 16; ++i) {
|
||||
usb_disable_endpoint(dev, i, false);
|
||||
usb_disable_endpoint(dev, i + USB_DIR_IN, false);
|
||||
}
|
||||
/* Remove endpoints from the host controller internal state */
|
||||
mutex_lock(hcd->bandwidth_mutex);
|
||||
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
|
||||
mutex_unlock(hcd->bandwidth_mutex);
|
||||
/* Second pass: remove endpoint pointers */
|
||||
}
|
||||
for (i = skip_ep0; i < 16; ++i) {
|
||||
usb_disable_endpoint(dev, i, true);
|
||||
usb_disable_endpoint(dev, i + USB_DIR_IN, true);
|
||||
}
|
||||
|
||||
usb_disable_device_endpoints(dev, skip_ep0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1522,6 +1535,9 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
|
||||
* The caller must own the device lock.
|
||||
*
|
||||
* Return: Zero on success, else a negative error code.
|
||||
*
|
||||
* If this routine fails the device will probably be in an unusable state
|
||||
* with endpoints disabled, and interfaces only partially enabled.
|
||||
*/
|
||||
int usb_reset_configuration(struct usb_device *dev)
|
||||
{
|
||||
@ -1537,10 +1553,7 @@ int usb_reset_configuration(struct usb_device *dev)
|
||||
* calls during probe() are fine
|
||||
*/
|
||||
|
||||
for (i = 1; i < 16; ++i) {
|
||||
usb_disable_endpoint(dev, i, true);
|
||||
usb_disable_endpoint(dev, i + USB_DIR_IN, true);
|
||||
}
|
||||
usb_disable_device_endpoints(dev, 1); /* skip ep0*/
|
||||
|
||||
config = dev->actconfig;
|
||||
retval = 0;
|
||||
@ -1553,34 +1566,10 @@ int usb_reset_configuration(struct usb_device *dev)
|
||||
mutex_unlock(hcd->bandwidth_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Make sure we have enough bandwidth for each alternate setting 0 */
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *intf = config->interface[i];
|
||||
struct usb_host_interface *alt;
|
||||
|
||||
alt = usb_altnum_to_altsetting(intf, 0);
|
||||
if (!alt)
|
||||
alt = &intf->altsetting[0];
|
||||
if (alt != intf->cur_altsetting)
|
||||
retval = usb_hcd_alloc_bandwidth(dev, NULL,
|
||||
intf->cur_altsetting, alt);
|
||||
if (retval < 0)
|
||||
break;
|
||||
}
|
||||
/* If not, reinstate the old alternate settings */
|
||||
/* xHCI adds all endpoints in usb_hcd_alloc_bandwidth */
|
||||
retval = usb_hcd_alloc_bandwidth(dev, config, NULL, NULL);
|
||||
if (retval < 0) {
|
||||
reset_old_alts:
|
||||
for (i--; i >= 0; i--) {
|
||||
struct usb_interface *intf = config->interface[i];
|
||||
struct usb_host_interface *alt;
|
||||
|
||||
alt = usb_altnum_to_altsetting(intf, 0);
|
||||
if (!alt)
|
||||
alt = &intf->altsetting[0];
|
||||
if (alt != intf->cur_altsetting)
|
||||
usb_hcd_alloc_bandwidth(dev, NULL,
|
||||
alt, intf->cur_altsetting);
|
||||
}
|
||||
usb_enable_lpm(dev);
|
||||
mutex_unlock(hcd->bandwidth_mutex);
|
||||
return retval;
|
||||
@ -1589,8 +1578,12 @@ reset_old_alts:
|
||||
USB_REQ_SET_CONFIGURATION, 0,
|
||||
config->desc.bConfigurationValue, 0,
|
||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
if (retval < 0)
|
||||
goto reset_old_alts;
|
||||
if (retval < 0) {
|
||||
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
|
||||
usb_enable_lpm(dev);
|
||||
mutex_unlock(hcd->bandwidth_mutex);
|
||||
return retval;
|
||||
}
|
||||
mutex_unlock(hcd->bandwidth_mutex);
|
||||
|
||||
/* re-init hc/hcd interface/endpoint state */
|
||||
|
@ -889,7 +889,11 @@ read_descriptors(struct file *filp, struct kobject *kobj,
|
||||
size_t srclen, n;
|
||||
int cfgno;
|
||||
void *src;
|
||||
int retval;
|
||||
|
||||
retval = usb_lock_device_interruptible(udev);
|
||||
if (retval < 0)
|
||||
return -EINTR;
|
||||
/* The binary attribute begins with the device descriptor.
|
||||
* Following that are the raw descriptor entries for all the
|
||||
* configurations (config plus subsidiary descriptors).
|
||||
@ -914,6 +918,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
|
||||
off -= srclen;
|
||||
}
|
||||
}
|
||||
usb_unlock_device(udev);
|
||||
return count - nleft;
|
||||
}
|
||||
|
||||
|
@ -737,13 +737,13 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
|
||||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(priv->reset);
|
||||
ret = reset_control_reset(priv->reset);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
goto err_disable_clks;
|
||||
|
||||
ret = dwc3_meson_g12a_get_phys(priv);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
goto err_disable_clks;
|
||||
|
||||
ret = priv->drvdata->setup_regmaps(priv, base);
|
||||
if (ret)
|
||||
@ -752,7 +752,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
|
||||
if (priv->vbus) {
|
||||
ret = regulator_enable(priv->vbus);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
/* Get dr_mode */
|
||||
@ -765,13 +765,13 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
|
||||
|
||||
ret = priv->drvdata->usb_init(priv);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
goto err_disable_clks;
|
||||
|
||||
/* Init PHYs */
|
||||
for (i = 0 ; i < PHY_COUNT ; ++i) {
|
||||
ret = phy_init(priv->phys[i]);
|
||||
if (ret)
|
||||
goto err_assert_reset;
|
||||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
/* Set PHY Power */
|
||||
@ -809,9 +809,6 @@ err_phys_exit:
|
||||
for (i = 0 ; i < PHY_COUNT ; ++i)
|
||||
phy_exit(priv->phys[i]);
|
||||
|
||||
err_assert_reset:
|
||||
reset_control_assert(priv->reset);
|
||||
|
||||
err_disable_clks:
|
||||
clk_bulk_disable_unprepare(priv->drvdata->num_clks,
|
||||
priv->drvdata->clks);
|
||||
|
@ -713,6 +713,7 @@ static const struct usb_device_id id_table_combined[] = {
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_MTIUSBCONVERTER_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
|
||||
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
|
||||
|
@ -160,6 +160,7 @@
|
||||
#define XSENS_AWINDA_DONGLE_PID 0x0102
|
||||
#define XSENS_MTW_PID 0x0200 /* Xsens MTw */
|
||||
#define XSENS_MTDEVBOARD_PID 0x0300 /* Motion Tracker Development Board */
|
||||
#define XSENS_MTIUSBCONVERTER_PID 0x0301 /* MTi USB converter */
|
||||
#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */
|
||||
|
||||
/* Xsens devices using FTDI VID */
|
||||
|
@ -1094,14 +1094,18 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
|
||||
.driver_info = RSVD(1) | RSVD(3) },
|
||||
/* Quectel products using Quectel vendor ID */
|
||||
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95),
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0xff, 0xff),
|
||||
.driver_info = NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0xff, 0xff),
|
||||
.driver_info = NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
|
||||
.driver_info = NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0xff, 0xff),
|
||||
.driver_info = NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
|
||||
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
|
||||
@ -1819,6 +1823,8 @@ 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_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),
|
||||
.driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) },
|
||||
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D),
|
||||
|
@ -61,14 +61,11 @@ enum {
|
||||
|
||||
#define PMC_USB_ALTMODE_ORI_SHIFT 1
|
||||
#define PMC_USB_ALTMODE_UFP_SHIFT 3
|
||||
#define PMC_USB_ALTMODE_ORI_AUX_SHIFT 4
|
||||
#define PMC_USB_ALTMODE_ORI_HSL_SHIFT 5
|
||||
|
||||
/* DP specific Mode Data bits */
|
||||
#define PMC_USB_ALTMODE_DP_MODE_SHIFT 8
|
||||
|
||||
/* TBT specific Mode Data bits */
|
||||
#define PMC_USB_ALTMODE_HPD_HIGH BIT(14)
|
||||
#define PMC_USB_ALTMODE_TBT_TYPE BIT(17)
|
||||
#define PMC_USB_ALTMODE_CABLE_TYPE BIT(18)
|
||||
#define PMC_USB_ALTMODE_ACTIVE_LINK BIT(20)
|
||||
@ -179,15 +176,9 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
|
||||
req.mode_data = (port->orientation - 1) << PMC_USB_ALTMODE_ORI_SHIFT;
|
||||
req.mode_data |= (port->role - 1) << PMC_USB_ALTMODE_UFP_SHIFT;
|
||||
|
||||
req.mode_data |= sbu_orientation(port) << PMC_USB_ALTMODE_ORI_AUX_SHIFT;
|
||||
req.mode_data |= hsl_orientation(port) << PMC_USB_ALTMODE_ORI_HSL_SHIFT;
|
||||
|
||||
req.mode_data |= (state->mode - TYPEC_STATE_MODAL) <<
|
||||
PMC_USB_ALTMODE_DP_MODE_SHIFT;
|
||||
|
||||
if (data->status & DP_STATUS_HPD_STATE)
|
||||
req.mode_data |= PMC_USB_ALTMODE_HPD_HIGH;
|
||||
|
||||
ret = pmc_usb_command(port, (void *)&req, sizeof(req));
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -212,9 +203,6 @@ pmc_usb_mux_tbt(struct pmc_usb_port *port, struct typec_mux_state *state)
|
||||
req.mode_data = (port->orientation - 1) << PMC_USB_ALTMODE_ORI_SHIFT;
|
||||
req.mode_data |= (port->role - 1) << PMC_USB_ALTMODE_UFP_SHIFT;
|
||||
|
||||
req.mode_data |= sbu_orientation(port) << PMC_USB_ALTMODE_ORI_AUX_SHIFT;
|
||||
req.mode_data |= hsl_orientation(port) << PMC_USB_ALTMODE_ORI_HSL_SHIFT;
|
||||
|
||||
if (TBT_ADAPTER(data->device_mode) == TBT_ADAPTER_TBT3)
|
||||
req.mode_data |= PMC_USB_ALTMODE_TBT_TYPE;
|
||||
|
||||
@ -497,6 +485,7 @@ err_remove_ports:
|
||||
for (i = 0; i < pmc->num_ports; i++) {
|
||||
typec_switch_unregister(pmc->port[i].typec_sw);
|
||||
typec_mux_unregister(pmc->port[i].typec_mux);
|
||||
usb_role_switch_unregister(pmc->port[i].usb_sw);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -510,6 +499,7 @@ static int pmc_usb_remove(struct platform_device *pdev)
|
||||
for (i = 0; i < pmc->num_ports; i++) {
|
||||
typec_switch_unregister(pmc->port[i].typec_sw);
|
||||
typec_mux_unregister(pmc->port[i].typec_mux);
|
||||
usb_role_switch_unregister(pmc->port[i].usb_sw);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -112,11 +112,15 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
|
||||
|
||||
static int ucsi_acpi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
|
||||
struct ucsi_acpi *ua;
|
||||
struct resource *res;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
if (adev->dep_unmet)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ua = devm_kzalloc(&pdev->dev, sizeof(*ua), GFP_KERNEL);
|
||||
if (!ua)
|
||||
return -ENOMEM;
|
||||
|
Loading…
Reference in New Issue
Block a user