2020-03-15 18:55:07 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2012-05-11 22:25:46 +08:00
|
|
|
/*
|
|
|
|
* udc.h - ChipIdea UDC structures
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Author: David Lopo
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __DRIVERS_USB_CHIPIDEA_UDC_H
|
|
|
|
#define __DRIVERS_USB_CHIPIDEA_UDC_H
|
|
|
|
|
|
|
|
#include <linux/list.h>
|
|
|
|
|
|
|
|
#define CTRL_PAYLOAD_MAX 64
|
|
|
|
#define RX 0 /* similar to USB_DIR_OUT but can be used as an index */
|
|
|
|
#define TX 1 /* similar to USB_DIR_IN but can be used as an index */
|
|
|
|
|
|
|
|
/* DMA layout of transfer descriptors */
|
2013-06-24 19:46:36 +08:00
|
|
|
struct ci_hw_td {
|
2012-05-11 22:25:46 +08:00
|
|
|
/* 0 */
|
2016-09-14 13:53:02 +08:00
|
|
|
__le32 next;
|
2012-05-11 22:25:46 +08:00
|
|
|
#define TD_TERMINATE BIT(0)
|
|
|
|
#define TD_ADDR_MASK (0xFFFFFFEUL << 5)
|
|
|
|
/* 1 */
|
2016-09-14 13:53:02 +08:00
|
|
|
__le32 token;
|
2012-05-11 22:25:46 +08:00
|
|
|
#define TD_STATUS (0x00FFUL << 0)
|
|
|
|
#define TD_STATUS_TR_ERR BIT(3)
|
|
|
|
#define TD_STATUS_DT_ERR BIT(5)
|
|
|
|
#define TD_STATUS_HALTED BIT(6)
|
|
|
|
#define TD_STATUS_ACTIVE BIT(7)
|
|
|
|
#define TD_MULTO (0x0003UL << 10)
|
|
|
|
#define TD_IOC BIT(15)
|
|
|
|
#define TD_TOTAL_BYTES (0x7FFFUL << 16)
|
|
|
|
/* 2 */
|
2016-09-14 13:53:02 +08:00
|
|
|
__le32 page[5];
|
2012-05-11 22:25:46 +08:00
|
|
|
#define TD_CURR_OFFSET (0x0FFFUL << 0)
|
|
|
|
#define TD_FRAME_NUM (0x07FFUL << 0)
|
|
|
|
#define TD_RESERVED_MASK (0x0FFFUL << 0)
|
2013-04-04 18:13:46 +08:00
|
|
|
} __attribute__ ((packed, aligned(4)));
|
2012-05-11 22:25:46 +08:00
|
|
|
|
|
|
|
/* DMA layout of queue heads */
|
2013-06-24 19:46:36 +08:00
|
|
|
struct ci_hw_qh {
|
2012-05-11 22:25:46 +08:00
|
|
|
/* 0 */
|
2016-09-14 13:53:02 +08:00
|
|
|
__le32 cap;
|
2012-05-11 22:25:46 +08:00
|
|
|
#define QH_IOS BIT(15)
|
|
|
|
#define QH_MAX_PKT (0x07FFUL << 16)
|
|
|
|
#define QH_ZLT BIT(29)
|
|
|
|
#define QH_MULT (0x0003UL << 30)
|
2013-06-13 22:59:47 +08:00
|
|
|
#define QH_ISO_MULT(x) ((x >> 11) & 0x03)
|
2012-05-11 22:25:46 +08:00
|
|
|
/* 1 */
|
2016-09-14 13:53:02 +08:00
|
|
|
__le32 curr;
|
2012-05-11 22:25:46 +08:00
|
|
|
/* 2 - 8 */
|
2013-06-24 19:46:36 +08:00
|
|
|
struct ci_hw_td td;
|
2012-05-11 22:25:46 +08:00
|
|
|
/* 9 */
|
2016-09-14 13:53:02 +08:00
|
|
|
__le32 RESERVED;
|
2012-05-11 22:25:46 +08:00
|
|
|
struct usb_ctrlrequest setup;
|
2013-04-04 18:13:46 +08:00
|
|
|
} __attribute__ ((packed, aligned(4)));
|
2012-05-11 22:25:46 +08:00
|
|
|
|
2013-06-13 22:59:53 +08:00
|
|
|
struct td_node {
|
|
|
|
struct list_head td;
|
|
|
|
dma_addr_t dma;
|
2013-06-24 19:46:36 +08:00
|
|
|
struct ci_hw_td *ptr;
|
usb: chipidea: udc: add software sg list support
The chipidea controller doesn't support short transfer for sg list,
so we still keep setting IOC per TD, otherwise, there will be no interrupt
for short transfer. Each TD has five entries for data buffer, each data
buffer could be non-countinuous 4KB buffer, so it could handle
up to 5 sg buffers one time. The benefit of this patch is avoiding
OOM for low memory system(eg, 256MB) during large USB transfers, see
below for detail. The non-sg handling has not changed.
ufb: page allocation failure: order:4, mode:0x40cc0(GFP_KERNEL|__GFP_COMP),
nodemask=(null),cpuset=/,mems_allowed=0
CPU: 2 PID: 370 Comm: ufb Not tainted 5.4.3-1.1.0+g54b3750d61fd #1
Hardware name: NXP i.MX8MNano DDR4 EVK board (DT)
Call trace:
dump_backtrace+0x0/0x140
show_stack+0x14/0x20
dump_stack+0xb4/0xf8
warn_alloc+0xec/0x158
__alloc_pages_slowpath+0x9cc/0x9f8
__alloc_pages_nodemask+0x21c/0x280
alloc_pages_current+0x7c/0xe8
kmalloc_order+0x1c/0x88
__kmalloc+0x25c/0x298
ffs_epfile_io.isra.0+0x20c/0x7d0
ffs_epfile_read_iter+0xa8/0x188
new_sync_read+0xe4/0x170
__vfs_read+0x2c/0x40
vfs_read+0xc8/0x1a0
ksys_read+0x68/0xf0
__arm64_sys_read+0x18/0x20
el0_svc_common.constprop.0+0x68/0x160
el0_svc_handler+0x20/0x80
el0_svc+0x8/0xc
Mem-Info:
active_anon:2856 inactive_anon:5269 isolated_anon:12
active_file:5238 inactive_file:18803 isolated_file:0
unevictable:0 dirty:22 writeback:416 unstable:0
slab_reclaimable:4073 slab_unreclaimable:3408
mapped:727 shmem:7393 pagetables:37 bounce:0
free:4104 free_pcp:118 free_cma:0
Node 0 active_anon:11436kB inactive_anon:21076kB active_file:20988kB inactive_file:75216kB unevictable:0kB isolated(ano
Node 0 DMA32 free:16820kB min:1808kB low:2260kB high:2712kB active_anon:11436kB inactive_anon:21076kB active_file:2098B
lowmem_reserve[]: 0 0 0
Node 0 DMA32: 508*4kB (UME) 242*8kB (UME) 730*16kB (UM) 21*32kB (UME) 5*64kB (UME) 2*128kB (M) 0*256kB 0*512kB 0*1024kB
Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=32768kB
Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=64kB
31455 total pagecache pages
0 pages in swap cache
Swap cache stats: add 0, delete 0, find 0/0
Free swap = 0kB
Total swap = 0kB
65536 pages RAM
0 pages HighMem/MovableOnly
10766 pages reserved
0 pages cma reserved
0 pages hwpoisoned
Reviewed-by: Jun Li <jun.li@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
2020-02-21 21:40:57 +08:00
|
|
|
int td_remaining_size;
|
2013-06-13 22:59:53 +08:00
|
|
|
};
|
|
|
|
|
2012-05-11 22:25:49 +08:00
|
|
|
/**
|
2013-06-24 19:46:36 +08:00
|
|
|
* struct ci_hw_req - usb request representation
|
2012-05-11 22:25:49 +08:00
|
|
|
* @req: request structure for gadget drivers
|
|
|
|
* @queue: link to QH list
|
2020-03-23 21:20:23 +08:00
|
|
|
* @tds: link to TD list
|
2012-05-11 22:25:49 +08:00
|
|
|
*/
|
2013-06-24 19:46:36 +08:00
|
|
|
struct ci_hw_req {
|
2012-05-11 22:25:49 +08:00
|
|
|
struct usb_request req;
|
|
|
|
struct list_head queue;
|
2013-06-13 22:59:53 +08:00
|
|
|
struct list_head tds;
|
2012-05-11 22:25:46 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef CONFIG_USB_CHIPIDEA_UDC
|
2012-05-11 22:25:47 +08:00
|
|
|
|
2013-06-24 19:46:36 +08:00
|
|
|
int ci_hdrc_gadget_init(struct ci_hdrc *ci);
|
2013-08-14 17:44:07 +08:00
|
|
|
void ci_hdrc_gadget_destroy(struct ci_hdrc *ci);
|
2012-05-11 22:25:47 +08:00
|
|
|
|
2012-05-11 22:25:46 +08:00
|
|
|
#else
|
|
|
|
|
2013-06-24 19:46:36 +08:00
|
|
|
static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci)
|
2012-05-11 22:25:46 +08:00
|
|
|
{
|
2012-05-11 22:25:47 +08:00
|
|
|
return -ENXIO;
|
2012-05-11 22:25:46 +08:00
|
|
|
}
|
|
|
|
|
2013-08-14 17:44:07 +08:00
|
|
|
static inline void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-05-11 22:25:46 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
|