Skip to content

Commit

Permalink
Merge tag 'usb-4.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  ...
  • Loading branch information
torvalds committed Oct 23, 2017
2 parents 02982f8 + 1ac7db6 commit 5805992
Show file tree
Hide file tree
Showing 18 changed files with 226 additions and 77 deletions.
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -9213,7 +9213,6 @@ F: include/linux/isicom.h
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Bin Liu <[email protected]>
L: [email protected]
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/musb/

Expand Down
18 changes: 14 additions & 4 deletions drivers/phy/marvell/phy-mvebu-cp110-comphy.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
#define MVEBU_COMPHY_CONF6_40B BIT(18)
#define MVEBU_COMPHY_SELECTOR 0x1140
#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_PORTS 3
Expand Down Expand Up @@ -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_priv *priv = lane->priv;
int ret;
u32 mux, val;
int ret, mux;
u32 val;

mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode);
if (mux < 0)
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);
val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id);
Expand Down Expand Up @@ -526,6 +532,10 @@ static int mvebu_comphy_power_off(struct phy *phy)
val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
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;
}

Expand Down Expand Up @@ -576,8 +586,8 @@ static int mvebu_comphy_probe(struct platform_device *pdev)
return PTR_ERR(priv->regmap);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res);
if (!priv->base)
return -ENOMEM;
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);

for_each_available_child_of_node(pdev->dev.of_node, child) {
struct mvebu_comphy_lane *lane;
Expand Down
3 changes: 2 additions & 1 deletion drivers/phy/mediatek/phy-mtk-tphy.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
/* banks shared by multiple 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_CHIP 0x300 /* shared by u3 phys */
/* u2 phy bank */
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000
/* u3/pcie/sata phy banks */
Expand Down Expand Up @@ -762,7 +763,7 @@ static void phy_v1_banks_init(struct mtk_tphy *tphy,
case PHY_TYPE_USB3:
case PHY_TYPE_PCIE:
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->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA;
break;
Expand Down
82 changes: 55 additions & 27 deletions drivers/phy/rockchip/phy-rockchip-typec.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,34 @@ static inline int property_enable(struct rockchip_typec_phy *tcphy,
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)
{
u16 tx_ana_ctrl_reg_1;
u16 rdata, rdata2, val;

/* disable txda_cal_latch_en for rewrite the calibration values */
rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
val = rdata & 0xdfff;
writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 &= ~BIT(13);
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
Expand All @@ -472,18 +492,19 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
* Activate this signal for 1 clock cycle to sample new calibration
* values.
*/
rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
val = rdata | 0x2000;
writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 |= BIT(13);
writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
usleep_range(150, 200);

/* set TX Voltage Level and TX Deemphasis to 0 */
writel(0, tcphy->base + PHY_DP_TX_CTL);
/* re-enable decap */
writel(0x100, 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);
writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 |= BIT(3);
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);

Expand All @@ -494,8 +515,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);

/* re-enables Bandgap reference for LDO */
writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 |= BIT(7);
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,
Expand All @@ -505,27 +528,26 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);

/*
* BIT 12: Controls auxda_polarity, which selects the polarity of the
* xcvr:
* 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)
* Do some magic undocumented stuff, some of which appears to
* undo the "re-enables Bandgap reference for LDO" above.
*/
val = 0xa078;
if (!tcphy->flip)
val |= BIT(12);
writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
tx_ana_ctrl_reg_1 |= BIT(15);
tx_ana_ctrl_reg_1 &= ~BIT(8);
tx_ana_ctrl_reg_1 &= ~BIT(7);
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_4);
writel(0, tcphy->base + TX_ANA_CTRL_REG_5);

/*
* Controls low_power_swing_en, set the voltage swing of the driver
* to 400mv. The values below are peak to peak (differential) values.
* Controls low_power_swing_en, don't set the voltage swing of the
* 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);

/* Controls tx_high_z_tm_en */
Expand Down Expand Up @@ -555,6 +577,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
reset_control_deassert(tcphy->tcphy_rst);

property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
tcphy_dp_aux_set_flip(tcphy);

tcphy_cfg_24m(tcphy);

Expand Down Expand Up @@ -685,8 +708,11 @@ static int rockchip_usb3_phy_power_on(struct phy *phy)
if (tcphy->mode == new_mode)
goto unlock_ret;

if (tcphy->mode == MODE_DISCONNECT)
tcphy_phy_init(tcphy, new_mode);
if (tcphy->mode == MODE_DISCONNECT) {
ret = tcphy_phy_init(tcphy, new_mode);
if (ret)
goto unlock_ret;
}

/* wait TCPHY for pipe ready */
for (timeout = 0; timeout < 100; timeout++) {
Expand Down Expand Up @@ -760,10 +786,12 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
*/
if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) {
tcphy_phy_deinit(tcphy);
tcphy_phy_init(tcphy, new_mode);
ret = tcphy_phy_init(tcphy, new_mode);
} 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,
val, val & DP_MODE_A2, 1000,
Expand Down
2 changes: 2 additions & 0 deletions drivers/phy/tegra/xusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ tegra_xusb_find_port_node(struct tegra_xusb_padctl *padctl, const char *type,
char *name;

name = kasprintf(GFP_KERNEL, "%s-%u", type, index);
if (!name)
return ERR_PTR(-ENOMEM);
np = of_find_node_by_name(np, name);
kfree(name);
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/class/cdc-acm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1832,6 +1832,9 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
.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 */
.driver_info = CLEAR_HALT_CONDITIONS,
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,10 +960,12 @@ int usb_get_bos_descriptor(struct usb_device *dev)
for (i = 0; i < num; i++) {
buffer += length;
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;
}
length = cap->bLength;
total_len -= length;

if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1576,11 +1576,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
totlen += isopkt[u].length;
}
u *= sizeof(struct usb_iso_packet_descriptor);
if (totlen <= uurb->buffer_length)
uurb->buffer_length = totlen;
else
WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d",
totlen, uurb->buffer_length);
uurb->buffer_length = totlen;
break;

default:
Expand Down
11 changes: 7 additions & 4 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -2710,13 +2710,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
if (!(portstatus & USB_PORT_STAT_CONNECTION))
return -ENOTCONN;

/* bomb out completely if the connection bounced. A USB 3.0
* connection may bounce if multiple warm resets were issued,
/* Retry if connect change is set but status is still connected.
* A USB 3.0 connection may bounce if multiple warm resets were issued,
* but the device may have successfully re-connected. Ignore it.
*/
if (!hub_is_superspeed(hub->hdev) &&
(portchange & USB_PORT_STAT_C_CONNECTION))
return -ENOTCONN;
(portchange & USB_PORT_STAT_C_CONNECTION)) {
usb_clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_CONNECTION);
return -EAGAIN;
}

if (!(portstatus & USB_PORT_STAT_ENABLE))
return -EBUSY;
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/core/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Corsair Strafe RGB */
{ 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 */
{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },

Expand Down
23 changes: 18 additions & 5 deletions drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
GFP_NOWAIT);
if (!command) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_free_command(xhci, cmd);
return -ENOMEM;
ret = -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);
spin_unlock_irqrestore(&xhci->lock, flags);

Expand All @@ -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");
ret = -ETIME;
}

cmd_cleanup:
xhci_free_command(xhci, cmd);
return ret;
}
Expand Down
21 changes: 14 additions & 7 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
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)
xhci_complete_del_and_free_cmd(cur_cmd, COMP_COMMAND_ABORTED);
}
Expand Down Expand Up @@ -2579,15 +2580,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
(struct xhci_generic_trb *) ep_trb);

/*
* No-op TRB should not trigger interrupts.
* If ep_trb is a no-op TRB, it means the
* corresponding TD has been cancelled. Just ignore
* the TD.
* No-op TRB could trigger interrupts in a case where
* a URB was killed and a STALL_ERROR happens right
* after the endpoint ring stopped. Reset the halted
* endpoint. Otherwise, the endpoint remains stalled
* indefinitely.
*/
if (trb_is_noop(ep_trb)) {
xhci_dbg(xhci,
"ep_trb is a no-op TRB. Skip it for slot %u ep %u\n",
slot_id, ep_index);
if (trb_comp_code == COMP_STALL_ERROR ||
xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
trb_comp_code))
xhci_cleanup_halted_endpoint(xhci, slot_id,
ep_index,
ep_ring->stream_id,
td, ep_trb,
EP_HARD_RESET);
goto cleanup;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -4805,7 +4805,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
*/
hcd->has_tt = 1;
} 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");
hcd->speed = HCD_USB31;
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
Expand Down
Loading

0 comments on commit 5805992

Please sign in to comment.