Commit a6d45ea0 authored by Paul Cercueil's avatar Paul Cercueil Committed by Greg Kroah-Hartman
Browse files

usb: musb: Allow running without CONFIG_USB_PHY



Modify the core so that musb->xceiv is never deferenced without being
checked first.

Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20221026182657.146630-4-paul@crapouillou.net


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 285f28bf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2448,7 +2448,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
	else
		musb->io.set_toggle = musb_default_set_toggle;

	if (!musb->xceiv->io_ops) {
	if (IS_ENABLED(CONFIG_USB_PHY) && musb->xceiv && !musb->xceiv->io_ops) {
		musb->xceiv->io_dev = musb->controller;
		musb->xceiv->io_priv = musb->mregs;
		musb->xceiv->io_ops = &musb_ulpi_access;
+10 −2
Original line number Diff line number Diff line
@@ -339,6 +339,8 @@ struct musb {
	struct usb_phy		*xceiv;
	struct phy		*phy;

	enum usb_otg_state	otg_state;

	int nIrq;
	unsigned		irq_wake:1;

@@ -595,12 +597,18 @@ static inline void musb_platform_clear_ep_rxintr(struct musb *musb, int epnum)
static inline void musb_set_state(struct musb *musb,
				  enum usb_otg_state otg_state)
{
	if (musb->xceiv)
		musb->xceiv->otg->state = otg_state;
	else
		musb->otg_state = otg_state;
}

static inline enum usb_otg_state musb_get_state(struct musb *musb)
{
	if (musb->xceiv)
		return musb->xceiv->otg->state;

	return musb->otg_state;
}

static inline const char *musb_otg_state_string(struct musb *musb)
+13 −8
Original line number Diff line number Diff line
@@ -1552,9 +1552,11 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
				break;
		}

		if (musb->xceiv) {
			spin_unlock_irqrestore(&musb->lock, flags);
			otg_start_srp(musb->xceiv->otg);
			spin_lock_irqsave(&musb->lock, flags);
		}

		/* Block idling for at least 1s */
		musb_platform_try_idle(musb,
@@ -1628,7 +1630,7 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
{
	struct musb	*musb = gadget_to_musb(gadget);

	if (!musb->xceiv->set_power)
	if (!musb->xceiv || !musb->xceiv->set_power)
		return -EOPNOTSUPP;
	return usb_phy_set_power(musb->xceiv, mA);
}
@@ -1834,7 +1836,6 @@ static int musb_gadget_start(struct usb_gadget *g,
		struct usb_gadget_driver *driver)
{
	struct musb		*musb = gadget_to_musb(g);
	struct usb_otg		*otg = musb->xceiv->otg;
	unsigned long		flags;
	int			retval = 0;

@@ -1851,7 +1852,9 @@ static int musb_gadget_start(struct usb_gadget *g,
	spin_lock_irqsave(&musb->lock, flags);
	musb->is_active = 1;

	otg_set_peripheral(otg, &musb->g);
	if (musb->xceiv)
		otg_set_peripheral(musb->xceiv->otg, &musb->g);

	musb_set_state(musb, OTG_STATE_B_IDLE);
	spin_unlock_irqrestore(&musb->lock, flags);

@@ -1861,7 +1864,7 @@ static int musb_gadget_start(struct usb_gadget *g,
	 * handles power budgeting ... this way also
	 * ensures HdrcStart is indirectly called.
	 */
	if (musb->xceiv->last_event == USB_EVENT_ID)
	if (musb->xceiv && musb->xceiv->last_event == USB_EVENT_ID)
		musb_platform_set_vbus(musb, 1);

	pm_runtime_mark_last_busy(musb->controller);
@@ -1899,6 +1902,8 @@ static int musb_gadget_stop(struct usb_gadget *g)

	musb_set_state(musb, OTG_STATE_UNDEFINED);
	musb_stop(musb);

	if (musb->xceiv)
		otg_set_peripheral(musb->xceiv->otg, NULL);

	musb->is_active = 0;
+6 −2
Original line number Diff line number Diff line
@@ -2722,10 +2722,14 @@ int musb_host_setup(struct musb *musb, int power_budget)
		MUSB_HST_MODE(musb);
		musb_set_state(musb, OTG_STATE_A_IDLE);
	}

	if (musb->xceiv) {
		otg_set_host(musb->xceiv->otg, &hcd->self);
		musb->xceiv->otg->host = &hcd->self;
	}

	/* don't support otg protocols */
	hcd->self.otg_port = 0;
	musb->xceiv->otg->host = &hcd->self;
	hcd->power_budget = 2 * (power_budget ? : 250);
	hcd->skip_phy_initialization = 1;

+5 −6
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ void musb_host_finish_resume(struct work_struct *work)

int musb_port_suspend(struct musb *musb, bool do_suspend)
{
	struct usb_otg	*otg = musb->xceiv->otg;
	u8		power;
	void __iomem	*mbase = musb->mregs;

@@ -88,7 +87,8 @@ int musb_port_suspend(struct musb *musb, bool do_suspend)
		switch (musb_get_state(musb)) {
		case OTG_STATE_A_HOST:
			musb_set_state(musb, OTG_STATE_A_SUSPEND);
			musb->is_active = otg->host->b_hnp_enable;
			musb->is_active = musb->xceiv &&
				musb->xceiv->otg->host->b_hnp_enable;
			if (musb->is_active)
				mod_timer(&musb->otg_timer, jiffies
					+ msecs_to_jiffies(
@@ -97,7 +97,8 @@ int musb_port_suspend(struct musb *musb, bool do_suspend)
			break;
		case OTG_STATE_B_HOST:
			musb_set_state(musb, OTG_STATE_B_WAIT_ACON);
			musb->is_active = otg->host->b_hnp_enable;
			musb->is_active = musb->xceiv &&
				musb->xceiv->otg->host->b_hnp_enable;
			musb_platform_try_idle(musb, 0);
			break;
		default:
@@ -196,8 +197,6 @@ void musb_port_reset(struct musb *musb, bool do_reset)

void musb_root_disconnect(struct musb *musb)
{
	struct usb_otg	*otg = musb->xceiv->otg;

	musb->port1_status = USB_PORT_STAT_POWER
			| (USB_PORT_STAT_C_CONNECTION << 16);

@@ -206,7 +205,7 @@ void musb_root_disconnect(struct musb *musb)

	switch (musb_get_state(musb)) {
	case OTG_STATE_A_SUSPEND:
		if (otg->host->b_hnp_enable) {
		if (musb->xceiv && musb->xceiv->otg->host->b_hnp_enable) {
			musb_set_state(musb, OTG_STATE_A_PERIPHERAL);
			musb->g.is_a_peripheral = 1;
			break;