Commit 958e052c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Felipe writes:

usb: changes for v4.16 merge window

Not many changes here, the most important being an improvement for TI's
AM57xx and DRA7xx devices which allows them to disable a metastability
workaround in situations where we know what's going on.

Other than that, we have a set of changes on Renesas UDC to make the
code a little easier to read and maintain while also better supporting
extcon framework.

The u_serial adaptation layer learned to use kfifo instead of cooking
its own FIFO implementation.

DWC3 learned to decode a few more USB requests on the trace output.
parents f7a5d7b3 8ada211d
......@@ -47,6 +47,8 @@ Optional properties:
from P0 to P1/P2/P3 without delay.
- snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
during HS transmit.
- snps,dis_metastability_quirk: when set, disable metastability workaround.
CAUTION: use only if you are absolutely sure of it.
- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
utmi_l1_suspend_n, false when asserts utmi_sleep_n
- snps,hird-threshold: HIRD threshold
......
......@@ -929,6 +929,7 @@ struct dwc2_hsotg {
int irq;
struct clk *clk;
struct reset_control *reset;
struct reset_control *reset_ecc;
unsigned int queuing_high_bandwidth:1;
unsigned int srp_success:1;
......@@ -971,6 +972,7 @@ struct dwc2_hsotg {
} flags;
struct list_head non_periodic_sched_inactive;
struct list_head non_periodic_sched_waiting;
struct list_head non_periodic_sched_active;
struct list_head *non_periodic_qh_ptr;
struct list_head periodic_sched_inactive;
......
......@@ -659,6 +659,10 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg,
list_for_each_entry(qh, &hsotg->non_periodic_sched_inactive,
qh_list_entry)
dev_dbg(hsotg->dev, " %p\n", qh);
dev_dbg(hsotg->dev, " NP waiting sched:\n");
list_for_each_entry(qh, &hsotg->non_periodic_sched_waiting,
qh_list_entry)
dev_dbg(hsotg->dev, " %p\n", qh);
dev_dbg(hsotg->dev, " NP active sched:\n");
list_for_each_entry(qh, &hsotg->non_periodic_sched_active,
qh_list_entry)
......@@ -1818,6 +1822,7 @@ static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg,
static void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg)
{
dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_inactive);
dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_waiting);
dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_active);
dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_inactive);
dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_ready);
......@@ -4998,6 +5003,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
/* Free memory for QH/QTD lists */
dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_inactive);
dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_waiting);
dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_active);
dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_inactive);
dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_ready);
......@@ -5159,6 +5165,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
/* Initialize the non-periodic schedule */
INIT_LIST_HEAD(&hsotg->non_periodic_sched_inactive);
INIT_LIST_HEAD(&hsotg->non_periodic_sched_waiting);
INIT_LIST_HEAD(&hsotg->non_periodic_sched_active);
/* Initialize the periodic schedule */
......
......@@ -314,12 +314,16 @@ struct dwc2_hs_transfer_time {
* descriptor and indicates original XferSize value for the
* descriptor
* @unreserve_timer: Timer for releasing periodic reservation.
* @wait_timer: Timer used to wait before re-queuing.
* @dwc2_tt: Pointer to our tt info (or NULL if no tt).
* @ttport: Port number within our tt.
* @tt_buffer_dirty True if clear_tt_buffer_complete is pending
* @unreserve_pending: True if we planned to unreserve but haven't yet.
* @schedule_low_speed: True if we have a low/full speed component (either the
* host is in low/full speed mode or do_split).
* @want_wait: We should wait before re-queuing; only matters for non-
* periodic transfers and is ignored for periodic ones.
* @wait_timer_cancel: Set to true to cancel the wait_timer.
*
* A Queue Head (QH) holds the static characteristics of an endpoint and
* maintains a list of transfers (QTDs) for that endpoint. A QH structure may
......@@ -354,11 +358,14 @@ struct dwc2_qh {
u32 desc_list_sz;
u32 *n_bytes;
struct timer_list unreserve_timer;
struct timer_list wait_timer;
struct dwc2_tt *dwc_tt;
int ttport;
unsigned tt_buffer_dirty:1;
unsigned unreserve_pending:1;
unsigned schedule_low_speed:1;
unsigned want_wait:1;
unsigned wait_timer_cancel:1;
};
/**
......@@ -389,6 +396,7 @@ struct dwc2_qh {
* @n_desc: Number of DMA descriptors for this QTD
* @isoc_frame_index_last: Last activated frame (packet) index, used in
* descriptor DMA mode only
* @num_naks: Number of NAKs received on this QTD.
* @urb: URB for this transfer
* @qh: Queue head for this QTD
* @qtd_list_entry: For linking to the QH's list of QTDs
......@@ -419,6 +427,7 @@ struct dwc2_qtd {
u8 error_count;
u8 n_desc;
u16 isoc_frame_index_last;
u16 num_naks;
struct dwc2_hcd_urb *urb;
struct dwc2_qh *qh;
struct list_head qtd_list_entry;
......
......@@ -53,6 +53,12 @@
#include "core.h"
#include "hcd.h"
/*
* If we get this many NAKs on a split transaction we'll slow down
* retransmission. A 1 here means delay after the first NAK.
*/
#define DWC2_NAKS_BEFORE_DELAY 3
/* This function is for debug only */
static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
{
......@@ -1201,11 +1207,25 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg,
/*
* Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
* interrupt. Re-start the SSPLIT transfer.
*
* Normally for non-periodic transfers we'll retry right away, but to
* avoid interrupt storms we'll wait before retrying if we've got
* several NAKs. If we didn't do this we'd retry directly from the
* interrupt handler and could end up quickly getting another
* interrupt (another NAK), which we'd retry.
*
* Note that in DMA mode software only gets involved to re-send NAKed
* transfers for split transactions, so we only need to apply this
* delaying logic when handling splits. In non-DMA mode presumably we
* might want a similar delay if someone can demonstrate this problem
* affects that code path too.
*/
if (chan->do_split) {
if (chan->complete_split)
qtd->error_count = 0;
qtd->complete_split = 0;
qtd->num_naks++;
qtd->qh->want_wait = qtd->num_naks >= DWC2_NAKS_BEFORE_DELAY;
dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NAK);
goto handle_nak_done;
}
......
......@@ -58,6 +58,9 @@
/* Wait this long before releasing periodic reservation */
#define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5))
/* If we get a NAK, wait this long before retrying */
#define DWC2_RETRY_WAIT_DELAY (msecs_to_jiffies(1))
/**
* dwc2_periodic_channel_available() - Checks that a channel is available for a
* periodic transfer
......@@ -1440,6 +1443,55 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
list_del_init(&qh->qh_list_entry);
}
/**
* dwc2_wait_timer_fn() - Timer function to re-queue after waiting
*
* As per the spec, a NAK indicates that "a function is temporarily unable to
* transmit or receive data, but will eventually be able to do so without need
* of host intervention".
*
* That means that when we encounter a NAK we're supposed to retry.
*
* ...but if we retry right away (from the interrupt handler that saw the NAK)
* then we can end up with an interrupt storm (if the other side keeps NAKing
* us) because on slow enough CPUs it could take us longer to get out of the
* interrupt routine than it takes for the device to send another NAK. That
* leads to a constant stream of NAK interrupts and the CPU locks.
*
* ...so instead of retrying right away in the case of a NAK we'll set a timer
* to retry some time later. This function handles that timer and moves the
* qh back to the "inactive" list, then queues transactions.
*
* @t: Pointer to wait_timer in a qh.
*/
static void dwc2_wait_timer_fn(struct timer_list *t)
{
struct dwc2_qh *qh = from_timer(qh, t, wait_timer);
struct dwc2_hsotg *hsotg = qh->hsotg;
unsigned long flags;
spin_lock_irqsave(&hsotg->lock, flags);
/*
* We'll set wait_timer_cancel to true if we want to cancel this
* operation in dwc2_hcd_qh_unlink().
*/
if (!qh->wait_timer_cancel) {
enum dwc2_transaction_type tr_type;
qh->want_wait = false;
list_move(&qh->qh_list_entry,
&hsotg->non_periodic_sched_inactive);
tr_type = dwc2_hcd_select_transactions(hsotg);
if (tr_type != DWC2_TRANSACTION_NONE)
dwc2_hcd_queue_transactions(hsotg, tr_type);
}
spin_unlock_irqrestore(&hsotg->lock, flags);
}
/**
* dwc2_qh_init() - Initializes a QH structure
*
......@@ -1468,6 +1520,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
/* Initialize QH */
qh->hsotg = hsotg;
timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0);
timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0);
qh->ep_type = ep_type;
qh->ep_is_in = ep_is_in;
......@@ -1628,6 +1681,16 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
dwc2_do_unreserve(hsotg, qh);
spin_unlock_irqrestore(&hsotg->lock, flags);
}
/*
* We don't have the lock so we can safely wait until the wait timer
* finishes. Of course, at this point in time we'd better have set
* wait_timer_active to false so if this timer was still pending it
* won't do anything anyway, but we want it to finish before we free
* memory.
*/
del_timer_sync(&qh->wait_timer);
dwc2_host_put_tt_info(hsotg, qh->dwc_tt);
if (qh->desc_list)
......@@ -1663,9 +1726,16 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
qh->start_active_frame = hsotg->frame_number;
qh->next_active_frame = qh->start_active_frame;
/* Always start in inactive schedule */
list_add_tail(&qh->qh_list_entry,
&hsotg->non_periodic_sched_inactive);
if (qh->want_wait) {
list_add_tail(&qh->qh_list_entry,
&hsotg->non_periodic_sched_waiting);
qh->wait_timer_cancel = false;
mod_timer(&qh->wait_timer,
jiffies + DWC2_RETRY_WAIT_DELAY + 1);
} else {
list_add_tail(&qh->qh_list_entry,
&hsotg->non_periodic_sched_inactive);
}
return 0;
}
......@@ -1695,6 +1765,9 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
dev_vdbg(hsotg->dev, "%s()\n", __func__);
/* If the wait_timer is pending, this will stop it from acting */
qh->wait_timer_cancel = true;
if (list_empty(&qh->qh_list_entry))
/* QH is not in a schedule */
return;
......@@ -1903,7 +1976,7 @@ void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
if (dwc2_qh_is_non_per(qh)) {
dwc2_hcd_qh_unlink(hsotg, qh);
if (!list_empty(&qh->qtd_list))
/* Add back to inactive non-periodic schedule */
/* Add back to inactive/waiting non-periodic schedule */
dwc2_hcd_qh_add(hsotg, qh);
return;
}
......
......@@ -221,6 +221,15 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
reset_control_deassert(hsotg->reset);
hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc");
if (IS_ERR(hsotg->reset_ecc)) {
ret = PTR_ERR(hsotg->reset_ecc);
dev_err(hsotg->dev, "error getting reset control for ecc %d\n", ret);
return ret;
}
reset_control_deassert(hsotg->reset_ecc);
/* Set default UTMI width */
hsotg->phyif = GUSBCFG_PHYIF16;
......@@ -319,6 +328,7 @@ static int dwc2_driver_remove(struct platform_device *dev)
dwc2_lowlevel_hw_disable(hsotg);
reset_control_assert(hsotg->reset);
reset_control_assert(hsotg->reset_ecc);
return 0;
}
......
......@@ -1062,6 +1062,9 @@ static void dwc3_get_properties(struct dwc3 *dwc)
device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
&dwc->fladj);
dwc->dis_metastability_quirk = device_property_read_bool(dev,
"snps,dis_metastability_quirk");
dwc->lpm_nyet_threshold = lpm_nyet_threshold;
dwc->tx_de_emphasis = tx_de_emphasis;
......
......@@ -796,7 +796,6 @@ struct dwc3_scratchpad_array {
* @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY
* @ulpi: pointer to ulpi interface
* @isoch_delay: wValue from Set Isochronous Delay request;
* @u2sel: parameter from Set SEL request.
* @u2pel: parameter from Set SEL request.
* @u1sel: parameter from Set SEL request.
......@@ -857,6 +856,7 @@ struct dwc3_scratchpad_array {
* 1 - -3.5dB de-emphasis
* 2 - No de-emphasis
* 3 - Reserved
* @dis_metastability_quirk: set to disable metastability quirk.
* @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable.
*/
......@@ -955,7 +955,6 @@ struct dwc3 {
enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state;
u16 isoch_delay;
u16 u2sel;
u16 u2pel;
u8 u1sel;
......@@ -1010,6 +1009,8 @@ struct dwc3 {
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
unsigned dis_metastability_quirk:1;
u16 imod_interval;
};
......
......@@ -247,6 +247,15 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
case USB_DEVICE_TEST_MODE:
s = "Test Mode";
break;
case USB_DEVICE_U1_ENABLE:
s = "U1 Enable";
break;
case USB_DEVICE_U2_ENABLE:
s = "U2 Enable";
break;
case USB_DEVICE_LTM_ENABLE:
s = "LTM Enable";
break;
default:
s = "UNKNOWN";
} s; }),
......
......@@ -736,11 +736,7 @@ static int dwc3_ep0_set_isoch_delay(struct dwc3 *dwc, struct usb_ctrlrequest *ct
if (wIndex || wLength)
return -EINVAL;
/*
* REVISIT It's unclear from Databook what to do with this
* value. For now, just cache it.
*/
dwc->isoch_delay = wValue;
dwc->gadget.isoch_delay = wValue;
return 0;
}
......
......@@ -2005,7 +2005,8 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
* STAR#9000525659: Clock Domain Crossing on DCTL in
* USB 2.0 Mode
*/
if (dwc->revision < DWC3_REVISION_220A) {
if (dwc->revision < DWC3_REVISION_220A &&
!dwc->dis_metastability_quirk) {
reg |= DWC3_DCFG_SUPERSPEED;
} else {
switch (speed) {
......@@ -3224,7 +3225,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
* is less than super speed because we don't have means, yet, to tell
* composite.c that we are USB 2.0 + LPM ECN.
*/
if (dwc->revision < DWC3_REVISION_220A)
if (dwc->revision < DWC3_REVISION_220A &&
!dwc->dis_metastability_quirk)
dev_info(dwc->dev, "changing max_speed on rev %08x\n",
dwc->revision);
......
......@@ -37,12 +37,12 @@ DECLARE_EVENT_CLASS(dwc3_log_io,
);
DEFINE_EVENT(dwc3_log_io, dwc3_readl,
TP_PROTO(void *base, u32 offset, u32 value),
TP_PROTO(void __iomem *base, u32 offset, u32 value),
TP_ARGS(base, offset, value)
);
DEFINE_EVENT(dwc3_log_io, dwc3_writel,
TP_PROTO(void *base, u32 offset, u32 value),
TP_PROTO(void __iomem *base, u32 offset, u32 value),
TP_ARGS(base, offset, value)
);
......
......@@ -266,6 +266,7 @@ static void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req)
}
static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
__releases(&ffs->ev.waitq.lock)
{
struct usb_request *req = ffs->ep0req;
int ret;
......@@ -458,6 +459,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
/* Called with ffs->ev.waitq.lock and ffs->mutex held, both released on exit. */
static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
size_t n)
__releases(&ffs->ev.waitq.lock)
{
/*
* n cannot be bigger than ffs->ev.count, which cannot be bigger than
......@@ -543,6 +545,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
break;
}
/* unlocks spinlock */
return __ffs_ep0_read_events(ffs, buf,
min(n, (size_t)ffs->ev.count));
......@@ -1246,7 +1249,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
desc = epfile->ep->descs[desc_idx];
spin_unlock_irq(&epfile->ffs->eps_lock);
ret = copy_to_user((void *)value, desc, desc->bLength);
ret = copy_to_user((void __user *)value, desc, desc->bLength);
if (ret)
ret = -EFAULT;
return ret;
......@@ -2324,7 +2327,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
length, pnl, type);
return -EINVAL;
}
pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
pdl = le32_to_cpu(*(__le32 *)((u8 *)data + 10 + pnl));
if (length != 14 + pnl + pdl) {
pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
length, pnl, pdl, type);
......@@ -2878,7 +2881,7 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
ext_prop->data_len = le32_to_cpu(*(u32 *)
ext_prop->data_len = le32_to_cpu(*(__le32 *)
usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
length = ext_prop->name_len + ext_prop->data_len + 14;
......
......@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/console.h>
#include <linux/kthread.h>
#include <linux/kfifo.h>
#include "u_serial.h"
......@@ -80,19 +81,11 @@
#define WRITE_BUF_SIZE 8192 /* TX only */
#define GS_CONSOLE_BUF_SIZE 8192
/* circular buffer */
struct gs_buf {
unsigned buf_size;
char *buf_buf;
char *buf_get;
char *buf_put;
};
/* console info */
struct gscons_info {
struct gs_port *port;
struct task_struct *console_thread;
struct gs_buf con_buf;
struct kfifo con_buf;
/* protect the buf and busy flag */
spinlock_t con_lock;
int req_busy;
......@@ -122,7 +115,7 @@ struct gs_port {
struct list_head write_pool;
int write_started;
int write_allocated;
struct gs_buf port_write_buf;
struct kfifo port_write_buf;
wait_queue_head_t drain_wait; /* wait while writes drain */
bool write_busy;
wait_queue_head_t close_wait;
......@@ -154,144 +147,6 @@ static struct portmaster {
/*-------------------------------------------------------------------------*/
/* Circular Buffer */
/*
* gs_buf_alloc
*
* Allocate a circular buffer and all associated memory.
*/
static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
{
gb->buf_buf = kmalloc(size, GFP_KERNEL);
if (gb->buf_buf == NULL)
return -ENOMEM;
gb->buf_size = size;
gb->buf_put = gb->buf_buf;
gb->buf_get = gb->buf_buf;
return 0;
}
/*
* gs_buf_free
*
* Free the buffer and all associated memory.
*/
static void gs_buf_free(struct gs_buf *gb)
{
kfree(gb->buf_buf);
gb->buf_buf = NULL;
}
/*
* gs_buf_clear
*
* Clear out all data in the circular buffer.
*/
static void gs_buf_clear(struct gs_buf *gb)
{
gb->buf_get = gb->buf_put;
/* equivalent to a get of all data available */
}
/*
* gs_buf_data_avail
*
* Return the number of bytes of data written into the circular
* buffer.
*/
static unsigned gs_buf_data_avail(struct gs_buf *gb)
{
return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
}
/*
* gs_buf_space_avail
*
* Return the number of bytes of space available in the circular
* buffer.
*/
static unsigned gs_buf_space_avail(struct gs_buf *gb)
{
return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
}
/*
* gs_buf_put
*
* Copy data data from a user buffer and put it into the circular buffer.
* Restrict to the amount of space available.
*
* Return the number of bytes copied.
*/
static unsigned
gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
{
unsigned len;
len = gs_buf_space_avail(gb);
if (count > len)
count = len;
if (count == 0)
return 0;
len = gb->buf_buf + gb->buf_size - gb->buf_put;
if (count > len) {
memcpy(gb->buf_put, buf, len);
memcpy(gb->buf_buf, buf+len, count - len);
gb->buf_put = gb->buf_buf + count - len;
} else {
memcpy(gb->buf_put, buf, count);
if (count < len)
gb->buf_put += count;
else /* count == len */
gb->buf_put = gb->buf_buf;
}
return count;
}
/*
* gs_buf_get
*
* Get data from the circular buffer and copy to the given buffer.
* Restrict to the amount of data available.
*
* Return the number of bytes copied.
*/
static unsigned
gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
{
unsigned len;
len = gs_buf_data_avail(gb);
if (count > len)
count = len;
if (count == 0)
return 0;
len = gb->buf_buf + gb->buf_size - gb->buf_get;
if (count > len) {
memcpy(buf, gb->buf_get, len);
memcpy(buf+len, gb->buf_buf, count - len);
gb->buf_get = gb->buf_buf + count - len;
} else {
memcpy(buf, gb->buf_get, count);
if (count < len)
gb->buf_get += count;
else /* count == len */
gb->buf_get = gb->buf_buf;
}
return count;
}
/*-------------------------------------------------------------------------*/
/* I/O glue between TTY (upper) and USB function (lower) driver layers */
/*
......@@ -346,11 +201,11 @@ gs_send_packet(struct gs_port *port, char *packet, unsigned size)
{
unsigned len;
len = gs_buf_data_avail(&port->port_write_buf);
len = kfifo_len(&port->port_write_buf);
if (len < size)
size = len;
if (size != 0)
size = gs_buf_get(&port->port_write_buf, packet, size);
size = kfifo_out(&port->port_write_buf, packet, size);
return size;
}
......@@ -398,7 +253,7 @@ __acquires(&port->port_lock)
req->length = len;
list_del(&req->list);
req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);
req->zero = kfifo_is_empty(&port->port_write_buf);
pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
port->port_num, len, *((u8 *)req->buf),
......@@ -787,10 +642,11 @@ static int gs_open(struct tty_struct *tty, struct file *file)
spin_lock_irq(&port->port_lock);
/* allocate circular buffer on first open */
if (port->port_write_buf.buf_buf == NULL) {
if (!kfifo_initialized(&port->port_write_buf)) {
spin_unlock_irq(&port->port_lock);
status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
status = kfifo_alloc(&port->port_write_buf,
WRITE_BUF_SIZE, GFP_KERNEL);
spin_lock_irq(&port->port_lock);
if (status) {
......@@ -839,7 +695,7 @@ static int gs_writes_finished(struct gs_port *p)
/* return true on disconnect or empty buffer */
spin_lock_irq(&p->port_lock);
cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf);
cond = (p->port_usb == NULL) || !kfifo_len(&p->port_write_buf);
spin_unlock_irq(&p->port_lock);
return cond;
......@@ -875,7 +731,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
/* wait for circular write buffer to drain, disconnect, or at
* most GS_CLOSE_TIMEOUT seconds; then discard the rest
*/
if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) {
if (kfifo_len(&port->port_write_buf) > 0 && gser) {
spin_unlock_irq(&port->port_lock);
wait_event_interruptible_timeout(port->drain_wait,
gs_writes_finished(port),
......@@ -889,9 +745,9 @@ static void gs_close(struct tty_struct *tty, struct file *file)
* let the push tasklet fire again until we're re-opened.
*/
if (gser == NULL)
gs_buf_free(&port->port_write_buf);
kfifo_free(&port->port_write_buf);
else
gs_buf_clear(&port->port_write_buf);
kfifo_reset(&port->port_write_buf);
port->port.tty = NULL;
......@@ -915,7 +771,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
spin_lock_irqsave(&port->port_lock, flags);
if (count)
count = gs_buf_put(&port->port_write_buf, buf, count);
count = kfifo_in(&port->port_write_buf, buf, count);
/* treat count == 0 as flush_chars() */
if (port->port_usb)
gs_start_tx(port);
......@@ -934,7 +790,7 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch)
port->port_num, tty, ch, __builtin_return_address(0));
spin_lock_irqsave(&port->port_lock, flags);
status = gs_buf_put(&port->port_write_buf, &ch, 1);
status = kfifo_put(&port->port_write_buf, ch);
spin_unlock_irqrestore(&port->port_lock, flags);
return status;
......@@ -961,7 +817,7 @@ static int gs_write_room(struct tty_struct *tty)
spin_lock_irqsave(&port->port_lock, flags);
if (port->port_usb)
room = gs_buf_space_avail(&port->port_write_buf);
room = kfifo_avail(&port->port_write_buf);
spin_unlock_irqrestore(&port->port_lock, flags);
pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
......@@ -977,7 +833,7 @@ static int gs_chars_in_buffer(struct tty_struct *tty)
int chars = 0;
spin_lock_irqsave(&port->port_lock, flags);
chars = gs_buf_data_avail(&port->port_write_buf);
chars = kfifo_len(&port->port_write_buf);
spin_unlock_irqrestore(&port->port_lock, flags);
pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
......@@ -1148,7 +1004,7 @@ static int gs_console_thread(void *data)
ep = port->port_usb->in;
spin_lock_irq(&info->con_lock);
count = gs_buf_data_avail(&info->con_buf);
count = kfifo_len(&info->con_buf);
size = ep->maxpacket;
if (count > 0 && !info->req_busy) {
......@@ -1156,7 +1012,7 @@ static int gs_console_thread(void *data)
if (count < size)
size = count;
xfer = gs_buf_get(&info->con_buf, req->buf, size);
xfer = kfifo_out(&info->con_buf, req->buf, size);
req->length = xfer;
spin_unlock(&info->con_lock);
......@@ -1192,7 +1048,7 @@ static int gs_console_setup(struct console *co, char *options)
info->req_busy = 0;
spin_lock_init(&info->con_lock);
status = gs_buf_alloc(&info->con_buf, GS_CONSOLE_BUF_SIZE);
status = kfifo_alloc(&info->con_buf, GS_CONSOLE_BUF_SIZE, GFP_KERNEL);
if (status) {
pr_err("%s: allocate console buffer failed\n", __func__);
return status;
......@@ -1202,7 +1058,7 @@ static int gs_console_setup(struct console *co, char *options)
co, "gs_console");
if (IS_ERR(info->console_thread)) {
pr_err("%s: cannot create console thread\n", __func__);
gs_buf_free(&info->con_buf);
kfifo_free(&info->con_buf);
return PTR_ERR(info->console_thread);
}
wake_up_process(info->console_thread);
......@@ -1217,7 +1073,7 @@ static void gs_console_write(struct console *co,
unsigned long flags;
spin_lock_irqsave(&info->con_lock, flags);
gs_buf_put(&info->con_buf, buf, count);
kfifo_in(&info->con_buf, buf, count);
spin_unlock_irqrestore(&info->con_lock, flags);
wake_up_process(info->console_thread);
......@@ -1256,7 +1112,7 @@ static void gserial_console_exit(void)
unregister_console(&gserial_cons);
if (!IS_ERR_OR_NULL(info->console_thread))
kthread_stop(info->console_thread);
gs_buf_free(&info->con_buf);
kfifo_free(&info->con_buf);
}
#else
......@@ -1529,7 +1385,7 @@ void gserial_disconnect(struct gserial *gser)
/* finally, free any unused/unusable I/O buffers */
spin_lock_irqsave(&port->port_lock, flags);
if (port->port.count == 0 && !port->openclose)
gs_buf_free(&port->port_write_buf);
kfifo_free(&port->port_write_buf);
gs_free_requests(gser->out, &port->read_pool, NULL);
gs_free_requests(gser->out, &port->read_queue, NULL);
gs_free_requests(gser->in, &port->write_pool, NULL);
......
......@@ -1470,7 +1470,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->setup_wLength = w_length;
dev->setup_out_ready = 0;
dev->setup_out_error = 0;
value = 0;
/* read DATA stage for OUT right away */
if (unlikely (!dev->setup_in && w_length)) {
......
......@@ -2385,10 +2385,8 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
goto out_uninit;
}
if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0,
dev_name(dev), udc) < 0) {
dev_err(dev, "error requesting IRQ #%d\n", irq);
goto out_uninit;
}
dev_name(dev), udc) < 0)
goto report_request_failure;
/* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */
for (i = 0; i < BCM63XX_NUM_IUDMA; i++) {
......@@ -2398,10 +2396,8 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
goto out_uninit;
}
if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0,
dev_name(dev), &udc->iudma[i]) < 0) {
dev_err(dev, "error requesting IRQ #%d\n", irq);
goto out_uninit;
}
dev_name(dev), &udc->iudma[i]) < 0)
goto report_request_failure;
}
bcm63xx_udc_init_debugfs(udc);
......@@ -2413,6 +2409,10 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
out_uninit:
bcm63xx_uninit_udc_hw(udc);
return rc;
report_request_failure:
dev_err(dev, "error requesting IRQ #%d\n", irq);
goto out_uninit;
}
/**
......
......@@ -925,20 +925,8 @@ static void dummy_udc_set_speed(struct usb_gadget *_gadget,
struct dummy *dum;
dum = gadget_dev_to_dummy(&_gadget->dev);
if (mod_data.is_super_speed)
dum->gadget.speed = min_t(u8, USB_SPEED_SUPER, speed);
else if (mod_data.is_high_speed)
dum->gadget.speed = min_t(u8, USB_SPEED_HIGH, speed);
else
dum->gadget.speed = USB_SPEED_FULL;
dum->gadget.speed = speed;
dummy_udc_update_ep0(dum);
if (dum->gadget.speed < speed)
dev_dbg(udc_dev(dum), "This device can perform faster"
" if you connect it to a %s port...\n",
usb_speed_string(speed));
}
static int dummy_udc_start(struct usb_gadget *g,
......@@ -2193,8 +2181,6 @@ static int dummy_hub_control(
USB_PORT_STAT_LOW_SPEED;
break;
default:
dum_hcd->dum->gadget.speed =
USB_SPEED_FULL;
break;
}
}
......
......@@ -1543,7 +1543,7 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
udc->ep0_state = WAIT_FOR_SETUP;
break;
case WAIT_FOR_SETUP:
ERR("Unexpect ep0 packets\n");
ERR("Unexpected ep0 packets\n");
break;
default:
ep0stall(udc);
......
......@@ -979,8 +979,6 @@ static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
max = ep->fifo_size;
do {
is_short = 0;
udccsr = udc_ep_readl(ep, UDCCSR);
if (udccsr & UDCCSR_PC) {
ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
......@@ -1134,7 +1132,6 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
if (unlikely(!_ep))
return -EINVAL;
dev = udc_usb_ep->dev;
ep = udc_usb_ep->pxa_ep;
if (unlikely(!ep))
return -EINVAL;
......
......@@ -225,6 +225,7 @@ DECLARE_EVENT_CLASS(udc_log_req,
__field(unsigned, short_not_ok)
__field(int, status)
__field(int, ret)
__field(struct usb_request *, req)
),
TP_fast_assign(
snprintf(__get_str(name), UDC_TRACE_STR_MAX, "%s", ep->name);
......@@ -238,9 +239,10 @@ DECLARE_EVENT_CLASS(udc_log_req,
__entry->short_not_ok = req->short_not_ok;
__entry->status = req->status;
__entry->ret = ret;
__entry->req = req;
),
TP_printk("%s: length %d/%d sgs %d/%d stream %d %s%s%s status %d --> %d",
__get_str(name), __entry->actual, __entry->length,
TP_printk("%s: req %p length %d/%d sgs %d/%d stream %d %s%s%s status %d --> %d",
__get_str(name),__entry->req, __entry->actual, __entry->length,
__entry->num_mapped_sgs, __entry->num_sgs, __entry->stream_id,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
......
......@@ -963,10 +963,8 @@ static struct usb_request *xudc_ep_alloc_request(struct usb_ep *_ep,
gfp_t gfp_flags)
{
struct xusb_ep *ep = to_xusb_ep(_ep);
struct xusb_udc *udc;
struct xusb_req *req;
udc = ep->udc;
req = kzalloc(sizeof(*req), gfp_flags);
if (!req)
return NULL;
......
......@@ -323,6 +323,14 @@ static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
return *phy == match_data;
}
static void usb_charger_init(struct usb_phy *usb_phy)
{
usb_phy->chg_type = UNKNOWN_TYPE;
usb_phy->chg_state = USB_CHARGER_DEFAULT;
usb_phy_set_default_current(usb_phy);
INIT_WORK(&usb_phy->chg_work, usb_phy_notify_charger_work);
}
static int usb_add_extcon(struct usb_phy *x)
{
int ret;
......@@ -406,10 +414,6 @@ static int usb_add_extcon(struct usb_phy *x)
}
}
usb_phy_set_default_current(x);
INIT_WORK(&x->chg_work, usb_phy_notify_charger_work);
x->chg_type = UNKNOWN_TYPE;
x->chg_state = USB_CHARGER_DEFAULT;
if (x->type_nb.notifier_call)
__usb_phy_get_charger_type(x);
......@@ -704,6 +708,7 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return -EINVAL;
}
usb_charger_init(x);
ret = usb_add_extcon(x);
if (ret)
return ret;
......@@ -749,6 +754,7 @@ int usb_add_phy_dev(struct usb_phy *x)
return -EINVAL;
}
usb_charger_init(x);
ret = usb_add_extcon(x);
if (ret)
return ret;
......
......@@ -581,6 +581,15 @@ static int usbhs_probe(struct platform_device *pdev)
break;
case USBHS_TYPE_RCAR_GEN3_WITH_PLL:
priv->pfunc = usbhs_rcar3_with_pll_ops;
if (!IS_ERR_OR_NULL(priv->edev)) {
priv->nb.notifier_call = priv->pfunc.notifier;
ret = devm_extcon_register_notifier(&pdev->dev,
priv->edev,
EXTCON_USB_HOST,
&priv->nb);
if (ret < 0)
dev_err(&pdev->dev, "no notifier registered\n");
}
break;
default:
if (!info->platform_callback.get_id) {
......
......@@ -249,6 +249,7 @@ struct usbhs_priv {
struct platform_device *pdev;
struct extcon_dev *edev;
struct notifier_block nb;
spinlock_t lock;
......
......@@ -94,8 +94,6 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
return list_first_entry_or_null(&pipe->list, struct usbhs_pkt, node);
}
static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
struct usbhs_fifo *fifo);
static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
struct usbhs_fifo *fifo);
static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo,
......@@ -124,10 +122,11 @@ struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
chan = usbhsf_dma_chan_get(fifo, pkt);
if (chan) {
dmaengine_terminate_all(chan);
usbhsf_fifo_clear(pipe, fifo);
usbhsf_dma_unmap(pkt);
}
usbhs_pipe_clear_without_sequence(pipe, 0, 0);
__usbhsf_pkt_del(pkt);
}
......@@ -256,15 +255,9 @@ static void usbhsf_send_terminator(struct usbhs_pipe *pipe,
static int usbhsf_fifo_barrier(struct usbhs_priv *priv,
struct usbhs_fifo *fifo)
{
int timeout = 1024;
do {
/* The FIFO port is accessible */
if (usbhs_read(priv, fifo->ctr) & FRDY)
return 0;
udelay(10);
} while (timeout--);
/* The FIFO port is accessible */
if (usbhs_read(priv, fifo->ctr) & FRDY)
return 0;
return -EBUSY;
}
......@@ -278,8 +271,8 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
if (!usbhs_pipe_is_dcp(pipe)) {
/*
* This driver checks the pipe condition first to avoid -EBUSY
* from usbhsf_fifo_barrier() with about 10 msec delay in
* the interrupt handler if the pipe is RX direction and empty.
* from usbhsf_fifo_barrier() if the pipe is RX direction and
* empty.
*/
if (usbhs_pipe_is_dir_in(pipe))
ret = usbhs_pipe_is_accessible(pipe);
......
......@@ -590,10 +590,22 @@ void usbhs_pipe_clear(struct usbhs_pipe *pipe)
}
}
void usbhs_pipe_config_change_bfre(struct usbhs_pipe *pipe, int enable)
/* Should call usbhsp_pipe_select() before */
void usbhs_pipe_clear_without_sequence(struct usbhs_pipe *pipe,
int needs_bfre, int bfre_enable)
{
int sequence;
usbhsp_pipe_select(pipe);
sequence = usbhs_pipe_get_data_sequence(pipe);
if (needs_bfre)
usbhsp_pipe_cfg_set(pipe, BFRE, bfre_enable ? BFRE : 0);
usbhs_pipe_clear(pipe);
usbhs_pipe_data_sequence(pipe, sequence);
}
void usbhs_pipe_config_change_bfre(struct usbhs_pipe *pipe, int enable)
{
if (usbhs_pipe_is_dcp(pipe))
return;
......@@ -602,10 +614,7 @@ void usbhs_pipe_config_change_bfre(struct usbhs_pipe *pipe, int enable)
if (!(enable ^ !!(usbhsp_pipe_cfg_get(pipe) & BFRE)))
return;
sequence = usbhs_pipe_get_data_sequence(pipe);
usbhsp_pipe_cfg_set(pipe, BFRE, enable ? BFRE : 0);
usbhs_pipe_clear(pipe);
usbhs_pipe_data_sequence(pipe, sequence);
usbhs_pipe_clear_without_sequence(pipe, 1, enable);
}
static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
......
......@@ -80,6 +80,8 @@ void usbhs_pipe_init(struct usbhs_priv *priv,
struct usbhs_pkt *pkt, int map));
int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
void usbhs_pipe_clear(struct usbhs_pipe *pipe);
void usbhs_pipe_clear_without_sequence(struct usbhs_pipe *pipe,
int needs_bfre, int bfre_enable);
int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe);
void usbhs_pipe_enable(struct usbhs_pipe *pipe);
void usbhs_pipe_disable(struct usbhs_pipe *pipe);
......
......@@ -27,6 +27,7 @@
* Remarks: bit[31:11] and bit[9:6] should be 0
*/
#define UGCTRL2_RESERVED_3 0x00000001 /* bit[3:0] should be B'0001 */
#define UGCTRL2_USB0SEL_EHCI 0x00000010
#define UGCTRL2_USB0SEL_HSUSB 0x00000020
#define UGCTRL2_USB0SEL_OTG 0x00000030
#define UGCTRL2_VBUSSEL 0x00000400
......@@ -44,13 +45,25 @@ static u32 usbhs_read32(struct usbhs_priv *priv, u32 reg)
return ioread32(priv->base + reg);
}
static void usbhs_rcar3_set_ugctrl2(struct usbhs_priv *priv, u32 val)
{
usbhs_write32(priv, UGCTRL2, val | UGCTRL2_RESERVED_3);
}
static void usbhs_rcar3_set_usbsel(struct usbhs_priv *priv, bool ehci)
{
if (ehci)
usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_EHCI);
else
usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_HSUSB);
}
static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
void __iomem *base, int enable)
{
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
usbhs_write32(priv, UGCTRL2, UGCTRL2_RESERVED_3 | UGCTRL2_USB0SEL_OTG |
UGCTRL2_VBUSSEL);
usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL);
if (enable) {
usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
......@@ -70,11 +83,14 @@ static int usbhs_rcar3_power_and_pll_ctrl(struct platform_device *pdev,
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
u32 val;
int timeout = 1000;
bool is_host = false;
if (enable) {
usbhs_write32(priv, UGCTRL, 0); /* release PLLRESET */
usbhs_write32(priv, UGCTRL2, UGCTRL2_RESERVED_3 |
UGCTRL2_USB0SEL_HSUSB);
if (priv->edev)
is_host = extcon_get_state(priv->edev, EXTCON_USB_HOST);
usbhs_rcar3_set_usbsel(priv, is_host);
usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
do {
......@@ -96,6 +112,16 @@ static int usbhs_rcar3_get_id(struct platform_device *pdev)
return USBHS_GADGET;
}
static int usbhs_rcar3_notifier(struct notifier_block *nb, unsigned long event,
void *data)
{
struct usbhs_priv *priv = container_of(nb, struct usbhs_priv, nb);
usbhs_rcar3_set_usbsel(priv, !!event);
return NOTIFY_DONE;
}
const struct renesas_usbhs_platform_callback usbhs_rcar3_ops = {
.power_ctrl = usbhs_rcar3_power_ctrl,
.get_id = usbhs_rcar3_get_id,
......@@ -104,4 +130,5 @@ const struct renesas_usbhs_platform_callback usbhs_rcar3_ops = {
const struct renesas_usbhs_platform_callback usbhs_rcar3_with_pll_ops = {
.power_ctrl = usbhs_rcar3_power_and_pll_ctrl,
.get_id = usbhs_rcar3_get_id,
.notifier = usbhs_rcar3_notifier,
};
......@@ -330,6 +330,7 @@ struct usb_gadget_ops {
* @name: Identifies the controller hardware type. Used in diagnostics
* and sometimes configuration.
* @dev: Driver model state for this abstract device.
* @isoch_delay: value from Set Isoch Delay request. Only valid on SS/SSP
* @out_epnum: last used out ep number
* @in_epnum: last used in ep number
* @mA: last set mA value
......@@ -394,6 +395,7 @@ struct usb_gadget {
enum usb_device_state state;
const char *name;
struct device dev;
unsigned isoch_delay;
unsigned out_epnum;
unsigned in_epnum;
unsigned mA;
......
......@@ -17,6 +17,7 @@
*/
#ifndef RENESAS_USB_H
#define RENESAS_USB_H
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/usb/ch9.h>
......@@ -98,6 +99,13 @@ struct renesas_usbhs_platform_callback {
* VBUS control is needed for Host
*/
int (*set_vbus)(struct platform_device *pdev, int enable);
/*
* option:
* extcon notifier to set host/peripheral mode.
*/
int (*notifier)(struct notifier_block *nb, unsigned long event,
void *data);
};
/*
......
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