Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea934651 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'usb-ci-v4.3-rc2' of...

Merge tag 'usb-ci-v4.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-linus

Peter writes:

USB Chipidea fixes for v4.3-rc2

- Fix the stall implementation
- Fix device mode transfer at zynq platform
- other small fixes
parents 74a09391 8315b77d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ Required properties:
	"lsi,zevio-usb"
	"qcom,ci-hdrc"
	"chipidea,usb2"
	"xlnx,zynq-usb-2.20a"
- reg: base address and length of the registers
- interrupts: interrupt for the USB controller

+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
	{ .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
	{ .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
	{ .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
	{ .compatible = "fsl,imx6sx-usb", .data = &imx6sl_usb_data},
	{ .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
+19 −6
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb/chipidea.h>
@@ -30,18 +31,36 @@ static const struct ci_hdrc_platform_data ci_default_pdata = {
	.flags		= CI_HDRC_DISABLE_STREAMING,
};

static struct ci_hdrc_platform_data ci_zynq_pdata = {
	.capoffset	= DEF_CAPOFFSET,
};

static const struct of_device_id ci_hdrc_usb2_of_match[] = {
	{ .compatible = "chipidea,usb2"},
	{ .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata},
	{ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);

static int ci_hdrc_usb2_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct ci_hdrc_usb2_priv *priv;
	struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
	int ret;
	const struct of_device_id *match;

	if (!ci_pdata) {
		ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
		*ci_pdata = ci_default_pdata;	/* struct copy */
	}

	match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev);
	if (match && match->data) {
		/* struct copy */
		*ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
	}

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
@@ -96,12 +115,6 @@ static int ci_hdrc_usb2_remove(struct platform_device *pdev)
	return 0;
}

static const struct of_device_id ci_hdrc_usb2_of_match[] = {
	{ .compatible = "chipidea,usb2" },
	{ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);

static struct platform_driver ci_hdrc_usb2_driver = {
	.probe	= ci_hdrc_usb2_probe,
	.remove	= ci_hdrc_usb2_remove,
+44 −40
Original line number Diff line number Diff line
@@ -656,6 +656,44 @@ __acquires(hwep->lock)
	return 0;
}

static int _ep_set_halt(struct usb_ep *ep, int value, bool check_transfer)
{
	struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
	int direction, retval = 0;
	unsigned long flags;

	if (ep == NULL || hwep->ep.desc == NULL)
		return -EINVAL;

	if (usb_endpoint_xfer_isoc(hwep->ep.desc))
		return -EOPNOTSUPP;

	spin_lock_irqsave(hwep->lock, flags);

	if (value && hwep->dir == TX && check_transfer &&
		!list_empty(&hwep->qh.queue) &&
			!usb_endpoint_xfer_control(hwep->ep.desc)) {
		spin_unlock_irqrestore(hwep->lock, flags);
		return -EAGAIN;
	}

	direction = hwep->dir;
	do {
		retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);

		if (!value)
			hwep->wedge = 0;

		if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
			hwep->dir = (hwep->dir == TX) ? RX : TX;

	} while (hwep->dir != direction);

	spin_unlock_irqrestore(hwep->lock, flags);
	return retval;
}


/**
 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
 * @gadget: gadget
@@ -1051,7 +1089,7 @@ __acquires(ci->lock)
				num += ci->hw_ep_max / 2;

			spin_unlock(&ci->lock);
			err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep);
			err = _ep_set_halt(&ci->ci_hw_ep[num].ep, 1, false);
			spin_lock(&ci->lock);
			if (!err)
				isr_setup_status_phase(ci);
@@ -1117,8 +1155,8 @@ __acquires(ci->lock)

	if (err < 0) {
		spin_unlock(&ci->lock);
		if (usb_ep_set_halt(&hwep->ep))
			dev_err(ci->dev, "error: ep_set_halt\n");
		if (_ep_set_halt(&hwep->ep, 1, false))
			dev_err(ci->dev, "error: _ep_set_halt\n");
		spin_lock(&ci->lock);
	}
}
@@ -1149,9 +1187,9 @@ __acquires(ci->lock)
					err = isr_setup_status_phase(ci);
				if (err < 0) {
					spin_unlock(&ci->lock);
					if (usb_ep_set_halt(&hwep->ep))
					if (_ep_set_halt(&hwep->ep, 1, false))
						dev_err(ci->dev,
							"error: ep_set_halt\n");
						"error: _ep_set_halt\n");
					spin_lock(&ci->lock);
				}
			}
@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 */
static int ep_set_halt(struct usb_ep *ep, int value)
{
	struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
	int direction, retval = 0;
	unsigned long flags;

	if (ep == NULL || hwep->ep.desc == NULL)
		return -EINVAL;

	if (usb_endpoint_xfer_isoc(hwep->ep.desc))
		return -EOPNOTSUPP;

	spin_lock_irqsave(hwep->lock, flags);

#ifndef STALL_IN
	/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
	if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX &&
	    !list_empty(&hwep->qh.queue)) {
		spin_unlock_irqrestore(hwep->lock, flags);
		return -EAGAIN;
	}
#endif

	direction = hwep->dir;
	do {
		retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);

		if (!value)
			hwep->wedge = 0;

		if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
			hwep->dir = (hwep->dir == TX) ? RX : TX;

	} while (hwep->dir != direction);

	spin_unlock_irqrestore(hwep->lock, flags);
	return retval;
	return _ep_set_halt(ep, value, true);
}

/**