Commit 215db948 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-for-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: patches for v4.8 merge window

Here's the big pull request for Peripheral stack and
all related drivers.

This time around with 109 non-merge commits mostly
concentrated on drivers/usb/gadget/udc (41.5%) and
drivers/usb/dwc3 (28.1%).

There's a big rework on dwc3's transfer handling
which gave us almost 3x faster USB3 speeds with Mass
Storage on a particular test scenario I measured. We
are also removing platform_data from dwc3 after
converting all users to built-in properties instead.

For the Gadget API, we're just adding tracepoints to
aid debugging activities.

Other than these, there's the usual set of spelling
fixes, minor bug fixes and sparse warnings cleanups.
parents 107a4b53 15e4292a
......@@ -176,6 +176,7 @@ config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
depends on USB_SUPPORT
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y'
select GENERIC_PHY
select USB_PHY
help
......
......@@ -309,6 +309,7 @@ config BATTERY_RX51
config CHARGER_ISP1704
tristate "ISP1704 USB Charger Detection"
depends on USB_PHY
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
help
Say Y to enable support for USB Charger Detection with
ISP1707/ISP1704 USB transceivers.
......
......@@ -131,15 +131,17 @@ EXPORT_SYMBOL_GPL(usb_get_dr_mode);
* of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device
* which is associated with the given phy device_node
* @np: Pointer to the given phy device_node
* @arg0: phandle args[0] for phy's with #phy-cells >= 1, or -1 for
* phys which do not have phy-cells
*
* In dts a usb controller associates with phy devices. The function gets
* the string from property 'dr_mode' of the controller associated with the
* given phy device node, and returns the correspondig enum usb_dr_mode.
*/
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np)
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
{
struct device_node *controller = NULL;
struct device_node *phy;
struct of_phandle_args args;
const char *dr_mode;
int index;
int err;
......@@ -148,12 +150,24 @@ enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np)
controller = of_find_node_with_property(controller, "phys");
index = 0;
do {
phy = of_parse_phandle(controller, "phys", index);
of_node_put(phy);
if (phy == phy_np)
if (arg0 == -1) {
args.np = of_parse_phandle(controller, "phys",
index);
args.args_count = 0;
} else {
err = of_parse_phandle_with_args(controller,
"phys", "#phy-cells",
index, &args);
if (err)
break;
}
of_node_put(args.np);
if (args.np == np && (args.args_count == 0 ||
args.args[0] == arg0))
goto finish;
index++;
} while (phy);
} while (args.np);
} while (controller);
finish:
......
......@@ -55,6 +55,7 @@ endchoice
config USB_DWC2_PCI
tristate "DWC2 PCI"
depends on PCI
depends on USB_GADGET || !USB_GADGET
default n
select NOP_USB_XCEIV
help
......
......@@ -166,7 +166,7 @@ struct dwc2_hsotg_req;
* means that it is sending data to the Host.
* @index: The index for the endpoint registers.
* @mc: Multi Count - number of transactions per microframe
* @interval - Interval for periodic endpoints
* @interval - Interval for periodic endpoints, in frames or microframes.
* @name: The name array passed to the USB core.
* @halted: Set if the endpoint has been halted.
* @periodic: Set if this is a periodic ep, such as Interrupt
......@@ -177,6 +177,8 @@ struct dwc2_hsotg_req;
* @fifo_load: The amount of data loaded into the FIFO (periodic IN)
* @last_load: The offset of data for the last start of request.
* @size_loaded: The last loaded size for DxEPTSIZE for periodic IN
* @target_frame: Targeted frame num to setup next ISOC transfer
* @frame_overrun: Indicates SOF number overrun in DSTS
*
* This is the driver's state for each registered enpoint, allowing it
* to keep track of transactions that need doing. Each endpoint has a
......@@ -213,7 +215,9 @@ struct dwc2_hsotg_ep {
unsigned int periodic:1;
unsigned int isochronous:1;
unsigned int send_zlp:1;
unsigned int has_correct_parity:1;
unsigned int target_frame;
#define TARGET_FRAME_INITIAL 0xFFFFFFFF
bool frame_overrun;
char name[10];
};
......
This diff is collapsed.
......@@ -367,7 +367,8 @@ static void pmap_unschedule(unsigned long *map, int bits_per_period,
* @fmt: The format for printf.
* @...: The args for printf.
*/
static void cat_printf(char **buf, size_t *size, const char *fmt, ...)
static __printf(3, 4)
void cat_printf(char **buf, size_t *size, const char *fmt, ...)
{
va_list args;
int i;
......
......@@ -459,6 +459,9 @@
#define DSTS_SUSPSTS (1 << 0)
#define DIEPMSK HSOTG_REG(0x810)
#define DIEPMSK_NAKMSK (1 << 13)
#define DIEPMSK_BNAININTRMSK (1 << 9)
#define DIEPMSK_TXFIFOUNDRNMSK (1 << 8)
#define DIEPMSK_TXFIFOEMPTY (1 << 7)
#define DIEPMSK_INEPNAKEFFMSK (1 << 6)
#define DIEPMSK_INTKNEPMISMSK (1 << 5)
......@@ -470,6 +473,7 @@
#define DOEPMSK HSOTG_REG(0x814)
#define DOEPMSK_BACK2BACKSETUP (1 << 6)
#define DOEPMSK_STSPHSERCVDMSK (1 << 5)
#define DOEPMSK_OUTTKNEPDISMSK (1 << 4)
#define DOEPMSK_SETUPMSK (1 << 3)
#define DOEPMSK_AHBERRMSK (1 << 2)
......@@ -486,6 +490,7 @@
#define DTKNQR2 HSOTG_REG(0x824)
#define DTKNQR3 HSOTG_REG(0x830)
#define DTKNQR4 HSOTG_REG(0x834)
#define DIEPEMPMSK HSOTG_REG(0x834)
#define DVBUSDIS HSOTG_REG(0x828)
#define DVBUSPULSE HSOTG_REG(0x82C)
......@@ -544,9 +549,18 @@
#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
#define DXEPINT_SETUP_RCVD (1 << 15)
#define DXEPINT_NYETINTRPT (1 << 14)
#define DXEPINT_NAKINTRPT (1 << 13)
#define DXEPINT_BBLEERRINTRPT (1 << 12)
#define DXEPINT_PKTDRPSTS (1 << 11)
#define DXEPINT_BNAINTR (1 << 9)
#define DXEPINT_TXFIFOUNDRN (1 << 8)
#define DXEPINT_OUTPKTERR (1 << 8)
#define DXEPINT_TXFEMP (1 << 7)
#define DXEPINT_INEPNAKEFF (1 << 6)
#define DXEPINT_BACK2BACKSETUP (1 << 6)
#define DXEPINT_INTKNEPMIS (1 << 5)
#define DXEPINT_STSPHSERCVD (1 << 5)
#define DXEPINT_INTKNTXFEMP (1 << 4)
#define DXEPINT_OUTTKNEPDIS (1 << 4)
#define DXEPINT_TIMEOUT (1 << 3)
......
This diff is collapsed.
......@@ -86,6 +86,7 @@
#define DWC3_GCTL 0xc110
#define DWC3_GEVTEN 0xc114
#define DWC3_GSTS 0xc118
#define DWC3_GUCTL1 0xc11c
#define DWC3_GSNPSID 0xc120
#define DWC3_GGPIO 0xc124
#define DWC3_GUID 0xc128
......@@ -138,10 +139,12 @@
#define DWC3_DGCMDPAR 0xc710
#define DWC3_DGCMD 0xc714
#define DWC3_DALEPENA 0xc720
#define DWC3_DEPCMDPAR2(n) (0xc800 + (n * 0x10))
#define DWC3_DEPCMDPAR1(n) (0xc804 + (n * 0x10))
#define DWC3_DEPCMDPAR0(n) (0xc808 + (n * 0x10))
#define DWC3_DEPCMD(n) (0xc80c + (n * 0x10))
#define DWC3_DEP_BASE(n) (0xc800 + (n * 0x10))
#define DWC3_DEPCMDPAR2 0x00
#define DWC3_DEPCMDPAR1 0x04
#define DWC3_DEPCMDPAR0 0x08
#define DWC3_DEPCMD 0x0c
/* OTG Registers */
#define DWC3_OCFG 0xcc00
......@@ -231,6 +234,14 @@
#define DWC3_GEVNTSIZ_INTMASK (1 << 31)
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
/* Global HWPARAMS0 Register */
#define DWC3_GHWPARAMS0_USB3_MODE(n) ((n) & 0x3)
#define DWC3_GHWPARAMS0_MBUS_TYPE(n) (((n) >> 3) & 0x7)
#define DWC3_GHWPARAMS0_SBUS_TYPE(n) (((n) >> 6) & 0x3)
#define DWC3_GHWPARAMS0_MDWIDTH(n) (((n) >> 8) & 0xff)
#define DWC3_GHWPARAMS0_SDWIDTH(n) (((n) >> 16) & 0xff)
#define DWC3_GHWPARAMS0_AWIDTH(n) (((n) >> 24) & 0xff)
/* Global HWPARAMS1 Register */
#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24)
#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
......@@ -260,6 +271,10 @@
/* Global HWPARAMS6 Register */
#define DWC3_GHWPARAMS6_EN_FPGA (1 << 7)
/* Global HWPARAMS7 Register */
#define DWC3_GHWPARAMS7_RAM1_DEPTH(n) ((n) & 0xffff)
#define DWC3_GHWPARAMS7_RAM2_DEPTH(n) (((n) >> 16) & 0xffff)
/* Global Frame Length Adjustment Register */
#define DWC3_GFLADJ_30MHZ_SDBND_SEL (1 << 7)
#define DWC3_GFLADJ_30MHZ_MASK 0x3f
......@@ -468,6 +483,8 @@ struct dwc3_event_buffer {
* @endpoint: usb endpoint
* @pending_list: list of pending requests for this endpoint
* @started_list: list of started requests on this endpoint
* @lock: spinlock for endpoint request queue traversal
* @regs: pointer to first endpoint register
* @trb_pool: array of transaction buffers
* @trb_pool_dma: dma address of @trb_pool
* @trb_enqueue: enqueue 'pointer' into TRB array
......@@ -480,6 +497,8 @@ struct dwc3_event_buffer {
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
* @resource_index: Resource transfer index
* @interval: the interval on which the ISOC transfer is started
* @allocated_requests: number of requests allocated
* @queued_requests: number of requests queued for transfer
* @name: a human readable name e.g. ep1out-bulk
* @direction: true for TX, false for RX
* @stream_capable: true when streams are enabled
......@@ -489,6 +508,9 @@ struct dwc3_ep {
struct list_head pending_list;
struct list_head started_list;
spinlock_t lock;
void __iomem *regs;
struct dwc3_trb *trb_pool;
dma_addr_t trb_pool_dma;
const struct usb_ss_ep_comp_descriptor *comp_desc;
......@@ -521,6 +543,8 @@ struct dwc3_ep {
u8 number;
u8 type;
u8 resource_index;
u32 allocated_requests;
u32 queued_requests;
u32 interval;
char name[20];
......@@ -712,6 +736,8 @@ struct dwc3_scratchpad_array {
* @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers
* @regs_size: address space size
* @fladj: frame length adjustment
* @irq_gadget: peripheral controller's IRQ number
* @nr_scratch: number of scratch buffers
* @u1u2: only used on revisions <1.83a for workaround
* @maximum_speed: maximum speed requested (mainly for testing purposes)
......@@ -744,6 +770,7 @@ struct dwc3_scratchpad_array {
* @lpm_nyet_threshold: LPM NYET response threshold
* @hird_threshold: HIRD threshold
* @hsphy_interface: "utmi" or "ulpi"
* @connected: true when we're connected to a host, false otherwise
* @delayed_status: true when gadget driver asks for delayed status
* @ep0_bounced: true when we used bounce buffer
* @ep0_expect_in: true when we expect a DATA IN transfer
......@@ -754,6 +781,7 @@ struct dwc3_scratchpad_array {
* 0 - utmi_sleep_n
* 1 - utmi_l1_suspend_n
* @is_fpga: true when we are using the FPGA board
* @pending_events: true when we have pending IRQs to be handled
* @pullups_connected: true when Run/Stop bit is set
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @start_config_issued: true when StartConfig command has been issued
......@@ -818,10 +846,8 @@ struct dwc3 {
enum usb_dr_mode dr_mode;
/* used for suspend/resume */
u32 dcfg;
u32 gctl;
u32 fladj;
u32 irq_gadget;
u32 nr_scratch;
u32 u1u2;
u32 maximum_speed;
......@@ -860,7 +886,7 @@ struct dwc3 {
* just so dwc31 revisions are always larger than dwc3.
*/
#define DWC3_REVISION_IS_DWC31 0x80000000
#define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_USB31)
#define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31)
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
......@@ -890,6 +916,7 @@ struct dwc3 {
const char *hsphy_interface;
unsigned connected:1;
unsigned delayed_status:1;
unsigned ep0_bounced:1;
unsigned ep0_expect_in:1;
......@@ -897,6 +924,7 @@ struct dwc3 {
unsigned has_lpm_erratum:1;
unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1;
unsigned pending_events:1;
unsigned pullups_connected:1;
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
......@@ -1094,8 +1122,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc);
int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode);
int dwc3_gadget_get_link_state(struct dwc3 *dwc);
int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state);
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
struct dwc3_gadget_ep_cmd_params *params);
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param);
#else
static inline int dwc3_gadget_init(struct dwc3 *dwc)
......@@ -1110,8 +1138,8 @@ static inline int dwc3_gadget_set_link_state(struct dwc3 *dwc,
enum dwc3_link_state state)
{ return 0; }
static inline int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params)
static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
struct dwc3_gadget_ep_cmd_params *params)
{ return 0; }
static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
int cmd, u32 param)
......@@ -1122,6 +1150,7 @@ static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
int dwc3_gadget_suspend(struct dwc3 *dwc);
int dwc3_gadget_resume(struct dwc3 *dwc);
void dwc3_gadget_process_pending_events(struct dwc3 *dwc);
#else
static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
{
......@@ -1132,6 +1161,10 @@ static inline int dwc3_gadget_resume(struct dwc3 *dwc)
{
return 0;
}
static inline void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
{
}
#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
#if IS_ENABLED(CONFIG_USB_DWC3_ULPI)
......
......@@ -128,56 +128,112 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state)
* dwc3_gadget_event_string - returns event name
* @event: the event code
*/
static inline const char *dwc3_gadget_event_string(u8 event)
static inline const char *
dwc3_gadget_event_string(const struct dwc3_event_devt *event)
{
switch (event) {
static char str[256];
enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
switch (event->type) {
case DWC3_DEVICE_EVENT_DISCONNECT:
return "Disconnect";
sprintf(str, "Disconnect: [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_RESET:
return "Reset";
sprintf(str, "Reset [%s]", dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_CONNECT_DONE:
return "Connection Done";
sprintf(str, "Connection Done [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
return "Link Status Change";
sprintf(str, "Link Change [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_WAKEUP:
return "WakeUp";
sprintf(str, "WakeUp [%s]", dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_EOPF:
return "End-Of-Frame";
sprintf(str, "End-Of-Frame [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_SOF:
return "Start-Of-Frame";
sprintf(str, "Start-Of-Frame [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
return "Erratic Error";
sprintf(str, "Erratic Error [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_CMD_CMPL:
return "Command Complete";
sprintf(str, "Command Complete [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_OVERFLOW:
return "Overflow";
sprintf(str, "Overflow [%s]", dwc3_gadget_link_string(state));
break;
default:
sprintf(str, "UNKNOWN");
}
return "UNKNOWN";
return str;
}
/**
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
static inline const char *dwc3_ep_event_string(u8 event)
static inline const char *
dwc3_ep_event_string(const struct dwc3_event_depevt *event)
{
switch (event) {
u8 epnum = event->endpoint_number;
static char str[256];
int status;
int ret;
ret = sprintf(str, "ep%d%s: ", epnum >> 1,
(epnum & 1) ? "in" : "in");
if (ret < 0)
return "UNKNOWN";
switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE:
return "Transfer Complete";
strcat(str, "Transfer Complete");
break;
case DWC3_DEPEVT_XFERINPROGRESS:
return "Transfer In-Progress";
strcat(str, "Transfer In-Progress");
break;
case DWC3_DEPEVT_XFERNOTREADY:
return "Transfer Not Ready";
strcat(str, "Transfer Not Ready");
status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
strcat(str, status ? " (Active)" : " (Not Active)");
break;
case DWC3_DEPEVT_RXTXFIFOEVT:
return "FIFO";
strcat(str, "FIFO");
break;
case DWC3_DEPEVT_STREAMEVT:
return "Stream";
status = event->status;
switch (status) {
case DEPEVT_STREAMEVT_FOUND:
sprintf(str + ret, " Stream %d Found",
event->parameters);
break;
case DEPEVT_STREAMEVT_NOTFOUND:
default:
strcat(str, " Stream Not Found");
break;
}
break;
case DWC3_DEPEVT_EPCMDCMPLT:
return "Endpoint Command Complete";
strcat(str, "Endpoint Command Complete");
break;
default:
sprintf(str, "UNKNOWN");
}
return "UNKNOWN";
return str;
}
/**
......@@ -214,6 +270,46 @@ static inline const char *dwc3_gadget_event_type_string(u8 event)
}
}
static inline const char *dwc3_decode_event(u32 event)
{
const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec)
return dwc3_gadget_event_string(&evt.devt);
else
return dwc3_ep_event_string(&evt.depevt);
}
static inline const char *dwc3_ep_cmd_status_string(int status)
{
switch (status) {
case -ETIMEDOUT:
return "Timed Out";
case 0:
return "Successful";
case DEPEVT_TRANSFER_NO_RESOURCE:
return "No Resource";
case DEPEVT_TRANSFER_BUS_EXPIRY:
return "Bus Expiry";
default:
return "UNKNOWN";
}
}
static inline const char *dwc3_gadget_generic_cmd_status_string(int status)
{
switch (status) {
case -ETIMEDOUT:
return "Timed Out";
case 0:
return "Successful";
case 1:
return "Error";
default:
return "UNKNOWN";
}
}
void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...);
#ifdef CONFIG_DEBUG_FS
......
......@@ -36,9 +36,32 @@
#define dump_register(nm) \
{ \
.name = __stringify(nm), \
.offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
.offset = DWC3_ ##nm, \
}
#define dump_ep_register_set(n) \
{ \
.name = "DEPCMDPAR2("__stringify(n)")", \
.offset = DWC3_DEP_BASE(n) + \
DWC3_DEPCMDPAR2, \
}, \
{ \
.name = "DEPCMDPAR1("__stringify(n)")", \
.offset = DWC3_DEP_BASE(n) + \
DWC3_DEPCMDPAR1, \
}, \
{ \
.name = "DEPCMDPAR0("__stringify(n)")", \
.offset = DWC3_DEP_BASE(n) + \
DWC3_DEPCMDPAR0, \
}, \
{ \
.name = "DEPCMD("__stringify(n)")", \
.offset = DWC3_DEP_BASE(n) + \
DWC3_DEPCMD, \
}
static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(GSBUSCFG0),
dump_register(GSBUSCFG1),
......@@ -47,6 +70,7 @@ static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(GCTL),
dump_register(GEVTEN),
dump_register(GSTS),
dump_register(GUCTL1),
dump_register(GSNPSID),
dump_register(GGPIO),
dump_register(GUID),
......@@ -218,137 +242,38 @@ static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(DGCMD),
dump_register(DALEPENA),
dump_register(DEPCMDPAR2(0)),
dump_register(DEPCMDPAR2(1)),
dump_register(DEPCMDPAR2(2)),
dump_register(DEPCMDPAR2(3)),
dump_register(DEPCMDPAR2(4)),
dump_register(DEPCMDPAR2(5)),
dump_register(DEPCMDPAR2(6)),
dump_register(DEPCMDPAR2(7)),
dump_register(DEPCMDPAR2(8)),
dump_register(DEPCMDPAR2(9)),
dump_register(DEPCMDPAR2(10)),
dump_register(DEPCMDPAR2(11)),
dump_register(DEPCMDPAR2(12)),
dump_register(DEPCMDPAR2(13)),
dump_register(DEPCMDPAR2(14)),
dump_register(DEPCMDPAR2(15)),
dump_register(DEPCMDPAR2(16)),
dump_register(DEPCMDPAR2(17)),
dump_register(DEPCMDPAR2(18)),
dump_register(DEPCMDPAR2(19)),
dump_register(DEPCMDPAR2(20)),
dump_register(DEPCMDPAR2(21)),
dump_register(DEPCMDPAR2(22)),
dump_register(DEPCMDPAR2(23)),
dump_register(DEPCMDPAR2(24)),
dump_register(DEPCMDPAR2(25)),
dump_register(DEPCMDPAR2(26)),
dump_register(DEPCMDPAR2(27)),
dump_register(DEPCMDPAR2(28)),
dump_register(DEPCMDPAR2(29)),
dump_register(DEPCMDPAR2(30)),
dump_register(DEPCMDPAR2(31)),
dump_register(DEPCMDPAR1(0)),
dump_register(DEPCMDPAR1(1)),
dump_register(DEPCMDPAR1(2)),
dump_register(DEPCMDPAR1(3)),
dump_register(DEPCMDPAR1(4)),
dump_register(DEPCMDPAR1(5)),
dump_register(DEPCMDPAR1(6)),
dump_register(DEPCMDPAR1(7)),
dump_register(DEPCMDPAR1(8)),
dump_register(DEPCMDPAR1(9)),
dump_register(DEPCMDPAR1(10)),
dump_register(DEPCMDPAR1(11)),
dump_register(DEPCMDPAR1(12)),
dump_register(DEPCMDPAR1(13)),
dump_register(DEPCMDPAR1(14)),
dump_register(DEPCMDPAR1(15)),
dump_register(DEPCMDPAR1(16)),
dump_register(DEPCMDPAR1(17)),
dump_register(DEPCMDPAR1(18)),
dump_register(DEPCMDPAR1(19)),
dump_register(DEPCMDPAR1(20)),
dump_register(DEPCMDPAR1(21)),
dump_register(DEPCMDPAR1(22)),
dump_register(DEPCMDPAR1(23)),
dump_register(DEPCMDPAR1(24)),
dump_register(DEPCMDPAR1(25)),
dump_register(DEPCMDPAR1(26)),
dump_register(DEPCMDPAR1(27)),
dump_register(DEPCMDPAR1(28)),
dump_register(DEPCMDPAR1(29)),
dump_register(DEPCMDPAR1(30)),
dump_register(DEPCMDPAR1(31)),
dump_register(DEPCMDPAR0(0)),
dump_register(DEPCMDPAR0(1)),
dump_register(DEPCMDPAR0(2)),
dump_register(DEPCMDPAR0(3)),
dump_register(DEPCMDPAR0(4)),
dump_register(DEPCMDPAR0(5)),
dump_register(DEPCMDPAR0(6)),
dump_register(DEPCMDPAR0(7)),
dump_register(DEPCMDPAR0(8)),
dump_register(DEPCMDPAR0(9)),
dump_register(DEPCMDPAR0(10)),
dump_register(DEPCMDPAR0(11)),
dump_register(DEPCMDPAR0(12)),
dump_register(DEPCMDPAR0(13)),
dump_register(DEPCMDPAR0(14)),
dump_register(DEPCMDPAR0(15)),
dump_register(DEPCMDPAR0(16)),
dump_register(DEPCMDPAR0(17)),
dump_register(DEPCMDPAR0(18)),
dump_register(DEPCMDPAR0(19)),
dump_register(DEPCMDPAR0(20)),
dump_register(DEPCMDPAR0(21)),
dump_register(DEPCMDPAR0(22)),
dump_register(DEPCMDPAR0(23)),
dump_register(DEPCMDPAR0(24)),
dump_register(DEPCMDPAR0(25)),
dump_register(DEPCMDPAR0(26)),
dump_register(DEPCMDPAR0(27)),
dump_register(DEPCMDPAR0(28)),
dump_register(DEPCMDPAR0(29)),
dump_register(DEPCMDPAR0(30)),
dump_register(DEPCMDPAR0(31)),
dump_register(DEPCMD(0)),
dump_register(DEPCMD(1)),
dump_register(DEPCMD(2)),
dump_register(DEPCMD(3)),
dump_register(DEPCMD(4)),
dump_register(DEPCMD(5)),
dump_register(DEPCMD(6)),
dump_register(DEPCMD(7)),
dump_register(DEPCMD(8)),
dump_register(DEPCMD(9)),
dump_register(DEPCMD(10)),
dump_register(DEPCMD(11)),
dump_register(DEPCMD(12)),
dump_register(DEPCMD(13)),
dump_register(DEPCMD(14)),
dump_register(DEPCMD(15)),
dump_register(DEPCMD(16)),
dump_register(DEPCMD(17)),
dump_register(DEPCMD(18)),
dump_register(DEPCMD(19)),
dump_register(DEPCMD(20)),
dump_register(DEPCMD(21)),
dump_register(DEPCMD(22)),
dump_register(DEPCMD(23)),
dump_register(DEPCMD(24)),
dump_register(DEPCMD(25)),
dump_register(DEPCMD(26)),
dump_register(DEPCMD(27)),
dump_register(DEPCMD(28)),
dump_register(DEPCMD(29)),
dump_register(DEPCMD(30)),
dump_register(DEPCMD(31)),
dump_ep_register_set(0),
dump_ep_register_set(1),
dump_ep_register_set(2),
dump_ep_register_set(3),
dump_ep_register_set(4),
dump_ep_register_set(5),
dump_ep_register_set(6),
dump_ep_register_set(7),
dump_ep_register_set(8),
dump_ep_register_set(9),
dump_ep_register_set(10),
dump_ep_register_set(11),
dump_ep_register_set(12),
dump_ep_register_set(13),
dump_ep_register_set(14),
dump_ep_register_set(15),
dump_ep_register_set(16),
dump_ep_register_set(17),
dump_ep_register_set(18),
dump_ep_register_set(19),
dump_ep_register_set(20),
dump_ep_register_set(21),
dump_ep_register_set(22),
dump_ep_register_set(23),
dump_ep_register_set(24),
dump_ep_register_set(25),
dump_ep_register_set(26),
dump_ep_register_set(27),
dump_ep_register_set(28),
dump_ep_register_set(29),
dump_ep_register_set(30),
dump_ep_register_set(31),
dump_register(OCFG),
dump_register(OCTL),
......@@ -939,7 +864,7 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
dwc->regset->regs = dwc3_regs;
dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
dwc->regset->base = dwc->regs;
dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START;
file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset);
if (!file)
......
......@@ -165,7 +165,7 @@ static void dwc3_omap_write_utmi_ctrl(struct dwc3_omap *omap, u32 value)
static u32 dwc3_omap_read_irq0_status(struct dwc3_omap *omap)
{
return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0 -
return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_RAW_0 -
omap->irq0_offset);
}
......@@ -178,7 +178,7 @@ static void dwc3_omap_write_irq0_status(struct dwc3_omap *omap, u32 value)
static u32 dwc3_omap_read_irqmisc_status(struct dwc3_omap *omap)
{
return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_MISC +
return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_RAW_MISC +
omap->irqmisc_offset);
}
......@@ -231,35 +231,30 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
}
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~(USBOTGSS_UTMI_OTG_CTRL_IDDIG
| USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
| USBOTGSS_UTMI_OTG_CTRL_SESSEND);
val |= USBOTGSS_UTMI_OTG_CTRL_SESSVALID
| USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT;
val &= ~USBOTGSS_UTMI_OTG_CTRL_IDDIG;
dwc3_omap_write_utmi_ctrl(omap, val);
break;
case OMAP_DWC3_VBUS_VALID:
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND;
val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG
| USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
| USBOTGSS_UTMI_OTG_CTRL_SESSVALID
| USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT;
val |= USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
| USBOTGSS_UTMI_OTG_CTRL_SESSVALID;
dwc3_omap_write_utmi_ctrl(omap, val);
break;
case OMAP_DWC3_ID_FLOAT:
if (omap->vbus_reg)
regulator_disable(omap->vbus_reg);
val = dwc3_omap_read_utmi_ctrl(omap);
val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG;
dwc3_omap_write_utmi_ctrl(omap, val);
case OMAP_DWC3_VBUS_OFF:
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID
| USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
| USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT);
val |= USBOTGSS_UTMI_OTG_CTRL_SESSEND
| USBOTGSS_UTMI_OTG_CTRL_IDDIG;
| USBOTGSS_UTMI_OTG_CTRL_VBUSVALID);
val |= USBOTGSS_UTMI_OTG_CTRL_SESSEND;
dwc3_omap_write_utmi_ctrl(omap, val);
break;
......@@ -268,19 +263,38 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
}
}
static void dwc3_omap_enable_irqs(struct dwc3_omap *omap);
static void dwc3_omap_disable_irqs(struct dwc3_omap *omap);
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{
struct dwc3_omap *omap = _omap;
if (dwc3_omap_read_irqmisc_status(omap) ||
dwc3_omap_read_irq0_status(omap)) {
/* mask irqs */
dwc3_omap_disable_irqs(omap);
return IRQ_WAKE_THREAD;
}
return IRQ_NONE;
}
static irqreturn_t dwc3_omap_interrupt_thread(int irq, void *_omap)
{
struct dwc3_omap *omap = _omap;
u32 reg;
/* clear irq status flags */
reg = dwc3_omap_read_irqmisc_status(omap);
dwc3_omap_write_irqmisc_status(omap, reg);
reg = dwc3_omap_read_irq0_status(omap);
dwc3_omap_write_irq0_status(omap, reg);
/* unmask irqs */
dwc3_omap_enable_irqs(omap);
return IRQ_HANDLED;
}
......@@ -497,8 +511,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
/* check the DMA Status */
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
"dwc3-omap", omap);
ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
dwc3_omap_interrupt_thread, IRQF_SHARED,
"dwc3-omap", omap);
if (ret) {
dev_err(dev, "failed to request IRQ #%d --> %d\n",
omap->irq, ret);
......
......@@ -20,11 +20,11 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/acpi.h>
#include "platform_data.h"
#include <linux/delay.h>
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI 0xabce
......@@ -51,62 +51,70 @@ static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3)
{
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
pdev->device == PCI_DEVICE_ID_AMD_NL_USB) {
struct dwc3_platform_data pdata;
memset(&pdata, 0, sizeof(pdata));
pdata.has_lpm_erratum = true;
pdata.lpm_nyet_threshold = 0xf;
pdata.u2exit_lfps_quirk = true;
pdata.u2ss_inp3_quirk = true;
pdata.req_p1p2p3_quirk = true;
pdata.del_p1p2p3_quirk = true;
pdata.del_phy_power_chg_quirk = true;
pdata.lfps_filter_quirk = true;
pdata.rx_detect_poll_quirk = true;
pdata.tx_de_emphasis_quirk = true;
pdata.tx_de_emphasis = 1;
/*
* FIXME these quirks should be removed when AMD NL
* taps out
*/
pdata.disable_scramble_quirk = true;
pdata.dis_u3_susphy_quirk = true;
pdata.dis_u2_susphy_quirk = true;
return platform_device_add_data(dwc3, &pdata, sizeof(pdata));
struct property_entry properties[] = {
PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
PROPERTY_ENTRY_U8("snps,lpm-nyet-threshold", 0xf),
PROPERTY_ENTRY_BOOL("snps,u2exit_lfps_quirk"),
PROPERTY_ENTRY_BOOL("snps,u2ss_inp3_quirk"),
PROPERTY_ENTRY_BOOL("snps,req_p1p2p3_quirk"),
PROPERTY_ENTRY_BOOL("snps,del_p1p2p3_quirk"),
PROPERTY_ENTRY_BOOL("snps,del_phy_power_chg_quirk"),
PROPERTY_ENTRY_BOOL("snps,lfps_filter_quirk"),
PROPERTY_ENTRY_BOOL("snps,rx_detect_poll_quirk"),
PROPERTY_ENTRY_BOOL("snps,tx_de_emphasis_quirk"),
PROPERTY_ENTRY_U8("snps,tx_de_emphasis", 1),
/*
* FIXME these quirks should be removed when AMD NL
* tapes out
*/
PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"),
PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
{ },
};
return platform_device_add_properties(dwc3, properties);
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
struct gpio_desc *gpio;
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
int ret;
acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
acpi_dwc3_byt_gpios);
struct property_entry properties[] = {
PROPERTY_ENTRY_STRING("dr-mode", "peripheral"),
{ }
};
/*
* These GPIOs will turn on the USB2 PHY. Note that we have to
* put the gpio descriptors again here because the phy driver
* might want to grab them, too.
*/
gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
ret = platform_device_add_properties(dwc3, properties);
if (ret < 0)
return ret;
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
struct gpio_desc *gpio;
gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
acpi_dwc3_byt_gpios);
/*
* These GPIOs will turn on the USB2 PHY. Note that we have to
* put the gpio descriptors again here because the phy driver
* might want to grab them, too.
*/
gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (gpio) {
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
usleep_range(10000, 11000);
gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (gpio) {
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
usleep_range(10000, 11000);
}
}
}
......@@ -114,15 +122,14 @@ static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3)
(pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 ||
pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI ||
pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31)) {
struct dwc3_platform_data pdata;
memset(&pdata, 0, sizeof(pdata));
pdata.usb3_lpm_capable = true;
pdata.has_lpm_erratum = true;
pdata.dis_enblslpm_quirk = true;
return platform_device_add_data(dwc3, &pdata, sizeof(pdata));
struct property_entry properties[] = {
PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"),
PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
PROPERTY_ENTRY_BOOL("snps,dis_enblslpm_quirk"),
{ },
};
return platform_device_add_properties(dwc3, properties);
}
return 0;
......@@ -180,7 +187,11 @@ static int dwc3_pci_probe(struct pci_dev *pci,
goto err;
}
device_init_wakeup(dev, true);
device_set_run_wake(dev, true);
pci_set_drvdata(pci, dwc3);
pm_runtime_put(dev);
return 0;
err:
platform_device_put(dwc3);
......@@ -189,6 +200,8 @@ static int dwc3_pci_probe(struct pci_dev *pci,
static void dwc3_pci_remove(struct pci_dev *pci)
{
device_init_wakeup(&pci->dev, false);
pm_runtime_get(&pci->dev);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev));
platform_device_unregister(pci_get_drvdata(pci));
}
......@@ -219,11 +232,43 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
#ifdef CONFIG_PM
static int dwc3_pci_runtime_suspend(struct device *dev)
{
if (device_run_wake(dev))
return 0;
return -EBUSY;
}
static int dwc3_pci_pm_dummy(struct device *dev)
{
/*
* There's nothing to do here. No, seriously. Everything is either taken
* care either by PCI subsystem or dwc3/core.c, so we have nothing
* missing here.
*
* So you'd think we didn't need this at all, but PCI subsystem will
* bail out if we don't have a valid callback :-s
*/
return 0;
}
#endif /* CONFIG_PM */
static struct dev_pm_ops dwc3_pci_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_pm_dummy, dwc3_pci_pm_dummy)
SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_pm_dummy,
NULL)
};
static struct pci_driver dwc3_pci_driver = {
.name = "dwc3-pci",
.id_table = dwc3_pci_id_table,
.probe = dwc3_pci_probe,
.remove = dwc3_pci_remove,
.driver = {
.pm = &dwc3_pci_dev_pm_ops,
}
};
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
......
......@@ -98,8 +98,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
trace_dwc3_prepare_trb(dep, trb);
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
DWC3_DEPCMD_STARTTRANSFER, &params);
ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, &params);
if (ret < 0) {
dwc3_trace(trace_dwc3_ep0, "%s STARTTRANSFER failed",
dep->name);
......@@ -107,9 +106,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
}
dep->flags |= DWC3_EP_BUSY;
dep->resource_index = dwc3_gadget_ep_get_transfer_index(dwc,
dep->number);
dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep);
dwc->ep0_next_event = DWC3_EP0_COMPLETE;
return 0;
......@@ -499,7 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
case USB_RECIP_ENDPOINT:
switch (wValue) {
case USB_ENDPOINT_HALT:
dep = dwc3_wIndex_to_dep(dwc, wIndex);
dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
if (!dep)
return -EINVAL;
if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
......@@ -622,8 +619,8 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
struct timing {
u8 u1sel;
u8 u1pel;
u16 u2sel;
u16 u2pel;
__le16 u2sel;
__le16 u2pel;
} __packed timing;
int ret;
......@@ -980,7 +977,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
if (ret) {
dwc3_trace(trace_dwc3_ep0, "failed to map request\n");
dwc3_trace(trace_dwc3_ep0, "failed to map request");
return;
}
......@@ -1008,7 +1005,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
if (ret) {
dwc3_trace(trace_dwc3_ep0, "failed to map request\n");
dwc3_trace(trace_dwc3_ep0, "failed to map request");
return;
}
......@@ -1058,7 +1055,7 @@ static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
cmd |= DWC3_DEPCMD_CMDIOC;
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
WARN_ON_ONCE(ret);
dep->resource_index = 0;
}
......@@ -1112,11 +1109,8 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
u8 epnum = event->endpoint_number;
dwc3_trace(trace_dwc3_ep0, "%s while ep%d%s in state '%s'",
dwc3_ep_event_string(event->endpoint_event),
epnum >> 1, (epnum & 1) ? "in" : "out",
dwc3_trace(trace_dwc3_ep0, "%s: state '%s'",
dwc3_ep_event_string(event),
dwc3_ep0_state_string(dwc->ep0state));
switch (event->endpoint_event) {
......
This diff is collapsed.
......@@ -95,11 +95,11 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
*
* Caller should take care of locking
*/
static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3 *dwc, u8 number)
static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep)
{
u32 res_id;
res_id = dwc3_readl(dwc->regs, DWC3_DEPCMD(number));
res_id = dwc3_readl(dep->regs, DWC3_DEPCMD);
return DWC3_DEPCMD_GET_RSC_IDX(res_id);
}
......
......@@ -26,7 +26,6 @@
static inline u32 dwc3_readl(void __iomem *base, u32 offset)
{
u32 offs = offset - DWC3_GLOBALS_REGS_START;
u32 value;
/*
......@@ -34,7 +33,7 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset)
* space, see dwc3_probe in core.c.
* However, the offsets are given starting from xHCI address space.
*/
value = readl(base + offs);
value = readl(base + offset - DWC3_GLOBALS_REGS_START);
/*
* When tracing we want to make it easy to find the correct address on
......@@ -49,14 +48,12 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset)
static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
{
u32 offs = offset - DWC3_GLOBALS_REGS_START;
/*
* We requested the mem region starting from the Globals address
* space, see dwc3_probe in core.c.
* However, the offsets are given starting from xHCI address space.
*/
writel(value, base + offs);
writel(value, base + offset - DWC3_GLOBALS_REGS_START);
/*
* When tracing we want to make it easy to find the correct address on
......
/**
* platform_data.h - USB DWC3 Platform Data Support
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/usb/ch9.h>
#include <linux/usb/otg.h>
struct dwc3_platform_data {
enum usb_device_speed maximum_speed;
enum usb_dr_mode dr_mode;
bool usb3_lpm_capable;
unsigned is_utmi_l1_suspend:1;
u8 hird_threshold;
u8 lpm_nyet_threshold;
unsigned disable_scramble_quirk:1;
unsigned has_lpm_erratum:1;
unsigned u2exit_lfps_quirk:1;
unsigned u2ss_inp3_quirk:1;
unsigned req_p1p2p3_quirk:1;
unsigned del_p1p2p3_quirk:1;
unsigned del_phy_power_chg_quirk:1;
unsigned lfps_filter_quirk:1;
unsigned rx_detect_poll_quirk:1;
unsigned dis_u3_susphy_quirk:1;
unsigned dis_u2_susphy_quirk:1;
unsigned dis_enblslpm_quirk:1;
unsigned dis_rxdet_inp3_quirk:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
u32 fladj_value;
const char *hsphy_interface;
};
......@@ -71,7 +71,8 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
TP_fast_assign(
__entry->event = event;
),
TP_printk("event %08x", __entry->event)
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event))
);
DEFINE_EVENT(dwc3_log_event, dwc3_event,
......@@ -85,21 +86,21 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
TP_STRUCT__entry(
__field(__u8, bRequestType)
__field(__u8, bRequest)
__field(__le16, wValue)
__field(__le16, wIndex)
__field(__le16, wLength)
__field(__u16, wValue)
__field(__u16, wIndex)
__field(__u16, wLength)
),
TP_fast_assign(
__entry->bRequestType = ctrl->bRequestType;
__entry->bRequest = ctrl->bRequest;
__entry->wValue = ctrl->wValue;
__entry->wIndex = ctrl->wIndex;
__entry->wLength = ctrl->wLength;
__entry->wValue = le16_to_cpu(ctrl->wValue);
__entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength);
),
TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
__entry->bRequestType, __entry->bRequest,
le16_to_cpu(__entry->wValue), le16_to_cpu(__entry->wIndex),
le16_to_cpu(__entry->wLength)
__entry->wValue, __entry->wIndex,
__entry->wLength
)
);
......@@ -166,37 +167,41 @@ DEFINE_EVENT(dwc3_log_request, dwc3_gadget_giveback,
);
DECLARE_EVENT_CLASS(dwc3_log_generic_cmd,
TP_PROTO(unsigned int cmd, u32 param),
TP_ARGS(cmd, param),
TP_PROTO(unsigned int cmd, u32 param, int status),
TP_ARGS(cmd, param, status),
TP_STRUCT__entry(
__field(unsigned int, cmd)
__field(u32, param)
__field(int, status)
),
TP_fast_assign(
__entry->cmd = cmd;
__entry->param = param;
__entry->status = status;
),
TP_printk("cmd '%s' [%d] param %08x",
TP_printk("cmd '%s' [%d] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
)
);
DEFINE_EVENT(dwc3_log_generic_cmd, dwc3_gadget_generic_cmd,
TP_PROTO(unsigned int cmd, u32 param),
TP_ARGS(cmd, param)
TP_PROTO(unsigned int cmd, u32 param, int status),
TP_ARGS(cmd, param, status)
);
DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
TP_PROTO(struct dwc3_ep *dep, unsigned int cmd,
struct dwc3_gadget_ep_cmd_params *params),
TP_ARGS(dep, cmd, params),
struct dwc3_gadget_ep_cmd_params *params, int cmd_status),
TP_ARGS(dep, cmd, params, cmd_status),
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__field(unsigned int, cmd)
__field(u32, param0)
__field(u32, param1)
__field(u32, param2)
__field(int, cmd_status)
),
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
......@@ -204,18 +209,20 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
__entry->param0 = params->param0;
__entry->param1 = params->param1;
__entry->param2 = params->param2;
__entry->cmd_status = cmd_status;
),
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x",
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2
__entry->param1, __entry->param2,
dwc3_ep_cmd_status_string(__entry->cmd_status)
)
);
DEFINE_EVENT(dwc3_log_gadget_ep_cmd, dwc3_gadget_ep_cmd,
TP_PROTO(struct dwc3_ep *dep, unsigned int cmd,
struct dwc3_gadget_ep_cmd_params *params),
TP_ARGS(dep, cmd, params)
struct dwc3_gadget_ep_cmd_params *params, int cmd_status),
TP_ARGS(dep, cmd, params, cmd_status)
);
DECLARE_EVENT_CLASS(dwc3_log_trb,
......@@ -224,6 +231,8 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__field(struct dwc3_trb *, trb)
__field(u32, allocated)
__field(u32, queued)
__field(u32, bpl)
__field(u32, bph)
__field(u32, size)
......@@ -232,14 +241,53 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__entry->trb = trb;
__entry->allocated = dep->allocated_requests;
__entry->queued = dep->queued_requests;
__entry->bpl = trb->bpl;
__entry->bph = trb->bph;
__entry->size = trb->size;
__entry->ctrl = trb->ctrl;
),
TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x",
__get_str(name), __entry->trb, __entry->bph, __entry->bpl,
__entry->size, __entry->ctrl
TP_printk("%s: %d/%d trb %p buf %08x%08x size %d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
__entry->size, __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
({char *s;
switch (__entry->ctrl & 0x3f0) {
case DWC3_TRBCTL_NORMAL:
s = "normal";
break;
case DWC3_TRBCTL_CONTROL_SETUP:
s = "setup";
break;
case DWC3_TRBCTL_CONTROL_STATUS2:
s = "status2";
break;
case DWC3_TRBCTL_CONTROL_STATUS3:
s = "status3";
break;
case DWC3_TRBCTL_CONTROL_DATA:
s = "data";
break;
case DWC3_TRBCTL_ISOCHRONOUS_FIRST:
s = "isoc-first";
break;
case DWC3_TRBCTL_ISOCHRONOUS:
s = "isoc";
break;
case DWC3_TRBCTL_LINK_TRB:
s = "link";
break;
default:
s = "UNKNOWN";
break;
} s; })
)
);
......
......@@ -114,7 +114,7 @@ config USB_GADGET_VBUS_DRAW
config USB_GADGET_STORAGE_NUM_BUFFERS
int "Number of storage pipeline buffers"
range 2 32
range 2 256
default 2
help
Usually 2 buffers are enough to establish a good buffering
......
......@@ -93,7 +93,7 @@ int usb_gadget_config_buf(
*cp = *config;
/* then interface/endpoint/class/vendor/... */
len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf,
length - USB_DT_CONFIG_SIZE, desc);
if (len < 0)
return len;
......
......@@ -130,6 +130,12 @@ struct ffs_epfile {
struct dentry *dentry;
/*
* Buffer for holding data from partial reads which may happen since
* we’re rounding user read requests to a multiple of a max packet size.
*/
struct ffs_buffer *read_buffer; /* P: epfile->mutex */
char name[5];
unsigned char in; /* P: ffs->eps_lock */
......@@ -138,6 +144,12 @@ struct ffs_epfile {
unsigned char _pad;
};
struct ffs_buffer {
size_t length;
char *data;
char storage[];
};
/* ffs_io_data structure ***************************************************/
struct ffs_io_data {
......@@ -640,6 +652,49 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
}
}
static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter)
{
ssize_t ret = copy_to_iter(data, data_len, iter);
if (likely(ret == data_len))
return ret;
if (unlikely(iov_iter_count(iter)))
return -EFAULT;
/*
* Dear user space developer!
*
* TL;DR: To stop getting below error message in your kernel log, change
* user space code using functionfs to align read buffers to a max
* packet size.
*
* Some UDCs (e.g. dwc3) require request sizes to be a multiple of a max
* packet size. When unaligned buffer is passed to functionfs, it
* internally uses a larger, aligned buffer so that such UDCs are happy.
*
* Unfortunately, this means that host may send more data than was
* requested in read(2) system call. f_fs doesn’t know what to do with
* that excess data so it simply drops it.
*
* Was the buffer aligned in the first place, no such problem would
* happen.
*
* Data may be dropped only in AIO reads. Synchronous reads are handled
* by splitting a request into multiple parts. This splitting may still
* be a problem though so it’s likely best to align the buffer
* regardless of it being AIO or not..
*
* This only affects OUT endpoints, i.e. reading data with a read(2),
* aio_read(2) etc. system calls. Writing data to an IN endpoint is not
* affected.
*/
pr_err("functionfs read size %d > requested size %zd, dropping excess data. "
"Align read buffer size to max packet size to avoid the problem.\n",
data_len, ret);
return ret;
}
static void ffs_user_copy_worker(struct work_struct *work)
{
struct ffs_io_data *io_data = container_of(work, struct ffs_io_data,
......@@ -650,9 +705,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
if (io_data->read && ret > 0) {
use_mm(io_data->mm);
ret = copy_to_iter(io_data->buf, ret, &io_data->data);
if (ret != io_data->req->actual && iov_iter_count(&io_data->data))
ret = -EFAULT;
ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
unuse_mm(io_data->mm);
}
......@@ -680,6 +733,58 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
schedule_work(&io_data->work);
}
/* Assumes epfile->mutex is held. */
static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile,
struct iov_iter *iter)
{
struct ffs_buffer *buf = epfile->read_buffer;
ssize_t ret;
if (!buf)
return 0;
ret = copy_to_iter(buf->data, buf->length, iter);
if (buf->length == ret) {
kfree(buf);
epfile->read_buffer = NULL;
} else if (unlikely(iov_iter_count(iter))) {
ret = -EFAULT;
} else {
buf->length -= ret;
buf->data += ret;
}
return ret;
}
/* Assumes epfile->mutex is held. */
static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
void *data, int data_len,
struct iov_iter *iter)
{
struct ffs_buffer *buf;
ssize_t ret = copy_to_iter(data, data_len, iter);
if (likely(data_len == ret))
return ret;
if (unlikely(iov_iter_count(iter)))
return -EFAULT;
/* See ffs_copy_to_iter for more context. */
pr_warn("functionfs read size %d > requested size %zd, splitting request into multiple reads.",
data_len, ret);
data_len -= ret;
buf = kmalloc(sizeof(*buf) + data_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf->length = data_len;
buf->data = buf->storage;
memcpy(buf->storage, data + ret, data_len);
epfile->read_buffer = buf;
return ret;
}
static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
{
struct ffs_epfile *epfile = file->private_data;
......@@ -709,21 +814,40 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
if (halt && epfile->isoc)
return -EINVAL;
/* We will be using request and read_buffer */
ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
if (unlikely(ret))
goto error;
/* Allocate & copy */
if (!halt) {
struct usb_gadget *gadget;
/*
* Do we have buffered data from previous partial read? Check
* that for synchronous case only because we do not have
* facility to ‘wake up’ a pending asynchronous read and push
* buffered data to it which we would need to make things behave
* consistently.
*/
if (!io_data->aio && io_data->read) {
ret = __ffs_epfile_read_buffered(epfile, &io_data->data);
if (ret)
goto error_mutex;
}
/*
* if we _do_ wait above, the epfile->ffs->gadget might be NULL
* before the waiting completes, so do not assign to 'gadget'
* earlier
*/
struct usb_gadget *gadget = epfile->ffs->gadget;
size_t copied;
gadget = epfile->ffs->gadget;
spin_lock_irq(&epfile->ffs->eps_lock);
/* In the meantime, endpoint got disabled or changed. */
if (epfile->ep != ep) {
spin_unlock_irq(&epfile->ffs->eps_lock);
return -ESHUTDOWN;
ret = -ESHUTDOWN;
goto error_lock;
}
data_len = iov_iter_count(&io_data->data);
/*
......@@ -735,22 +859,17 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
spin_unlock_irq(&epfile->ffs->eps_lock);
data = kmalloc(data_len, GFP_KERNEL);
if (unlikely(!data))
return -ENOMEM;
if (!io_data->read) {
copied = copy_from_iter(data, data_len, &io_data->data);
if (copied != data_len) {
ret = -EFAULT;
goto error;
}
if (unlikely(!data)) {
ret = -ENOMEM;
goto error_mutex;
}
if (!io_data->read &&
copy_from_iter(data, data_len, &io_data->data) != data_len) {
ret = -EFAULT;
goto error_mutex;
}
}
/* We will be using request */
ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
if (unlikely(ret))
goto error;
spin_lock_irq(&epfile->ffs->eps_lock);
if (epfile->ep != ep) {
......@@ -803,18 +922,13 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
interrupted = ep->status < 0;
}
/*
* XXX We may end up silently droping data here. Since data_len
* (i.e. req->length) may be bigger than len (after being
* rounded up to maxpacketsize), we may end up with more data
* then user space has space for.
*/
ret = interrupted ? -EINTR : ep->status;
if (io_data->read && ret > 0) {
ret = copy_to_iter(data, ret, &io_data->data);
if (!ret)
ret = -EFAULT;
}
if (interrupted)
ret = -EINTR;
else if (io_data->read && ep->status > 0)
ret = __ffs_epfile_read_data(epfile, data, ep->status,
&io_data->data);
else
ret = ep->status;
goto error_mutex;
} else if (!(req = usb_ep_alloc_request(ep->ep, GFP_KERNEL))) {
ret = -ENOMEM;
......@@ -980,6 +1094,8 @@ ffs_epfile_release(struct inode *inode, struct file *file)
ENTER();
kfree(epfile->read_buffer);
epfile->read_buffer = NULL;
ffs_data_closed(epfile->ffs);
return 0;
......@@ -1605,19 +1721,24 @@ static void ffs_func_eps_disable(struct ffs_function *func)
unsigned count = func->ffs->eps_count;
unsigned long flags;
spin_lock_irqsave(&func->ffs->eps_lock, flags);
do {
if (epfile)
mutex_lock(&epfile->mutex);
spin_lock_irqsave(&func->ffs->eps_lock, flags);
/* pending requests get nuked */
if (likely(ep->ep))
usb_ep_disable(ep->ep);
++ep;
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
if (epfile) {
epfile->ep = NULL;
kfree(epfile->read_buffer);
epfile->read_buffer = NULL;
mutex_unlock(&epfile->mutex);
++epfile;
}
} while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
}
static int ffs_func_eps_enable(struct ffs_function *func)
......@@ -2227,8 +2348,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
{
u32 str_count, needed_count, lang_count;
struct usb_gadget_strings **stringtabs, *t;
struct usb_string *strings, *s;
const char *data = _data;
struct usb_string *s;
ENTER();
......@@ -2286,7 +2407,6 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
stringtabs = vla_ptr(vlabuf, d, stringtabs);
t = vla_ptr(vlabuf, d, stringtab);
s = vla_ptr(vlabuf, d, strings);
strings = s;
}
/* For each language */
......
......@@ -2655,18 +2655,6 @@ void fsg_common_put(struct fsg_common *common)
}
EXPORT_SYMBOL_GPL(fsg_common_put);
/* check if fsg_num_buffers is within a valid range */
static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
{
#define FSG_MAX_NUM_BUFFERS 32
if (fsg_num_buffers >= 2 && fsg_num_buffers <= FSG_MAX_NUM_BUFFERS)
return 0;
pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
fsg_num_buffers, 2, FSG_MAX_NUM_BUFFERS);
return -EINVAL;
}
static struct fsg_common *fsg_common_setup(struct fsg_common *common)
{
if (!common) {
......@@ -2709,11 +2697,7 @@ static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n)
int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
{
struct fsg_buffhd *bh, *buffhds;
int i, rc;
rc = fsg_num_buffers_validate(n);
if (rc != 0)
return rc;
int i;
buffhds = kcalloc(n, sizeof(*buffhds), GFP_KERNEL);
if (!buffhds)
......@@ -3401,10 +3385,6 @@ static ssize_t fsg_opts_num_buffers_store(struct config_item *item,
if (ret)
goto end;
ret = fsg_num_buffers_validate(num);
if (ret)
goto end;
fsg_common_set_num_buffers(opts->common, num);
ret = len;
......
......@@ -907,7 +907,6 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
struct gs_port *port = tty->driver_data;
unsigned long flags;
int status;
pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
port->port_num, tty, count);
......@@ -917,7 +916,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
count = gs_buf_put(&port->port_write_buf, buf, count);
/* treat count == 0 as flush_chars() */
if (port->port_usb)
status = gs_start_tx(port);
gs_start_tx(port);
spin_unlock_irqrestore(&port->port_lock, flags);
return count;
......
......@@ -265,7 +265,7 @@ static void *functionfs_acquire_dev(struct ffs_dev *dev)
{
if (!try_module_get(THIS_MODULE))
return ERR_PTR(-ENOENT);
return NULL;
}
......@@ -275,7 +275,7 @@ static void functionfs_release_dev(struct ffs_dev *dev)
}
/*
* The caller of this function takes ffs_lock
* The caller of this function takes ffs_lock
*/
static int functionfs_ready_callback(struct ffs_data *ffs)
{
......@@ -294,12 +294,12 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
++missing_funcs;
gfs_registered = false;
}
return ret;
}
/*
* The caller of this function takes ffs_lock
* The caller of this function takes ffs_lock
*/
static void functionfs_closed_callback(struct ffs_data *ffs)
{
......@@ -347,17 +347,14 @@ static int gfs_bind(struct usb_composite_dev *cdev)
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{
struct f_rndis_opts *rndis_opts;
fi_rndis = usb_get_function_instance("rndis");
if (IS_ERR(fi_rndis)) {
ret = PTR_ERR(fi_rndis);
goto error;
}
rndis_opts = container_of(fi_rndis, struct f_rndis_opts,
func_inst);
#ifndef CONFIG_USB_FUNCTIONFS_ETH
net = rndis_opts->net;
net = container_of(fi_rndis, struct f_rndis_opts,
func_inst)->net;
#endif
}
#endif
......
......@@ -312,7 +312,7 @@ config USB_NET2272_DMA
If unsure, say "N" here. The driver works fine in PIO mode.
config USB_NET2280
tristate "NetChip 228x / PLX USB338x"
tristate "NetChip NET228x / PLX USB3x8x"
depends on PCI
help
NetChip 2280 / 2282 is a PCI based USB peripheral controller which
......@@ -322,6 +322,8 @@ config USB_NET2280
(for control transfers) and several endpoints with dedicated
functions.
PLX 2380 is a PCIe version of the PLX 2380.
PLX 3380 / 3382 is a PCIe based USB peripheral controller which
supports full, high speed USB 2.0 and super speed USB 3.0
data transfers.
......
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
udc-core-y := core.o trace.o
#
# USB peripheral controller drivers
#
......
......@@ -2340,7 +2340,6 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
struct udc_ep *ep;
struct udc_request *req;
struct udc_data_dma *td;
unsigned dma_done;
unsigned len;
ep = &dev->ep[ep_ix];
......@@ -2385,13 +2384,8 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
*/
if (use_dma_ppb_du) {
td = udc_get_last_dma_desc(req);
if (td) {
dma_done =
AMD_GETBITS(td->status,
UDC_DMA_IN_STS_BS);
/* don't care DMA done */
if (td)
req->req.actual = req->req.length;
}
} else {
/* assume all bytes transferred */
req->req.actual = req->req.length;
......@@ -3417,4 +3411,3 @@ module_pci_driver(udc_pci_driver);
MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
MODULE_AUTHOR("Thomas Dahlmann");
MODULE_LICENSE("GPL");
......@@ -1920,6 +1920,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
udc->errata = match->data;
udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc");
if (IS_ERR(udc->pmc))
udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc");
if (udc->errata && IS_ERR(udc->pmc))
return ERR_CAST(udc->pmc);
......
......@@ -57,7 +57,6 @@ static int bdc_submit_cmd(struct bdc *bdc, u32 cmd_sc,
u32 param0, u32 param1, u32 param2)
{
u32 temp, cmd_status;
int reset_bdc = 0;
int ret;
temp = bdc_readl(bdc->regs, BDC_CMDSC);
......@@ -94,7 +93,6 @@ static int bdc_submit_cmd(struct bdc *bdc, u32 cmd_sc,
case BDC_CMDS_INTL:
dev_err(bdc->dev, "BDC Internal error\n");
reset_bdc = 1;
ret = -ECONNRESET;
break;
......@@ -102,7 +100,6 @@ static int bdc_submit_cmd(struct bdc *bdc, u32 cmd_sc,
dev_err(bdc->dev,
"command timedout waited for %dusec\n",
BDC_CMD_TIMEOUT);
reset_bdc = 1;
ret = -ECONNRESET;
break;
default:
......
......@@ -81,7 +81,7 @@ static void ep_bd_list_free(struct bdc_ep *ep, u32 num_tabs)
continue;
}
if (!bd_table->start_bd) {
dev_dbg(bdc->dev, "bd dma pool not allocted\n");
dev_dbg(bdc->dev, "bd dma pool not allocated\n");
continue;
}
......@@ -702,11 +702,9 @@ static int ep0_queue(struct bdc_ep *ep, struct bdc_req *req)
/* Queue data stage */
static int ep0_queue_data_stage(struct bdc *bdc)
{
struct usb_request *ep0_usb_req;
struct bdc_ep *ep;
dev_dbg(bdc->dev, "%s\n", __func__);
ep0_usb_req = &bdc->ep0_req.usb_req;
ep = bdc->bdc_ep_array[1];
bdc->ep0_req.ep = ep;
bdc->ep0_req.usb_req.complete = NULL;
......@@ -1393,10 +1391,8 @@ static int ep0_set_sel(struct bdc *bdc,
{
struct bdc_ep *ep;
u16 wLength;
u16 wValue;
dev_dbg(bdc->dev, "%s\n", __func__);
wValue = le16_to_cpu(setup_pkt->wValue);
wLength = le16_to_cpu(setup_pkt->wLength);
if (unlikely(wLength != 6)) {
dev_err(bdc->dev, "%s Wrong wLength:%d\n", __func__, wLength);
......
......@@ -647,12 +647,10 @@ static int dummy_disable(struct usb_ep *_ep)
static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
gfp_t mem_flags)
{
struct dummy_ep *ep;
struct dummy_request *req;
if (!_ep)
return NULL;
ep = usb_ep_to_dummy_ep(_ep);
req = kzalloc(sizeof(*req), mem_flags);
if (!req)
......@@ -2444,9 +2442,6 @@ static int dummy_start(struct usb_hcd *hcd)
static void dummy_stop(struct usb_hcd *hcd)
{
struct dummy *dum;
dum = hcd_to_dummy_hcd(hcd)->dum;
device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
}
......
......@@ -1199,8 +1199,6 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
struct m66592 *m66592 = _m66592;
u16 intsts0;
u16 intenb0;
u16 brdysts, nrdysts, bempsts;
u16 brdyenb, nrdyenb, bempenb;
u16 savepipe;
u16 mask0;
......@@ -1224,12 +1222,10 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
mask0 = intsts0 & intenb0;
if (mask0) {
brdysts = m66592_read(m66592, M66592_BRDYSTS);
nrdysts = m66592_read(m66592, M66592_NRDYSTS);
bempsts = m66592_read(m66592, M66592_BEMPSTS);
brdyenb = m66592_read(m66592, M66592_BRDYENB);
nrdyenb = m66592_read(m66592, M66592_NRDYENB);
bempenb = m66592_read(m66592, M66592_BEMPENB);
u16 brdysts = m66592_read(m66592, M66592_BRDYSTS);
u16 bempsts = m66592_read(m66592, M66592_BEMPSTS);
u16 brdyenb = m66592_read(m66592, M66592_BRDYENB);
u16 bempenb = m66592_read(m66592, M66592_BEMPENB);
if (mask0 & M66592_VBINT) {
m66592_write(m66592, 0xffff & ~M66592_VBINT,
......@@ -1408,28 +1404,20 @@ static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int m66592_set_halt(struct usb_ep *_ep, int value)
{
struct m66592_ep *ep;
struct m66592_request *req;
struct m66592_ep *ep = container_of(_ep, struct m66592_ep, ep);
unsigned long flags;
int ret = 0;
ep = container_of(_ep, struct m66592_ep, ep);
req = list_entry(ep->queue.next, struct m66592_request, queue);
spin_lock_irqsave(&ep->m66592->lock, flags);
if (!list_empty(&ep->queue)) {
ret = -EAGAIN;
goto out;
}
if (value) {
} else if (value) {
ep->busy = 1;
pipe_stall(ep->m66592, ep->pipenum);
} else {
ep->busy = 0;
pipe_stop(ep->m66592, ep->pipenum);
}
out:
spin_unlock_irqrestore(&ep->m66592->lock, flags);
return ret;
}
......
......@@ -119,18 +119,14 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
struct mv_u3d_req *curr_req)
{
struct mv_u3d_trb *curr_trb;
dma_addr_t cur_deq_lo;
struct mv_u3d_ep_context *curr_ep_context;
int trb_complete, actual, remaining_length = 0;
int actual, remaining_length = 0;
int direction, ep_num;
int retval = 0;
u32 tmp, status, length;
curr_ep_context = &u3d->ep_context[index];
direction = index % 2;
ep_num = index / 2;
trb_complete = 0;
actual = curr_req->req.length;
while (!list_empty(&curr_req->trb_list)) {
......@@ -143,15 +139,10 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
}
curr_trb->trb_hw->ctrl.own = 0;
if (direction == MV_U3D_EP_DIR_OUT) {
if (direction == MV_U3D_EP_DIR_OUT)
tmp = ioread32(&u3d->vuc_regs->rxst[ep_num].statuslo);
cur_deq_lo =
ioread32(&u3d->vuc_regs->rxst[ep_num].curdeqlo);
} else {
else
tmp = ioread32(&u3d->vuc_regs->txst[ep_num].statuslo);
cur_deq_lo =
ioread32(&u3d->vuc_regs->txst[ep_num].curdeqlo);
}
status = tmp >> MV_U3D_XFERSTATUS_COMPLETE_SHIFT;
length = tmp & MV_U3D_XFERSTATUS_TRB_LENGTH_MASK;
......@@ -527,7 +518,6 @@ static int mv_u3d_ep_enable(struct usb_ep *_ep,
{
struct mv_u3d *u3d;
struct mv_u3d_ep *ep;
struct mv_u3d_ep_context *ep_context;
u16 max = 0;
unsigned maxburst = 0;
u32 epxcr, direction;
......@@ -548,9 +538,6 @@ static int mv_u3d_ep_enable(struct usb_ep *_ep,
_ep->maxburst = 1;
maxburst = _ep->maxburst;
/* Get the endpoint context address */
ep_context = (struct mv_u3d_ep_context *)ep->ep_context;
/* Set the max burst size */
switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
case USB_ENDPOINT_XFER_BULK:
......@@ -633,7 +620,6 @@ static int mv_u3d_ep_disable(struct usb_ep *_ep)
{
struct mv_u3d *u3d;
struct mv_u3d_ep *ep;
struct mv_u3d_ep_context *ep_context;
u32 epxcr, direction;
unsigned long flags;
......@@ -646,9 +632,6 @@ static int mv_u3d_ep_disable(struct usb_ep *_ep)
u3d = ep->u3d;
/* Get the endpoint context address */
ep_context = ep->ep_context;
direction = mv_u3d_ep_dir(ep);
/* nuke all pending requests (does flush) */
......
......@@ -129,7 +129,7 @@ static int process_ep_req(struct mv_udc *udc, int index,
{
struct mv_dtd *curr_dtd;
struct mv_dqh *curr_dqh;
int td_complete, actual, remaining_length;
int actual, remaining_length;
int i, direction;
int retval = 0;
u32 errors;
......@@ -139,7 +139,6 @@ static int process_ep_req(struct mv_udc *udc, int index,
direction = index % 2;
curr_dtd = curr_req->head;
td_complete = 0;
actual = curr_req->req.length;
for (i = 0; i < curr_req->dtd_count; i++) {
......@@ -412,11 +411,8 @@ static int req_to_dtd(struct mv_req *req)
unsigned count;
int is_last, is_first = 1;
struct mv_dtd *dtd, *last_dtd = NULL;
struct mv_udc *udc;
dma_addr_t dma;
udc = req->ep->udc;
do {
dtd = build_dtd(req, &count, &dma, &is_last);
if (dtd == NULL)
......@@ -567,7 +563,7 @@ static int mv_ep_disable(struct usb_ep *_ep)
struct mv_udc *udc;
struct mv_ep *ep;
struct mv_dqh *dqh;
u32 bit_pos, epctrlx, direction;
u32 epctrlx, direction;
unsigned long flags;
ep = container_of(_ep, struct mv_ep, ep);
......@@ -582,7 +578,6 @@ static int mv_ep_disable(struct usb_ep *_ep)
spin_lock_irqsave(&udc->lock, flags);
direction = ep_dir(ep);
bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
/* Reset the max packet length and the interrupt on Setup */
dqh->max_packet_length = 0;
......
......@@ -329,12 +329,10 @@ static int net2272_disable(struct usb_ep *_ep)
static struct usb_request *
net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
{
struct net2272_ep *ep;
struct net2272_request *req;
if (!_ep)
return NULL;
ep = container_of(_ep, struct net2272_ep, ep);
req = kzalloc(sizeof(*req), gfp_flags);
if (!req)
......@@ -348,10 +346,8 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
static void
net2272_free_request(struct usb_ep *_ep, struct usb_request *_req)
{
struct net2272_ep *ep;
struct net2272_request *req;
ep = container_of(_ep, struct net2272_ep, ep);
if (!_ep || !_req)
return;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment