mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 22:09:30 +02:00
Merge tag 'usb-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are some small USB driver fixes for reported problems and regressions. Include in here are: - xhci driver fixes - cdns3 driver fixes - usb gadget driver fixes for syzbot found problems - typec driver fixes for broken hardware and other bugs found - kernel data leaks in mdc800 driver - usb storage driver fixes - other small USB driver fixes All of these have been in linux-next this week with no reported issues" * tag 'usb-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (25 commits) usb: typec: qcom-pmic-typec: drain cc_debounce_dwork if port_start() fails usb: typec: qcom-pmic-typec: disable cc_debounce_dwork on stop usb: gadget: fix null pointer dereference in usb_put_function_instance() usb: typec: qcom-pmic: cancel reset_work on stop usb: gadget: f_mass_storage: fix null pointer dereference in fsg_common_set_num_buffers() usb: f_mass_storage: Bump local buffer size in fsg_common_create_luns() usb: storage: realtek_cr: fix use-after-free on disconnect usb: cdnsp: fix wakeup from S3 after controller context loss usb-storage: ene_ub6250: fix race between scan work and probe USB: gadget: fix NULL pointer dereference in gadget_dev_ioctl() usb: gadget: f_midi: initialize work in f_midi_alloc() usb: gadget: f_midi2: fix use-after-free in string attribute show path usb: typec: tipd: Fix Thunderbolt altmode VDOs for cd321x usb: gadget: midi2: Fix null-pointer dereference in f_midi2_free_ep_reqs usb: typec: hd3ss3220: track VBUS enable state per consumer usb: dwc3: clear forceRM when issuing EndTransfer usb: dwc3: google: Initialise probe properties with DWC3_DEFAULT_PROPERTIES usb: typec: mux: avoid duplicated mux switches usb: typec: mux: Fix typec_switch_match() usb: image: mdc800: change kmalloc() to kzalloc() ...
This commit is contained in:
@@ -1338,7 +1338,6 @@ static int cdnsp_run(struct cdnsp_device *pdev,
|
||||
|
||||
cdnsp_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
|
||||
|
||||
|
||||
ret = cdnsp_start(pdev);
|
||||
if (ret) {
|
||||
ret = -ENODEV;
|
||||
@@ -1837,6 +1836,82 @@ static void cdnsp_get_rev_cap(struct cdnsp_device *pdev)
|
||||
readl(&pdev->rev_cap->tx_buff_size));
|
||||
}
|
||||
|
||||
static void cdnsp_set_event_deq(struct cdnsp_device *pdev)
|
||||
{
|
||||
dma_addr_t deq;
|
||||
u64 temp;
|
||||
|
||||
deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg,
|
||||
pdev->event_ring->dequeue);
|
||||
|
||||
/* Update controller event ring dequeue pointer */
|
||||
temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue);
|
||||
temp &= ERST_PTR_MASK;
|
||||
|
||||
/*
|
||||
* Don't clear the EHB bit (which is RW1C) because
|
||||
* there might be more events to service.
|
||||
*/
|
||||
temp &= ~ERST_EHB;
|
||||
|
||||
cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp,
|
||||
&pdev->ir_set->erst_dequeue);
|
||||
}
|
||||
|
||||
static void cdnsp_add_interrupter(struct cdnsp_device *pdev)
|
||||
{
|
||||
u64 erst_base;
|
||||
u32 erst_size;
|
||||
|
||||
/* Set ERST count with the number of entries in the segment table. */
|
||||
erst_size = readl(&pdev->ir_set->erst_size);
|
||||
erst_size &= ERST_SIZE_MASK;
|
||||
erst_size |= ERST_NUM_SEGS;
|
||||
writel(erst_size, &pdev->ir_set->erst_size);
|
||||
|
||||
/* Set the segment table base address. */
|
||||
erst_base = cdnsp_read_64(&pdev->ir_set->erst_base);
|
||||
erst_base &= ERST_PTR_MASK;
|
||||
erst_base |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK);
|
||||
cdnsp_write_64(erst_base, &pdev->ir_set->erst_base);
|
||||
|
||||
/* Set the event ring dequeue address. */
|
||||
cdnsp_set_event_deq(pdev);
|
||||
}
|
||||
|
||||
/* Set up basic CDNSP registers */
|
||||
static void cdnsp_init(struct cdnsp_device *pdev)
|
||||
{
|
||||
unsigned int val;
|
||||
u64 val_64;
|
||||
|
||||
val = readl(&pdev->op_regs->config_reg);
|
||||
val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E;
|
||||
writel(val, &pdev->op_regs->config_reg);
|
||||
|
||||
/* Initialize the Command ring */
|
||||
cdnsp_ring_init(pdev, pdev->cmd_ring);
|
||||
|
||||
/* Set the address in the Command Ring Control register */
|
||||
val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring);
|
||||
val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) |
|
||||
(pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) |
|
||||
pdev->cmd_ring->cycle_state;
|
||||
cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring);
|
||||
|
||||
/* Set Device Context Base Address Array pointer */
|
||||
cdnsp_write_64(pdev->dcbaa->dma, &pdev->op_regs->dcbaa_ptr);
|
||||
|
||||
/* Set Doorbell array pointer */
|
||||
val = readl(&pdev->cap_regs->db_off);
|
||||
val &= DBOFF_MASK;
|
||||
pdev->dba = (void __iomem *)pdev->cap_regs + val;
|
||||
|
||||
/* Initialize the Primary interrupter */
|
||||
cdnsp_ring_init(pdev, pdev->event_ring);
|
||||
cdnsp_add_interrupter(pdev);
|
||||
}
|
||||
|
||||
static int cdnsp_gen_setup(struct cdnsp_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1902,6 +1977,8 @@ static int cdnsp_gen_setup(struct cdnsp_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cdnsp_init(pdev);
|
||||
|
||||
/*
|
||||
* Software workaround for U1: after transition
|
||||
* to U1 the controller starts gating clock, and in some cases,
|
||||
@@ -2031,9 +2108,6 @@ static int cdnsp_gadget_suspend(struct cdns *cdns, bool do_wakeup)
|
||||
struct cdnsp_device *pdev = cdns->gadget_dev;
|
||||
unsigned long flags;
|
||||
|
||||
if (pdev->link_state == XDEV_U3)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&pdev->lock, flags);
|
||||
cdnsp_disconnect_gadget(pdev);
|
||||
cdnsp_stop(pdev);
|
||||
@@ -2047,12 +2121,38 @@ static int cdnsp_gadget_resume(struct cdns *cdns, bool lost_power)
|
||||
struct cdnsp_device *pdev = cdns->gadget_dev;
|
||||
enum usb_device_speed max_speed;
|
||||
unsigned long flags;
|
||||
bool context_lost;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (!pdev->gadget_driver)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&pdev->lock, flags);
|
||||
val = readl(&pdev->port3x_regs->mode_2);
|
||||
context_lost = !!(val & CFG_3XPORT_U1_PIPE_CLK_GATE_EN) || lost_power;
|
||||
|
||||
if (context_lost) {
|
||||
cdnsp_halt(pdev);
|
||||
cdnsp_set_apb_timeout_value(pdev);
|
||||
|
||||
/* Reset the internal controller memory state and registers. */
|
||||
ret = cdnsp_reset(pdev);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
val = readl(&pdev->port3x_regs->mode_2);
|
||||
val &= ~CFG_3XPORT_U1_PIPE_CLK_GATE_EN;
|
||||
writel(val, &pdev->port3x_regs->mode_2);
|
||||
|
||||
cdnsp_clear_cmd_ring(pdev);
|
||||
|
||||
memset(pdev->event_ring->first_seg->trbs, 0,
|
||||
sizeof(union cdnsp_trb) * (TRBS_PER_SEGMENT));
|
||||
|
||||
cdnsp_init(pdev);
|
||||
}
|
||||
|
||||
max_speed = pdev->gadget_driver->max_speed;
|
||||
|
||||
/* Limit speed if necessary. */
|
||||
@@ -2060,9 +2160,10 @@ static int cdnsp_gadget_resume(struct cdns *cdns, bool lost_power)
|
||||
|
||||
ret = cdnsp_run(pdev, max_speed);
|
||||
|
||||
if (pdev->link_state == XDEV_U3)
|
||||
if (!context_lost && pdev->link_state == XDEV_U3)
|
||||
__cdnsp_gadget_wakeup(pdev);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&pdev->lock, flags);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -1510,6 +1510,7 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev,
|
||||
int cdnsp_ring_expansion(struct cdnsp_device *pdev,
|
||||
struct cdnsp_ring *ring,
|
||||
unsigned int num_trbs, gfp_t flags);
|
||||
void cdnsp_ring_init(struct cdnsp_device *pdev, struct cdnsp_ring *ring);
|
||||
struct cdnsp_ring *cdnsp_dma_to_transfer_ring(struct cdnsp_ep *ep, u64 address);
|
||||
int cdnsp_alloc_stream_info(struct cdnsp_device *pdev,
|
||||
struct cdnsp_ep *pep,
|
||||
|
||||
@@ -394,13 +394,6 @@ static struct cdnsp_ring *cdnsp_ring_alloc(struct cdnsp_device *pdev,
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/* Only event ring does not use link TRB. */
|
||||
if (type != TYPE_EVENT)
|
||||
ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
|
||||
cpu_to_le32(LINK_TOGGLE);
|
||||
|
||||
cdnsp_initialize_ring_info(ring);
|
||||
trace_cdnsp_ring_alloc(ring);
|
||||
return ring;
|
||||
fail:
|
||||
kfree(ring);
|
||||
@@ -603,6 +596,7 @@ int cdnsp_alloc_stream_info(struct cdnsp_device *pdev,
|
||||
if (!cur_ring)
|
||||
goto cleanup_rings;
|
||||
|
||||
cdnsp_ring_init(pdev, cur_ring);
|
||||
cur_ring->stream_id = cur_stream;
|
||||
cur_ring->trb_address_map = &stream_info->trb_address_map;
|
||||
|
||||
@@ -698,6 +692,8 @@ static int cdnsp_alloc_priv_device(struct cdnsp_device *pdev)
|
||||
if (!pdev->eps[0].ring)
|
||||
goto fail;
|
||||
|
||||
cdnsp_ring_init(pdev, pdev->eps[0].ring);
|
||||
|
||||
/* Point to output device context in dcbaa. */
|
||||
pdev->dcbaa->dev_context_ptrs[1] = cpu_to_le64(pdev->out_ctx.dma);
|
||||
pdev->cmd.in_ctx = &pdev->in_ctx;
|
||||
@@ -991,6 +987,8 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev,
|
||||
if (!pep->ring)
|
||||
return -ENOMEM;
|
||||
|
||||
cdnsp_ring_init(pdev, pep->ring);
|
||||
|
||||
pep->skip = false;
|
||||
|
||||
/* Fill the endpoint context */
|
||||
@@ -1096,28 +1094,6 @@ void cdnsp_mem_cleanup(struct cdnsp_device *pdev)
|
||||
pdev->active_port = NULL;
|
||||
}
|
||||
|
||||
static void cdnsp_set_event_deq(struct cdnsp_device *pdev)
|
||||
{
|
||||
dma_addr_t deq;
|
||||
u64 temp;
|
||||
|
||||
deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg,
|
||||
pdev->event_ring->dequeue);
|
||||
|
||||
/* Update controller event ring dequeue pointer */
|
||||
temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue);
|
||||
temp &= ERST_PTR_MASK;
|
||||
|
||||
/*
|
||||
* Don't clear the EHB bit (which is RW1C) because
|
||||
* there might be more events to service.
|
||||
*/
|
||||
temp &= ~ERST_EHB;
|
||||
|
||||
cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp,
|
||||
&pdev->ir_set->erst_dequeue);
|
||||
}
|
||||
|
||||
static void cdnsp_add_in_port(struct cdnsp_device *pdev,
|
||||
struct cdnsp_port *port,
|
||||
__le32 __iomem *addr)
|
||||
@@ -1226,6 +1202,36 @@ static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdnsp_initialize_ring_segments(struct cdnsp_device *pdev, struct cdnsp_ring *ring)
|
||||
{
|
||||
struct cdnsp_segment *seg;
|
||||
|
||||
/* Only event ring does not use link TRB. */
|
||||
if (ring->type == TYPE_EVENT)
|
||||
return;
|
||||
|
||||
seg = ring->first_seg;
|
||||
|
||||
while (seg) {
|
||||
struct cdnsp_segment *next = seg->next;
|
||||
|
||||
cdnsp_link_segments(pdev, seg, next, ring->type);
|
||||
if (next == ring->first_seg)
|
||||
break;
|
||||
|
||||
seg = next;
|
||||
}
|
||||
|
||||
ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |= cpu_to_le32(LINK_TOGGLE);
|
||||
}
|
||||
|
||||
void cdnsp_ring_init(struct cdnsp_device *pdev, struct cdnsp_ring *ring)
|
||||
{
|
||||
cdnsp_initialize_ring_segments(pdev, ring);
|
||||
cdnsp_initialize_ring_info(ring);
|
||||
trace_cdnsp_ring_alloc(ring);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize memory for CDNSP (one-time init).
|
||||
*
|
||||
@@ -1237,10 +1243,8 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
|
||||
{
|
||||
struct device *dev = pdev->dev;
|
||||
int ret = -ENOMEM;
|
||||
unsigned int val;
|
||||
dma_addr_t dma;
|
||||
u32 page_size;
|
||||
u64 val_64;
|
||||
|
||||
/*
|
||||
* Use 4K pages, since that's common and the minimum the
|
||||
@@ -1248,10 +1252,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
|
||||
*/
|
||||
page_size = 1 << 12;
|
||||
|
||||
val = readl(&pdev->op_regs->config_reg);
|
||||
val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E;
|
||||
writel(val, &pdev->op_regs->config_reg);
|
||||
|
||||
/*
|
||||
* Doorbell array must be physically contiguous
|
||||
* and 64-byte (cache line) aligned.
|
||||
@@ -1263,8 +1263,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
|
||||
|
||||
pdev->dcbaa->dma = dma;
|
||||
|
||||
cdnsp_write_64(dma, &pdev->op_regs->dcbaa_ptr);
|
||||
|
||||
/*
|
||||
* Initialize the ring segment pool. The ring must be a contiguous
|
||||
* structure comprised of TRBs. The TRBs must be 16 byte aligned,
|
||||
@@ -1290,17 +1288,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
|
||||
if (!pdev->cmd_ring)
|
||||
goto destroy_device_pool;
|
||||
|
||||
/* Set the address in the Command Ring Control register */
|
||||
val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring);
|
||||
val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) |
|
||||
(pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) |
|
||||
pdev->cmd_ring->cycle_state;
|
||||
cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring);
|
||||
|
||||
val = readl(&pdev->cap_regs->db_off);
|
||||
val &= DBOFF_MASK;
|
||||
pdev->dba = (void __iomem *)pdev->cap_regs + val;
|
||||
|
||||
/* Set ir_set to interrupt register set 0 */
|
||||
pdev->ir_set = &pdev->run_regs->ir_set[0];
|
||||
|
||||
@@ -1317,21 +1304,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
|
||||
if (ret)
|
||||
goto free_event_ring;
|
||||
|
||||
/* Set ERST count with the number of entries in the segment table. */
|
||||
val = readl(&pdev->ir_set->erst_size);
|
||||
val &= ERST_SIZE_MASK;
|
||||
val |= ERST_NUM_SEGS;
|
||||
writel(val, &pdev->ir_set->erst_size);
|
||||
|
||||
/* Set the segment table base address. */
|
||||
val_64 = cdnsp_read_64(&pdev->ir_set->erst_base);
|
||||
val_64 &= ERST_PTR_MASK;
|
||||
val_64 |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK);
|
||||
cdnsp_write_64(val_64, &pdev->ir_set->erst_base);
|
||||
|
||||
/* Set the event ring dequeue address. */
|
||||
cdnsp_set_event_deq(pdev);
|
||||
|
||||
ret = cdnsp_setup_port_arrays(pdev);
|
||||
if (ret)
|
||||
goto free_erst;
|
||||
|
||||
@@ -442,6 +442,7 @@ static int dwc3_google_probe(struct platform_device *pdev)
|
||||
probe_data.dwc = &google->dwc;
|
||||
probe_data.res = res;
|
||||
probe_data.ignore_clocks_and_resets = true;
|
||||
probe_data.properties = DWC3_DEFAULT_PROPERTIES;
|
||||
ret = dwc3_core_probe(&probe_data);
|
||||
if (ret) {
|
||||
ret = dev_err_probe(dev, ret, "failed to register DWC3 Core\n");
|
||||
|
||||
@@ -304,7 +304,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
|
||||
|
||||
dwc3_ep->flags &= ~DWC3_EP_DELAY_STOP;
|
||||
if (dwc->connected)
|
||||
dwc3_stop_active_transfer(dwc3_ep, true, true);
|
||||
dwc3_stop_active_transfer(dwc3_ep, false, true);
|
||||
else
|
||||
dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN);
|
||||
}
|
||||
|
||||
@@ -1004,7 +1004,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
|
||||
* controller to generate an ERDY to initiate the
|
||||
* stream.
|
||||
*/
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
|
||||
/*
|
||||
* All stream eps will reinitiate stream on NoStream
|
||||
@@ -1032,7 +1032,7 @@ void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status)
|
||||
{
|
||||
struct dwc3_request *req;
|
||||
|
||||
dwc3_stop_active_transfer(dep, true, false);
|
||||
dwc3_stop_active_transfer(dep, false, false);
|
||||
|
||||
/* If endxfer is delayed, avoid unmapping requests */
|
||||
if (dep->flags & DWC3_EP_DELAY_STOP)
|
||||
@@ -1720,7 +1720,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
|
||||
if (ret == -EAGAIN)
|
||||
return ret;
|
||||
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
|
||||
list_for_each_entry_safe(req, tmp, &dep->started_list, list)
|
||||
dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_DEQUEUED);
|
||||
@@ -1757,6 +1757,11 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
|
||||
* the controller won't update the TRB progress on command
|
||||
* completion. It also won't clear the HWO bit in the TRB.
|
||||
* The command will also not complete immediately in that case.
|
||||
*
|
||||
* Older programming guide revisions recommended setting ForceRM to 1
|
||||
* when ending a transfer. Newer programming guide revisions now
|
||||
* recommend keeping ForceRM cleared, and TRBs are properly updated
|
||||
* on command completion.
|
||||
*/
|
||||
static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
|
||||
{
|
||||
@@ -1882,7 +1887,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
|
||||
* to wait for the next XferNotReady to test the command again
|
||||
*/
|
||||
if (cmd_status == 0) {
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -2165,7 +2170,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
|
||||
struct dwc3_request *t;
|
||||
|
||||
/* wait until it is processed */
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
|
||||
/*
|
||||
* Remove any started request if the transfer is
|
||||
@@ -2242,7 +2247,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
|
||||
list_for_each_entry_safe(req, tmp, &dep->started_list, list)
|
||||
dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_STALLED);
|
||||
@@ -3368,7 +3373,7 @@ static void dwc3_nostream_work(struct work_struct *work)
|
||||
dwc3_send_gadget_generic_command(dwc, cmd, dep->number);
|
||||
} else {
|
||||
dep->flags |= DWC3_EP_DELAY_START;
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
return;
|
||||
}
|
||||
@@ -3726,7 +3731,7 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
|
||||
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
|
||||
list_empty(&dep->started_list) &&
|
||||
(list_empty(&dep->pending_list) || status == -EXDEV))
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dwc3_stop_active_transfer(dep, false, true);
|
||||
else if (dwc3_gadget_ep_should_continue(dep))
|
||||
if (__dwc3_gadget_kick_transfer(dep) == 0)
|
||||
no_started_trb = false;
|
||||
|
||||
@@ -2747,6 +2747,9 @@ int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
|
||||
struct fsg_buffhd *bh, *buffhds;
|
||||
int i;
|
||||
|
||||
if (n < 2)
|
||||
return -EINVAL;
|
||||
|
||||
buffhds = kzalloc_objs(*buffhds, n);
|
||||
if (!buffhds)
|
||||
return -ENOMEM;
|
||||
@@ -2960,7 +2963,7 @@ EXPORT_SYMBOL_GPL(fsg_common_create_lun);
|
||||
|
||||
int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
|
||||
{
|
||||
char buf[8]; /* enough for 100000000 different numbers, decimal */
|
||||
char buf[14];
|
||||
int i, rc;
|
||||
|
||||
fsg_common_remove_luns(common);
|
||||
|
||||
@@ -879,7 +879,6 @@ 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;
|
||||
INIT_WORK(&midi->work, f_midi_in_work);
|
||||
status = f_midi_register_card(midi);
|
||||
if (status < 0)
|
||||
goto fail_register;
|
||||
@@ -1377,6 +1376,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
|
||||
status = -ENOMEM;
|
||||
goto midi_free;
|
||||
}
|
||||
INIT_WORK(&midi->work, f_midi_in_work);
|
||||
midi->out_ports = opts->out_ports;
|
||||
midi->index = opts->index;
|
||||
midi->buflen = opts->buflen;
|
||||
|
||||
@@ -1145,7 +1145,7 @@ static int f_midi2_alloc_ep_reqs(struct f_midi2_usb_ep *usb_ep)
|
||||
if (!usb_ep->reqs)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < midi2->info.num_reqs; i++) {
|
||||
for (i = 0; i < usb_ep->num_reqs; i++) {
|
||||
if (usb_ep->reqs[i].req)
|
||||
continue;
|
||||
usb_ep->reqs[i].req = alloc_ep_req(usb_ep->usb_ep,
|
||||
@@ -1160,10 +1160,9 @@ static int f_midi2_alloc_ep_reqs(struct f_midi2_usb_ep *usb_ep)
|
||||
/* Free allocated requests */
|
||||
static void f_midi2_free_ep_reqs(struct f_midi2_usb_ep *usb_ep)
|
||||
{
|
||||
struct f_midi2 *midi2 = usb_ep->card;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < midi2->info.num_reqs; i++) {
|
||||
for (i = 0; i < usb_ep->num_reqs; i++) {
|
||||
if (!usb_ep->reqs[i].req)
|
||||
continue;
|
||||
free_ep_req(usb_ep->usb_ep, usb_ep->reqs[i].req);
|
||||
@@ -2178,13 +2177,13 @@ end:
|
||||
|
||||
/* generic show/store for string */
|
||||
static ssize_t f_midi2_opts_str_show(struct f_midi2_opts *opts,
|
||||
const char *str, char *page)
|
||||
const char **strp, char *page)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (str)
|
||||
result = scnprintf(page, PAGE_SIZE, "%s\n", str);
|
||||
if (*strp)
|
||||
result = scnprintf(page, PAGE_SIZE, "%s\n", *strp);
|
||||
mutex_unlock(&opts->lock);
|
||||
return result;
|
||||
}
|
||||
@@ -2278,7 +2277,7 @@ static ssize_t f_midi2_block_opts_name_show(struct config_item *item,
|
||||
{
|
||||
struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item);
|
||||
|
||||
return f_midi2_opts_str_show(opts->ep->opts, opts->info.name, page);
|
||||
return f_midi2_opts_str_show(opts->ep->opts, &opts->info.name, page);
|
||||
}
|
||||
|
||||
static ssize_t f_midi2_block_opts_name_store(struct config_item *item,
|
||||
@@ -2435,7 +2434,7 @@ static ssize_t f_midi2_ep_opts_##name##_show(struct config_item *item, \
|
||||
char *page) \
|
||||
{ \
|
||||
struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); \
|
||||
return f_midi2_opts_str_show(opts->opts, opts->info.name, page);\
|
||||
return f_midi2_opts_str_show(opts->opts, &opts->info.name, page);\
|
||||
} \
|
||||
\
|
||||
static ssize_t f_midi2_ep_opts_##name##_store(struct config_item *item, \
|
||||
@@ -2590,7 +2589,7 @@ static ssize_t f_midi2_opts_iface_name_show(struct config_item *item,
|
||||
{
|
||||
struct f_midi2_opts *opts = to_f_midi2_opts(item);
|
||||
|
||||
return f_midi2_opts_str_show(opts, opts->info.iface_name, page);
|
||||
return f_midi2_opts_str_show(opts, &opts->info.iface_name, page);
|
||||
}
|
||||
|
||||
static ssize_t f_midi2_opts_iface_name_store(struct config_item *item,
|
||||
|
||||
@@ -70,7 +70,7 @@ void usb_put_function_instance(struct usb_function_instance *fi)
|
||||
{
|
||||
struct module *mod;
|
||||
|
||||
if (!fi)
|
||||
if (!fi || !fi->fd)
|
||||
return;
|
||||
|
||||
mod = fi->fd->mod;
|
||||
|
||||
@@ -1260,10 +1260,11 @@ out:
|
||||
static long gadget_dev_ioctl (struct file *fd, unsigned code, unsigned long value)
|
||||
{
|
||||
struct dev_data *dev = fd->private_data;
|
||||
struct usb_gadget *gadget = dev->gadget;
|
||||
struct usb_gadget *gadget;
|
||||
long ret = -ENOTTY;
|
||||
|
||||
spin_lock_irq(&dev->lock);
|
||||
gadget = dev->gadget;
|
||||
if (dev->state == STATE_DEV_OPENED ||
|
||||
dev->state == STATE_DEV_UNBOUND) {
|
||||
/* Not bound to a UDC */
|
||||
|
||||
@@ -2301,7 +2301,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
|
||||
if (!segs)
|
||||
segs = ERST_DEFAULT_SEGS;
|
||||
|
||||
max_segs = FIELD_GET(HCS_ERST_MAX, xhci->hcs_params2) << 2;
|
||||
max_segs = BIT(FIELD_GET(HCS_ERST_MAX, xhci->hcs_params2));
|
||||
segs = min(segs, max_segs);
|
||||
|
||||
ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev));
|
||||
|
||||
@@ -824,21 +824,18 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
|
||||
usb_hcd_giveback_urb(hcd, urb, status);
|
||||
}
|
||||
|
||||
static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ring, struct xhci_td *td)
|
||||
static void xhci_unmap_one_bounce_buffer(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ring, struct xhci_td *td,
|
||||
struct xhci_segment *seg)
|
||||
{
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
|
||||
struct xhci_segment *seg = td->bounce_seg;
|
||||
struct urb *urb = td->urb;
|
||||
size_t len;
|
||||
|
||||
if (!ring || !seg || !urb)
|
||||
return;
|
||||
|
||||
if (usb_urb_dir_out(urb)) {
|
||||
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
|
||||
DMA_TO_DEVICE);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
|
||||
@@ -854,10 +851,29 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
|
||||
memcpy(urb->transfer_buffer + seg->bounce_offs, seg->bounce_buf,
|
||||
seg->bounce_len);
|
||||
}
|
||||
done:
|
||||
seg->bounce_len = 0;
|
||||
seg->bounce_offs = 0;
|
||||
}
|
||||
|
||||
static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ring, struct xhci_td *td)
|
||||
{
|
||||
struct xhci_segment *seg;
|
||||
int i = 0;
|
||||
|
||||
if (!td->bounce_seg || !ring || !td->urb)
|
||||
return;
|
||||
|
||||
/* td->bounce_seg is the last one bounced, unmap them all */
|
||||
for (seg = td->start_seg; i++ < ring->num_segs; seg = seg->next) {
|
||||
if (seg->bounce_len)
|
||||
xhci_unmap_one_bounce_buffer(xhci, ring, td, seg);
|
||||
if (seg == td->bounce_seg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
|
||||
struct xhci_ring *ep_ring, int status)
|
||||
{
|
||||
@@ -3685,7 +3701,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
&trb_buff_len,
|
||||
ring->enq_seg)) {
|
||||
send_addr = ring->enq_seg->bounce_dma;
|
||||
/* assuming TD won't span 2 segs */
|
||||
/* TD bounced at least, and last on this seg */
|
||||
td->bounce_seg = ring->enq_seg;
|
||||
}
|
||||
}
|
||||
@@ -4312,11 +4328,16 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
check_interval(urb, ep_ctx);
|
||||
|
||||
/*
|
||||
* Check if this starts the isoc data flow. Relies on hw setting ep ctx
|
||||
* state after doorbell ring. Consider adding list_empty(td_list) check
|
||||
* Schedule the URB discontiguously if all previous URBs have completed.
|
||||
* XXX core can't tell if completions are pending but not running yet.
|
||||
*/
|
||||
if (GET_EP_CTX_STATE(ep_ctx) != EP_STATE_RUNNING)
|
||||
if (list_empty(&ep_ring->td_list) &&
|
||||
!hcd_periodic_completion_in_progress(xhci_to_hcd(xhci), urb->ep)) {
|
||||
if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_RUNNING)
|
||||
xhci_dbg(xhci, "Unexpected running ring at isoc stream start, uframe: %d\n",
|
||||
xep->next_uframe);
|
||||
xep->next_uframe = -1;
|
||||
}
|
||||
|
||||
return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
|
||||
}
|
||||
|
||||
@@ -1000,13 +1000,13 @@ static int __init usb_mdc800_init (void)
|
||||
mdc800->downloaded = 0;
|
||||
mdc800->written = 0;
|
||||
|
||||
mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
|
||||
mdc800->irq_urb_buffer=kzalloc (8, GFP_KERNEL);
|
||||
if (!mdc800->irq_urb_buffer)
|
||||
goto cleanup_on_fail;
|
||||
mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
|
||||
if (!mdc800->write_urb_buffer)
|
||||
goto cleanup_on_fail;
|
||||
mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
|
||||
mdc800->download_urb_buffer=kzalloc (64, GFP_KERNEL);
|
||||
if (!mdc800->download_urb_buffer)
|
||||
goto cleanup_on_fail;
|
||||
|
||||
|
||||
@@ -2357,7 +2357,9 @@ static int ene_ub6250_probe(struct usb_interface *intf,
|
||||
return result;
|
||||
|
||||
/* probe card type */
|
||||
mutex_lock(&us->dev_mutex);
|
||||
result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
|
||||
mutex_unlock(&us->dev_mutex);
|
||||
if (result != USB_STOR_XFER_GOOD) {
|
||||
usb_stor_disconnect(intf);
|
||||
return USB_STOR_TRANSPORT_ERROR;
|
||||
|
||||
@@ -916,7 +916,6 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)
|
||||
us->proto_handler = rts51x_invoke_transport;
|
||||
|
||||
chip->timer_expires = 0;
|
||||
timer_setup(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, 0);
|
||||
fw5895_init(us);
|
||||
|
||||
/* enable autosuspend function of the usb device */
|
||||
@@ -934,10 +933,7 @@ static void realtek_cr_destructor(void *extra)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_REALTEK_AUTOPM
|
||||
if (ss_en) {
|
||||
timer_delete(&chip->rts51x_suspend_timer);
|
||||
chip->timer_expires = 0;
|
||||
}
|
||||
timer_shutdown_sync(&chip->rts51x_suspend_timer);
|
||||
#endif
|
||||
kfree(chip->status);
|
||||
}
|
||||
@@ -982,6 +978,9 @@ static int init_realtek_cr(struct us_data *us)
|
||||
|
||||
us->extra = chip;
|
||||
us->extra_destructor = realtek_cr_destructor;
|
||||
#ifdef CONFIG_REALTEK_AUTOPM
|
||||
timer_setup(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, 0);
|
||||
#endif
|
||||
us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
|
||||
chip->us = us;
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ struct hd3ss3220 {
|
||||
int id_irq;
|
||||
|
||||
struct regulator *vbus;
|
||||
bool vbus_enabled;
|
||||
};
|
||||
|
||||
static int hd3ss3220_set_power_opmode(struct hd3ss3220 *hd3ss3220, int power_opmode)
|
||||
@@ -208,7 +209,7 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (regulator_is_enabled(hd3ss3220->vbus) == on)
|
||||
if (hd3ss3220->vbus_enabled == on)
|
||||
return;
|
||||
|
||||
if (on)
|
||||
@@ -216,9 +217,13 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on)
|
||||
else
|
||||
ret = regulator_disable(hd3ss3220->vbus);
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(hd3ss3220->dev,
|
||||
"vbus regulator %s failed: %d\n", on ? "enable" : "disable", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
hd3ss3220->vbus_enabled = on;
|
||||
}
|
||||
|
||||
static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
|
||||
|
||||
+18
-3
@@ -57,6 +57,8 @@ static void *typec_switch_match(const struct fwnode_handle *fwnode,
|
||||
*/
|
||||
dev = class_find_device(&typec_mux_class, NULL, fwnode,
|
||||
switch_fwnode_match);
|
||||
if (!dev)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
/* Skip duplicates */
|
||||
for (i = 0; i < TYPEC_MUX_MAX_DEVS; i++)
|
||||
@@ -65,7 +67,7 @@ static void *typec_switch_match(const struct fwnode_handle *fwnode,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev ? to_typec_switch_dev(dev) : ERR_PTR(-EPROBE_DEFER);
|
||||
return to_typec_switch_dev(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,7 +277,9 @@ static int mux_fwnode_match(struct device *dev, const void *fwnode)
|
||||
static void *typec_mux_match(const struct fwnode_handle *fwnode,
|
||||
const char *id, void *data)
|
||||
{
|
||||
struct typec_mux_dev **mux_devs = data;
|
||||
struct device *dev;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Device graph (OF graph) does not give any means to identify the
|
||||
@@ -290,8 +294,18 @@ static void *typec_mux_match(const struct fwnode_handle *fwnode,
|
||||
|
||||
dev = class_find_device(&typec_mux_class, NULL, fwnode,
|
||||
mux_fwnode_match);
|
||||
if (!dev)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
return dev ? to_typec_mux_dev(dev) : ERR_PTR(-EPROBE_DEFER);
|
||||
/* Skip duplicates */
|
||||
for (i = 0; i < TYPEC_MUX_MAX_DEVS; i++)
|
||||
if (to_typec_mux_dev(dev) == mux_devs[i]) {
|
||||
put_device(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return to_typec_mux_dev(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,7 +330,8 @@ struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
count = fwnode_connection_find_matches(fwnode, "mode-switch",
|
||||
NULL, typec_mux_match,
|
||||
(void **)mux_devs,
|
||||
typec_mux_match,
|
||||
(void **)mux_devs,
|
||||
ARRAY_SIZE(mux_devs));
|
||||
if (count <= 0) {
|
||||
|
||||
@@ -543,6 +543,8 @@ static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
|
||||
for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
|
||||
disable_irq(pmic_typec_pdphy->irq_data[i].irq);
|
||||
|
||||
cancel_work_sync(&pmic_typec_pdphy->reset_work);
|
||||
|
||||
qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
|
||||
|
||||
regulator_disable(pmic_typec_pdphy->vdd_pdphy);
|
||||
|
||||
@@ -683,6 +683,9 @@ static int qcom_pmic_typec_port_start(struct pmic_typec *tcpm,
|
||||
enable_irq(pmic_typec_port->irq_data[i].irq);
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
disable_delayed_work_sync(&pmic_typec_port->cc_debounce_dwork);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -693,6 +696,8 @@ static void qcom_pmic_typec_port_stop(struct pmic_typec *tcpm)
|
||||
|
||||
for (i = 0; i < pmic_typec_port->nr_irqs; i++)
|
||||
disable_irq(pmic_typec_port->irq_data[i].irq);
|
||||
|
||||
disable_delayed_work_sync(&pmic_typec_port->cc_debounce_dwork);
|
||||
}
|
||||
|
||||
int qcom_pmic_typec_port_probe(struct platform_device *pdev,
|
||||
|
||||
@@ -7119,16 +7119,32 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
|
||||
}
|
||||
}
|
||||
if (events & TCPM_SOURCING_VBUS) {
|
||||
tcpm_log(port, "sourcing vbus");
|
||||
/*
|
||||
* In fast role swap case TCPC autonomously sources vbus. Set vbus_source
|
||||
* true as TCPM wouldn't have called tcpm_set_vbus.
|
||||
* true conditionally as TCPM wouldn't have called tcpm_set_vbus.
|
||||
* If TCPM calls tcpm_set_vbus to source vbus, vbus_source would already
|
||||
* be true.
|
||||
*
|
||||
* When vbus is sourced on the command on TCPM i.e. TCPM called
|
||||
* tcpm_set_vbus to source vbus, vbus_source would already be true.
|
||||
* When TCPM_FRS_EVENT and TCPM_SOURCING_VBUS arrive simultaneously,
|
||||
* handling TCPM_FRS_EVENT above transitions the state to AMS_START
|
||||
* with upcoming_state FR_SWAP_SEND.
|
||||
*/
|
||||
port->vbus_source = true;
|
||||
_tcpm_pd_vbus_on(port);
|
||||
|
||||
if (tcpm_port_is_source(port) ||
|
||||
tcpm_port_is_debug_source(port) ||
|
||||
(port->state == AMS_START && port->upcoming_state == FR_SWAP_SEND) ||
|
||||
port->state == FR_SWAP_SEND ||
|
||||
port->state == FR_SWAP_SEND_TIMEOUT ||
|
||||
port->state == FR_SWAP_SNK_SRC_TRANSITION_TO_OFF ||
|
||||
port->state == FR_SWAP_SNK_SRC_NEW_SINK_READY ||
|
||||
port->state == FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) {
|
||||
tcpm_log(port, "sourcing vbus");
|
||||
port->vbus_source = true;
|
||||
_tcpm_pd_vbus_on(port);
|
||||
} else {
|
||||
tcpm_log(port, "Discarding sourcing vbus! Invalid state %s",
|
||||
tcpm_states[port->state]);
|
||||
}
|
||||
}
|
||||
if (events & TCPM_PORT_CLEAN) {
|
||||
tcpm_log(port, "port clean");
|
||||
|
||||
@@ -114,7 +114,6 @@ struct tps6598x_intel_vid_status_reg {
|
||||
__le32 attention_vdo;
|
||||
__le16 enter_vdo;
|
||||
__le16 device_mode;
|
||||
__le16 cable_mode;
|
||||
} __packed;
|
||||
|
||||
/* Standard Task return codes */
|
||||
@@ -731,9 +730,19 @@ static void cd321x_typec_update_mode(struct tps6598x *tps, struct cd321x_status
|
||||
cd321x->state.mode == TYPEC_TBT_MODE)
|
||||
return;
|
||||
|
||||
tbt_data.cable_mode = le16_to_cpu(st->intel_vid_status.cable_mode);
|
||||
tbt_data.device_mode = le16_to_cpu(st->intel_vid_status.device_mode);
|
||||
tbt_data.enter_vdo = le16_to_cpu(st->intel_vid_status.enter_vdo);
|
||||
tbt_data.cable_mode = TBT_MODE |
|
||||
TBT_SET_CABLE_SPEED(TPS_DATA_STATUS_TBT_CABLE_SPEED(st->data_status)) |
|
||||
TBT_SET_CABLE_ROUNDED(TPS_DATA_STATUS_TBT_CABLE_GEN(st->data_status));
|
||||
if (st->data_status & TPS_DATA_STATUS_OPTICAL_CABLE)
|
||||
tbt_data.cable_mode |= TBT_CABLE_OPTICAL;
|
||||
if (st->data_status & TPS_DATA_STATUS_ACTIVE_LINK_TRAIN)
|
||||
tbt_data.cable_mode |= TBT_CABLE_LINK_TRAINING;
|
||||
if (st->data_status & TPS_DATA_STATUS_ACTIVE_CABLE)
|
||||
tbt_data.cable_mode |= TBT_CABLE_ACTIVE_PASSIVE;
|
||||
tbt_data.device_mode = TBT_MODE |
|
||||
(u32)le16_to_cpu(st->intel_vid_status.device_mode) << 16;
|
||||
tbt_data.enter_vdo =
|
||||
(u32)le16_to_cpu(st->intel_vid_status.enter_vdo) << 16;
|
||||
cd321x->state.alt = cd321x->port_altmode_tbt;
|
||||
cd321x->state.mode = TYPEC_TBT_MODE;
|
||||
cd321x->state.data = &tbt_data;
|
||||
|
||||
@@ -210,10 +210,10 @@
|
||||
#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) \
|
||||
TPS_FIELD_GET(TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK, (x))
|
||||
#define TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK GENMASK(27, 25)
|
||||
#define TPS_DATA_STATUS_TBT_CABLE_SPEED \
|
||||
#define TPS_DATA_STATUS_TBT_CABLE_SPEED(x) \
|
||||
TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK, (x))
|
||||
#define TPS_DATA_STATUS_TBT_CABLE_GEN_MASK GENMASK(29, 28)
|
||||
#define TPS_DATA_STATUS_TBT_CABLE_GEN \
|
||||
#define TPS_DATA_STATUS_TBT_CABLE_GEN(x) \
|
||||
TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_GEN_MASK, (x))
|
||||
|
||||
/* Map data status to DP spec assignments */
|
||||
|
||||
@@ -74,7 +74,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
|
||||
cur = 0xff;
|
||||
}
|
||||
|
||||
if (cur != 0xff) {
|
||||
if (cur < UCSI_MAX_ALTMODES) {
|
||||
ret = dp->con->port_altmode[cur] == alt ? 0 : -EBUSY;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user