diff options
Diffstat (limited to 'drivers/usb/mtu3')
| -rw-r--r-- | drivers/usb/mtu3/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3.h | 37 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_core.c | 2 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_debugfs.c | 43 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_dr.c | 4 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_gadget.c | 8 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_host.c | 33 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_hw_regs.h | 1 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_plat.c | 21 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_qmu.c | 53 | ||||
| -rw-r--r-- | drivers/usb/mtu3/mtu3_trace.h | 8 |
11 files changed, 140 insertions, 72 deletions
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index bf98fd36341d..d281da1cdbcc 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -21,7 +21,7 @@ config USB_MTU3 if USB_MTU3 choice - bool "MTU3 Mode Selection" + prompt "MTU3 Mode Selection" default USB_MTU3_DUAL_ROLE if (USB && USB_GADGET) default USB_MTU3_HOST if (USB && !USB_GADGET) default USB_MTU3_GADGET if (!USB && USB_GADGET) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 2d7b57e07eee..ba5a63669e5f 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -16,6 +16,7 @@ #include <linux/extcon.h> #include <linux/interrupt.h> #include <linux/list.h> +#include <linux/of.h> #include <linux/phy/phy.h> #include <linux/regulator/consumer.h> #include <linux/usb.h> @@ -64,7 +65,7 @@ struct mtu3_request; #define MTU3_U3_IP_SLOT_DEFAULT 2 #define MTU3_U2_IP_SLOT_DEFAULT 1 -/** +/* * IP TRUNK version * from 0x1003 version, USB3 Gen2 is supported, two changes affect driver: * 1. MAXPKT and MULTI bits layout of TXCSR1 and RXCSR1 are adjusted, @@ -73,9 +74,9 @@ struct mtu3_request; */ #define MTU3_TRUNK_VERS_1003 0x1003 -/** +/* * Normally the device works on HS or SS, to simplify fifo management, - * devide fifo into some 512B parts, use bitmap to manage it; And + * divide fifo into some 512B parts, use bitmap to manage it; And * 128 bits size of bitmap is large enough, that means it can manage * up to 64KB fifo size. * NOTE: MTU3_EP_FIFO_UNIT should be power of two @@ -84,13 +85,13 @@ struct mtu3_request; #define MTU3_FIFO_BIT_SIZE 128 #define MTU3_U2_IP_EP0_FIFO_SIZE 64 -/** +/* * Maximum size of ep0 response buffer for ch9 requests, * the SET_SEL request uses 6 so far, and GET_STATUS is 2 */ #define EP0_RESPONSE_BUF 6 -#define BULK_CLKS_CNT 4 +#define BULK_CLKS_CNT 6 /* device operated link and speed got from DEVICE_CONF register */ enum mtu3_speed { @@ -102,6 +103,7 @@ enum mtu3_speed { }; /** + * enum mtu3_g_ep0_state - endpoint 0 states * @MU3D_EP0_STATE_SETUP: waits for SETUP or received a SETUP * without data stage. * @MU3D_EP0_STATE_TX: IN data stage @@ -120,11 +122,12 @@ enum mtu3_g_ep0_state { }; /** - * MTU3_DR_FORCE_NONE: automatically switch host and periperal mode + * enum mtu3_dr_force_mode - indicates host/OTG operating mode + * @MTU3_DR_FORCE_NONE: automatically switch host and peripheral mode * by IDPIN signal. - * MTU3_DR_FORCE_HOST: force to enter host mode and override OTG + * @MTU3_DR_FORCE_HOST: force to enter host mode and override OTG * IDPIN signal. - * MTU3_DR_FORCE_DEVICE: force to enter peripheral mode. + * @MTU3_DR_FORCE_DEVICE: force to enter peripheral mode. */ enum mtu3_dr_force_mode { MTU3_DR_FORCE_NONE = 0, @@ -133,6 +136,7 @@ enum mtu3_dr_force_mode { }; /** + * struct mtu3_fifo_info - HW FIFO description and management data * @base: the base address of fifo * @limit: the bitmap size in bits * @bitmap: fifo bitmap in unit of @MTU3_EP_FIFO_UNIT @@ -144,7 +148,7 @@ struct mtu3_fifo_info { }; /** - * General Purpose Descriptor (GPD): + * struct qmu_gpd - General Purpose Descriptor (GPD): * The format of TX GPD is a little different from RX one. * And the size of GPD is 16 bytes. * @@ -178,11 +182,13 @@ struct qmu_gpd { } __packed; /** -* dma: physical base address of GPD segment -* start: virtual base address of GPD segment -* end: the last GPD element -* enqueue: the first empty GPD to use -* dequeue: the first completed GPD serviced by ISR +* struct mtu3_gpd_ring - GPD ring descriptor +* @dma: physical base address of GPD segment +* @start: virtual base address of GPD segment +* @end: the last GPD element +* @enqueue: the first empty GPD to use +* @dequeue: the first completed GPD serviced by ISR +* * NOTE: the size of GPD ring should be >= 2 */ struct mtu3_gpd_ring { @@ -194,6 +200,7 @@ struct mtu3_gpd_ring { }; /** +* struct otg_switch_mtk - OTG/dual-role switch management * @vbus: vbus 5V used by host mode * @edev: external connector used to detect vbus and iddig changes * @id_nb : notifier for iddig(idpin) detection @@ -221,6 +228,7 @@ struct otg_switch_mtk { }; /** + * struct ssusb_mtk - SuperSpeed USB descriptor (MTK) * @mac_base: register base address of device MAC, exclude xHCI's * @ippc_base: register base address of IP Power and Clock interface (IPPC) * @vusb33: usb3.3V shared by device/host IP @@ -267,6 +275,7 @@ struct ssusb_mtk { }; /** + * struct mtu3_ep - common mtu3 endpoint description * @fifo_size: it is (@slot + 1) * @fifo_seg_size * @fifo_seg_size: it is roundup_pow_of_two(@maxp) */ diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index a3a6282893d0..3a25ee18f144 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -290,7 +290,7 @@ static void mtu3_csr_init(struct mtu3 *mtu) /* delay about 0.1us from detecting reset to send chirp-K */ mtu3_clrbits(mbase, U3D_LINK_RESET_INFO, WTCHRP_MSK); - /* enable automatical HWRW from L1 */ + /* enable automatic HWRW from L1 */ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); } diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index f0de99858353..c003049bafbf 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -7,6 +7,7 @@ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> */ +#include <linux/string_choices.h> #include <linux/uaccess.h> #include "mtu3.h" @@ -256,16 +257,7 @@ static const struct mtu3_file_map mtu3_ep_files[] = { static int mtu3_ep_open(struct inode *inode, struct file *file) { - const char *file_name = file_dentry(file)->d_iname; - const struct mtu3_file_map *f_map; - int i; - - for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) { - f_map = &mtu3_ep_files[i]; - - if (strcmp(f_map->name, file_name) == 0) - break; - } + const struct mtu3_file_map *f_map = debugfs_get_aux(file); return single_open(file, f_map->show, inode->i_private); } @@ -288,17 +280,8 @@ static const struct debugfs_reg32 mtu3_prb_regs[] = { static int mtu3_probe_show(struct seq_file *sf, void *unused) { - const char *file_name = file_dentry(sf->file)->d_iname; struct mtu3 *mtu = sf->private; - const struct debugfs_reg32 *regs; - int i; - - for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { - regs = &mtu3_prb_regs[i]; - - if (strcmp(regs->name, file_name) == 0) - break; - } + const struct debugfs_reg32 *regs = debugfs_get_aux(sf->file); seq_printf(sf, "0x%04x - 0x%08x\n", (u32)regs->offset, mtu3_readl(mtu->ippc_base, (u32)regs->offset)); @@ -314,13 +297,11 @@ static int mtu3_probe_open(struct inode *inode, struct file *file) static ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { - const char *file_name = file_dentry(file)->d_iname; struct seq_file *sf = file->private_data; struct mtu3 *mtu = sf->private; - const struct debugfs_reg32 *regs; + const struct debugfs_reg32 *regs = debugfs_get_aux(file); char buf[32]; u32 val; - int i; if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) return -EFAULT; @@ -328,12 +309,6 @@ static ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf, if (kstrtou32(buf, 0, &val)) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { - regs = &mtu3_prb_regs[i]; - - if (strcmp(regs->name, file_name) == 0) - break; - } mtu3_writel(mtu->ippc_base, (u32)regs->offset, val); return count; @@ -358,8 +333,8 @@ static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu) for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { regs = &mtu3_prb_regs[i]; - debugfs_create_file(regs->name, 0644, dir_prb, - mtu, &mtu3_probe_fops); + debugfs_create_file_aux(regs->name, 0644, dir_prb, + mtu, regs, &mtu3_probe_fops); } mtu3_debugfs_regset(mtu, mtu->ippc_base, mtu3_prb_regs, @@ -379,8 +354,8 @@ static void mtu3_debugfs_create_ep_dir(struct mtu3_ep *mep, for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) { files = &mtu3_ep_files[i]; - debugfs_create_file(files->name, 0444, dir_ep, - mep, &mtu3_ep_fops); + debugfs_create_file_aux(files->name, 0444, dir_ep, + mep, files, &mtu3_ep_fops); } } @@ -479,7 +454,7 @@ static int ssusb_vbus_show(struct seq_file *sf, void *unused) struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; seq_printf(sf, "vbus state: %s\n(echo on/off)\n", - regulator_is_enabled(otg_sx->vbus) ? "on" : "off"); + str_on_off(regulator_is_enabled(otg_sx->vbus))); return 0; } diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 9b8aded3d95e..ffa5b9401dad 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,6 +7,7 @@ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> */ +#include <linux/string_choices.h> #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -109,7 +110,7 @@ int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) if (!vbus) return 0; - dev_dbg(ssusb->dev, "%s: turn %s\n", __func__, is_on ? "on" : "off"); + dev_dbg(ssusb->dev, "%s: turn %s\n", __func__, str_on_off(is_on)); if (is_on) { ret = regulator_enable(vbus); @@ -294,6 +295,7 @@ static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) role_sx_desc.get = ssusb_role_sw_get; role_sx_desc.fwnode = dev_fwnode(dev); role_sx_desc.driver_data = ssusb; + role_sx_desc.allow_userspace_control = true; otg_sx->role_sw = usb_role_switch_register(dev, &role_sx_desc); if (IS_ERR(otg_sx->role_sw)) return PTR_ERR(otg_sx->role_sw); diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index 80236e7b0895..bf73fbc29976 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -7,6 +7,7 @@ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> */ +#include <linux/string_choices.h> #include "mtu3.h" #include "mtu3_trace.h" @@ -23,7 +24,6 @@ __acquires(mep->mtu->lock) req->status = status; trace_mtu3_req_complete(mreq); - spin_unlock(&mtu->lock); /* ep0 makes use of PIO, needn't unmap it */ if (mep->epnum) @@ -32,6 +32,7 @@ __acquires(mep->mtu->lock) dev_dbg(mtu->dev, "%s complete req: %p, sts %d, %d/%d\n", mep->name, req, req->status, req->actual, req->length); + spin_unlock(&mtu->lock); usb_gadget_giveback_request(&mep->ep, req); spin_lock(&mtu->lock); } @@ -133,10 +134,9 @@ static int mtu3_ep_disable(struct mtu3_ep *mep) { struct mtu3 *mtu = mep->mtu; - mtu3_qmu_stop(mep); - /* abort all pending requests */ nuke(mep, -ESHUTDOWN); + mtu3_qmu_stop(mep); mtu3_deconfig_ep(mtu, mep); mtu3_gpd_ring_free(mep); @@ -491,7 +491,7 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on) unsigned long flags; dev_dbg(mtu->dev, "%s (%s) for %sactive device\n", __func__, - is_on ? "on" : "off", mtu->is_active ? "" : "in"); + str_on_off(is_on), mtu->is_active ? "" : "in"); pm_runtime_get_sync(mtu->dev); diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index f3903367a6a0..7c657ea2dabd 100644 --- a/drivers/usb/mtu3/mtu3_host.c +++ b/drivers/usb/mtu3/mtu3_host.c @@ -11,7 +11,8 @@ #include <linux/irq.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/regmap.h> #include "mtu3.h" @@ -33,6 +34,18 @@ #define WC0_SSUSB0_CDEN BIT(6) #define WC0_IS_SPM_EN BIT(1) +/* mt8195 */ +#define PERI_WK_CTRL0_8195 0x04 +#define WC0_IS_P_95 BIT(30) /* polarity */ +#define WC0_IS_C_95(x) ((u32)(((x) & 0x7) << 27)) +#define WC0_IS_EN_P3_95 BIT(26) +#define WC0_IS_EN_P2_95 BIT(25) + +#define PERI_WK_CTRL1_8195 0x20 +#define WC1_IS_C_95(x) ((u32)(((x) & 0xf) << 28)) +#define WC1_IS_P_95 BIT(12) +#define WC1_IS_EN_P0_95 BIT(6) + /* mt2712 etc */ #define PERI_SSUSB_SPM_CTRL 0x0 #define SSC_IP_SLEEP_EN BIT(4) @@ -43,6 +56,9 @@ enum ssusb_uwk_vers { SSUSB_UWK_V2, SSUSB_UWK_V1_1 = 101, /* specific revision 1.01 */ SSUSB_UWK_V1_2, /* specific revision 1.02 */ + SSUSB_UWK_V1_3, /* mt8195 IP0 */ + SSUSB_UWK_V1_5 = 105, /* mt8195 IP2 */ + SSUSB_UWK_V1_6, /* mt8195 IP3 */ }; /* @@ -69,6 +85,21 @@ static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk *ssusb, bool enable) msk = WC0_SSUSB0_CDEN | WC0_IS_SPM_EN; val = enable ? msk : 0; break; + case SSUSB_UWK_V1_3: + reg = ssusb->uwk_reg_base + PERI_WK_CTRL1_8195; + msk = WC1_IS_EN_P0_95 | WC1_IS_C_95(0xf) | WC1_IS_P_95; + val = enable ? (WC1_IS_EN_P0_95 | WC1_IS_C_95(0x1)) : 0; + break; + case SSUSB_UWK_V1_5: + reg = ssusb->uwk_reg_base + PERI_WK_CTRL0_8195; + msk = WC0_IS_EN_P2_95 | WC0_IS_C_95(0x7) | WC0_IS_P_95; + val = enable ? (WC0_IS_EN_P2_95 | WC0_IS_C_95(0x1)) : 0; + break; + case SSUSB_UWK_V1_6: + reg = ssusb->uwk_reg_base + PERI_WK_CTRL0_8195; + msk = WC0_IS_EN_P3_95 | WC0_IS_C_95(0x7) | WC0_IS_P_95; + val = enable ? (WC0_IS_EN_P3_95 | WC0_IS_C_95(0x1)) : 0; + break; case SSUSB_UWK_V2: reg = ssusb->uwk_reg_base + PERI_SSUSB_SPM_CTRL; msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN; diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index 519a58301f45..ee30ae0a4b54 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -128,6 +128,7 @@ #define TX_FIFOEMPTY BIT(24) #define TX_SENTSTALL BIT(22) #define TX_SENDSTALL BIT(21) +#define TX_FLUSHFIFO BIT(20) #define TX_TXPKTRDY BIT(16) #define TX_TXMAXPKTSZ_MSK GENMASK(10, 0) #define TX_TXMAXPKTSZ(x) ((x) & TX_TXMAXPKTSZ_MSK) diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index d78ae52b4e26..cc8a864dbd63 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -234,6 +234,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) clks[1].id = "ref_ck"; clks[2].id = "mcu_ck"; clks[3].id = "dma_ck"; + clks[4].id = "xhci_ck"; + clks[5].id = "frmcnt_ck"; ret = devm_clk_bulk_get_optional(dev, BULK_CLKS_CNT, clks); if (ret) return ret; @@ -305,7 +307,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled) goto out; - if (of_property_read_bool(node, "extcon")) { + if (of_property_present(node, "extcon")) { otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); if (IS_ERR(otg_sx->edev)) { return dev_err_probe(dev, PTR_ERR(otg_sx->edev), @@ -429,7 +431,6 @@ static int mtu3_probe(struct platform_device *pdev) } device_enable_async_suspend(dev); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); pm_runtime_forbid(dev); @@ -449,7 +450,7 @@ comm_init_err: return ret; } -static int mtu3_remove(struct platform_device *pdev) +static void mtu3_remove(struct platform_device *pdev) { struct ssusb_mtk *ssusb = platform_get_drvdata(pdev); @@ -467,8 +468,16 @@ static int mtu3_remove(struct platform_device *pdev) ssusb_gadget_exit(ssusb); ssusb_host_exit(ssusb); break; - default: - return -EINVAL; + case USB_DR_MODE_UNKNOWN: + /* + * This cannot happen because with dr_mode == + * USB_DR_MODE_UNKNOWN, .probe() doesn't succeed and so + * .remove() wouldn't be called at all. However (little + * surprising) the compiler isn't smart enough to see that, so + * we explicitly have this case item to not make the compiler + * wail about an unhandled enumeration value. + */ + break; } ssusb_rscs_exit(ssusb); @@ -476,8 +485,6 @@ static int mtu3_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - - return 0; } static int resume_ip_and_ports(struct ssusb_mtk *ssusb, pm_message_t msg) diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c index 2ea3157ddb6e..03f26589b056 100644 --- a/drivers/usb/mtu3/mtu3_qmu.c +++ b/drivers/usb/mtu3/mtu3_qmu.c @@ -210,6 +210,7 @@ static struct qmu_gpd *advance_enq_gpd(struct mtu3_gpd_ring *ring) return ring->enqueue; } +/* @dequeue may be NULL if ring is unallocated or freed */ static struct qmu_gpd *advance_deq_gpd(struct mtu3_gpd_ring *ring) { if (ring->dequeue < ring->end) @@ -220,8 +221,8 @@ static struct qmu_gpd *advance_deq_gpd(struct mtu3_gpd_ring *ring) return ring->dequeue; } -/* check if a ring is emtpy */ -static int gpd_ring_empty(struct mtu3_gpd_ring *ring) +/* check if a ring is empty */ +static bool gpd_ring_empty(struct mtu3_gpd_ring *ring) { struct qmu_gpd *enq = ring->enqueue; struct qmu_gpd *next; @@ -388,6 +389,9 @@ void mtu3_qmu_stop(struct mtu3_ep *mep) } mtu3_writel(mbase, qcsr, QMU_Q_STOP); + if (mep->is_in) + mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_FLUSHFIFO); + ret = readl_poll_timeout_atomic(mbase + qcsr, value, !(value & QMU_Q_ACTIVE), 1, 1000); if (ret) { @@ -395,6 +399,10 @@ void mtu3_qmu_stop(struct mtu3_ep *mep) return; } + /* flush fifo again to make sure the fifo is empty */ + if (mep->is_in) + mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_FLUSHFIFO); + dev_dbg(mtu->dev, "%s's qmu stop now!\n", mep->name); } @@ -460,6 +468,37 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) } /* + * when rx error happens (except zlperr), QMU will stop, and RQCPR saves + * the GPD encountered error, Done irq will arise after resuming QMU again. + */ +static void qmu_error_rx(struct mtu3 *mtu, u8 epnum) +{ + struct mtu3_ep *mep = mtu->out_eps + epnum; + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + struct qmu_gpd *gpd_current = NULL; + struct mtu3_request *mreq; + dma_addr_t cur_gpd_dma; + + cur_gpd_dma = read_rxq_cur_addr(mtu->mac_base, epnum); + gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); + + mreq = next_request(mep); + if (!mreq || mreq->gpd != gpd_current) { + dev_err(mtu->dev, "no correct RX req is found\n"); + return; + } + + mreq->request.status = -EAGAIN; + + /* by pass the current GDP */ + gpd_current->dw0_info |= cpu_to_le32(GPD_FLAGS_BPS | GPD_FLAGS_HWO); + mtu3_qmu_resume(mep); + + dev_dbg(mtu->dev, "%s EP%d, current=%p, req=%p\n", + __func__, epnum, gpd_current, mreq); +} + +/* * NOTE: request list maybe is already empty as following case: * queue_tx --> qmu_interrupt(clear interrupt pending, schedule tasklet)--> * queue_tx --> process_tasklet(meanwhile, the second one is transferred, @@ -484,7 +523,7 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum) dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n", __func__, epnum, gpd, gpd_current, ring->enqueue); - while (gpd != gpd_current && !GET_GPD_HWO(gpd)) { + while (gpd && gpd != gpd_current && !GET_GPD_HWO(gpd)) { mreq = next_request(mep); @@ -523,7 +562,7 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum) dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n", __func__, epnum, gpd, gpd_current, ring->enqueue); - while (gpd != gpd_current && !GET_GPD_HWO(gpd)) { + while (gpd && gpd != gpd_current && !GET_GPD_HWO(gpd)) { mreq = next_request(mep); @@ -564,14 +603,18 @@ static void qmu_exception_isr(struct mtu3 *mtu, u32 qmu_status) if ((qmu_status & RXQ_CSERR_INT) || (qmu_status & RXQ_LENERR_INT)) { errval = mtu3_readl(mbase, U3D_RQERRIR0); + mtu3_writel(mbase, U3D_RQERRIR0, errval); + for (i = 1; i < mtu->num_eps; i++) { if (errval & QMU_RX_CS_ERR(i)) dev_err(mtu->dev, "Rx %d CS error!\n", i); if (errval & QMU_RX_LEN_ERR(i)) dev_err(mtu->dev, "RX %d Length error\n", i); + + if (errval & (QMU_RX_CS_ERR(i) | QMU_RX_LEN_ERR(i))) + qmu_error_rx(mtu, i); } - mtu3_writel(mbase, U3D_RQERRIR0, errval); } if (qmu_status & RXQ_ZLPERR_INT) { diff --git a/drivers/usb/mtu3/mtu3_trace.h b/drivers/usb/mtu3/mtu3_trace.h index 03d2a9bac27e..89870175d635 100644 --- a/drivers/usb/mtu3/mtu3_trace.h +++ b/drivers/usb/mtu3/mtu3_trace.h @@ -26,7 +26,7 @@ TRACE_EVENT(mtu3_log, __vstring(msg, vaf->fmt, vaf->va) ), TP_fast_assign( - __assign_str(name, dev_name(dev)); + __assign_str(name); __assign_vstr(msg, vaf->fmt, vaf->va); ), TP_printk("%s: %s", __get_str(name), __get_str(msg)) @@ -127,7 +127,7 @@ DECLARE_EVENT_CLASS(mtu3_log_request, __field(int, no_interrupt) ), TP_fast_assign( - __assign_str(name, mreq->mep->name); + __assign_str(name); __entry->mreq = mreq; __entry->gpd = mreq->gpd; __entry->actual = mreq->request.actual; @@ -182,7 +182,7 @@ DECLARE_EVENT_CLASS(mtu3_log_gpd, __field(u32, dw3) ), TP_fast_assign( - __assign_str(name, mep->name); + __assign_str(name); __entry->gpd = gpd; __entry->dw0 = le32_to_cpu(gpd->dw0_info); __entry->dw1 = le32_to_cpu(gpd->next_gpd); @@ -226,7 +226,7 @@ DECLARE_EVENT_CLASS(mtu3_log_ep, __field(struct mtu3_gpd_ring *, gpd_ring) ), TP_fast_assign( - __assign_str(name, mep->name); + __assign_str(name); __entry->type = mep->type; __entry->slot = mep->slot; __entry->maxp = mep->ep.maxpacket; |
