提交 58059921 编写于 作者: L Linus Torvalds

Merge tag 'usb-4.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB/PHY fixes from Greg KH:
 "Here are a small number of USB and PHY driver fixes for 4.14-rc6

  There is the usual musb and xhci fixes in here, as well as some needed
  phy patches. Also is a nasty regression fix for usbfs that has started
  to hit a lot of people using virtual machines.

  All of these have been in linux-next with no reported problems"

* tag 'usb-4.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits)
  usb: hub: Allow reset retry for USB2 devices on connect bounce
  USB: core: fix out-of-bounds access bug in usb_get_bos_descriptor()
  MAINTAINERS: fix git tree url for musb module
  usb: quirks: add quirk for WORLDE MINI MIDI keyboard
  usb: musb: sunxi: Explicitly release USB PHY on exit
  usb: musb: Check for host-mode using is_host_active() on reset interrupt
  usb: musb: musb_cppi41: Configure the number of channels for DA8xx
  usb: musb: musb_cppi41: Fix cppi41_set_dma_mode() for DA8xx
  usb: musb: musb_cppi41: Fix the address of teardown and autoreq registers
  USB: musb: fix late external abort on suspend
  USB: musb: fix session-bit runtime-PM quirk
  usb: cdc_acm: Add quirk for Elatec TWN3
  USB: devio: Revert "USB: devio: Don't corrupt user memory"
  usb: xhci: Handle error condition in xhci_stop_device()
  usb: xhci: Reset halted endpoint if trb is noop
  xhci: Cleanup current_cmd in xhci_cleanup_command_queue()
  xhci: Identify USB 3.1 capable hosts by their port protocol capability
  USB: serial: metro-usb: add MS7820 device id
  phy: rockchip-typec: Check for errors from tcphy_phy_init()
  phy: rockchip-typec: Don't set the aux voltage swing to 400 mV
  ...
...@@ -9213,7 +9213,6 @@ F: include/linux/isicom.h ...@@ -9213,7 +9213,6 @@ F: include/linux/isicom.h
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Bin Liu <b-liu@ti.com> M: Bin Liu <b-liu@ti.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained S: Maintained
F: drivers/usb/musb/ F: drivers/usb/musb/
......
...@@ -111,6 +111,8 @@ ...@@ -111,6 +111,8 @@
#define MVEBU_COMPHY_CONF6_40B BIT(18) #define MVEBU_COMPHY_CONF6_40B BIT(18)
#define MVEBU_COMPHY_SELECTOR 0x1140 #define MVEBU_COMPHY_SELECTOR 0x1140
#define MVEBU_COMPHY_SELECTOR_PHY(n) ((n) * 0x4) #define MVEBU_COMPHY_SELECTOR_PHY(n) ((n) * 0x4)
#define MVEBU_COMPHY_PIPE_SELECTOR 0x1144
#define MVEBU_COMPHY_PIPE_SELECTOR_PIPE(n) ((n) * 0x4)
#define MVEBU_COMPHY_LANES 6 #define MVEBU_COMPHY_LANES 6
#define MVEBU_COMPHY_PORTS 3 #define MVEBU_COMPHY_PORTS 3
...@@ -468,13 +470,17 @@ static int mvebu_comphy_power_on(struct phy *phy) ...@@ -468,13 +470,17 @@ static int mvebu_comphy_power_on(struct phy *phy)
{ {
struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
struct mvebu_comphy_priv *priv = lane->priv; struct mvebu_comphy_priv *priv = lane->priv;
int ret; int ret, mux;
u32 mux, val; u32 val;
mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode); mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode);
if (mux < 0) if (mux < 0)
return -ENOTSUPP; return -ENOTSUPP;
regmap_read(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, &val);
val &= ~(0xf << MVEBU_COMPHY_PIPE_SELECTOR_PIPE(lane->id));
regmap_write(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, val);
regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val); regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val);
val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id)); val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id); val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id);
...@@ -526,6 +532,10 @@ static int mvebu_comphy_power_off(struct phy *phy) ...@@ -526,6 +532,10 @@ static int mvebu_comphy_power_off(struct phy *phy)
val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id)); val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
regmap_read(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, &val);
val &= ~(0xf << MVEBU_COMPHY_PIPE_SELECTOR_PIPE(lane->id));
regmap_write(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, val);
return 0; return 0;
} }
...@@ -576,8 +586,8 @@ static int mvebu_comphy_probe(struct platform_device *pdev) ...@@ -576,8 +586,8 @@ static int mvebu_comphy_probe(struct platform_device *pdev)
return PTR_ERR(priv->regmap); return PTR_ERR(priv->regmap);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res); priv->base = devm_ioremap_resource(&pdev->dev, res);
if (!priv->base) if (IS_ERR(priv->base))
return -ENOMEM; return PTR_ERR(priv->base);
for_each_available_child_of_node(pdev->dev.of_node, child) { for_each_available_child_of_node(pdev->dev.of_node, child) {
struct mvebu_comphy_lane *lane; struct mvebu_comphy_lane *lane;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
/* banks shared by multiple phys */ /* banks shared by multiple phys */
#define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */ #define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */
#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */ #define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */
#define SSUSB_SIFSLV_V1_CHIP 0x300 /* shared by u3 phys */
/* u2 phy bank */ /* u2 phy bank */
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000 #define SSUSB_SIFSLV_V1_U2PHY_COM 0x000
/* u3/pcie/sata phy banks */ /* u3/pcie/sata phy banks */
...@@ -762,7 +763,7 @@ static void phy_v1_banks_init(struct mtk_tphy *tphy, ...@@ -762,7 +763,7 @@ static void phy_v1_banks_init(struct mtk_tphy *tphy,
case PHY_TYPE_USB3: case PHY_TYPE_USB3:
case PHY_TYPE_PCIE: case PHY_TYPE_PCIE:
u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC; u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
u3_banks->chip = NULL; u3_banks->chip = tphy->sif_base + SSUSB_SIFSLV_V1_CHIP;
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD; u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA; u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA;
break; break;
......
...@@ -443,14 +443,34 @@ static inline int property_enable(struct rockchip_typec_phy *tcphy, ...@@ -443,14 +443,34 @@ static inline int property_enable(struct rockchip_typec_phy *tcphy,
return regmap_write(tcphy->grf_regs, reg->offset, val | mask); return regmap_write(tcphy->grf_regs, reg->offset, val | mask);
} }
static void tcphy_dp_aux_set_flip(struct rockchip_typec_phy *tcphy)
{
u16 tx_ana_ctrl_reg_1;
/*
* Select the polarity of the xcvr:
* 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull
* down aux_m)
* 0, Normal polarity (if TYPEC, pulls up aux_m and pulls down
* aux_p)
*/
tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
if (!tcphy->flip)
tx_ana_ctrl_reg_1 |= BIT(12);
else
tx_ana_ctrl_reg_1 &= ~BIT(12);
writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
}
static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
{ {
u16 tx_ana_ctrl_reg_1;
u16 rdata, rdata2, val; u16 rdata, rdata2, val;
/* disable txda_cal_latch_en for rewrite the calibration values */ /* disable txda_cal_latch_en for rewrite the calibration values */
rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
val = rdata & 0xdfff; tx_ana_ctrl_reg_1 &= ~BIT(13);
writel(val, tcphy->base + TX_ANA_CTRL_REG_1); writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
/* /*
* read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and
...@@ -472,9 +492,8 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) ...@@ -472,9 +492,8 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
* Activate this signal for 1 clock cycle to sample new calibration * Activate this signal for 1 clock cycle to sample new calibration
* values. * values.
*/ */
rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); tx_ana_ctrl_reg_1 |= BIT(13);
val = rdata | 0x2000; writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
usleep_range(150, 200); usleep_range(150, 200);
/* set TX Voltage Level and TX Deemphasis to 0 */ /* set TX Voltage Level and TX Deemphasis to 0 */
...@@ -482,8 +501,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) ...@@ -482,8 +501,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
/* re-enable decap */ /* re-enable decap */
writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2); writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2); writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1); tx_ana_ctrl_reg_1 |= BIT(3);
writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1); writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 |= BIT(4);
writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
writel(0, tcphy->base + TX_ANA_CTRL_REG_5); writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
...@@ -494,8 +515,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) ...@@ -494,8 +515,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4); writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
/* re-enables Bandgap reference for LDO */ /* re-enables Bandgap reference for LDO */
writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1); tx_ana_ctrl_reg_1 |= BIT(7);
writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1); writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 |= BIT(8);
writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
/* /*
* re-enables the transmitter pre-driver, driver data selection MUX, * re-enables the transmitter pre-driver, driver data selection MUX,
...@@ -505,27 +528,26 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) ...@@ -505,27 +528,26 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2); writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
/* /*
* BIT 12: Controls auxda_polarity, which selects the polarity of the * Do some magic undocumented stuff, some of which appears to
* xcvr: * undo the "re-enables Bandgap reference for LDO" above.
* 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull
* down aux_m)
* 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down
* aux_p)
*/ */
val = 0xa078; tx_ana_ctrl_reg_1 |= BIT(15);
if (!tcphy->flip) tx_ana_ctrl_reg_1 &= ~BIT(8);
val |= BIT(12); tx_ana_ctrl_reg_1 &= ~BIT(7);
writel(val, tcphy->base + TX_ANA_CTRL_REG_1); tx_ana_ctrl_reg_1 |= BIT(6);
tx_ana_ctrl_reg_1 |= BIT(5);
writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
writel(0, tcphy->base + TX_ANA_CTRL_REG_3); writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
writel(0, tcphy->base + TX_ANA_CTRL_REG_4); writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
writel(0, tcphy->base + TX_ANA_CTRL_REG_5); writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
/* /*
* Controls low_power_swing_en, set the voltage swing of the driver * Controls low_power_swing_en, don't set the voltage swing of the
* to 400mv. The values below are peak to peak (differential) values. * driver to 400mv. The values below are peak to peak (differential)
* values.
*/ */
writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL); writel(0, tcphy->base + TXDA_COEFF_CALC_CTRL);
writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA); writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
/* Controls tx_high_z_tm_en */ /* Controls tx_high_z_tm_en */
...@@ -555,6 +577,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode) ...@@ -555,6 +577,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
reset_control_deassert(tcphy->tcphy_rst); reset_control_deassert(tcphy->tcphy_rst);
property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip); property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
tcphy_dp_aux_set_flip(tcphy);
tcphy_cfg_24m(tcphy); tcphy_cfg_24m(tcphy);
...@@ -685,8 +708,11 @@ static int rockchip_usb3_phy_power_on(struct phy *phy) ...@@ -685,8 +708,11 @@ static int rockchip_usb3_phy_power_on(struct phy *phy)
if (tcphy->mode == new_mode) if (tcphy->mode == new_mode)
goto unlock_ret; goto unlock_ret;
if (tcphy->mode == MODE_DISCONNECT) if (tcphy->mode == MODE_DISCONNECT) {
tcphy_phy_init(tcphy, new_mode); ret = tcphy_phy_init(tcphy, new_mode);
if (ret)
goto unlock_ret;
}
/* wait TCPHY for pipe ready */ /* wait TCPHY for pipe ready */
for (timeout = 0; timeout < 100; timeout++) { for (timeout = 0; timeout < 100; timeout++) {
...@@ -760,10 +786,12 @@ static int rockchip_dp_phy_power_on(struct phy *phy) ...@@ -760,10 +786,12 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
*/ */
if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) { if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) {
tcphy_phy_deinit(tcphy); tcphy_phy_deinit(tcphy);
tcphy_phy_init(tcphy, new_mode); ret = tcphy_phy_init(tcphy, new_mode);
} else if (tcphy->mode == MODE_DISCONNECT) { } else if (tcphy->mode == MODE_DISCONNECT) {
tcphy_phy_init(tcphy, new_mode); ret = tcphy_phy_init(tcphy, new_mode);
} }
if (ret)
goto unlock_ret;
ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
val, val & DP_MODE_A2, 1000, val, val & DP_MODE_A2, 1000,
......
...@@ -454,6 +454,8 @@ tegra_xusb_find_port_node(struct tegra_xusb_padctl *padctl, const char *type, ...@@ -454,6 +454,8 @@ tegra_xusb_find_port_node(struct tegra_xusb_padctl *padctl, const char *type,
char *name; char *name;
name = kasprintf(GFP_KERNEL, "%s-%u", type, index); name = kasprintf(GFP_KERNEL, "%s-%u", type, index);
if (!name)
return ERR_PTR(-ENOMEM);
np = of_find_node_by_name(np, name); np = of_find_node_by_name(np, name);
kfree(name); kfree(name);
} }
......
...@@ -1832,6 +1832,9 @@ static const struct usb_device_id acm_ids[] = { ...@@ -1832,6 +1832,9 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
}, },
{ USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */
.driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */
},
{ USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
.driver_info = CLEAR_HALT_CONDITIONS, .driver_info = CLEAR_HALT_CONDITIONS,
......
...@@ -960,10 +960,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) ...@@ -960,10 +960,12 @@ int usb_get_bos_descriptor(struct usb_device *dev)
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
buffer += length; buffer += length;
cap = (struct usb_dev_cap_header *)buffer; cap = (struct usb_dev_cap_header *)buffer;
length = cap->bLength;
if (total_len < length) if (total_len < sizeof(*cap) || total_len < cap->bLength) {
dev->bos->desc->bNumDeviceCaps = i;
break; break;
}
length = cap->bLength;
total_len -= length; total_len -= length;
if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
......
...@@ -1576,11 +1576,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb ...@@ -1576,11 +1576,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
totlen += isopkt[u].length; totlen += isopkt[u].length;
} }
u *= sizeof(struct usb_iso_packet_descriptor); u *= sizeof(struct usb_iso_packet_descriptor);
if (totlen <= uurb->buffer_length) uurb->buffer_length = totlen;
uurb->buffer_length = totlen;
else
WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d",
totlen, uurb->buffer_length);
break; break;
default: default:
......
...@@ -2710,13 +2710,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, ...@@ -2710,13 +2710,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
if (!(portstatus & USB_PORT_STAT_CONNECTION)) if (!(portstatus & USB_PORT_STAT_CONNECTION))
return -ENOTCONN; return -ENOTCONN;
/* bomb out completely if the connection bounced. A USB 3.0 /* Retry if connect change is set but status is still connected.
* connection may bounce if multiple warm resets were issued, * A USB 3.0 connection may bounce if multiple warm resets were issued,
* but the device may have successfully re-connected. Ignore it. * but the device may have successfully re-connected. Ignore it.
*/ */
if (!hub_is_superspeed(hub->hdev) && if (!hub_is_superspeed(hub->hdev) &&
(portchange & USB_PORT_STAT_C_CONNECTION)) (portchange & USB_PORT_STAT_C_CONNECTION)) {
return -ENOTCONN; usb_clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_CONNECTION);
return -EAGAIN;
}
if (!(portstatus & USB_PORT_STAT_ENABLE)) if (!(portstatus & USB_PORT_STAT_ENABLE))
return -EBUSY; return -EBUSY;
......
...@@ -221,6 +221,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -221,6 +221,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Corsair Strafe RGB */ /* Corsair Strafe RGB */
{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT },
/* MIDI keyboard WORLDE MINI */
{ USB_DEVICE(0x1c75, 0x0204), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
/* Acer C120 LED Projector */ /* Acer C120 LED Projector */
{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
......
...@@ -420,14 +420,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) ...@@ -420,14 +420,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
GFP_NOWAIT); GFP_NOWAIT);
if (!command) { if (!command) {
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
xhci_free_command(xhci, cmd); ret = -ENOMEM;
return -ENOMEM; goto cmd_cleanup;
}
ret = xhci_queue_stop_endpoint(xhci, command, slot_id,
i, suspend);
if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_free_command(xhci, command);
goto cmd_cleanup;
} }
xhci_queue_stop_endpoint(xhci, command, slot_id, i,
suspend);
} }
} }
xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); ret = xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
goto cmd_cleanup;
}
xhci_ring_cmd_db(xhci); xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
...@@ -439,6 +450,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) ...@@ -439,6 +450,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
ret = -ETIME; ret = -ETIME;
} }
cmd_cleanup:
xhci_free_command(xhci, cmd); xhci_free_command(xhci, cmd);
return ret; return ret;
} }
......
...@@ -1309,6 +1309,7 @@ static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 status) ...@@ -1309,6 +1309,7 @@ static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 status)
void xhci_cleanup_command_queue(struct xhci_hcd *xhci) void xhci_cleanup_command_queue(struct xhci_hcd *xhci)
{ {
struct xhci_command *cur_cmd, *tmp_cmd; struct xhci_command *cur_cmd, *tmp_cmd;
xhci->current_cmd = NULL;
list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list, cmd_list) list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list, cmd_list)
xhci_complete_del_and_free_cmd(cur_cmd, COMP_COMMAND_ABORTED); xhci_complete_del_and_free_cmd(cur_cmd, COMP_COMMAND_ABORTED);
} }
...@@ -2579,15 +2580,21 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2579,15 +2580,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
(struct xhci_generic_trb *) ep_trb); (struct xhci_generic_trb *) ep_trb);
/* /*
* No-op TRB should not trigger interrupts. * No-op TRB could trigger interrupts in a case where
* If ep_trb is a no-op TRB, it means the * a URB was killed and a STALL_ERROR happens right
* corresponding TD has been cancelled. Just ignore * after the endpoint ring stopped. Reset the halted
* the TD. * endpoint. Otherwise, the endpoint remains stalled
* indefinitely.
*/ */
if (trb_is_noop(ep_trb)) { if (trb_is_noop(ep_trb)) {
xhci_dbg(xhci, if (trb_comp_code == COMP_STALL_ERROR ||
"ep_trb is a no-op TRB. Skip it for slot %u ep %u\n", xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
slot_id, ep_index); trb_comp_code))
xhci_cleanup_halted_endpoint(xhci, slot_id,
ep_index,
ep_ring->stream_id,
td, ep_trb,
EP_HARD_RESET);
goto cleanup; goto cleanup;
} }
......
...@@ -4805,7 +4805,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) ...@@ -4805,7 +4805,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
*/ */
hcd->has_tt = 1; hcd->has_tt = 1;
} else { } else {
if (xhci->sbrn == 0x31) { /* Some 3.1 hosts return sbrn 0x30, can't rely on sbrn alone */
if (xhci->sbrn == 0x31 || xhci->usb3_rhub.min_rev >= 1) {
xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n"); xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n");
hcd->speed = HCD_USB31; hcd->speed = HCD_USB31;
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
......
...@@ -906,7 +906,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -906,7 +906,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
*/ */
if (int_usb & MUSB_INTR_RESET) { if (int_usb & MUSB_INTR_RESET) {
handled = IRQ_HANDLED; handled = IRQ_HANDLED;
if (devctl & MUSB_DEVCTL_HM) { if (is_host_active(musb)) {
/* /*
* When BABBLE happens what we can depends on which * When BABBLE happens what we can depends on which
* platform MUSB is running, because some platforms * platform MUSB is running, because some platforms
...@@ -916,9 +916,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -916,9 +916,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
* drop the session. * drop the session.
*/ */
dev_err(musb->controller, "Babble\n"); dev_err(musb->controller, "Babble\n");
musb_recover_from_babble(musb);
if (is_host_active(musb))
musb_recover_from_babble(musb);
} else { } else {
musb_dbg(musb, "BUS RESET as %s", musb_dbg(musb, "BUS RESET as %s",
usb_otg_state_string(musb->xceiv->otg->state)); usb_otg_state_string(musb->xceiv->otg->state));
...@@ -1861,22 +1859,22 @@ static void musb_pm_runtime_check_session(struct musb *musb) ...@@ -1861,22 +1859,22 @@ static void musb_pm_runtime_check_session(struct musb *musb)
MUSB_DEVCTL_HR; MUSB_DEVCTL_HR;
switch (devctl & ~s) { switch (devctl & ~s) {
case MUSB_QUIRK_B_INVALID_VBUS_91: case MUSB_QUIRK_B_INVALID_VBUS_91:
if (musb->quirk_retries--) { if (musb->quirk_retries && !musb->flush_irq_work) {
musb_dbg(musb, musb_dbg(musb,
"Poll devctl on invalid vbus, assume no session"); "Poll devctl on invalid vbus, assume no session");
schedule_delayed_work(&musb->irq_work, schedule_delayed_work(&musb->irq_work,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
musb->quirk_retries--;
return; return;
} }
/* fall through */ /* fall through */
case MUSB_QUIRK_A_DISCONNECT_19: case MUSB_QUIRK_A_DISCONNECT_19:
if (musb->quirk_retries--) { if (musb->quirk_retries && !musb->flush_irq_work) {
musb_dbg(musb, musb_dbg(musb,
"Poll devctl on possible host mode disconnect"); "Poll devctl on possible host mode disconnect");
schedule_delayed_work(&musb->irq_work, schedule_delayed_work(&musb->irq_work,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
musb->quirk_retries--;
return; return;
} }
if (!musb->session) if (!musb->session)
...@@ -2681,8 +2679,15 @@ static int musb_suspend(struct device *dev) ...@@ -2681,8 +2679,15 @@ static int musb_suspend(struct device *dev)
musb_platform_disable(musb); musb_platform_disable(musb);
musb_disable_interrupts(musb); musb_disable_interrupts(musb);
musb->flush_irq_work = true;
while (flush_delayed_work(&musb->irq_work))
;
musb->flush_irq_work = false;
if (!(musb->io.quirks & MUSB_PRESERVE_SESSION)) if (!(musb->io.quirks & MUSB_PRESERVE_SESSION))
musb_writeb(musb->mregs, MUSB_DEVCTL, 0); musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
WARN_ON(!list_empty(&musb->pending_list)); WARN_ON(!list_empty(&musb->pending_list));
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
......
...@@ -428,6 +428,8 @@ struct musb { ...@@ -428,6 +428,8 @@ struct musb {
unsigned test_mode:1; unsigned test_mode:1;
unsigned softconnect:1; unsigned softconnect:1;
unsigned flush_irq_work:1;
u8 address; u8 address;
u8 test_mode_nr; u8 test_mode_nr;
u16 ackpend; /* ep0 */ u16 ackpend; /* ep0 */
......
...@@ -26,15 +26,28 @@ ...@@ -26,15 +26,28 @@
#define MUSB_DMA_NUM_CHANNELS 15 #define MUSB_DMA_NUM_CHANNELS 15
#define DA8XX_USB_MODE 0x10
#define DA8XX_USB_AUTOREQ 0x14
#define DA8XX_USB_TEARDOWN 0x1c
#define DA8XX_DMA_NUM_CHANNELS 4
struct cppi41_dma_controller { struct cppi41_dma_controller {
struct dma_controller controller; struct dma_controller controller;
struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS]; struct cppi41_dma_channel *rx_channel;
struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS]; struct cppi41_dma_channel *tx_channel;
struct hrtimer early_tx; struct hrtimer early_tx;
struct list_head early_tx_list; struct list_head early_tx_list;
u32 rx_mode; u32 rx_mode;
u32 tx_mode; u32 tx_mode;
u32 auto_req; u32 auto_req;
u32 tdown_reg;
u32 autoreq_reg;
void (*set_dma_mode)(struct cppi41_dma_channel *cppi41_channel,
unsigned int mode);
u8 num_channels;
}; };
static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel) static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
...@@ -349,6 +362,32 @@ static void cppi41_set_dma_mode(struct cppi41_dma_channel *cppi41_channel, ...@@ -349,6 +362,32 @@ static void cppi41_set_dma_mode(struct cppi41_dma_channel *cppi41_channel,
} }
} }
static void da8xx_set_dma_mode(struct cppi41_dma_channel *cppi41_channel,
unsigned int mode)
{
struct cppi41_dma_controller *controller = cppi41_channel->controller;
struct musb *musb = controller->controller.musb;
unsigned int shift;
u32 port;
u32 new_mode;
u32 old_mode;
old_mode = controller->tx_mode;
port = cppi41_channel->port_num;
shift = (port - 1) * 4;
if (!cppi41_channel->is_tx)
shift += 16;
new_mode = old_mode & ~(3 << shift);
new_mode |= mode << shift;
if (new_mode == old_mode)
return;
controller->tx_mode = new_mode;
musb_writel(musb->ctrl_base, DA8XX_USB_MODE, new_mode);
}
static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel, static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel,
unsigned mode) unsigned mode)
{ {
...@@ -364,8 +403,8 @@ static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel, ...@@ -364,8 +403,8 @@ static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel,
if (new_mode == old_mode) if (new_mode == old_mode)
return; return;
controller->auto_req = new_mode; controller->auto_req = new_mode;
musb_writel(controller->controller.musb->ctrl_base, USB_CTRL_AUTOREQ, musb_writel(controller->controller.musb->ctrl_base,
new_mode); controller->autoreq_reg, new_mode);
} }
static bool cppi41_configure_channel(struct dma_channel *channel, static bool cppi41_configure_channel(struct dma_channel *channel,
...@@ -373,6 +412,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, ...@@ -373,6 +412,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
dma_addr_t dma_addr, u32 len) dma_addr_t dma_addr, u32 len)
{ {
struct cppi41_dma_channel *cppi41_channel = channel->private_data; struct cppi41_dma_channel *cppi41_channel = channel->private_data;
struct cppi41_dma_controller *controller = cppi41_channel->controller;
struct dma_chan *dc = cppi41_channel->dc; struct dma_chan *dc = cppi41_channel->dc;
struct dma_async_tx_descriptor *dma_desc; struct dma_async_tx_descriptor *dma_desc;
enum dma_transfer_direction direction; enum dma_transfer_direction direction;
...@@ -398,7 +438,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, ...@@ -398,7 +438,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
musb_writel(musb->ctrl_base, musb_writel(musb->ctrl_base,
RNDIS_REG(cppi41_channel->port_num), len); RNDIS_REG(cppi41_channel->port_num), len);
/* gen rndis */ /* gen rndis */
cppi41_set_dma_mode(cppi41_channel, controller->set_dma_mode(cppi41_channel,
EP_MODE_DMA_GEN_RNDIS); EP_MODE_DMA_GEN_RNDIS);
/* auto req */ /* auto req */
...@@ -407,14 +447,15 @@ static bool cppi41_configure_channel(struct dma_channel *channel, ...@@ -407,14 +447,15 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
} else { } else {
musb_writel(musb->ctrl_base, musb_writel(musb->ctrl_base,
RNDIS_REG(cppi41_channel->port_num), 0); RNDIS_REG(cppi41_channel->port_num), 0);
cppi41_set_dma_mode(cppi41_channel, controller->set_dma_mode(cppi41_channel,
EP_MODE_DMA_TRANSPARENT); EP_MODE_DMA_TRANSPARENT);
cppi41_set_autoreq_mode(cppi41_channel, cppi41_set_autoreq_mode(cppi41_channel,
EP_MODE_AUTOREQ_NONE); EP_MODE_AUTOREQ_NONE);
} }
} else { } else {
/* fallback mode */ /* fallback mode */
cppi41_set_dma_mode(cppi41_channel, EP_MODE_DMA_TRANSPARENT); controller->set_dma_mode(cppi41_channel,
EP_MODE_DMA_TRANSPARENT);
cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE); cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE);
len = min_t(u32, packet_sz, len); len = min_t(u32, packet_sz, len);
} }
...@@ -445,7 +486,7 @@ static struct dma_channel *cppi41_dma_channel_allocate(struct dma_controller *c, ...@@ -445,7 +486,7 @@ static struct dma_channel *cppi41_dma_channel_allocate(struct dma_controller *c,
struct cppi41_dma_channel *cppi41_channel = NULL; struct cppi41_dma_channel *cppi41_channel = NULL;
u8 ch_num = hw_ep->epnum - 1; u8 ch_num = hw_ep->epnum - 1;
if (ch_num >= MUSB_DMA_NUM_CHANNELS) if (ch_num >= controller->num_channels)
return NULL; return NULL;
if (is_tx) if (is_tx)
...@@ -581,12 +622,13 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) ...@@ -581,12 +622,13 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
do { do {
if (is_tx) if (is_tx)
musb_writel(musb->ctrl_base, USB_TDOWN, tdbit); musb_writel(musb->ctrl_base, controller->tdown_reg,
tdbit);
ret = dmaengine_terminate_all(cppi41_channel->dc); ret = dmaengine_terminate_all(cppi41_channel->dc);
} while (ret == -EAGAIN); } while (ret == -EAGAIN);
if (is_tx) { if (is_tx) {
musb_writel(musb->ctrl_base, USB_TDOWN, tdbit); musb_writel(musb->ctrl_base, controller->tdown_reg, tdbit);
csr = musb_readw(epio, MUSB_TXCSR); csr = musb_readw(epio, MUSB_TXCSR);
if (csr & MUSB_TXCSR_TXPKTRDY) { if (csr & MUSB_TXCSR_TXPKTRDY) {
...@@ -604,7 +646,7 @@ static void cppi41_release_all_dma_chans(struct cppi41_dma_controller *ctrl) ...@@ -604,7 +646,7 @@ static void cppi41_release_all_dma_chans(struct cppi41_dma_controller *ctrl)
struct dma_chan *dc; struct dma_chan *dc;
int i; int i;
for (i = 0; i < MUSB_DMA_NUM_CHANNELS; i++) { for (i = 0; i < ctrl->num_channels; i++) {
dc = ctrl->tx_channel[i].dc; dc = ctrl->tx_channel[i].dc;
if (dc) if (dc)
dma_release_channel(dc); dma_release_channel(dc);
...@@ -656,7 +698,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller) ...@@ -656,7 +698,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
goto err; goto err;
ret = -EINVAL; ret = -EINVAL;
if (port > MUSB_DMA_NUM_CHANNELS || !port) if (port > controller->num_channels || !port)
goto err; goto err;
if (is_tx) if (is_tx)
cppi41_channel = &controller->tx_channel[port - 1]; cppi41_channel = &controller->tx_channel[port - 1];
...@@ -697,6 +739,8 @@ void cppi41_dma_controller_destroy(struct dma_controller *c) ...@@ -697,6 +739,8 @@ void cppi41_dma_controller_destroy(struct dma_controller *c)
hrtimer_cancel(&controller->early_tx); hrtimer_cancel(&controller->early_tx);
cppi41_dma_controller_stop(controller); cppi41_dma_controller_stop(controller);
kfree(controller->rx_channel);
kfree(controller->tx_channel);
kfree(controller); kfree(controller);
} }
EXPORT_SYMBOL_GPL(cppi41_dma_controller_destroy); EXPORT_SYMBOL_GPL(cppi41_dma_controller_destroy);
...@@ -705,6 +749,7 @@ struct dma_controller * ...@@ -705,6 +749,7 @@ struct dma_controller *
cppi41_dma_controller_create(struct musb *musb, void __iomem *base) cppi41_dma_controller_create(struct musb *musb, void __iomem *base)
{ {
struct cppi41_dma_controller *controller; struct cppi41_dma_controller *controller;
int channel_size;
int ret = 0; int ret = 0;
if (!musb->controller->parent->of_node) { if (!musb->controller->parent->of_node) {
...@@ -727,12 +772,37 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base) ...@@ -727,12 +772,37 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base)
controller->controller.is_compatible = cppi41_is_compatible; controller->controller.is_compatible = cppi41_is_compatible;
controller->controller.musb = musb; controller->controller.musb = musb;
if (musb->io.quirks & MUSB_DA8XX) {
controller->tdown_reg = DA8XX_USB_TEARDOWN;
controller->autoreq_reg = DA8XX_USB_AUTOREQ;
controller->set_dma_mode = da8xx_set_dma_mode;
controller->num_channels = DA8XX_DMA_NUM_CHANNELS;
} else {
controller->tdown_reg = USB_TDOWN;
controller->autoreq_reg = USB_CTRL_AUTOREQ;
controller->set_dma_mode = cppi41_set_dma_mode;
controller->num_channels = MUSB_DMA_NUM_CHANNELS;
}
channel_size = controller->num_channels *
sizeof(struct cppi41_dma_channel);
controller->rx_channel = kzalloc(channel_size, GFP_KERNEL);
if (!controller->rx_channel)
goto rx_channel_alloc_fail;
controller->tx_channel = kzalloc(channel_size, GFP_KERNEL);
if (!controller->tx_channel)
goto tx_channel_alloc_fail;
ret = cppi41_dma_controller_start(controller); ret = cppi41_dma_controller_start(controller);
if (ret) if (ret)
goto plat_get_fail; goto plat_get_fail;
return &controller->controller; return &controller->controller;
plat_get_fail: plat_get_fail:
kfree(controller->tx_channel);
tx_channel_alloc_fail:
kfree(controller->rx_channel);
rx_channel_alloc_fail:
kfree(controller); kfree(controller);
kzalloc_fail: kzalloc_fail:
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
......
...@@ -297,6 +297,8 @@ static int sunxi_musb_exit(struct musb *musb) ...@@ -297,6 +297,8 @@ static int sunxi_musb_exit(struct musb *musb)
if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
sunxi_sram_release(musb->controller->parent); sunxi_sram_release(musb->controller->parent);
devm_usb_put_phy(glue->dev, glue->xceiv);
return 0; return 0;
} }
......
...@@ -45,6 +45,7 @@ struct metrousb_private { ...@@ -45,6 +45,7 @@ struct metrousb_private {
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) },
{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
{ USB_DEVICE_INTERFACE_CLASS(0x0c2e, 0x0730, 0xff) }, /* MS7820 */
{ }, /* Terminating entry. */ { }, /* Terminating entry. */
}; };
MODULE_DEVICE_TABLE(usb, id_table); MODULE_DEVICE_TABLE(usb, id_table);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册