From 2acee0d5bbf99edfffd184d8cbb5ee40ffe33ea9 Mon Sep 17 00:00:00 2001 From: Hanjie Lin Date: Sat, 20 May 2023 13:20:14 +0800 Subject: [PATCH] usb: can not recognize U disk. [1/1] PD#SWPL-139784 Problem: Solution: Revert "usb: IDT test failed with replacing gki [1/2]" This reverts commit 8dd2c1a59088518bf3c9f85261eb50e4c0d6d0c3. Revert "usb: IDT test failed with replacing gki [2/2]" This reverts commit 9221d31343516789406a12370317a21fed41f53b. Revert "usb: IDT test failed with replacing gki [2/2]" This reverts commit 78671889714d3b7b690a1a1e58a10452df9ec40f. Verify: verify by ohm. Change-Id: Ic4b6853719ff17d49c366feccbaff3320cadc464 Signed-off-by: Luan Yuan --- android/common14-5.15_abi_gki_aarch64_amlogic | 3 - ...-cts-USB-Device-Test-module-fail-1-2.patch | 71 ++ ... 0008-usb-USB-low-speed-problem-1-1.patch} | 0 drivers/usb/crg/Makefile | 1 - drivers/usb/crg/crg.c | 4 +- drivers/usb/crg/crg_drd.c | 4 +- drivers/usb/crg/crg_xhci.c | 763 ------------------ drivers/usb/crg/crg_xhci.h | 12 - 8 files changed, 73 insertions(+), 785 deletions(-) create mode 100644 auto_patch/common14-5.15/common/08_usb/0007-usb-cts-USB-Device-Test-module-fail-1-2.patch rename auto_patch/common14-5.15/common/08_usb/{0007-usb-USB-low-speed-problem-1-1.patch => 0008-usb-USB-low-speed-problem-1-1.patch} (100%) delete mode 100644 drivers/usb/crg/crg_xhci.c delete mode 100644 drivers/usb/crg/crg_xhci.h diff --git a/android/common14-5.15_abi_gki_aarch64_amlogic b/android/common14-5.15_abi_gki_aarch64_amlogic index 2ec997ac5..e69de29bb 100644 --- a/android/common14-5.15_abi_gki_aarch64_amlogic +++ b/android/common14-5.15_abi_gki_aarch64_amlogic @@ -1,3 +0,0 @@ - sg_pcopy_to_buffer - usb_hcd_is_primary_hcd - usb_hcd_map_urb_for_dma diff --git a/auto_patch/common14-5.15/common/08_usb/0007-usb-cts-USB-Device-Test-module-fail-1-2.patch b/auto_patch/common14-5.15/common/08_usb/0007-usb-cts-USB-Device-Test-module-fail-1-2.patch new file mode 100644 index 000000000..09705cff3 --- /dev/null +++ b/auto_patch/common14-5.15/common/08_usb/0007-usb-cts-USB-Device-Test-module-fail-1-2.patch @@ -0,0 +1,71 @@ +From 3897a9e000b5c14ebe8938ead7e4882e8b569a74 Mon Sep 17 00:00:00 2001 +From: Yue Wang +Date: Fri, 4 Nov 2022 13:18:14 +0800 +Subject: [PATCH 68/95] usb: cts: USB Device Test module fail [1/2] + +PD#SWPL-99116 + +Problem: +cts: USB Device Test module fail + +Solution: +Don't use IDT transmissions for CRG control + +Verify: +t3 + +Change-Id: Ic5c59615e6139382ae348e37501f665bd373c1ef +Signed-off-by: Yue Wang +--- + drivers/usb/host/xhci-plat.c | 5 +++++ + drivers/usb/host/xhci.h | 11 +++++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 972a44b2a7f1..b2c6e2e35e30 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -323,6 +323,11 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (device_property_read_bool(tmpdev, "quirk-broken-port-ped")) + xhci->quirks |= XHCI_BROKEN_PORT_PED; + ++#if IS_ENABLED(CONFIG_AMLOGIC_COMMON_USB) ++ if (device_property_read_bool(tmpdev, "xhci-crg-host")) ++ xhci->quirks |= XHCI_DISABLE_IDT; ++#endif ++ + device_property_read_u32(tmpdev, "imod-interval-ns", + &xhci->imod_interval); + } +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 119d2541fe5e..168ef5e123ec 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1917,6 +1917,9 @@ struct xhci_hcd { + #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) + #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) + #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) ++#if IS_ENABLED(CONFIG_AMLOGIC_COMMON_USB) ++#define XHCI_DISABLE_IDT BIT_ULL(45) ++#endif + + unsigned int num_active_eps; + unsigned int limit_active_eps; +@@ -2240,6 +2243,14 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, + */ + static inline bool xhci_urb_suitable_for_idt(struct urb *urb) + { ++#if IS_ENABLED(CONFIG_AMLOGIC_COMMON_USB) ++ struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); ++ struct xhci_hcd *xhci = hcd_to_xhci(hcd); ++ ++ if (xhci->quirks & XHCI_DISABLE_IDT) ++ return false; ++#endif ++ + if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && + usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && + urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE && +-- +2.25.1 + diff --git a/auto_patch/common14-5.15/common/08_usb/0007-usb-USB-low-speed-problem-1-1.patch b/auto_patch/common14-5.15/common/08_usb/0008-usb-USB-low-speed-problem-1-1.patch similarity index 100% rename from auto_patch/common14-5.15/common/08_usb/0007-usb-USB-low-speed-problem-1-1.patch rename to auto_patch/common14-5.15/common/08_usb/0008-usb-USB-low-speed-problem-1-1.patch diff --git a/drivers/usb/crg/Makefile b/drivers/usb/crg/Makefile index 73c780b77..4a3058c0b 100644 --- a/drivers/usb/crg/Makefile +++ b/drivers/usb/crg/Makefile @@ -8,5 +8,4 @@ $(MODULE_NAME)-$(CONFIG_AMLOGIC_CRG) += crg/crg_drd.o $(MODULE_NAME)-$(CONFIG_AMLOGIC_CRG) += crg/crg_udc.o $(MODULE_NAME)-$(CONFIG_AMLOGIC_CRG) += crg/crg_usbphy.o -$(MODULE_NAME)-$(CONFIG_AMLOGIC_CRG) += crg/crg_xhci.o diff --git a/drivers/usb/crg/crg.c b/drivers/usb/crg/crg.c index 84145ffd3..61d116716 100644 --- a/drivers/usb/crg/crg.c +++ b/drivers/usb/crg/crg.c @@ -29,7 +29,6 @@ #include #include "xhci.h" #include "xhci-plat.h" -#include "crg_xhci.h" #define CRG_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ #define CRG_XHCI_RESOURCES_NUM 2 @@ -233,7 +232,7 @@ int crg_host_init(struct crg *crg) props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-crg-host"); props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb2-lpm-disable"); - crg_control_flag = 1; + if (prop_idx) { ret = device_create_managed_software_node(&xhci->dev, props, NULL); if (ret) { @@ -596,7 +595,6 @@ static struct platform_driver crg_driver = { /* AMLOGIC corigine driver does not allow module unload */ int __init amlogic_crg_init(void) { - crg_xhci_init(); platform_driver_probe(&crg_driver, crg_probe); return 0; } diff --git a/drivers/usb/crg/crg_drd.c b/drivers/usb/crg/crg_drd.c index 5f483bf9b..089a6244f 100644 --- a/drivers/usb/crg/crg_drd.c +++ b/drivers/usb/crg/crg_drd.c @@ -32,7 +32,6 @@ #include "xhci.h" #include "xhci-plat.h" -#include "crg_xhci.h" static const struct xhci_plat_priv crg_xhci_plat_priv = { .quirks = XHCI_NO_64BIT_SUPPORT | XHCI_RESET_ON_RESUME, @@ -259,7 +258,7 @@ static int crg_host_init(struct crg_drd *crg) props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-crg-host"); props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb2-lpm-disable"); - crg_control_flag = 1; + if (prop_idx) { ret = device_create_managed_software_node(&xhci->dev, props, NULL); if (ret) { @@ -667,7 +666,6 @@ EXPORT_SYMBOL_GPL(crg_init); /* AMLOGIC corigine driver does not allow module unload */ int __init amlogic_crg_host_driver_init(void) { - crg_xhci_init(); platform_driver_probe(&crg_host_driver, crg_probe); return 0; diff --git a/drivers/usb/crg/crg_xhci.c b/drivers/usb/crg/crg_xhci.c deleted file mode 100644 index 7884e73b9..000000000 --- a/drivers/usb/crg/crg_xhci.c +++ /dev/null @@ -1,763 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include "xhci.h" -#include "xhci-trace.h" - -static int usb_debug; -module_param(usb_debug, int, 0644); - -static int (*aml_prepare_transfer) (struct xhci_hcd *xhci, - struct xhci_virt_device *xdev, - unsigned int ep_index, - unsigned int stream_id, - unsigned int num_trbs, - struct urb *urb, - unsigned int td_index, - gfp_t mem_flags); - -static void (*aml_queue_trb) (struct xhci_hcd *xhci, struct xhci_ring *ring, - bool more_trbs_coming, - u32 field1, u32 field2, u32 field3, u32 field4); - -static void (* aml_xhci_ring_ep_doorbell) (struct xhci_hcd *xhci, - unsigned int slot_id, - unsigned int ep_index, - unsigned int stream_id); - -static struct xhci_ring * (*aml_xhci_triad_to_transfer_ring) (struct xhci_hcd *xhci, - unsigned int slot_id, unsigned int ep_index, - unsigned int stream_id); - -static unsigned int (*aml_xhci_get_endpoint_index) (struct usb_endpoint_descriptor *desc); - -unsigned char crg_control_flag; - -static bool aml_xhci_urb_suitable_for_idt(struct urb *urb) -{ - if (crg_control_flag) - return false; - - if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && - usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && - urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE && - !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) && - !urb->num_sgs) - return true; - - return false; -} - -static inline __nocfi struct xhci_ring *aml_xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, - struct urb *urb) -{ - return aml_xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, - aml_xhci_get_endpoint_index(&urb->ep->desc), - urb->stream_id); -} - -static __nocfi unsigned int aml_count_trbs(u64 addr, u64 len) -{ - unsigned int num_trbs; - - num_trbs = DIV_ROUND_UP(len + (addr & (TRB_MAX_BUFF_SIZE - 1)), - TRB_MAX_BUFF_SIZE); - if (num_trbs == 0) - num_trbs++; - - return num_trbs; -} - -static __nocfi bool trb_is_link(union xhci_trb *trb) -{ - return TRB_TYPE_LINK_LE32(trb->link.control); -} - -static inline unsigned int count_trbs_needed(struct urb *urb) -{ - return aml_count_trbs(urb->transfer_dma, urb->transfer_buffer_length); -} - -static __nocfi unsigned int count_sg_trbs_needed(struct urb *urb) -{ - struct scatterlist *sg; - unsigned int i, len, full_len, num_trbs = 0; - - full_len = urb->transfer_buffer_length; - - for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { - len = sg_dma_len(sg); - num_trbs += aml_count_trbs(sg_dma_address(sg), len); - len = min_t(unsigned int, len, full_len); - full_len -= len; - if (full_len == 0) - break; - } - - return num_trbs; -} - -static __nocfi int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, - u32 *trb_buff_len, struct xhci_segment *seg) -{ - struct device *dev = xhci_to_hcd(xhci)->self.controller; - unsigned int unalign; - unsigned int max_pkt; - u32 new_buff_len; - size_t len; - - max_pkt = usb_endpoint_maxp(&urb->ep->desc); - unalign = (enqd_len + *trb_buff_len) % max_pkt; - - /* we got lucky, last normal TRB data on segment is packet aligned */ - if (unalign == 0) - return 0; - - xhci_dbg(xhci, "Unaligned %d bytes, buff len %d\n", - unalign, *trb_buff_len); - - /* is the last nornal TRB alignable by splitting it */ - if (*trb_buff_len > unalign) { - *trb_buff_len -= unalign; - xhci_dbg(xhci, "split align, new buff len %d\n", *trb_buff_len); - return 0; - } - - /* - * We want enqd_len + trb_buff_len to sum up to a number aligned to - * number which is divisible by the endpoint's wMaxPacketSize. IOW: - * (size of currently enqueued TRBs + remainder) % wMaxPacketSize == 0. - */ - new_buff_len = max_pkt - (enqd_len % max_pkt); - - if (new_buff_len > (urb->transfer_buffer_length - enqd_len)) - new_buff_len = (urb->transfer_buffer_length - enqd_len); - - /* create a max max_pkt sized bounce buffer pointed to by last trb */ - if (usb_urb_dir_out(urb)) { - if (urb->num_sgs) { - len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs, - seg->bounce_buf, new_buff_len, enqd_len); - if (len != new_buff_len) - xhci_warn(xhci, "WARN Wrong bounce buffer write length: %zu != %d\n", - len, new_buff_len); - } else { - memcpy(seg->bounce_buf, urb->transfer_buffer + enqd_len, new_buff_len); - } - - seg->bounce_dma = dma_map_single(dev, seg->bounce_buf, - max_pkt, DMA_TO_DEVICE); - } else { - seg->bounce_dma = dma_map_single(dev, seg->bounce_buf, - max_pkt, DMA_FROM_DEVICE); - } - - if (dma_mapping_error(dev, seg->bounce_dma)) { - /* try without aligning. Some host controllers survive */ - xhci_warn(xhci, "Failed mapping bounce buffer, not aligning\n"); - return 0; - } - *trb_buff_len = new_buff_len; - seg->bounce_len = new_buff_len; - seg->bounce_offs = enqd_len; - - xhci_dbg(xhci, "Bounce align, new buff len %d\n", *trb_buff_len); - - return 1; -} - -static __nocfi void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, - unsigned int ep_index, unsigned int stream_id, int start_cycle, - struct xhci_generic_trb *start_trb) -{ - /* - * Pass all the TRBs to the hardware at once and make sure this write - * isn't reordered. - */ - wmb(); - if (start_cycle) - start_trb->field[3] |= cpu_to_le32(start_cycle); - else - start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); - aml_xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); -} -static __nocfi void check_trb_math(struct urb *urb, int running_total) -{ - if (unlikely(running_total != urb->transfer_buffer_length)) - dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " - "queued %#x (%d), asked for %#x (%d)\n", - __func__, - urb->ep->desc.bEndpointAddress, - running_total, running_total, - urb->transfer_buffer_length, - urb->transfer_buffer_length); -} - -static __nocfi u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, - int trb_buff_len, unsigned int td_total_len, - struct urb *urb, bool more_trbs_coming) -{ - u32 maxp, total_packet_count; - - /* MTK xHCI 0.96 contains some features from 1.0 */ - if (xhci->hci_version < 0x100 && !(xhci->quirks & XHCI_MTK_HOST)) - return ((td_total_len - transferred) >> 10); - - /* One TRB with a zero-length data packet. */ - if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0) || - trb_buff_len == td_total_len) - return 0; - - /* for MTK xHCI 0.96, TD size include this TRB, but not in 1.x */ - if ((xhci->quirks & XHCI_MTK_HOST) && (xhci->hci_version < 0x100)) - trb_buff_len = 0; - - maxp = usb_endpoint_maxp(&urb->ep->desc); - total_packet_count = DIV_ROUND_UP(td_total_len, maxp); - - /* Queueing functions don't count the current TRB into transferred */ - return (total_packet_count - ((transferred + trb_buff_len) / maxp)); -} - -static bool xhci_urb_temp_buffer_required(struct usb_hcd *hcd, - struct urb *urb) -{ - bool ret = false; - unsigned int i; - unsigned int len = 0; - unsigned int trb_size; - unsigned int max_pkt; - struct scatterlist *sg; - struct scatterlist *tail_sg; - - tail_sg = urb->sg; - max_pkt = usb_endpoint_maxp(&urb->ep->desc); - - if (!urb->num_sgs) - return ret; - - if (urb->dev->speed >= USB_SPEED_SUPER) - trb_size = TRB_CACHE_SIZE_SS; - else - trb_size = TRB_CACHE_SIZE_HS; - - if (urb->transfer_buffer_length != 0 && - !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { - for_each_sg(urb->sg, sg, urb->num_sgs, i) { - len = len + sg->length; - if (i > trb_size - 2) { - len = len - tail_sg->length; - if (len < max_pkt) { - ret = true; - break; - } - - tail_sg = sg_next(tail_sg); - } - } - } - return ret; -} - -static int xhci_map_temp_buffer(struct usb_hcd *hcd, struct urb *urb) -{ - void *temp; - int ret = 0; - unsigned int buf_len; - enum dma_data_direction dir; - - dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - buf_len = urb->transfer_buffer_length; - - temp = kzalloc_node(buf_len, GFP_ATOMIC, - dev_to_node(hcd->self.sysdev)); - - if (usb_urb_dir_out(urb)) - sg_pcopy_to_buffer(urb->sg, urb->num_sgs, - temp, buf_len, 0); - - urb->transfer_buffer = temp; - urb->transfer_dma = dma_map_single(hcd->self.sysdev, - urb->transfer_buffer, - urb->transfer_buffer_length, - dir); - - if (dma_mapping_error(hcd->self.sysdev, - urb->transfer_dma)) { - ret = -EAGAIN; - kfree(temp); - } else { - urb->transfer_flags |= URB_DMA_MAP_SINGLE; - } - - return ret; -} - - -/* This is very similar to what ehci-q.c qtd_fill() does */ -int __nocfi aml_xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) -{ - struct xhci_ring *ring; - struct urb_priv *urb_priv; - struct xhci_td *td; - struct xhci_generic_trb *start_trb; - struct scatterlist *sg = NULL; - bool more_trbs_coming = true; - bool need_zero_pkt = false; - bool first_trb = true; - unsigned int num_trbs; - unsigned int start_cycle, num_sgs = 0; - unsigned int enqd_len, block_len, trb_buff_len, full_len; - int sent_len, ret; - u32 field, length_field, remainder; - u64 addr, send_addr; - - if (usb_debug) - pr_info("%s():%d\n", __func__, __LINE__); - - ring = aml_xhci_urb_to_transfer_ring(xhci, urb); - if (!ring) - return -EINVAL; - - full_len = urb->transfer_buffer_length; - /* If we have scatter/gather list, we use it. */ - if (urb->num_sgs && !(urb->transfer_flags & URB_DMA_MAP_SINGLE)) { - num_sgs = urb->num_mapped_sgs; - sg = urb->sg; - addr = (u64) sg_dma_address(sg); - block_len = sg_dma_len(sg); - num_trbs = count_sg_trbs_needed(urb); - } else { - num_trbs = count_trbs_needed(urb); - addr = (u64) urb->transfer_dma; - block_len = full_len; - } - ret = aml_prepare_transfer(xhci, xhci->devs[slot_id], - ep_index, urb->stream_id, - num_trbs, urb, 0, mem_flags); - if (unlikely(ret < 0)) - return ret; - - urb_priv = urb->hcpriv; - - /* Deal with URB_ZERO_PACKET - need one more td/trb */ - if (urb->transfer_flags & URB_ZERO_PACKET && urb_priv->num_tds > 1) - need_zero_pkt = true; - - td = &urb_priv->td[0]; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ring->enqueue->generic; - start_cycle = ring->cycle_state; - send_addr = addr; - - /* Queue the TRBs, even if they are zero-length */ - for (enqd_len = 0; first_trb || enqd_len < full_len; - enqd_len += trb_buff_len) { - field = TRB_TYPE(TRB_NORMAL); - - /* TRB buffer should not cross 64KB boundaries */ - trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr); - trb_buff_len = min_t(unsigned int, trb_buff_len, block_len); - - if (enqd_len + trb_buff_len > full_len) - trb_buff_len = full_len - enqd_len; - - /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) { - first_trb = false; - if (start_cycle == 0) - field |= TRB_CYCLE; - } else - field |= ring->cycle_state; - - /* Chain all the TRBs together; clear the chain bit in the last - * TRB to indicate it's the last TRB in the chain. - */ - if (enqd_len + trb_buff_len < full_len) { - field |= TRB_CHAIN; - if (trb_is_link(ring->enqueue + 1)) { - if (xhci_align_td(xhci, urb, enqd_len, - &trb_buff_len, - ring->enq_seg)) { - send_addr = ring->enq_seg->bounce_dma; - /* assuming TD won't span 2 segs */ - td->bounce_seg = ring->enq_seg; - } - } - } - if (enqd_len + trb_buff_len >= full_len) { - field &= ~TRB_CHAIN; - field |= TRB_IOC; - more_trbs_coming = false; - td->last_trb = ring->enqueue; - td->last_trb_seg = ring->enq_seg; - if (aml_xhci_urb_suitable_for_idt(urb)) { - memcpy(&send_addr, urb->transfer_buffer, - trb_buff_len); - le64_to_cpus(&send_addr); - field |= TRB_IDT; - } - } - - /* Only set interrupt on short packet for IN endpoints */ - if (usb_urb_dir_in(urb)) - field |= TRB_ISP; - - /* Set the TRB length, TD size, and interrupter fields. */ - remainder = xhci_td_remainder(xhci, enqd_len, trb_buff_len, - full_len, urb, more_trbs_coming); - - length_field = TRB_LEN(trb_buff_len) | - TRB_TD_SIZE(remainder) | - TRB_INTR_TARGET(0); - - aml_queue_trb(xhci, ring, more_trbs_coming | need_zero_pkt, - lower_32_bits(send_addr), - upper_32_bits(send_addr), - length_field, - field); - td->num_trbs++; - addr += trb_buff_len; - sent_len = trb_buff_len; - - while (sg && sent_len >= block_len) { - /* New sg entry */ - --num_sgs; - sent_len -= block_len; - sg = sg_next(sg); - if (num_sgs != 0 && sg) { - block_len = sg_dma_len(sg); - addr = (u64) sg_dma_address(sg); - addr += sent_len; - } - } - block_len -= sent_len; - send_addr = addr; - } - - if (need_zero_pkt) { - ret = aml_prepare_transfer(xhci, xhci->devs[slot_id], - ep_index, urb->stream_id, - 1, urb, 1, mem_flags); - urb_priv->td[1].last_trb = ring->enqueue; - urb_priv->td[1].last_trb_seg = ring->enq_seg; - field = TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC; - aml_queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field); - urb_priv->td[1].num_trbs++; - } - - check_trb_math(urb, enqd_len); - giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, - start_cycle, start_trb); - return 0; -} - - -/* Caller must have locked xhci->lock */ -int __nocfi aml_xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) -{ - struct xhci_ring *ep_ring; - int num_trbs; - int ret; - struct usb_ctrlrequest *setup; - struct xhci_generic_trb *start_trb; - int start_cycle; - u32 field; - struct urb_priv *urb_priv; - struct xhci_td *td; - - if (usb_debug) - pr_info("%s():%d\n", __func__, __LINE__); - - ep_ring = aml_xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) - return -EINVAL; - - /* - * Need to copy setup packet into setup TRB, so we can't use the setup - * DMA address. - */ - if (!urb->setup_packet) - return -EINVAL; - - /* 1 TRB for setup, 1 for status */ - num_trbs = 2; - /* - * Don't need to check if we need additional event data and normal TRBs, - * since data in control transfers will never get bigger than 16MB - * XXX: can we get a buffer that crosses 64KB boundaries? - */ - if (urb->transfer_buffer_length > 0) - num_trbs++; - ret = aml_prepare_transfer(xhci, xhci->devs[slot_id], - ep_index, urb->stream_id, - num_trbs, urb, 0, mem_flags); - if (ret < 0) - return ret; - - urb_priv = urb->hcpriv; - td = &urb_priv->td[0]; - td->num_trbs = num_trbs; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ep_ring->enqueue->generic; - start_cycle = ep_ring->cycle_state; - - /* Queue setup TRB - see section 6.4.1.2.1 */ - /* FIXME better way to translate setup_packet into two u32 fields? */ - setup = (struct usb_ctrlrequest *) urb->setup_packet; - field = 0; - field |= TRB_IDT | TRB_TYPE(TRB_SETUP); - if (start_cycle == 0) - field |= 0x1; - - /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ - if ((xhci->hci_version >= 0x100) || (xhci->quirks & XHCI_MTK_HOST)) { - if (urb->transfer_buffer_length > 0) { - if (setup->bRequestType & USB_DIR_IN) - field |= TRB_TX_TYPE(TRB_DATA_IN); - else - field |= TRB_TX_TYPE(TRB_DATA_OUT); - } - } - - aml_queue_trb(xhci, ep_ring, true, - setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16, - le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16, - TRB_LEN(8) | TRB_INTR_TARGET(0), - /* Immediate data in pointer */ - field); - - /* If there's data, queue data TRBs */ - /* Only set interrupt on short packet for IN endpoints */ - if (usb_urb_dir_in(urb)) - field = TRB_ISP | TRB_TYPE(TRB_DATA); - else - field = TRB_TYPE(TRB_DATA); - - if (urb->transfer_buffer_length > 0) { - u32 length_field, remainder; - u64 addr; - - if (aml_xhci_urb_suitable_for_idt(urb)) { - memcpy(&addr, urb->transfer_buffer, - urb->transfer_buffer_length); - le64_to_cpus(&addr); - field |= TRB_IDT; - } else { - addr = (u64) urb->transfer_dma; - } - - remainder = xhci_td_remainder(xhci, 0, - urb->transfer_buffer_length, - urb->transfer_buffer_length, - urb, 1); - length_field = TRB_LEN(urb->transfer_buffer_length) | - TRB_TD_SIZE(remainder) | - TRB_INTR_TARGET(0); - if (setup->bRequestType & USB_DIR_IN) - field |= TRB_DIR_IN; - aml_queue_trb(xhci, ep_ring, true, - lower_32_bits(addr), - upper_32_bits(addr), - length_field, - field | ep_ring->cycle_state); - } - - /* Save the DMA address of the last TRB in the TD */ - td->last_trb = ep_ring->enqueue; - td->last_trb_seg = ep_ring->enq_seg; - - /* Queue status TRB - see Table 7 and sections 4.11.2.2 and 6.4.1.2.3 */ - /* If the device sent data, the status stage is an OUT transfer */ - if (urb->transfer_buffer_length > 0 && setup->bRequestType & USB_DIR_IN) - field = 0; - else - field = TRB_DIR_IN; - aml_queue_trb(xhci, ep_ring, false, - 0, - 0, - TRB_INTR_TARGET(0), - /* Event on completion */ - field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state); - - giveback_first_trb(xhci, slot_id, ep_index, 0, - start_cycle, start_trb); - return 0; -} - -int __nocfi aml_xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, - gfp_t mem_flags) -{ - struct xhci_hcd *xhci; - - if (usb_debug) - pr_info("%s():%d\n", __func__, __LINE__); - - xhci = hcd_to_xhci(hcd); - - if (aml_xhci_urb_suitable_for_idt(urb)) - return 0; - - if (xhci->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK) { - if (xhci_urb_temp_buffer_required(hcd, urb)) - return xhci_map_temp_buffer(hcd, urb); - } - return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); -} - -static void *get_symbol_addr(const char *symbol_name) -{ - struct kprobe kp; - int ret; - - kp.symbol_name = symbol_name; - - ret = register_kprobe(&kp); - if (ret < 0) { - pr_err("register_kprobe:%s failed, returned %d\n", symbol_name, ret); - return NULL; - } - pr_debug("symbol_name:%s addr=%px\n", symbol_name, kp.addr); - unregister_kprobe(&kp); - - return kp.addr; -} - -static int __nocfi __kprobes xhci_queue_bulk_tx_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - /* - int ret; - - ret = aml_xhci_queue_bulk_tx((struct xhci_hcd *)regs->regs[0], - (gfp_t)regs->regs[1], - (struct urb *)regs->regs[2], - (int)regs->regs[3], - (unsigned int)regs->regs[4]); - - regs->regs[0] = ret; - regs->pc = regs->regs[30]; - */ - - //restore to origin context - instruction_pointer_set(regs, (unsigned long)aml_xhci_queue_bulk_tx); - - //no need continue do single-step - return 1; -} - -struct kprobe kp_xhci_queue_bulk_tx = { - .symbol_name = "xhci_queue_bulk_tx", - .pre_handler = xhci_queue_bulk_tx_pre_handler, -}; - -static int __nocfi __kprobes xhci_map_urb_for_dma_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - /* - int ret; - - ret = aml_xhci_map_urb_for_dma((struct usb_hcd *)regs->regs[0], - (struct urb *)regs->regs[1], - (gfp_t)regs->regs[2]); - - regs->regs[0] = ret; - regs->pc = regs->regs[30]; - */ - - //restore to origin context - instruction_pointer_set(regs, (unsigned long)aml_xhci_map_urb_for_dma); - - //no need continue do single-step - return 1; -} - -struct kprobe kp_xhci_map_urb_for_dma = { - .symbol_name = "xhci_map_urb_for_dma", - .pre_handler = xhci_map_urb_for_dma_pre_handler, -}; - -static int __nocfi __kprobes xhci_queue_ctrl_tx_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - /* - int ret; - - ret = aml_xhci_queue_ctrl_tx((struct xhci_hcd *)regs->regs[0], - (gfp_t)regs->regs[1], - (struct urb *)regs->regs[2], - (int)regs->regs[3], - (unsigned int)regs->regs[4]); - - regs->regs[0] = ret; - regs->pc = regs->regs[30]; - */ - - //restore to origin context - instruction_pointer_set(regs, (unsigned long)aml_xhci_queue_ctrl_tx); - - //no need continue do single-step - return 1; -} - -struct kprobe kp_xhci_queue_ctrl_tx = { - .symbol_name = "xhci_queue_ctrl_tx", - .pre_handler = xhci_queue_ctrl_tx_pre_handler, -}; - -int crg_xhci_init(void) -{ - int ret; - - aml_prepare_transfer = get_symbol_addr("prepare_transfer"); - aml_queue_trb = get_symbol_addr("queue_trb"); - aml_xhci_ring_ep_doorbell = get_symbol_addr("xhci_ring_ep_doorbell"); - aml_xhci_triad_to_transfer_ring = get_symbol_addr("xhci_triad_to_transfer_ring"); - aml_xhci_get_endpoint_index = get_symbol_addr("xhci_get_endpoint_index"); - - if (!aml_prepare_transfer || !aml_queue_trb || !aml_xhci_ring_ep_doorbell || - !aml_xhci_triad_to_transfer_ring || !aml_xhci_get_endpoint_index) - return 1; - - ret = register_kprobe(&kp_xhci_queue_bulk_tx); - if (ret < 0) { - pr_err("register_kprobe:%s failed, returned %d\n", - kp_xhci_queue_bulk_tx.symbol_name, ret); - return 1; - } - - ret = register_kprobe(&kp_xhci_queue_ctrl_tx); - if (ret < 0) { - pr_err("register_kprobe:%s failed, returned %d\n", - kp_xhci_queue_ctrl_tx.symbol_name, ret); - unregister_kprobe(&kp_xhci_queue_bulk_tx); - return 1; - } - - ret = register_kprobe(&kp_xhci_map_urb_for_dma); - if (ret < 0) { - pr_err("register_kprobe:%s failed, returned %d\n", - kp_xhci_map_urb_for_dma.symbol_name, ret); - unregister_kprobe(&kp_xhci_queue_bulk_tx); - unregister_kprobe(&kp_xhci_queue_ctrl_tx); - return 1; - } - - return 0; -} diff --git a/drivers/usb/crg/crg_xhci.h b/drivers/usb/crg/crg_xhci.h deleted file mode 100644 index a5bd69cbf..000000000 --- a/drivers/usb/crg/crg_xhci.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ -/* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. - */ - -#ifndef __CRG_XHCI_H__ -#define __CRG_XHCI_H__ - -extern unsigned char crg_control_flag; -int crg_xhci_init(void); - -#endif