xref: /openbmc/linux/drivers/usb/cdns3/cdnsp-mem.c (revision 7d94bc8e)
13d829045SPawel Laszczak // SPDX-License-Identifier: GPL-2.0
23d829045SPawel Laszczak /*
33d829045SPawel Laszczak  * Cadence CDNSP DRD Driver.
43d829045SPawel Laszczak  *
53d829045SPawel Laszczak  * Copyright (C) 2020 Cadence.
63d829045SPawel Laszczak  *
73d829045SPawel Laszczak  * Author: Pawel Laszczak <pawell@cadence.com>
83d829045SPawel Laszczak  *
93d829045SPawel Laszczak  * Code based on Linux XHCI driver.
103d829045SPawel Laszczak  * Origin: Copyright (C) 2008 Intel Corp.
113d829045SPawel Laszczak  */
123d829045SPawel Laszczak 
133d829045SPawel Laszczak #include <linux/dma-mapping.h>
143d829045SPawel Laszczak #include <linux/dmapool.h>
153d829045SPawel Laszczak #include <linux/slab.h>
163d829045SPawel Laszczak #include <linux/usb.h>
173d829045SPawel Laszczak 
183d829045SPawel Laszczak #include "cdnsp-gadget.h"
19118b2a32SPawel Laszczak #include "cdnsp-trace.h"
203d829045SPawel Laszczak 
213d829045SPawel Laszczak static void cdnsp_free_stream_info(struct cdnsp_device *pdev,
223d829045SPawel Laszczak 				   struct cdnsp_ep *pep);
233d829045SPawel Laszczak /*
243d829045SPawel Laszczak  * Allocates a generic ring segment from the ring pool, sets the dma address,
253d829045SPawel Laszczak  * initializes the segment to zero, and sets the private next pointer to NULL.
263d829045SPawel Laszczak  *
273d829045SPawel Laszczak  * "All components of all Command and Transfer TRBs shall be initialized to '0'"
283d829045SPawel Laszczak  */
cdnsp_segment_alloc(struct cdnsp_device * pdev,unsigned int cycle_state,unsigned int max_packet,gfp_t flags)293d829045SPawel Laszczak static struct cdnsp_segment *cdnsp_segment_alloc(struct cdnsp_device *pdev,
303d829045SPawel Laszczak 						 unsigned int cycle_state,
313d829045SPawel Laszczak 						 unsigned int max_packet,
323d829045SPawel Laszczak 						 gfp_t flags)
333d829045SPawel Laszczak {
343d829045SPawel Laszczak 	struct cdnsp_segment *seg;
353d829045SPawel Laszczak 	dma_addr_t dma;
363d829045SPawel Laszczak 	int i;
373d829045SPawel Laszczak 
383d829045SPawel Laszczak 	seg = kzalloc(sizeof(*seg), flags);
393d829045SPawel Laszczak 	if (!seg)
403d829045SPawel Laszczak 		return NULL;
413d829045SPawel Laszczak 
423d829045SPawel Laszczak 	seg->trbs = dma_pool_zalloc(pdev->segment_pool, flags, &dma);
433d829045SPawel Laszczak 	if (!seg->trbs) {
443d829045SPawel Laszczak 		kfree(seg);
453d829045SPawel Laszczak 		return NULL;
463d829045SPawel Laszczak 	}
473d829045SPawel Laszczak 
483d829045SPawel Laszczak 	if (max_packet) {
493d829045SPawel Laszczak 		seg->bounce_buf = kzalloc(max_packet, flags | GFP_DMA);
503d829045SPawel Laszczak 		if (!seg->bounce_buf)
513d829045SPawel Laszczak 			goto free_dma;
523d829045SPawel Laszczak 	}
533d829045SPawel Laszczak 
543d829045SPawel Laszczak 	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs. */
553d829045SPawel Laszczak 	if (cycle_state == 0) {
563d829045SPawel Laszczak 		for (i = 0; i < TRBS_PER_SEGMENT; i++)
573d829045SPawel Laszczak 			seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE);
583d829045SPawel Laszczak 	}
593d829045SPawel Laszczak 	seg->dma = dma;
603d829045SPawel Laszczak 	seg->next = NULL;
613d829045SPawel Laszczak 
623d829045SPawel Laszczak 	return seg;
633d829045SPawel Laszczak 
643d829045SPawel Laszczak free_dma:
653d829045SPawel Laszczak 	dma_pool_free(pdev->segment_pool, seg->trbs, dma);
663d829045SPawel Laszczak 	kfree(seg);
673d829045SPawel Laszczak 
683d829045SPawel Laszczak 	return NULL;
693d829045SPawel Laszczak }
703d829045SPawel Laszczak 
cdnsp_segment_free(struct cdnsp_device * pdev,struct cdnsp_segment * seg)713d829045SPawel Laszczak static void cdnsp_segment_free(struct cdnsp_device *pdev,
723d829045SPawel Laszczak 			       struct cdnsp_segment *seg)
733d829045SPawel Laszczak {
743d829045SPawel Laszczak 	if (seg->trbs)
753d829045SPawel Laszczak 		dma_pool_free(pdev->segment_pool, seg->trbs, seg->dma);
763d829045SPawel Laszczak 
773d829045SPawel Laszczak 	kfree(seg->bounce_buf);
783d829045SPawel Laszczak 	kfree(seg);
793d829045SPawel Laszczak }
803d829045SPawel Laszczak 
cdnsp_free_segments_for_ring(struct cdnsp_device * pdev,struct cdnsp_segment * first)813d829045SPawel Laszczak static void cdnsp_free_segments_for_ring(struct cdnsp_device *pdev,
823d829045SPawel Laszczak 					 struct cdnsp_segment *first)
833d829045SPawel Laszczak {
843d829045SPawel Laszczak 	struct cdnsp_segment *seg;
853d829045SPawel Laszczak 
863d829045SPawel Laszczak 	seg = first->next;
873d829045SPawel Laszczak 
883d829045SPawel Laszczak 	while (seg != first) {
893d829045SPawel Laszczak 		struct cdnsp_segment *next = seg->next;
903d829045SPawel Laszczak 
913d829045SPawel Laszczak 		cdnsp_segment_free(pdev, seg);
923d829045SPawel Laszczak 		seg = next;
933d829045SPawel Laszczak 	}
943d829045SPawel Laszczak 
953d829045SPawel Laszczak 	cdnsp_segment_free(pdev, first);
963d829045SPawel Laszczak }
973d829045SPawel Laszczak 
983d829045SPawel Laszczak /*
993d829045SPawel Laszczak  * Make the prev segment point to the next segment.
1003d829045SPawel Laszczak  *
1013d829045SPawel Laszczak  * Change the last TRB in the prev segment to be a Link TRB which points to the
1023d829045SPawel Laszczak  * DMA address of the next segment. The caller needs to set any Link TRB
1033d829045SPawel Laszczak  * related flags, such as End TRB, Toggle Cycle, and no snoop.
1043d829045SPawel Laszczak  */
cdnsp_link_segments(struct cdnsp_device * pdev,struct cdnsp_segment * prev,struct cdnsp_segment * next,enum cdnsp_ring_type type)1053d829045SPawel Laszczak static void cdnsp_link_segments(struct cdnsp_device *pdev,
1063d829045SPawel Laszczak 				struct cdnsp_segment *prev,
1073d829045SPawel Laszczak 				struct cdnsp_segment *next,
1083d829045SPawel Laszczak 				enum cdnsp_ring_type type)
1093d829045SPawel Laszczak {
1103d829045SPawel Laszczak 	struct cdnsp_link_trb *link;
1113d829045SPawel Laszczak 	u32 val;
1123d829045SPawel Laszczak 
1133d829045SPawel Laszczak 	if (!prev || !next)
1143d829045SPawel Laszczak 		return;
1153d829045SPawel Laszczak 
1163d829045SPawel Laszczak 	prev->next = next;
1173d829045SPawel Laszczak 	if (type != TYPE_EVENT) {
1183d829045SPawel Laszczak 		link = &prev->trbs[TRBS_PER_SEGMENT - 1].link;
1193d829045SPawel Laszczak 		link->segment_ptr = cpu_to_le64(next->dma);
1203d829045SPawel Laszczak 
1213d829045SPawel Laszczak 		/*
1223d829045SPawel Laszczak 		 * Set the last TRB in the segment to have a TRB type ID
1233d829045SPawel Laszczak 		 * of Link TRB
1243d829045SPawel Laszczak 		 */
1253d829045SPawel Laszczak 		val = le32_to_cpu(link->control);
1263d829045SPawel Laszczak 		val &= ~TRB_TYPE_BITMASK;
1273d829045SPawel Laszczak 		val |= TRB_TYPE(TRB_LINK);
1283d829045SPawel Laszczak 		link->control = cpu_to_le32(val);
1293d829045SPawel Laszczak 	}
1303d829045SPawel Laszczak }
1313d829045SPawel Laszczak 
1323d829045SPawel Laszczak /*
1333d829045SPawel Laszczak  * Link the ring to the new segments.
1343d829045SPawel Laszczak  * Set Toggle Cycle for the new ring if needed.
1353d829045SPawel Laszczak  */
cdnsp_link_rings(struct cdnsp_device * pdev,struct cdnsp_ring * ring,struct cdnsp_segment * first,struct cdnsp_segment * last,unsigned int num_segs)1363d829045SPawel Laszczak static void cdnsp_link_rings(struct cdnsp_device *pdev,
1373d829045SPawel Laszczak 			     struct cdnsp_ring *ring,
1383d829045SPawel Laszczak 			     struct cdnsp_segment *first,
1393d829045SPawel Laszczak 			     struct cdnsp_segment *last,
1403d829045SPawel Laszczak 			     unsigned int num_segs)
1413d829045SPawel Laszczak {
1423d829045SPawel Laszczak 	struct cdnsp_segment *next;
1433d829045SPawel Laszczak 
1443d829045SPawel Laszczak 	if (!ring || !first || !last)
1453d829045SPawel Laszczak 		return;
1463d829045SPawel Laszczak 
1473d829045SPawel Laszczak 	next = ring->enq_seg->next;
1483d829045SPawel Laszczak 	cdnsp_link_segments(pdev, ring->enq_seg, first, ring->type);
1493d829045SPawel Laszczak 	cdnsp_link_segments(pdev, last, next, ring->type);
1503d829045SPawel Laszczak 	ring->num_segs += num_segs;
1513d829045SPawel Laszczak 	ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
1523d829045SPawel Laszczak 
1533d829045SPawel Laszczak 	if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
1543d829045SPawel Laszczak 		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control &=
1553d829045SPawel Laszczak 			~cpu_to_le32(LINK_TOGGLE);
1563d829045SPawel Laszczak 		last->trbs[TRBS_PER_SEGMENT - 1].link.control |=
1573d829045SPawel Laszczak 			cpu_to_le32(LINK_TOGGLE);
1583d829045SPawel Laszczak 		ring->last_seg = last;
1593d829045SPawel Laszczak 	}
1603d829045SPawel Laszczak }
1613d829045SPawel Laszczak 
1623d829045SPawel Laszczak /*
1633d829045SPawel Laszczak  * We need a radix tree for mapping physical addresses of TRBs to which stream
1643d829045SPawel Laszczak  * ID they belong to. We need to do this because the device controller won't
1653d829045SPawel Laszczak  * tell us which stream ring the TRB came from. We could store the stream ID
1663d829045SPawel Laszczak  * in an event data TRB, but that doesn't help us for the cancellation case,
1673d829045SPawel Laszczak  * since the endpoint may stop before it reaches that event data TRB.
1683d829045SPawel Laszczak  *
1693d829045SPawel Laszczak  * The radix tree maps the upper portion of the TRB DMA address to a ring
1703d829045SPawel Laszczak  * segment that has the same upper portion of DMA addresses. For example,
1713d829045SPawel Laszczak  * say I have segments of size 1KB, that are always 1KB aligned. A segment may
1723d829045SPawel Laszczak  * start at 0x10c91000 and end at 0x10c913f0. If I use the upper 10 bits, the
1733d829045SPawel Laszczak  * key to the stream ID is 0x43244. I can use the DMA address of the TRB to
1743d829045SPawel Laszczak  * pass the radix tree a key to get the right stream ID:
1753d829045SPawel Laszczak  *
1763d829045SPawel Laszczak  *	0x10c90fff >> 10 = 0x43243
1773d829045SPawel Laszczak  *	0x10c912c0 >> 10 = 0x43244
1783d829045SPawel Laszczak  *	0x10c91400 >> 10 = 0x43245
1793d829045SPawel Laszczak  *
1803d829045SPawel Laszczak  * Obviously, only those TRBs with DMA addresses that are within the segment
1813d829045SPawel Laszczak  * will make the radix tree return the stream ID for that ring.
1823d829045SPawel Laszczak  *
1833d829045SPawel Laszczak  * Caveats for the radix tree:
1843d829045SPawel Laszczak  *
1853d829045SPawel Laszczak  * The radix tree uses an unsigned long as a key pair. On 32-bit systems, an
1863d829045SPawel Laszczak  * unsigned long will be 32-bits; on a 64-bit system an unsigned long will be
1873d829045SPawel Laszczak  * 64-bits. Since we only request 32-bit DMA addresses, we can use that as the
1883d829045SPawel Laszczak  * key on 32-bit or 64-bit systems (it would also be fine if we asked for 64-bit
1893d829045SPawel Laszczak  * PCI DMA addresses on a 64-bit system). There might be a problem on 32-bit
1903d829045SPawel Laszczak  * extended systems (where the DMA address can be bigger than 32-bits),
1913d829045SPawel Laszczak  * if we allow the PCI dma mask to be bigger than 32-bits. So don't do that.
1923d829045SPawel Laszczak  */
cdnsp_insert_segment_mapping(struct radix_tree_root * trb_address_map,struct cdnsp_ring * ring,struct cdnsp_segment * seg,gfp_t mem_flags)1933d829045SPawel Laszczak static int cdnsp_insert_segment_mapping(struct radix_tree_root *trb_address_map,
1943d829045SPawel Laszczak 					struct cdnsp_ring *ring,
1953d829045SPawel Laszczak 					struct cdnsp_segment *seg,
1963d829045SPawel Laszczak 					gfp_t mem_flags)
1973d829045SPawel Laszczak {
1983d829045SPawel Laszczak 	unsigned long key;
1993d829045SPawel Laszczak 	int ret;
2003d829045SPawel Laszczak 
2013d829045SPawel Laszczak 	key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
2023d829045SPawel Laszczak 
2033d829045SPawel Laszczak 	/* Skip any segments that were already added. */
2043d829045SPawel Laszczak 	if (radix_tree_lookup(trb_address_map, key))
2053d829045SPawel Laszczak 		return 0;
2063d829045SPawel Laszczak 
2073d829045SPawel Laszczak 	ret = radix_tree_maybe_preload(mem_flags);
2083d829045SPawel Laszczak 	if (ret)
2093d829045SPawel Laszczak 		return ret;
2103d829045SPawel Laszczak 
2113d829045SPawel Laszczak 	ret = radix_tree_insert(trb_address_map, key, ring);
2123d829045SPawel Laszczak 	radix_tree_preload_end();
2133d829045SPawel Laszczak 
2143d829045SPawel Laszczak 	return ret;
2153d829045SPawel Laszczak }
2163d829045SPawel Laszczak 
cdnsp_remove_segment_mapping(struct radix_tree_root * trb_address_map,struct cdnsp_segment * seg)2173d829045SPawel Laszczak static void cdnsp_remove_segment_mapping(struct radix_tree_root *trb_address_map,
2183d829045SPawel Laszczak 					 struct cdnsp_segment *seg)
2193d829045SPawel Laszczak {
2203d829045SPawel Laszczak 	unsigned long key;
2213d829045SPawel Laszczak 
2223d829045SPawel Laszczak 	key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
2233d829045SPawel Laszczak 	if (radix_tree_lookup(trb_address_map, key))
2243d829045SPawel Laszczak 		radix_tree_delete(trb_address_map, key);
2253d829045SPawel Laszczak }
2263d829045SPawel Laszczak 
cdnsp_update_stream_segment_mapping(struct radix_tree_root * trb_address_map,struct cdnsp_ring * ring,struct cdnsp_segment * first_seg,struct cdnsp_segment * last_seg,gfp_t mem_flags)2273d829045SPawel Laszczak static int cdnsp_update_stream_segment_mapping(struct radix_tree_root *trb_address_map,
2283d829045SPawel Laszczak 					       struct cdnsp_ring *ring,
2293d829045SPawel Laszczak 					       struct cdnsp_segment *first_seg,
2303d829045SPawel Laszczak 					       struct cdnsp_segment *last_seg,
2313d829045SPawel Laszczak 					       gfp_t mem_flags)
2323d829045SPawel Laszczak {
2333d829045SPawel Laszczak 	struct cdnsp_segment *failed_seg;
2343d829045SPawel Laszczak 	struct cdnsp_segment *seg;
2353d829045SPawel Laszczak 	int ret;
2363d829045SPawel Laszczak 
2373d829045SPawel Laszczak 	seg = first_seg;
2383d829045SPawel Laszczak 	do {
2393d829045SPawel Laszczak 		ret = cdnsp_insert_segment_mapping(trb_address_map, ring, seg,
2403d829045SPawel Laszczak 						   mem_flags);
2413d829045SPawel Laszczak 		if (ret)
2423d829045SPawel Laszczak 			goto remove_streams;
2433d829045SPawel Laszczak 		if (seg == last_seg)
2443d829045SPawel Laszczak 			return 0;
2453d829045SPawel Laszczak 		seg = seg->next;
2463d829045SPawel Laszczak 	} while (seg != first_seg);
2473d829045SPawel Laszczak 
2483d829045SPawel Laszczak 	return 0;
2493d829045SPawel Laszczak 
2503d829045SPawel Laszczak remove_streams:
2513d829045SPawel Laszczak 	failed_seg = seg;
2523d829045SPawel Laszczak 	seg = first_seg;
2533d829045SPawel Laszczak 	do {
2543d829045SPawel Laszczak 		cdnsp_remove_segment_mapping(trb_address_map, seg);
2553d829045SPawel Laszczak 		if (seg == failed_seg)
2563d829045SPawel Laszczak 			return ret;
2573d829045SPawel Laszczak 		seg = seg->next;
2583d829045SPawel Laszczak 	} while (seg != first_seg);
2593d829045SPawel Laszczak 
2603d829045SPawel Laszczak 	return ret;
2613d829045SPawel Laszczak }
2623d829045SPawel Laszczak 
cdnsp_remove_stream_mapping(struct cdnsp_ring * ring)2633d829045SPawel Laszczak static void cdnsp_remove_stream_mapping(struct cdnsp_ring *ring)
2643d829045SPawel Laszczak {
2653d829045SPawel Laszczak 	struct cdnsp_segment *seg;
2663d829045SPawel Laszczak 
2673d829045SPawel Laszczak 	seg = ring->first_seg;
2683d829045SPawel Laszczak 	do {
2693d829045SPawel Laszczak 		cdnsp_remove_segment_mapping(ring->trb_address_map, seg);
2703d829045SPawel Laszczak 		seg = seg->next;
2713d829045SPawel Laszczak 	} while (seg != ring->first_seg);
2723d829045SPawel Laszczak }
2733d829045SPawel Laszczak 
cdnsp_update_stream_mapping(struct cdnsp_ring * ring)2743d829045SPawel Laszczak static int cdnsp_update_stream_mapping(struct cdnsp_ring *ring)
2753d829045SPawel Laszczak {
2763d829045SPawel Laszczak 	return cdnsp_update_stream_segment_mapping(ring->trb_address_map, ring,
2773d829045SPawel Laszczak 			ring->first_seg, ring->last_seg, GFP_ATOMIC);
2783d829045SPawel Laszczak }
2793d829045SPawel Laszczak 
cdnsp_ring_free(struct cdnsp_device * pdev,struct cdnsp_ring * ring)2803d829045SPawel Laszczak static void cdnsp_ring_free(struct cdnsp_device *pdev, struct cdnsp_ring *ring)
2813d829045SPawel Laszczak {
2823d829045SPawel Laszczak 	if (!ring)
2833d829045SPawel Laszczak 		return;
2843d829045SPawel Laszczak 
285118b2a32SPawel Laszczak 	trace_cdnsp_ring_free(ring);
286118b2a32SPawel Laszczak 
2873d829045SPawel Laszczak 	if (ring->first_seg) {
2883d829045SPawel Laszczak 		if (ring->type == TYPE_STREAM)
2893d829045SPawel Laszczak 			cdnsp_remove_stream_mapping(ring);
2903d829045SPawel Laszczak 
2913d829045SPawel Laszczak 		cdnsp_free_segments_for_ring(pdev, ring->first_seg);
2923d829045SPawel Laszczak 	}
2933d829045SPawel Laszczak 
2943d829045SPawel Laszczak 	kfree(ring);
2953d829045SPawel Laszczak }
2963d829045SPawel Laszczak 
cdnsp_initialize_ring_info(struct cdnsp_ring * ring)2973d829045SPawel Laszczak void cdnsp_initialize_ring_info(struct cdnsp_ring *ring)
2983d829045SPawel Laszczak {
2993d829045SPawel Laszczak 	ring->enqueue = ring->first_seg->trbs;
3003d829045SPawel Laszczak 	ring->enq_seg = ring->first_seg;
3013d829045SPawel Laszczak 	ring->dequeue = ring->enqueue;
3023d829045SPawel Laszczak 	ring->deq_seg = ring->first_seg;
3033d829045SPawel Laszczak 
3043d829045SPawel Laszczak 	/*
3053d829045SPawel Laszczak 	 * The ring is initialized to 0. The producer must write 1 to the cycle
3063d829045SPawel Laszczak 	 * bit to handover ownership of the TRB, so PCS = 1. The consumer must
3073d829045SPawel Laszczak 	 * compare CCS to the cycle bit to check ownership, so CCS = 1.
3083d829045SPawel Laszczak 	 *
3093d829045SPawel Laszczak 	 * New rings are initialized with cycle state equal to 1; if we are
3103d829045SPawel Laszczak 	 * handling ring expansion, set the cycle state equal to the old ring.
3113d829045SPawel Laszczak 	 */
3123d829045SPawel Laszczak 	ring->cycle_state = 1;
3133d829045SPawel Laszczak 
3143d829045SPawel Laszczak 	/*
3153d829045SPawel Laszczak 	 * Each segment has a link TRB, and leave an extra TRB for SW
3163d829045SPawel Laszczak 	 * accounting purpose
3173d829045SPawel Laszczak 	 */
3183d829045SPawel Laszczak 	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
3193d829045SPawel Laszczak }
3203d829045SPawel Laszczak 
3213d829045SPawel Laszczak /* Allocate segments and link them for a ring. */
cdnsp_alloc_segments_for_ring(struct cdnsp_device * pdev,struct cdnsp_segment ** first,struct cdnsp_segment ** last,unsigned int num_segs,unsigned int cycle_state,enum cdnsp_ring_type type,unsigned int max_packet,gfp_t flags)3223d829045SPawel Laszczak static int cdnsp_alloc_segments_for_ring(struct cdnsp_device *pdev,
3233d829045SPawel Laszczak 					 struct cdnsp_segment **first,
3243d829045SPawel Laszczak 					 struct cdnsp_segment **last,
3253d829045SPawel Laszczak 					 unsigned int num_segs,
3263d829045SPawel Laszczak 					 unsigned int cycle_state,
3273d829045SPawel Laszczak 					 enum cdnsp_ring_type type,
3283d829045SPawel Laszczak 					 unsigned int max_packet,
3293d829045SPawel Laszczak 					 gfp_t flags)
3303d829045SPawel Laszczak {
3313d829045SPawel Laszczak 	struct cdnsp_segment *prev;
3323d829045SPawel Laszczak 
3333d829045SPawel Laszczak 	/* Allocate first segment. */
3343d829045SPawel Laszczak 	prev = cdnsp_segment_alloc(pdev, cycle_state, max_packet, flags);
3353d829045SPawel Laszczak 	if (!prev)
3363d829045SPawel Laszczak 		return -ENOMEM;
3373d829045SPawel Laszczak 
3383d829045SPawel Laszczak 	num_segs--;
3393d829045SPawel Laszczak 	*first = prev;
3403d829045SPawel Laszczak 
3413d829045SPawel Laszczak 	/* Allocate all other segments. */
3423d829045SPawel Laszczak 	while (num_segs > 0) {
3433d829045SPawel Laszczak 		struct cdnsp_segment	*next;
3443d829045SPawel Laszczak 
3453d829045SPawel Laszczak 		next = cdnsp_segment_alloc(pdev, cycle_state,
3463d829045SPawel Laszczak 					   max_packet, flags);
3473d829045SPawel Laszczak 		if (!next) {
3483d829045SPawel Laszczak 			cdnsp_free_segments_for_ring(pdev, *first);
3493d829045SPawel Laszczak 			return -ENOMEM;
3503d829045SPawel Laszczak 		}
3513d829045SPawel Laszczak 
3523d829045SPawel Laszczak 		cdnsp_link_segments(pdev, prev, next, type);
3533d829045SPawel Laszczak 
3543d829045SPawel Laszczak 		prev = next;
3553d829045SPawel Laszczak 		num_segs--;
3563d829045SPawel Laszczak 	}
3573d829045SPawel Laszczak 
3583d829045SPawel Laszczak 	cdnsp_link_segments(pdev, prev, *first, type);
3593d829045SPawel Laszczak 	*last = prev;
3603d829045SPawel Laszczak 
3613d829045SPawel Laszczak 	return 0;
3623d829045SPawel Laszczak }
3633d829045SPawel Laszczak 
3643d829045SPawel Laszczak /*
3653d829045SPawel Laszczak  * Create a new ring with zero or more segments.
3663d829045SPawel Laszczak  *
3673d829045SPawel Laszczak  * Link each segment together into a ring.
3683d829045SPawel Laszczak  * Set the end flag and the cycle toggle bit on the last segment.
3693d829045SPawel Laszczak  */
cdnsp_ring_alloc(struct cdnsp_device * pdev,unsigned int num_segs,enum cdnsp_ring_type type,unsigned int max_packet,gfp_t flags)3703d829045SPawel Laszczak static struct cdnsp_ring *cdnsp_ring_alloc(struct cdnsp_device *pdev,
3713d829045SPawel Laszczak 					   unsigned int num_segs,
3723d829045SPawel Laszczak 					   enum cdnsp_ring_type type,
3733d829045SPawel Laszczak 					   unsigned int max_packet,
3743d829045SPawel Laszczak 					   gfp_t flags)
3753d829045SPawel Laszczak {
3763d829045SPawel Laszczak 	struct cdnsp_ring *ring;
3773d829045SPawel Laszczak 	int ret;
3783d829045SPawel Laszczak 
3793d829045SPawel Laszczak 	ring = kzalloc(sizeof *(ring), flags);
3803d829045SPawel Laszczak 	if (!ring)
3813d829045SPawel Laszczak 		return NULL;
3823d829045SPawel Laszczak 
3833d829045SPawel Laszczak 	ring->num_segs = num_segs;
3843d829045SPawel Laszczak 	ring->bounce_buf_len = max_packet;
3853d829045SPawel Laszczak 	INIT_LIST_HEAD(&ring->td_list);
3863d829045SPawel Laszczak 	ring->type = type;
3873d829045SPawel Laszczak 
3883d829045SPawel Laszczak 	if (num_segs == 0)
3893d829045SPawel Laszczak 		return ring;
3903d829045SPawel Laszczak 
3913d829045SPawel Laszczak 	ret = cdnsp_alloc_segments_for_ring(pdev, &ring->first_seg,
3923d829045SPawel Laszczak 					    &ring->last_seg, num_segs,
3933d829045SPawel Laszczak 					    1, type, max_packet, flags);
3943d829045SPawel Laszczak 	if (ret)
3953d829045SPawel Laszczak 		goto fail;
3963d829045SPawel Laszczak 
3973d829045SPawel Laszczak 	/* Only event ring does not use link TRB. */
3983d829045SPawel Laszczak 	if (type != TYPE_EVENT)
3993d829045SPawel Laszczak 		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
4003d829045SPawel Laszczak 			cpu_to_le32(LINK_TOGGLE);
4013d829045SPawel Laszczak 
4023d829045SPawel Laszczak 	cdnsp_initialize_ring_info(ring);
403118b2a32SPawel Laszczak 	trace_cdnsp_ring_alloc(ring);
4043d829045SPawel Laszczak 	return ring;
4053d829045SPawel Laszczak fail:
4063d829045SPawel Laszczak 	kfree(ring);
4073d829045SPawel Laszczak 	return NULL;
4083d829045SPawel Laszczak }
4093d829045SPawel Laszczak 
cdnsp_free_endpoint_rings(struct cdnsp_device * pdev,struct cdnsp_ep * pep)4103d829045SPawel Laszczak void cdnsp_free_endpoint_rings(struct cdnsp_device *pdev, struct cdnsp_ep *pep)
4113d829045SPawel Laszczak {
4123d829045SPawel Laszczak 	cdnsp_ring_free(pdev, pep->ring);
4133d829045SPawel Laszczak 	pep->ring = NULL;
4143d829045SPawel Laszczak 	cdnsp_free_stream_info(pdev, pep);
4153d829045SPawel Laszczak }
4163d829045SPawel Laszczak 
4173d829045SPawel Laszczak /*
4183d829045SPawel Laszczak  * Expand an existing ring.
4193d829045SPawel Laszczak  * Allocate a new ring which has same segment numbers and link the two rings.
4203d829045SPawel Laszczak  */
cdnsp_ring_expansion(struct cdnsp_device * pdev,struct cdnsp_ring * ring,unsigned int num_trbs,gfp_t flags)4213d829045SPawel Laszczak int cdnsp_ring_expansion(struct cdnsp_device *pdev,
4223d829045SPawel Laszczak 			 struct cdnsp_ring *ring,
4233d829045SPawel Laszczak 			 unsigned int num_trbs,
4243d829045SPawel Laszczak 			 gfp_t flags)
4253d829045SPawel Laszczak {
4263d829045SPawel Laszczak 	unsigned int num_segs_needed;
4273d829045SPawel Laszczak 	struct cdnsp_segment *first;
4283d829045SPawel Laszczak 	struct cdnsp_segment *last;
4293d829045SPawel Laszczak 	unsigned int num_segs;
4303d829045SPawel Laszczak 	int ret;
4313d829045SPawel Laszczak 
4323d829045SPawel Laszczak 	num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) /
4333d829045SPawel Laszczak 			(TRBS_PER_SEGMENT - 1);
4343d829045SPawel Laszczak 
4353d829045SPawel Laszczak 	/* Allocate number of segments we needed, or double the ring size. */
4363d829045SPawel Laszczak 	num_segs = max(ring->num_segs, num_segs_needed);
4373d829045SPawel Laszczak 
4383d829045SPawel Laszczak 	ret = cdnsp_alloc_segments_for_ring(pdev, &first, &last, num_segs,
4393d829045SPawel Laszczak 					    ring->cycle_state, ring->type,
4403d829045SPawel Laszczak 					    ring->bounce_buf_len, flags);
4413d829045SPawel Laszczak 	if (ret)
4423d829045SPawel Laszczak 		return -ENOMEM;
4433d829045SPawel Laszczak 
4443d829045SPawel Laszczak 	if (ring->type == TYPE_STREAM)
4453d829045SPawel Laszczak 		ret = cdnsp_update_stream_segment_mapping(ring->trb_address_map,
4463d829045SPawel Laszczak 							  ring, first,
4473d829045SPawel Laszczak 							  last, flags);
4483d829045SPawel Laszczak 
4493d829045SPawel Laszczak 	if (ret) {
4503d829045SPawel Laszczak 		cdnsp_free_segments_for_ring(pdev, first);
4513d829045SPawel Laszczak 
4523d829045SPawel Laszczak 		return ret;
4533d829045SPawel Laszczak 	}
4543d829045SPawel Laszczak 
4553d829045SPawel Laszczak 	cdnsp_link_rings(pdev, ring, first, last, num_segs);
456118b2a32SPawel Laszczak 	trace_cdnsp_ring_expansion(ring);
4573d829045SPawel Laszczak 
4583d829045SPawel Laszczak 	return 0;
4593d829045SPawel Laszczak }
4603d829045SPawel Laszczak 
cdnsp_init_device_ctx(struct cdnsp_device * pdev)4613d829045SPawel Laszczak static int cdnsp_init_device_ctx(struct cdnsp_device *pdev)
4623d829045SPawel Laszczak {
4633d829045SPawel Laszczak 	int size = HCC_64BYTE_CONTEXT(pdev->hcc_params) ? 2048 : 1024;
4643d829045SPawel Laszczak 
4653d829045SPawel Laszczak 	pdev->out_ctx.type = CDNSP_CTX_TYPE_DEVICE;
4663d829045SPawel Laszczak 	pdev->out_ctx.size = size;
4673d829045SPawel Laszczak 	pdev->out_ctx.ctx_size = CTX_SIZE(pdev->hcc_params);
4683d829045SPawel Laszczak 	pdev->out_ctx.bytes = dma_pool_zalloc(pdev->device_pool, GFP_ATOMIC,
4693d829045SPawel Laszczak 					      &pdev->out_ctx.dma);
4703d829045SPawel Laszczak 
4713d829045SPawel Laszczak 	if (!pdev->out_ctx.bytes)
4723d829045SPawel Laszczak 		return -ENOMEM;
4733d829045SPawel Laszczak 
4743d829045SPawel Laszczak 	pdev->in_ctx.type = CDNSP_CTX_TYPE_INPUT;
4753d829045SPawel Laszczak 	pdev->in_ctx.ctx_size = pdev->out_ctx.ctx_size;
4763d829045SPawel Laszczak 	pdev->in_ctx.size = size + pdev->out_ctx.ctx_size;
4773d829045SPawel Laszczak 	pdev->in_ctx.bytes = dma_pool_zalloc(pdev->device_pool, GFP_ATOMIC,
4783d829045SPawel Laszczak 					     &pdev->in_ctx.dma);
4793d829045SPawel Laszczak 
4803d829045SPawel Laszczak 	if (!pdev->in_ctx.bytes) {
4813d829045SPawel Laszczak 		dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes,
4823d829045SPawel Laszczak 			      pdev->out_ctx.dma);
4833d829045SPawel Laszczak 		return -ENOMEM;
4843d829045SPawel Laszczak 	}
4853d829045SPawel Laszczak 
4863d829045SPawel Laszczak 	return 0;
4873d829045SPawel Laszczak }
4883d829045SPawel Laszczak 
4893d829045SPawel Laszczak struct cdnsp_input_control_ctx
cdnsp_get_input_control_ctx(struct cdnsp_container_ctx * ctx)4903d829045SPawel Laszczak 	*cdnsp_get_input_control_ctx(struct cdnsp_container_ctx *ctx)
4913d829045SPawel Laszczak {
4923d829045SPawel Laszczak 	if (ctx->type != CDNSP_CTX_TYPE_INPUT)
4933d829045SPawel Laszczak 		return NULL;
4943d829045SPawel Laszczak 
4953d829045SPawel Laszczak 	return (struct cdnsp_input_control_ctx *)ctx->bytes;
4963d829045SPawel Laszczak }
4973d829045SPawel Laszczak 
cdnsp_get_slot_ctx(struct cdnsp_container_ctx * ctx)4983d829045SPawel Laszczak struct cdnsp_slot_ctx *cdnsp_get_slot_ctx(struct cdnsp_container_ctx *ctx)
4993d829045SPawel Laszczak {
5003d829045SPawel Laszczak 	if (ctx->type == CDNSP_CTX_TYPE_DEVICE)
5013d829045SPawel Laszczak 		return (struct cdnsp_slot_ctx *)ctx->bytes;
5023d829045SPawel Laszczak 
5033d829045SPawel Laszczak 	return (struct cdnsp_slot_ctx *)(ctx->bytes + ctx->ctx_size);
5043d829045SPawel Laszczak }
5053d829045SPawel Laszczak 
cdnsp_get_ep_ctx(struct cdnsp_container_ctx * ctx,unsigned int ep_index)5063d829045SPawel Laszczak struct cdnsp_ep_ctx *cdnsp_get_ep_ctx(struct cdnsp_container_ctx *ctx,
5073d829045SPawel Laszczak 				      unsigned int ep_index)
5083d829045SPawel Laszczak {
5093d829045SPawel Laszczak 	/* Increment ep index by offset of start of ep ctx array. */
5103d829045SPawel Laszczak 	ep_index++;
5113d829045SPawel Laszczak 	if (ctx->type == CDNSP_CTX_TYPE_INPUT)
5123d829045SPawel Laszczak 		ep_index++;
5133d829045SPawel Laszczak 
5143d829045SPawel Laszczak 	return (struct cdnsp_ep_ctx *)(ctx->bytes + (ep_index * ctx->ctx_size));
5153d829045SPawel Laszczak }
5163d829045SPawel Laszczak 
cdnsp_free_stream_ctx(struct cdnsp_device * pdev,struct cdnsp_ep * pep)5173d829045SPawel Laszczak static void cdnsp_free_stream_ctx(struct cdnsp_device *pdev,
5183d829045SPawel Laszczak 				  struct cdnsp_ep *pep)
5193d829045SPawel Laszczak {
5203d829045SPawel Laszczak 	dma_pool_free(pdev->device_pool, pep->stream_info.stream_ctx_array,
5213d829045SPawel Laszczak 		      pep->stream_info.ctx_array_dma);
5223d829045SPawel Laszczak }
5233d829045SPawel Laszczak 
5243d829045SPawel Laszczak /* The stream context array must be a power of 2. */
5253d829045SPawel Laszczak static struct cdnsp_stream_ctx
cdnsp_alloc_stream_ctx(struct cdnsp_device * pdev,struct cdnsp_ep * pep)5263d829045SPawel Laszczak 	*cdnsp_alloc_stream_ctx(struct cdnsp_device *pdev, struct cdnsp_ep *pep)
5273d829045SPawel Laszczak {
5283d829045SPawel Laszczak 	size_t size = sizeof(struct cdnsp_stream_ctx) *
5293d829045SPawel Laszczak 		      pep->stream_info.num_stream_ctxs;
5303d829045SPawel Laszczak 
5313d829045SPawel Laszczak 	if (size > CDNSP_CTX_SIZE)
5323d829045SPawel Laszczak 		return NULL;
5333d829045SPawel Laszczak 
5343d829045SPawel Laszczak 	/**
5353d829045SPawel Laszczak 	 * Driver uses intentionally the device_pool to allocated stream
5363d829045SPawel Laszczak 	 * context array. Device Pool has 2048 bytes of size what gives us
5373d829045SPawel Laszczak 	 * 128 entries.
5383d829045SPawel Laszczak 	 */
5393d829045SPawel Laszczak 	return dma_pool_zalloc(pdev->device_pool, GFP_DMA32 | GFP_ATOMIC,
5403d829045SPawel Laszczak 			       &pep->stream_info.ctx_array_dma);
5413d829045SPawel Laszczak }
5423d829045SPawel Laszczak 
cdnsp_dma_to_transfer_ring(struct cdnsp_ep * pep,u64 address)5433d829045SPawel Laszczak struct cdnsp_ring *cdnsp_dma_to_transfer_ring(struct cdnsp_ep *pep, u64 address)
5443d829045SPawel Laszczak {
5453d829045SPawel Laszczak 	if (pep->ep_state & EP_HAS_STREAMS)
5463d829045SPawel Laszczak 		return radix_tree_lookup(&pep->stream_info.trb_address_map,
5473d829045SPawel Laszczak 					 address >> TRB_SEGMENT_SHIFT);
5483d829045SPawel Laszczak 
5493d829045SPawel Laszczak 	return pep->ring;
5503d829045SPawel Laszczak }
5513d829045SPawel Laszczak 
5523d829045SPawel Laszczak /*
5533d829045SPawel Laszczak  * Change an endpoint's internal structure so it supports stream IDs.
5543d829045SPawel Laszczak  * The number of requested streams includes stream 0, which cannot be used by
5553d829045SPawel Laszczak  * driver.
5563d829045SPawel Laszczak  *
5573d829045SPawel Laszczak  * The number of stream contexts in the stream context array may be bigger than
5583d829045SPawel Laszczak  * the number of streams the driver wants to use. This is because the number of
5593d829045SPawel Laszczak  * stream context array entries must be a power of two.
5603d829045SPawel Laszczak  */
cdnsp_alloc_stream_info(struct cdnsp_device * pdev,struct cdnsp_ep * pep,unsigned int num_stream_ctxs,unsigned int num_streams)5613d829045SPawel Laszczak int cdnsp_alloc_stream_info(struct cdnsp_device *pdev,
5623d829045SPawel Laszczak 			    struct cdnsp_ep *pep,
5633d829045SPawel Laszczak 			    unsigned int num_stream_ctxs,
5643d829045SPawel Laszczak 			    unsigned int num_streams)
5653d829045SPawel Laszczak {
5663d829045SPawel Laszczak 	struct cdnsp_stream_info *stream_info;
5673d829045SPawel Laszczak 	struct cdnsp_ring *cur_ring;
5683d829045SPawel Laszczak 	u32 cur_stream;
5693d829045SPawel Laszczak 	u64 addr;
5703d829045SPawel Laszczak 	int ret;
5713d829045SPawel Laszczak 	int mps;
5723d829045SPawel Laszczak 
5733d829045SPawel Laszczak 	stream_info = &pep->stream_info;
5743d829045SPawel Laszczak 	stream_info->num_streams = num_streams;
5753d829045SPawel Laszczak 	stream_info->num_stream_ctxs = num_stream_ctxs;
5763d829045SPawel Laszczak 
5773d829045SPawel Laszczak 	/* Initialize the array of virtual pointers to stream rings. */
5783d829045SPawel Laszczak 	stream_info->stream_rings = kcalloc(num_streams,
5793d829045SPawel Laszczak 					    sizeof(struct cdnsp_ring *),
5803d829045SPawel Laszczak 					    GFP_ATOMIC);
5813d829045SPawel Laszczak 	if (!stream_info->stream_rings)
5823d829045SPawel Laszczak 		return -ENOMEM;
5833d829045SPawel Laszczak 
5843d829045SPawel Laszczak 	/* Initialize the array of DMA addresses for stream rings for the HW. */
5853d829045SPawel Laszczak 	stream_info->stream_ctx_array = cdnsp_alloc_stream_ctx(pdev, pep);
5863d829045SPawel Laszczak 	if (!stream_info->stream_ctx_array)
5873d829045SPawel Laszczak 		goto cleanup_stream_rings;
5883d829045SPawel Laszczak 
5893d829045SPawel Laszczak 	memset(stream_info->stream_ctx_array, 0,
5903d829045SPawel Laszczak 	       sizeof(struct cdnsp_stream_ctx) * num_stream_ctxs);
5913d829045SPawel Laszczak 	INIT_RADIX_TREE(&stream_info->trb_address_map, GFP_ATOMIC);
5923d829045SPawel Laszczak 	mps = usb_endpoint_maxp(pep->endpoint.desc);
5933d829045SPawel Laszczak 
5943d829045SPawel Laszczak 	/*
5953d829045SPawel Laszczak 	 * Allocate rings for all the streams that the driver will use,
5963d829045SPawel Laszczak 	 * and add their segment DMA addresses to the radix tree.
5973d829045SPawel Laszczak 	 * Stream 0 is reserved.
5983d829045SPawel Laszczak 	 */
5993d829045SPawel Laszczak 	for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
6003d829045SPawel Laszczak 		cur_ring = cdnsp_ring_alloc(pdev, 2, TYPE_STREAM, mps,
6013d829045SPawel Laszczak 					    GFP_ATOMIC);
6023d829045SPawel Laszczak 		stream_info->stream_rings[cur_stream] = cur_ring;
6033d829045SPawel Laszczak 
6043d829045SPawel Laszczak 		if (!cur_ring)
6053d829045SPawel Laszczak 			goto cleanup_rings;
6063d829045SPawel Laszczak 
6073d829045SPawel Laszczak 		cur_ring->stream_id = cur_stream;
6083d829045SPawel Laszczak 		cur_ring->trb_address_map = &stream_info->trb_address_map;
6093d829045SPawel Laszczak 
6103d829045SPawel Laszczak 		/* Set deq ptr, cycle bit, and stream context type. */
6113d829045SPawel Laszczak 		addr = cur_ring->first_seg->dma | SCT_FOR_CTX(SCT_PRI_TR) |
6123d829045SPawel Laszczak 		       cur_ring->cycle_state;
6133d829045SPawel Laszczak 
6143d829045SPawel Laszczak 		stream_info->stream_ctx_array[cur_stream].stream_ring =
6153d829045SPawel Laszczak 			cpu_to_le64(addr);
6163d829045SPawel Laszczak 
617118b2a32SPawel Laszczak 		trace_cdnsp_set_stream_ring(cur_ring);
618118b2a32SPawel Laszczak 
6193d829045SPawel Laszczak 		ret = cdnsp_update_stream_mapping(cur_ring);
6203d829045SPawel Laszczak 		if (ret)
6213d829045SPawel Laszczak 			goto cleanup_rings;
6223d829045SPawel Laszczak 	}
6233d829045SPawel Laszczak 
6243d829045SPawel Laszczak 	return 0;
6253d829045SPawel Laszczak 
6263d829045SPawel Laszczak cleanup_rings:
6273d829045SPawel Laszczak 	for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
6283d829045SPawel Laszczak 		cur_ring = stream_info->stream_rings[cur_stream];
6293d829045SPawel Laszczak 		if (cur_ring) {
6303d829045SPawel Laszczak 			cdnsp_ring_free(pdev, cur_ring);
6313d829045SPawel Laszczak 			stream_info->stream_rings[cur_stream] = NULL;
6323d829045SPawel Laszczak 		}
6333d829045SPawel Laszczak 	}
6343d829045SPawel Laszczak 
6353d829045SPawel Laszczak cleanup_stream_rings:
6363d829045SPawel Laszczak 	kfree(pep->stream_info.stream_rings);
6373d829045SPawel Laszczak 
6383d829045SPawel Laszczak 	return -ENOMEM;
6393d829045SPawel Laszczak }
6403d829045SPawel Laszczak 
6413d829045SPawel Laszczak /* Frees all stream contexts associated with the endpoint. */
cdnsp_free_stream_info(struct cdnsp_device * pdev,struct cdnsp_ep * pep)6423d829045SPawel Laszczak static void cdnsp_free_stream_info(struct cdnsp_device *pdev,
6433d829045SPawel Laszczak 				   struct cdnsp_ep *pep)
6443d829045SPawel Laszczak {
6453d829045SPawel Laszczak 	struct cdnsp_stream_info *stream_info = &pep->stream_info;
6463d829045SPawel Laszczak 	struct cdnsp_ring *cur_ring;
6473d829045SPawel Laszczak 	int cur_stream;
6483d829045SPawel Laszczak 
6493d829045SPawel Laszczak 	if (!(pep->ep_state & EP_HAS_STREAMS))
6503d829045SPawel Laszczak 		return;
6513d829045SPawel Laszczak 
6523d829045SPawel Laszczak 	for (cur_stream = 1; cur_stream < stream_info->num_streams;
6533d829045SPawel Laszczak 	     cur_stream++) {
6543d829045SPawel Laszczak 		cur_ring = stream_info->stream_rings[cur_stream];
6553d829045SPawel Laszczak 		if (cur_ring) {
6563d829045SPawel Laszczak 			cdnsp_ring_free(pdev, cur_ring);
6573d829045SPawel Laszczak 			stream_info->stream_rings[cur_stream] = NULL;
6583d829045SPawel Laszczak 		}
6593d829045SPawel Laszczak 	}
6603d829045SPawel Laszczak 
6613d829045SPawel Laszczak 	if (stream_info->stream_ctx_array)
6623d829045SPawel Laszczak 		cdnsp_free_stream_ctx(pdev, pep);
6633d829045SPawel Laszczak 
6643d829045SPawel Laszczak 	kfree(stream_info->stream_rings);
6653d829045SPawel Laszczak 	pep->ep_state &= ~EP_HAS_STREAMS;
6663d829045SPawel Laszczak }
6673d829045SPawel Laszczak 
6683d829045SPawel Laszczak /* All the cdnsp_tds in the ring's TD list should be freed at this point.*/
cdnsp_free_priv_device(struct cdnsp_device * pdev)6693d829045SPawel Laszczak static void cdnsp_free_priv_device(struct cdnsp_device *pdev)
6703d829045SPawel Laszczak {
6713d829045SPawel Laszczak 	pdev->dcbaa->dev_context_ptrs[1] = 0;
6723d829045SPawel Laszczak 
6733d829045SPawel Laszczak 	cdnsp_free_endpoint_rings(pdev, &pdev->eps[0]);
6743d829045SPawel Laszczak 
6753d829045SPawel Laszczak 	if (pdev->in_ctx.bytes)
6763d829045SPawel Laszczak 		dma_pool_free(pdev->device_pool, pdev->in_ctx.bytes,
6773d829045SPawel Laszczak 			      pdev->in_ctx.dma);
6783d829045SPawel Laszczak 
6793d829045SPawel Laszczak 	if (pdev->out_ctx.bytes)
6803d829045SPawel Laszczak 		dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes,
6813d829045SPawel Laszczak 			      pdev->out_ctx.dma);
6823d829045SPawel Laszczak 
6833d829045SPawel Laszczak 	pdev->in_ctx.bytes = NULL;
6843d829045SPawel Laszczak 	pdev->out_ctx.bytes = NULL;
6853d829045SPawel Laszczak }
6863d829045SPawel Laszczak 
cdnsp_alloc_priv_device(struct cdnsp_device * pdev)687dc68ba6cSPawel Laszczak static int cdnsp_alloc_priv_device(struct cdnsp_device *pdev)
6883d829045SPawel Laszczak {
6899ecc3eb0SColin Ian King 	int ret;
6903d829045SPawel Laszczak 
6913d829045SPawel Laszczak 	ret = cdnsp_init_device_ctx(pdev);
6923d829045SPawel Laszczak 	if (ret)
6933d829045SPawel Laszczak 		return ret;
6943d829045SPawel Laszczak 
6953d829045SPawel Laszczak 	/* Allocate endpoint 0 ring. */
696dc68ba6cSPawel Laszczak 	pdev->eps[0].ring = cdnsp_ring_alloc(pdev, 2, TYPE_CTRL, 0, GFP_ATOMIC);
6973d829045SPawel Laszczak 	if (!pdev->eps[0].ring)
6983d829045SPawel Laszczak 		goto fail;
6993d829045SPawel Laszczak 
7003d829045SPawel Laszczak 	/* Point to output device context in dcbaa. */
7013d829045SPawel Laszczak 	pdev->dcbaa->dev_context_ptrs[1] = cpu_to_le64(pdev->out_ctx.dma);
7023d829045SPawel Laszczak 	pdev->cmd.in_ctx = &pdev->in_ctx;
7033d829045SPawel Laszczak 
704118b2a32SPawel Laszczak 	trace_cdnsp_alloc_priv_device(pdev);
7053d829045SPawel Laszczak 	return 0;
7063d829045SPawel Laszczak fail:
7073d829045SPawel Laszczak 	dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes,
7083d829045SPawel Laszczak 		      pdev->out_ctx.dma);
7093d829045SPawel Laszczak 	dma_pool_free(pdev->device_pool, pdev->in_ctx.bytes,
7103d829045SPawel Laszczak 		      pdev->in_ctx.dma);
7113d829045SPawel Laszczak 
7123d829045SPawel Laszczak 	return ret;
7133d829045SPawel Laszczak }
7143d829045SPawel Laszczak 
cdnsp_copy_ep0_dequeue_into_input_ctx(struct cdnsp_device * pdev)7153d829045SPawel Laszczak void cdnsp_copy_ep0_dequeue_into_input_ctx(struct cdnsp_device *pdev)
7163d829045SPawel Laszczak {
7173d829045SPawel Laszczak 	struct cdnsp_ep_ctx *ep0_ctx = pdev->eps[0].in_ctx;
7183d829045SPawel Laszczak 	struct cdnsp_ring *ep_ring = pdev->eps[0].ring;
7193d829045SPawel Laszczak 	dma_addr_t dma;
7203d829045SPawel Laszczak 
7213d829045SPawel Laszczak 	dma = cdnsp_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue);
7223d829045SPawel Laszczak 	ep0_ctx->deq = cpu_to_le64(dma | ep_ring->cycle_state);
7233d829045SPawel Laszczak }
7243d829045SPawel Laszczak 
7253d829045SPawel Laszczak /* Setup an controller private device for a Set Address command. */
cdnsp_setup_addressable_priv_dev(struct cdnsp_device * pdev)7263d829045SPawel Laszczak int cdnsp_setup_addressable_priv_dev(struct cdnsp_device *pdev)
7273d829045SPawel Laszczak {
7283d829045SPawel Laszczak 	struct cdnsp_slot_ctx *slot_ctx;
7293d829045SPawel Laszczak 	struct cdnsp_ep_ctx *ep0_ctx;
7303d829045SPawel Laszczak 	u32 max_packets, port;
7313d829045SPawel Laszczak 
7323d829045SPawel Laszczak 	ep0_ctx = cdnsp_get_ep_ctx(&pdev->in_ctx, 0);
7333d829045SPawel Laszczak 	slot_ctx = cdnsp_get_slot_ctx(&pdev->in_ctx);
7343d829045SPawel Laszczak 
7353d829045SPawel Laszczak 	/* Only the control endpoint is valid - one endpoint context. */
7363d829045SPawel Laszczak 	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
7373d829045SPawel Laszczak 
7383d829045SPawel Laszczak 	switch (pdev->gadget.speed) {
7393d829045SPawel Laszczak 	case USB_SPEED_SUPER_PLUS:
7403d829045SPawel Laszczak 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP);
7413d829045SPawel Laszczak 		max_packets = MAX_PACKET(512);
7423d829045SPawel Laszczak 		break;
7433d829045SPawel Laszczak 	case USB_SPEED_SUPER:
7443d829045SPawel Laszczak 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS);
7453d829045SPawel Laszczak 		max_packets = MAX_PACKET(512);
7463d829045SPawel Laszczak 		break;
7473d829045SPawel Laszczak 	case USB_SPEED_HIGH:
7483d829045SPawel Laszczak 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS);
7493d829045SPawel Laszczak 		max_packets = MAX_PACKET(64);
7503d829045SPawel Laszczak 		break;
7513d829045SPawel Laszczak 	case USB_SPEED_FULL:
7523d829045SPawel Laszczak 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS);
7533d829045SPawel Laszczak 		max_packets = MAX_PACKET(64);
7543d829045SPawel Laszczak 		break;
7553d829045SPawel Laszczak 	default:
7563d829045SPawel Laszczak 		/* Speed was not set , this shouldn't happen. */
7573d829045SPawel Laszczak 		return -EINVAL;
7583d829045SPawel Laszczak 	}
7593d829045SPawel Laszczak 
7603d829045SPawel Laszczak 	port = DEV_PORT(pdev->active_port->port_num);
7613d829045SPawel Laszczak 	slot_ctx->dev_port |= cpu_to_le32(port);
76216e36101SPawel Laszczak 	slot_ctx->dev_state = cpu_to_le32((pdev->device_address &
76316e36101SPawel Laszczak 					   DEV_ADDR_MASK));
76416e36101SPawel Laszczak 	ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(0x8));
7653d829045SPawel Laszczak 	ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP));
7663d829045SPawel Laszczak 	ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3) |
7673d829045SPawel Laszczak 					 max_packets);
7683d829045SPawel Laszczak 
7693d829045SPawel Laszczak 	ep0_ctx->deq = cpu_to_le64(pdev->eps[0].ring->first_seg->dma |
7703d829045SPawel Laszczak 				   pdev->eps[0].ring->cycle_state);
7713d829045SPawel Laszczak 
772118b2a32SPawel Laszczak 	trace_cdnsp_setup_addressable_priv_device(pdev);
773118b2a32SPawel Laszczak 
7743d829045SPawel Laszczak 	return 0;
7753d829045SPawel Laszczak }
7763d829045SPawel Laszczak 
7773d829045SPawel Laszczak /*
7783d829045SPawel Laszczak  * Convert interval expressed as 2^(bInterval - 1) == interval into
7793d829045SPawel Laszczak  * straight exponent value 2^n == interval.
7803d829045SPawel Laszczak  */
cdnsp_parse_exponent_interval(struct usb_gadget * g,struct cdnsp_ep * pep)7813d829045SPawel Laszczak static unsigned int cdnsp_parse_exponent_interval(struct usb_gadget *g,
7823d829045SPawel Laszczak 						  struct cdnsp_ep *pep)
7833d829045SPawel Laszczak {
7843d829045SPawel Laszczak 	unsigned int interval;
7853d829045SPawel Laszczak 
7863d829045SPawel Laszczak 	interval = clamp_val(pep->endpoint.desc->bInterval, 1, 16) - 1;
7873d829045SPawel Laszczak 	if (interval != pep->endpoint.desc->bInterval - 1)
7883d829045SPawel Laszczak 		dev_warn(&g->dev, "ep %s - rounding interval to %d %sframes\n",
7893d829045SPawel Laszczak 			 pep->name, 1 << interval,
7903d829045SPawel Laszczak 			 g->speed == USB_SPEED_FULL ? "" : "micro");
7913d829045SPawel Laszczak 
7923d829045SPawel Laszczak 	/*
7933d829045SPawel Laszczak 	 * Full speed isoc endpoints specify interval in frames,
7943d829045SPawel Laszczak 	 * not microframes. We are using microframes everywhere,
7953d829045SPawel Laszczak 	 * so adjust accordingly.
7963d829045SPawel Laszczak 	 */
7973d829045SPawel Laszczak 	if (g->speed == USB_SPEED_FULL)
7983d829045SPawel Laszczak 		interval += 3;	/* 1 frame = 2^3 uframes */
7993d829045SPawel Laszczak 
8003d829045SPawel Laszczak 	/* Controller handles only up to 512ms (2^12). */
8013d829045SPawel Laszczak 	if (interval > 12)
8023d829045SPawel Laszczak 		interval = 12;
8033d829045SPawel Laszczak 
8043d829045SPawel Laszczak 	return interval;
8053d829045SPawel Laszczak }
8063d829045SPawel Laszczak 
8073d829045SPawel Laszczak /*
8083d829045SPawel Laszczak  * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
8093d829045SPawel Laszczak  * microframes, rounded down to nearest power of 2.
8103d829045SPawel Laszczak  */
cdnsp_microframes_to_exponent(struct usb_gadget * g,struct cdnsp_ep * pep,unsigned int desc_interval,unsigned int min_exponent,unsigned int max_exponent)8113d829045SPawel Laszczak static unsigned int cdnsp_microframes_to_exponent(struct usb_gadget *g,
8123d829045SPawel Laszczak 						  struct cdnsp_ep *pep,
8133d829045SPawel Laszczak 						  unsigned int desc_interval,
8143d829045SPawel Laszczak 						  unsigned int min_exponent,
8153d829045SPawel Laszczak 						  unsigned int max_exponent)
8163d829045SPawel Laszczak {
8173d829045SPawel Laszczak 	unsigned int interval;
8183d829045SPawel Laszczak 
8193d829045SPawel Laszczak 	interval = fls(desc_interval) - 1;
8203d829045SPawel Laszczak 	return clamp_val(interval, min_exponent, max_exponent);
8213d829045SPawel Laszczak }
8223d829045SPawel Laszczak 
8233d829045SPawel Laszczak /*
8243d829045SPawel Laszczak  * Return the polling interval.
8253d829045SPawel Laszczak  *
8263d829045SPawel Laszczak  * The polling interval is expressed in "microframes". If controllers's Interval
8273d829045SPawel Laszczak  * field is set to N, it will service the endpoint every 2^(Interval)*125us.
8283d829045SPawel Laszczak  */
cdnsp_get_endpoint_interval(struct usb_gadget * g,struct cdnsp_ep * pep)8293d829045SPawel Laszczak static unsigned int cdnsp_get_endpoint_interval(struct usb_gadget *g,
8303d829045SPawel Laszczak 						struct cdnsp_ep *pep)
8313d829045SPawel Laszczak {
8323d829045SPawel Laszczak 	unsigned int interval = 0;
8333d829045SPawel Laszczak 
8343d829045SPawel Laszczak 	switch (g->speed) {
8353d829045SPawel Laszczak 	case USB_SPEED_HIGH:
8363d829045SPawel Laszczak 	case USB_SPEED_SUPER_PLUS:
8373d829045SPawel Laszczak 	case USB_SPEED_SUPER:
8383d829045SPawel Laszczak 		if (usb_endpoint_xfer_int(pep->endpoint.desc) ||
8393d829045SPawel Laszczak 		    usb_endpoint_xfer_isoc(pep->endpoint.desc))
8403d829045SPawel Laszczak 			interval = cdnsp_parse_exponent_interval(g, pep);
8413d829045SPawel Laszczak 		break;
8423d829045SPawel Laszczak 	case USB_SPEED_FULL:
8433d829045SPawel Laszczak 		if (usb_endpoint_xfer_isoc(pep->endpoint.desc)) {
8443d829045SPawel Laszczak 			interval = cdnsp_parse_exponent_interval(g, pep);
8453d829045SPawel Laszczak 		} else if (usb_endpoint_xfer_int(pep->endpoint.desc)) {
8463d829045SPawel Laszczak 			interval = pep->endpoint.desc->bInterval << 3;
8473d829045SPawel Laszczak 			interval = cdnsp_microframes_to_exponent(g, pep,
8483d829045SPawel Laszczak 								 interval,
8493d829045SPawel Laszczak 								 3, 10);
8503d829045SPawel Laszczak 		}
8513d829045SPawel Laszczak 
8523d829045SPawel Laszczak 		break;
8533d829045SPawel Laszczak 	default:
8543d829045SPawel Laszczak 		WARN_ON(1);
8553d829045SPawel Laszczak 	}
8563d829045SPawel Laszczak 
8573d829045SPawel Laszczak 	return interval;
8583d829045SPawel Laszczak }
8593d829045SPawel Laszczak 
8603d829045SPawel Laszczak /*
8613d829045SPawel Laszczak  * The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
8623d829045SPawel Laszczak  * High speed endpoint descriptors can define "the number of additional
8633d829045SPawel Laszczak  * transaction opportunities per microframe", but that goes in the Max Burst
8643d829045SPawel Laszczak  * endpoint context field.
8653d829045SPawel Laszczak  */
cdnsp_get_endpoint_mult(struct usb_gadget * g,struct cdnsp_ep * pep)8663d829045SPawel Laszczak static u32 cdnsp_get_endpoint_mult(struct usb_gadget *g, struct cdnsp_ep *pep)
8673d829045SPawel Laszczak {
8683d829045SPawel Laszczak 	if (g->speed < USB_SPEED_SUPER ||
8693d829045SPawel Laszczak 	    !usb_endpoint_xfer_isoc(pep->endpoint.desc))
8703d829045SPawel Laszczak 		return 0;
8713d829045SPawel Laszczak 
8723d829045SPawel Laszczak 	return pep->endpoint.comp_desc->bmAttributes;
8733d829045SPawel Laszczak }
8743d829045SPawel Laszczak 
cdnsp_get_endpoint_max_burst(struct usb_gadget * g,struct cdnsp_ep * pep)8753d829045SPawel Laszczak static u32 cdnsp_get_endpoint_max_burst(struct usb_gadget *g,
8763d829045SPawel Laszczak 					struct cdnsp_ep *pep)
8773d829045SPawel Laszczak {
8783d829045SPawel Laszczak 	/* Super speed and Plus have max burst in ep companion desc */
8793d829045SPawel Laszczak 	if (g->speed >= USB_SPEED_SUPER)
8803d829045SPawel Laszczak 		return pep->endpoint.comp_desc->bMaxBurst;
8813d829045SPawel Laszczak 
8823d829045SPawel Laszczak 	if (g->speed == USB_SPEED_HIGH &&
8833d829045SPawel Laszczak 	    (usb_endpoint_xfer_isoc(pep->endpoint.desc) ||
8843d829045SPawel Laszczak 	     usb_endpoint_xfer_int(pep->endpoint.desc)))
885e9ab75f2SChunfeng Yun 		return usb_endpoint_maxp_mult(pep->endpoint.desc) - 1;
8863d829045SPawel Laszczak 
8873d829045SPawel Laszczak 	return 0;
8883d829045SPawel Laszczak }
8893d829045SPawel Laszczak 
cdnsp_get_endpoint_type(const struct usb_endpoint_descriptor * desc)8903d829045SPawel Laszczak static u32 cdnsp_get_endpoint_type(const struct usb_endpoint_descriptor *desc)
8913d829045SPawel Laszczak {
8923d829045SPawel Laszczak 	int in;
8933d829045SPawel Laszczak 
8943d829045SPawel Laszczak 	in = usb_endpoint_dir_in(desc);
8953d829045SPawel Laszczak 
8963d829045SPawel Laszczak 	switch (usb_endpoint_type(desc)) {
8973d829045SPawel Laszczak 	case USB_ENDPOINT_XFER_CONTROL:
8983d829045SPawel Laszczak 		return CTRL_EP;
8993d829045SPawel Laszczak 	case USB_ENDPOINT_XFER_BULK:
9003d829045SPawel Laszczak 		return in ? BULK_IN_EP : BULK_OUT_EP;
9013d829045SPawel Laszczak 	case USB_ENDPOINT_XFER_ISOC:
9023d829045SPawel Laszczak 		return in ? ISOC_IN_EP : ISOC_OUT_EP;
9033d829045SPawel Laszczak 	case USB_ENDPOINT_XFER_INT:
9043d829045SPawel Laszczak 		return in ? INT_IN_EP : INT_OUT_EP;
9053d829045SPawel Laszczak 	}
9063d829045SPawel Laszczak 
9073d829045SPawel Laszczak 	return 0;
9083d829045SPawel Laszczak }
9093d829045SPawel Laszczak 
9103d829045SPawel Laszczak /*
9113d829045SPawel Laszczak  * Return the maximum endpoint service interval time (ESIT) payload.
9123d829045SPawel Laszczak  * Basically, this is the maxpacket size, multiplied by the burst size
9133d829045SPawel Laszczak  * and mult size.
9143d829045SPawel Laszczak  */
cdnsp_get_max_esit_payload(struct usb_gadget * g,struct cdnsp_ep * pep)9153d829045SPawel Laszczak static u32 cdnsp_get_max_esit_payload(struct usb_gadget *g,
9163d829045SPawel Laszczak 				      struct cdnsp_ep *pep)
9173d829045SPawel Laszczak {
9183d829045SPawel Laszczak 	int max_packet;
9193d829045SPawel Laszczak 	int max_burst;
9203d829045SPawel Laszczak 
9213d829045SPawel Laszczak 	/* Only applies for interrupt or isochronous endpoints*/
9223d829045SPawel Laszczak 	if (usb_endpoint_xfer_control(pep->endpoint.desc) ||
9233d829045SPawel Laszczak 	    usb_endpoint_xfer_bulk(pep->endpoint.desc))
9243d829045SPawel Laszczak 		return 0;
9253d829045SPawel Laszczak 
9263d829045SPawel Laszczak 	/* SuperSpeedPlus Isoc ep sending over 48k per EIST. */
9273d829045SPawel Laszczak 	if (g->speed >= USB_SPEED_SUPER_PLUS &&
9283d829045SPawel Laszczak 	    USB_SS_SSP_ISOC_COMP(pep->endpoint.desc->bmAttributes))
92916e36101SPawel Laszczak 		return le16_to_cpu(pep->endpoint.comp_desc->wBytesPerInterval);
9303d829045SPawel Laszczak 	/* SuperSpeed or SuperSpeedPlus Isoc ep with less than 48k per esit */
9313d829045SPawel Laszczak 	else if (g->speed >= USB_SPEED_SUPER)
9323d829045SPawel Laszczak 		return le16_to_cpu(pep->endpoint.comp_desc->wBytesPerInterval);
9333d829045SPawel Laszczak 
9343d829045SPawel Laszczak 	max_packet = usb_endpoint_maxp(pep->endpoint.desc);
9353d829045SPawel Laszczak 	max_burst = usb_endpoint_maxp_mult(pep->endpoint.desc);
9363d829045SPawel Laszczak 
9373d829045SPawel Laszczak 	/* A 0 in max burst means 1 transfer per ESIT */
9383d829045SPawel Laszczak 	return max_packet * max_burst;
9393d829045SPawel Laszczak }
9403d829045SPawel Laszczak 
cdnsp_endpoint_init(struct cdnsp_device * pdev,struct cdnsp_ep * pep,gfp_t mem_flags)9413d829045SPawel Laszczak int cdnsp_endpoint_init(struct cdnsp_device *pdev,
9423d829045SPawel Laszczak 			struct cdnsp_ep *pep,
9433d829045SPawel Laszczak 			gfp_t mem_flags)
9443d829045SPawel Laszczak {
9453d829045SPawel Laszczak 	enum cdnsp_ring_type ring_type;
9463d829045SPawel Laszczak 	struct cdnsp_ep_ctx *ep_ctx;
9473d829045SPawel Laszczak 	unsigned int err_count = 0;
9483d829045SPawel Laszczak 	unsigned int avg_trb_len;
9493d829045SPawel Laszczak 	unsigned int max_packet;
9503d829045SPawel Laszczak 	unsigned int max_burst;
9513d829045SPawel Laszczak 	unsigned int interval;
9523d829045SPawel Laszczak 	u32 max_esit_payload;
9533d829045SPawel Laszczak 	unsigned int mult;
9543d829045SPawel Laszczak 	u32 endpoint_type;
9553d829045SPawel Laszczak 	int ret;
9563d829045SPawel Laszczak 
9573d829045SPawel Laszczak 	ep_ctx = pep->in_ctx;
9583d829045SPawel Laszczak 
9593d829045SPawel Laszczak 	endpoint_type = cdnsp_get_endpoint_type(pep->endpoint.desc);
9603d829045SPawel Laszczak 	if (!endpoint_type)
9613d829045SPawel Laszczak 		return -EINVAL;
9623d829045SPawel Laszczak 
9633d829045SPawel Laszczak 	ring_type = usb_endpoint_type(pep->endpoint.desc);
9643d829045SPawel Laszczak 
9653d829045SPawel Laszczak 	/*
9663d829045SPawel Laszczak 	 * Get values to fill the endpoint context, mostly from ep descriptor.
9673d829045SPawel Laszczak 	 * The average TRB buffer length for bulk endpoints is unclear as we
9683d829045SPawel Laszczak 	 * have no clue on scatter gather list entry size. For Isoc and Int,
9693d829045SPawel Laszczak 	 * set it to max available.
9703d829045SPawel Laszczak 	 */
9713d829045SPawel Laszczak 	max_esit_payload = cdnsp_get_max_esit_payload(&pdev->gadget, pep);
9723d829045SPawel Laszczak 	interval = cdnsp_get_endpoint_interval(&pdev->gadget, pep);
9733d829045SPawel Laszczak 	mult = cdnsp_get_endpoint_mult(&pdev->gadget, pep);
9743d829045SPawel Laszczak 	max_packet = usb_endpoint_maxp(pep->endpoint.desc);
9753d829045SPawel Laszczak 	max_burst = cdnsp_get_endpoint_max_burst(&pdev->gadget, pep);
9763d829045SPawel Laszczak 	avg_trb_len = max_esit_payload;
9773d829045SPawel Laszczak 
9783d829045SPawel Laszczak 	/* Allow 3 retries for everything but isoc, set CErr = 3. */
9793d829045SPawel Laszczak 	if (!usb_endpoint_xfer_isoc(pep->endpoint.desc))
9803d829045SPawel Laszczak 		err_count = 3;
9813d829045SPawel Laszczak 	if (usb_endpoint_xfer_bulk(pep->endpoint.desc) &&
9823d829045SPawel Laszczak 	    pdev->gadget.speed == USB_SPEED_HIGH)
9833d829045SPawel Laszczak 		max_packet = 512;
9843d829045SPawel Laszczak 	/* Controller spec indicates that ctrl ep avg TRB Length should be 8. */
9853d829045SPawel Laszczak 	if (usb_endpoint_xfer_control(pep->endpoint.desc))
9863d829045SPawel Laszczak 		avg_trb_len = 8;
9873d829045SPawel Laszczak 
9883d829045SPawel Laszczak 	/* Set up the endpoint ring. */
9893d829045SPawel Laszczak 	pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags);
990*7d94bc8eSZhou Qingyang 	if (!pep->ring)
991*7d94bc8eSZhou Qingyang 		return -ENOMEM;
992*7d94bc8eSZhou Qingyang 
9933d829045SPawel Laszczak 	pep->skip = false;
9943d829045SPawel Laszczak 
9953d829045SPawel Laszczak 	/* Fill the endpoint context */
9963d829045SPawel Laszczak 	ep_ctx->ep_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) |
9973d829045SPawel Laszczak 				EP_INTERVAL(interval) | EP_MULT(mult));
9983d829045SPawel Laszczak 	ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) |
9993d829045SPawel Laszczak 				MAX_PACKET(max_packet) | MAX_BURST(max_burst) |
10003d829045SPawel Laszczak 				ERROR_COUNT(err_count));
10013d829045SPawel Laszczak 	ep_ctx->deq = cpu_to_le64(pep->ring->first_seg->dma |
10023d829045SPawel Laszczak 				  pep->ring->cycle_state);
10033d829045SPawel Laszczak 
10043d829045SPawel Laszczak 	ep_ctx->tx_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_LO(max_esit_payload) |
10053d829045SPawel Laszczak 				EP_AVG_TRB_LENGTH(avg_trb_len));
10063d829045SPawel Laszczak 
10073d829045SPawel Laszczak 	if (usb_endpoint_xfer_bulk(pep->endpoint.desc) &&
10083d829045SPawel Laszczak 	    pdev->gadget.speed > USB_SPEED_HIGH) {
10093d829045SPawel Laszczak 		ret = cdnsp_alloc_streams(pdev, pep);
10103d829045SPawel Laszczak 		if (ret < 0)
10113d829045SPawel Laszczak 			return ret;
10123d829045SPawel Laszczak 	}
10133d829045SPawel Laszczak 
10143d829045SPawel Laszczak 	return 0;
10153d829045SPawel Laszczak }
10163d829045SPawel Laszczak 
cdnsp_endpoint_zero(struct cdnsp_device * pdev,struct cdnsp_ep * pep)10173d829045SPawel Laszczak void cdnsp_endpoint_zero(struct cdnsp_device *pdev, struct cdnsp_ep *pep)
10183d829045SPawel Laszczak {
10193d829045SPawel Laszczak 	pep->in_ctx->ep_info = 0;
10203d829045SPawel Laszczak 	pep->in_ctx->ep_info2 = 0;
10213d829045SPawel Laszczak 	pep->in_ctx->deq = 0;
10223d829045SPawel Laszczak 	pep->in_ctx->tx_info = 0;
10233d829045SPawel Laszczak }
10243d829045SPawel Laszczak 
cdnsp_alloc_erst(struct cdnsp_device * pdev,struct cdnsp_ring * evt_ring,struct cdnsp_erst * erst)10253d829045SPawel Laszczak static int cdnsp_alloc_erst(struct cdnsp_device *pdev,
10263d829045SPawel Laszczak 			    struct cdnsp_ring *evt_ring,
1027dc68ba6cSPawel Laszczak 			    struct cdnsp_erst *erst)
10283d829045SPawel Laszczak {
10293d829045SPawel Laszczak 	struct cdnsp_erst_entry *entry;
10303d829045SPawel Laszczak 	struct cdnsp_segment *seg;
10313d829045SPawel Laszczak 	unsigned int val;
10323d829045SPawel Laszczak 	size_t size;
10333d829045SPawel Laszczak 
10343d829045SPawel Laszczak 	size = sizeof(struct cdnsp_erst_entry) * evt_ring->num_segs;
10353d829045SPawel Laszczak 	erst->entries = dma_alloc_coherent(pdev->dev, size,
1036dc68ba6cSPawel Laszczak 					   &erst->erst_dma_addr, GFP_KERNEL);
10373d829045SPawel Laszczak 	if (!erst->entries)
10383d829045SPawel Laszczak 		return -ENOMEM;
10393d829045SPawel Laszczak 
10403d829045SPawel Laszczak 	erst->num_entries = evt_ring->num_segs;
10413d829045SPawel Laszczak 
10423d829045SPawel Laszczak 	seg = evt_ring->first_seg;
10433d829045SPawel Laszczak 	for (val = 0; val < evt_ring->num_segs; val++) {
10443d829045SPawel Laszczak 		entry = &erst->entries[val];
10453d829045SPawel Laszczak 		entry->seg_addr = cpu_to_le64(seg->dma);
10463d829045SPawel Laszczak 		entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
10473d829045SPawel Laszczak 		entry->rsvd = 0;
10483d829045SPawel Laszczak 		seg = seg->next;
10493d829045SPawel Laszczak 	}
10503d829045SPawel Laszczak 
10513d829045SPawel Laszczak 	return 0;
10523d829045SPawel Laszczak }
10533d829045SPawel Laszczak 
cdnsp_free_erst(struct cdnsp_device * pdev,struct cdnsp_erst * erst)10543d829045SPawel Laszczak static void cdnsp_free_erst(struct cdnsp_device *pdev, struct cdnsp_erst *erst)
10553d829045SPawel Laszczak {
10563d829045SPawel Laszczak 	size_t size = sizeof(struct cdnsp_erst_entry) * (erst->num_entries);
10573d829045SPawel Laszczak 	struct device *dev = pdev->dev;
10583d829045SPawel Laszczak 
10593d829045SPawel Laszczak 	if (erst->entries)
10603d829045SPawel Laszczak 		dma_free_coherent(dev, size, erst->entries,
10613d829045SPawel Laszczak 				  erst->erst_dma_addr);
10623d829045SPawel Laszczak 
10633d829045SPawel Laszczak 	erst->entries = NULL;
10643d829045SPawel Laszczak }
10653d829045SPawel Laszczak 
cdnsp_mem_cleanup(struct cdnsp_device * pdev)10663d829045SPawel Laszczak void cdnsp_mem_cleanup(struct cdnsp_device *pdev)
10673d829045SPawel Laszczak {
10683d829045SPawel Laszczak 	struct device *dev = pdev->dev;
10693d829045SPawel Laszczak 
10703d829045SPawel Laszczak 	cdnsp_free_priv_device(pdev);
10713d829045SPawel Laszczak 	cdnsp_free_erst(pdev, &pdev->erst);
10723d829045SPawel Laszczak 
10733d829045SPawel Laszczak 	if (pdev->event_ring)
10743d829045SPawel Laszczak 		cdnsp_ring_free(pdev, pdev->event_ring);
10753d829045SPawel Laszczak 
10763d829045SPawel Laszczak 	pdev->event_ring = NULL;
10773d829045SPawel Laszczak 
10783d829045SPawel Laszczak 	if (pdev->cmd_ring)
10793d829045SPawel Laszczak 		cdnsp_ring_free(pdev, pdev->cmd_ring);
10803d829045SPawel Laszczak 
10813d829045SPawel Laszczak 	pdev->cmd_ring = NULL;
10823d829045SPawel Laszczak 
10833d829045SPawel Laszczak 	dma_pool_destroy(pdev->segment_pool);
10843d829045SPawel Laszczak 	pdev->segment_pool = NULL;
10853d829045SPawel Laszczak 	dma_pool_destroy(pdev->device_pool);
10863d829045SPawel Laszczak 	pdev->device_pool = NULL;
10873d829045SPawel Laszczak 
10883d829045SPawel Laszczak 	dma_free_coherent(dev, sizeof(*pdev->dcbaa),
10893d829045SPawel Laszczak 			  pdev->dcbaa, pdev->dcbaa->dma);
10903d829045SPawel Laszczak 
10913d829045SPawel Laszczak 	pdev->dcbaa = NULL;
10923d829045SPawel Laszczak 
10933d829045SPawel Laszczak 	pdev->usb2_port.exist = 0;
10943d829045SPawel Laszczak 	pdev->usb3_port.exist = 0;
10953d829045SPawel Laszczak 	pdev->usb2_port.port_num = 0;
10963d829045SPawel Laszczak 	pdev->usb3_port.port_num = 0;
10973d829045SPawel Laszczak 	pdev->active_port = NULL;
10983d829045SPawel Laszczak }
10993d829045SPawel Laszczak 
cdnsp_set_event_deq(struct cdnsp_device * pdev)11003d829045SPawel Laszczak static void cdnsp_set_event_deq(struct cdnsp_device *pdev)
11013d829045SPawel Laszczak {
11023d829045SPawel Laszczak 	dma_addr_t deq;
11033d829045SPawel Laszczak 	u64 temp;
11043d829045SPawel Laszczak 
11053d829045SPawel Laszczak 	deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg,
11063d829045SPawel Laszczak 				    pdev->event_ring->dequeue);
11073d829045SPawel Laszczak 
11083d829045SPawel Laszczak 	/* Update controller event ring dequeue pointer */
11093d829045SPawel Laszczak 	temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue);
11103d829045SPawel Laszczak 	temp &= ERST_PTR_MASK;
11113d829045SPawel Laszczak 
11123d829045SPawel Laszczak 	/*
11133d829045SPawel Laszczak 	 * Don't clear the EHB bit (which is RW1C) because
11143d829045SPawel Laszczak 	 * there might be more events to service.
11153d829045SPawel Laszczak 	 */
11163d829045SPawel Laszczak 	temp &= ~ERST_EHB;
11173d829045SPawel Laszczak 
11183d829045SPawel Laszczak 	cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp,
11193d829045SPawel Laszczak 		       &pdev->ir_set->erst_dequeue);
11203d829045SPawel Laszczak }
11213d829045SPawel Laszczak 
cdnsp_add_in_port(struct cdnsp_device * pdev,struct cdnsp_port * port,__le32 __iomem * addr)11223d829045SPawel Laszczak static void cdnsp_add_in_port(struct cdnsp_device *pdev,
11233d829045SPawel Laszczak 			      struct cdnsp_port *port,
11243d829045SPawel Laszczak 			      __le32 __iomem *addr)
11253d829045SPawel Laszczak {
1126118b2a32SPawel Laszczak 	u32 temp, port_offset, port_count;
11273d829045SPawel Laszczak 
11283d829045SPawel Laszczak 	temp = readl(addr);
11293d829045SPawel Laszczak 	port->maj_rev = CDNSP_EXT_PORT_MAJOR(temp);
11303d829045SPawel Laszczak 	port->min_rev = CDNSP_EXT_PORT_MINOR(temp);
11313d829045SPawel Laszczak 
11323d829045SPawel Laszczak 	/* Port offset and count in the third dword.*/
11333d829045SPawel Laszczak 	temp = readl(addr + 2);
11343d829045SPawel Laszczak 	port_offset = CDNSP_EXT_PORT_OFF(temp);
1135118b2a32SPawel Laszczak 	port_count = CDNSP_EXT_PORT_COUNT(temp);
1136118b2a32SPawel Laszczak 
1137118b2a32SPawel Laszczak 	trace_cdnsp_port_info(addr, port_offset, port_count, port->maj_rev);
11383d829045SPawel Laszczak 
11393d829045SPawel Laszczak 	port->port_num = port_offset;
11403d829045SPawel Laszczak 	port->exist = 1;
11413d829045SPawel Laszczak }
11423d829045SPawel Laszczak 
11433d829045SPawel Laszczak /*
11443d829045SPawel Laszczak  * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that
11453d829045SPawel Laszczak  * specify what speeds each port is supposed to be.
11463d829045SPawel Laszczak  */
cdnsp_setup_port_arrays(struct cdnsp_device * pdev)1147dc68ba6cSPawel Laszczak static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
11483d829045SPawel Laszczak {
11493d829045SPawel Laszczak 	void __iomem *base;
11503d829045SPawel Laszczak 	u32 offset;
11513d829045SPawel Laszczak 	int i;
11523d829045SPawel Laszczak 
11533d829045SPawel Laszczak 	base = &pdev->cap_regs->hc_capbase;
11543d829045SPawel Laszczak 	offset = cdnsp_find_next_ext_cap(base, 0,
11553d829045SPawel Laszczak 					 EXT_CAP_CFG_DEV_20PORT_CAP_ID);
11563d829045SPawel Laszczak 	pdev->port20_regs = base + offset;
11573d829045SPawel Laszczak 
11583d829045SPawel Laszczak 	offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
11593d829045SPawel Laszczak 	pdev->port3x_regs =  base + offset;
11603d829045SPawel Laszczak 
11613d829045SPawel Laszczak 	offset = 0;
11623d829045SPawel Laszczak 	base = &pdev->cap_regs->hc_capbase;
11633d829045SPawel Laszczak 
11643d829045SPawel Laszczak 	/* Driver expects max 2 extended protocol capability. */
11653d829045SPawel Laszczak 	for (i = 0; i < 2; i++) {
11663d829045SPawel Laszczak 		u32 temp;
11673d829045SPawel Laszczak 
11683d829045SPawel Laszczak 		offset = cdnsp_find_next_ext_cap(base, offset,
11693d829045SPawel Laszczak 						 EXT_CAPS_PROTOCOL);
11703d829045SPawel Laszczak 		temp = readl(base + offset);
11713d829045SPawel Laszczak 
11723d829045SPawel Laszczak 		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x03 &&
11733d829045SPawel Laszczak 		    !pdev->usb3_port.port_num)
11743d829045SPawel Laszczak 			cdnsp_add_in_port(pdev, &pdev->usb3_port,
11753d829045SPawel Laszczak 					  base + offset);
11763d829045SPawel Laszczak 
11773d829045SPawel Laszczak 		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02 &&
11783d829045SPawel Laszczak 		    !pdev->usb2_port.port_num)
11793d829045SPawel Laszczak 			cdnsp_add_in_port(pdev, &pdev->usb2_port,
11803d829045SPawel Laszczak 					  base + offset);
11813d829045SPawel Laszczak 	}
11823d829045SPawel Laszczak 
11833d829045SPawel Laszczak 	if (!pdev->usb2_port.exist || !pdev->usb3_port.exist) {
11843d829045SPawel Laszczak 		dev_err(pdev->dev, "Error: Only one port detected\n");
11853d829045SPawel Laszczak 		return -ENODEV;
11863d829045SPawel Laszczak 	}
11873d829045SPawel Laszczak 
1188118b2a32SPawel Laszczak 	trace_cdnsp_init("Found USB 2.0 ports and  USB 3.0 ports.");
1189118b2a32SPawel Laszczak 
119016e36101SPawel Laszczak 	pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
11913d829045SPawel Laszczak 			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
11923d829045SPawel Laszczak 				(pdev->usb2_port.port_num - 1));
11933d829045SPawel Laszczak 
119416e36101SPawel Laszczak 	pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
11953d829045SPawel Laszczak 			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
11963d829045SPawel Laszczak 				(pdev->usb3_port.port_num - 1));
11973d829045SPawel Laszczak 
11983d829045SPawel Laszczak 	return 0;
11993d829045SPawel Laszczak }
12003d829045SPawel Laszczak 
12013d829045SPawel Laszczak /*
12023d829045SPawel Laszczak  * Initialize memory for CDNSP (one-time init).
12033d829045SPawel Laszczak  *
12043d829045SPawel Laszczak  * Program the PAGESIZE register, initialize the device context array, create
12053d829045SPawel Laszczak  * device contexts, set up a command ring segment, create event
12063d829045SPawel Laszczak  * ring (one for now).
12073d829045SPawel Laszczak  */
cdnsp_mem_init(struct cdnsp_device * pdev)1208dc68ba6cSPawel Laszczak int cdnsp_mem_init(struct cdnsp_device *pdev)
12093d829045SPawel Laszczak {
12103d829045SPawel Laszczak 	struct device *dev = pdev->dev;
12113d829045SPawel Laszczak 	int ret = -ENOMEM;
12123d829045SPawel Laszczak 	unsigned int val;
12133d829045SPawel Laszczak 	dma_addr_t dma;
12143d829045SPawel Laszczak 	u32 page_size;
12153d829045SPawel Laszczak 	u64 val_64;
12163d829045SPawel Laszczak 
12173d829045SPawel Laszczak 	/*
12183d829045SPawel Laszczak 	 * Use 4K pages, since that's common and the minimum the
12193d829045SPawel Laszczak 	 * controller supports
12203d829045SPawel Laszczak 	 */
12213d829045SPawel Laszczak 	page_size = 1 << 12;
12223d829045SPawel Laszczak 
12233d829045SPawel Laszczak 	val = readl(&pdev->op_regs->config_reg);
12243d829045SPawel Laszczak 	val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E;
12253d829045SPawel Laszczak 	writel(val, &pdev->op_regs->config_reg);
12263d829045SPawel Laszczak 
12273d829045SPawel Laszczak 	/*
12283d829045SPawel Laszczak 	 * Doorbell array must be physically contiguous
12293d829045SPawel Laszczak 	 * and 64-byte (cache line) aligned.
12303d829045SPawel Laszczak 	 */
12313d829045SPawel Laszczak 	pdev->dcbaa = dma_alloc_coherent(dev, sizeof(*pdev->dcbaa),
12323d829045SPawel Laszczak 					 &dma, GFP_KERNEL);
12333d829045SPawel Laszczak 	if (!pdev->dcbaa)
1234e2d60f8cSPawel Laszczak 		return -ENOMEM;
12353d829045SPawel Laszczak 
12363d829045SPawel Laszczak 	pdev->dcbaa->dma = dma;
12373d829045SPawel Laszczak 
12383d829045SPawel Laszczak 	cdnsp_write_64(dma, &pdev->op_regs->dcbaa_ptr);
12393d829045SPawel Laszczak 
12403d829045SPawel Laszczak 	/*
12413d829045SPawel Laszczak 	 * Initialize the ring segment pool.  The ring must be a contiguous
12423d829045SPawel Laszczak 	 * structure comprised of TRBs. The TRBs must be 16 byte aligned,
12433d829045SPawel Laszczak 	 * however, the command ring segment needs 64-byte aligned segments
12443d829045SPawel Laszczak 	 * and our use of dma addresses in the trb_address_map radix tree needs
12453d829045SPawel Laszczak 	 * TRB_SEGMENT_SIZE alignment, so driver pick the greater alignment
12463d829045SPawel Laszczak 	 * need.
12473d829045SPawel Laszczak 	 */
12483d829045SPawel Laszczak 	pdev->segment_pool = dma_pool_create("CDNSP ring segments", dev,
12493d829045SPawel Laszczak 					     TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE,
12503d829045SPawel Laszczak 					     page_size);
1251e2d60f8cSPawel Laszczak 	if (!pdev->segment_pool)
1252e2d60f8cSPawel Laszczak 		goto release_dcbaa;
12533d829045SPawel Laszczak 
12543d829045SPawel Laszczak 	pdev->device_pool = dma_pool_create("CDNSP input/output contexts", dev,
12553d829045SPawel Laszczak 					    CDNSP_CTX_SIZE, 64, page_size);
1256e2d60f8cSPawel Laszczak 	if (!pdev->device_pool)
1257e2d60f8cSPawel Laszczak 		goto destroy_segment_pool;
12583d829045SPawel Laszczak 
12593d829045SPawel Laszczak 
12603d829045SPawel Laszczak 	/* Set up the command ring to have one segments for now. */
1261dc68ba6cSPawel Laszczak 	pdev->cmd_ring = cdnsp_ring_alloc(pdev, 1, TYPE_COMMAND, 0, GFP_KERNEL);
12623d829045SPawel Laszczak 	if (!pdev->cmd_ring)
1263e2d60f8cSPawel Laszczak 		goto destroy_device_pool;
12643d829045SPawel Laszczak 
12653d829045SPawel Laszczak 	/* Set the address in the Command Ring Control register */
12663d829045SPawel Laszczak 	val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring);
12673d829045SPawel Laszczak 	val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) |
12683d829045SPawel Laszczak 		 (pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) |
12693d829045SPawel Laszczak 		 pdev->cmd_ring->cycle_state;
12703d829045SPawel Laszczak 	cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring);
12713d829045SPawel Laszczak 
12723d829045SPawel Laszczak 	val = readl(&pdev->cap_regs->db_off);
12733d829045SPawel Laszczak 	val &= DBOFF_MASK;
12743d829045SPawel Laszczak 	pdev->dba = (void __iomem *)pdev->cap_regs + val;
12753d829045SPawel Laszczak 
12763d829045SPawel Laszczak 	/* Set ir_set to interrupt register set 0 */
12773d829045SPawel Laszczak 	pdev->ir_set = &pdev->run_regs->ir_set[0];
12783d829045SPawel Laszczak 
12793d829045SPawel Laszczak 	/*
12803d829045SPawel Laszczak 	 * Event ring setup: Allocate a normal ring, but also setup
12813d829045SPawel Laszczak 	 * the event ring segment table (ERST).
12823d829045SPawel Laszczak 	 */
12833d829045SPawel Laszczak 	pdev->event_ring = cdnsp_ring_alloc(pdev, ERST_NUM_SEGS, TYPE_EVENT,
1284dc68ba6cSPawel Laszczak 					    0, GFP_KERNEL);
12853d829045SPawel Laszczak 	if (!pdev->event_ring)
1286e2d60f8cSPawel Laszczak 		goto free_cmd_ring;
12873d829045SPawel Laszczak 
1288dc68ba6cSPawel Laszczak 	ret = cdnsp_alloc_erst(pdev, pdev->event_ring, &pdev->erst);
12893d829045SPawel Laszczak 	if (ret)
1290e2d60f8cSPawel Laszczak 		goto free_event_ring;
12913d829045SPawel Laszczak 
12923d829045SPawel Laszczak 	/* Set ERST count with the number of entries in the segment table. */
12933d829045SPawel Laszczak 	val = readl(&pdev->ir_set->erst_size);
12943d829045SPawel Laszczak 	val &= ERST_SIZE_MASK;
12953d829045SPawel Laszczak 	val |= ERST_NUM_SEGS;
12963d829045SPawel Laszczak 	writel(val, &pdev->ir_set->erst_size);
12973d829045SPawel Laszczak 
12983d829045SPawel Laszczak 	/* Set the segment table base address. */
12993d829045SPawel Laszczak 	val_64 = cdnsp_read_64(&pdev->ir_set->erst_base);
13003d829045SPawel Laszczak 	val_64 &= ERST_PTR_MASK;
13013d829045SPawel Laszczak 	val_64 |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK);
13023d829045SPawel Laszczak 	cdnsp_write_64(val_64, &pdev->ir_set->erst_base);
13033d829045SPawel Laszczak 
13043d829045SPawel Laszczak 	/* Set the event ring dequeue address. */
13053d829045SPawel Laszczak 	cdnsp_set_event_deq(pdev);
13063d829045SPawel Laszczak 
1307dc68ba6cSPawel Laszczak 	ret = cdnsp_setup_port_arrays(pdev);
13083d829045SPawel Laszczak 	if (ret)
1309e2d60f8cSPawel Laszczak 		goto free_erst;
13103d829045SPawel Laszczak 
1311dc68ba6cSPawel Laszczak 	ret = cdnsp_alloc_priv_device(pdev);
13123d829045SPawel Laszczak 	if (ret) {
13133d829045SPawel Laszczak 		dev_err(pdev->dev,
13143d829045SPawel Laszczak 			"Could not allocate cdnsp_device data structures\n");
1315e2d60f8cSPawel Laszczak 		goto free_erst;
13163d829045SPawel Laszczak 	}
13173d829045SPawel Laszczak 
13183d829045SPawel Laszczak 	return 0;
13193d829045SPawel Laszczak 
1320e2d60f8cSPawel Laszczak free_erst:
1321e2d60f8cSPawel Laszczak 	cdnsp_free_erst(pdev, &pdev->erst);
1322e2d60f8cSPawel Laszczak free_event_ring:
1323e2d60f8cSPawel Laszczak 	cdnsp_ring_free(pdev, pdev->event_ring);
1324e2d60f8cSPawel Laszczak free_cmd_ring:
1325e2d60f8cSPawel Laszczak 	cdnsp_ring_free(pdev, pdev->cmd_ring);
1326e2d60f8cSPawel Laszczak destroy_device_pool:
1327e2d60f8cSPawel Laszczak 	dma_pool_destroy(pdev->device_pool);
1328e2d60f8cSPawel Laszczak destroy_segment_pool:
1329e2d60f8cSPawel Laszczak 	dma_pool_destroy(pdev->segment_pool);
1330e2d60f8cSPawel Laszczak release_dcbaa:
1331e2d60f8cSPawel Laszczak 	dma_free_coherent(dev, sizeof(*pdev->dcbaa), pdev->dcbaa,
1332e2d60f8cSPawel Laszczak 			  pdev->dcbaa->dma);
1333e2d60f8cSPawel Laszczak 
13343d829045SPawel Laszczak 	cdnsp_reset(pdev);
13353d829045SPawel Laszczak 
13363d829045SPawel Laszczak 	return ret;
13373d829045SPawel Laszczak }
1338