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

Commit 7d5e650a authored by Felipe Balbi's avatar Felipe Balbi
Browse files

usb: dwc3: ep0: use immediate SETUP on TRB



If we pass TRB's own address on bpl/bph fields, we can get our SETUP
packet as immediate data on the TRB itself, without having to allocate
extra memory for it.

Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 374a1020
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -760,12 +760,10 @@ struct dwc3_scratchpad_array {


/**
/**
 * struct dwc3 - representation of our controller
 * struct dwc3 - representation of our controller
 * @ctrl_req: usb control request which is used for ep0
 * @ep0_trb: trb which is used for the ctrl_req
 * @ep0_trb: trb which is used for the ctrl_req
 * @ep0_bounce: bounce buffer for ep0
 * @ep0_bounce: bounce buffer for ep0
 * @zlp_buf: used when request->zero is set
 * @zlp_buf: used when request->zero is set
 * @setup_buf: used while precessing STD USB requests
 * @setup_buf: used while precessing STD USB requests
 * @ctrl_req_addr: dma address of ctrl_req
 * @ep0_trb: dma address of ep0_trb
 * @ep0_trb: dma address of ep0_trb
 * @ep0_usb_req: dummy req used while handling STD USB requests
 * @ep0_usb_req: dummy req used while handling STD USB requests
 * @ep0_bounce_addr: dma address of ep0_bounce
 * @ep0_bounce_addr: dma address of ep0_bounce
@@ -859,14 +857,12 @@ struct dwc3_scratchpad_array {
 *                 increments or 0 to disable.
 *                 increments or 0 to disable.
 */
 */
struct dwc3 {
struct dwc3 {
	struct usb_ctrlrequest	*ctrl_req;
	struct dwc3_trb		*ep0_trb;
	struct dwc3_trb		*ep0_trb;
	void			*bounce;
	void			*bounce;
	void			*ep0_bounce;
	void			*ep0_bounce;
	void			*zlp_buf;
	void			*zlp_buf;
	void			*scratchbuf;
	void			*scratchbuf;
	u8			*setup_buf;
	u8			*setup_buf;
	dma_addr_t		ctrl_req_addr;
	dma_addr_t		ep0_trb_addr;
	dma_addr_t		ep0_trb_addr;
	dma_addr_t		bounce_addr;
	dma_addr_t		bounce_addr;
	dma_addr_t		ep0_bounce_addr;
	dma_addr_t		ep0_bounce_addr;
+6 −5
Original line number Original line Diff line number Diff line
@@ -283,7 +283,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)


	complete(&dwc->ep0_in_setup);
	complete(&dwc->ep0_in_setup);


	dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8,
	dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ep0_trb_addr, 8,
			DWC3_TRBCTL_CONTROL_SETUP, false);
			DWC3_TRBCTL_CONTROL_SETUP, false);
	ret = dwc3_ep0_start_trans(dwc, 0);
	ret = dwc3_ep0_start_trans(dwc, 0);
	WARN_ON(ret < 0);
	WARN_ON(ret < 0);
@@ -794,7 +794,7 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
		const struct dwc3_event_depevt *event)
{
{
	struct usb_ctrlrequest *ctrl = dwc->ctrl_req;
	struct usb_ctrlrequest *ctrl = (void *) dwc->ep0_trb;
	int ret = -EINVAL;
	int ret = -EINVAL;
	u32 len;
	u32 len;


@@ -916,7 +916,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,


			dwc->ep0_next_event = DWC3_EP0_COMPLETE;
			dwc->ep0_next_event = DWC3_EP0_COMPLETE;


			dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr,
			dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ep0_trb_addr,
					0, DWC3_TRBCTL_CONTROL_DATA, false);
					0, DWC3_TRBCTL_CONTROL_DATA, false);
			ret = dwc3_ep0_start_trans(dwc, epnum);
			ret = dwc3_ep0_start_trans(dwc, epnum);
			WARN_ON(ret < 0);
			WARN_ON(ret < 0);
@@ -997,8 +997,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
	req->direction = !!dep->number;
	req->direction = !!dep->number;


	if (req->request.length == 0) {
	if (req->request.length == 0) {

		dwc3_ep0_prepare_one_trb(dwc, dep->number,
		dwc3_ep0_prepare_one_trb(dwc, dep->number,
				dwc->ctrl_req_addr, 0,
				dwc->ep0_trb_addr, 0,
				DWC3_TRBCTL_CONTROL_DATA, false);
				DWC3_TRBCTL_CONTROL_DATA, false);
		ret = dwc3_ep0_start_trans(dwc, dep->number);
		ret = dwc3_ep0_start_trans(dwc, dep->number);
	} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
	} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
@@ -1056,7 +1057,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
		: DWC3_TRBCTL_CONTROL_STATUS2;
		: DWC3_TRBCTL_CONTROL_STATUS2;


	dwc3_ep0_prepare_one_trb(dwc, dep->number,
	dwc3_ep0_prepare_one_trb(dwc, dep->number,
			dwc->ctrl_req_addr, 0, type, false);
			dwc->ep0_trb_addr, 0, type, false);
	return dwc3_ep0_start_trans(dwc, dep->number);
	return dwc3_ep0_start_trans(dwc, dep->number);
}
}


+12 −27
Original line number Original line Diff line number Diff line
@@ -3144,27 +3144,19 @@ int dwc3_gadget_init(struct dwc3 *dwc)


	dwc->irq_gadget = irq;
	dwc->irq_gadget = irq;


	dwc->ctrl_req = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req),
			&dwc->ctrl_req_addr, GFP_KERNEL);
	if (!dwc->ctrl_req) {
		dev_err(dwc->dev, "failed to allocate ctrl request\n");
		ret = -ENOMEM;
		goto err0;
	}

	dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev,
	dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev,
					  sizeof(*dwc->ep0_trb) * 2,
					  sizeof(*dwc->ep0_trb) * 2,
					  &dwc->ep0_trb_addr, GFP_KERNEL);
					  &dwc->ep0_trb_addr, GFP_KERNEL);
	if (!dwc->ep0_trb) {
	if (!dwc->ep0_trb) {
		dev_err(dwc->dev, "failed to allocate ep0 trb\n");
		dev_err(dwc->dev, "failed to allocate ep0 trb\n");
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err1;
		goto err0;
	}
	}


	dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
	dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
	if (!dwc->setup_buf) {
	if (!dwc->setup_buf) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err2;
		goto err1;
	}
	}


	dwc->ep0_bounce = dma_alloc_coherent(dwc->sysdev,
	dwc->ep0_bounce = dma_alloc_coherent(dwc->sysdev,
@@ -3173,20 +3165,20 @@ int dwc3_gadget_init(struct dwc3 *dwc)
	if (!dwc->ep0_bounce) {
	if (!dwc->ep0_bounce) {
		dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
		dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err3;
		goto err2;
	}
	}


	dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL);
	dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL);
	if (!dwc->zlp_buf) {
	if (!dwc->zlp_buf) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err4;
		goto err3;
	}
	}


	dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE,
	dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE,
			&dwc->bounce_addr, GFP_KERNEL);
			&dwc->bounce_addr, GFP_KERNEL);
	if (!dwc->bounce) {
	if (!dwc->bounce) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto err5;
		goto err4;
	}
	}


	init_completion(&dwc->ep0_in_setup);
	init_completion(&dwc->ep0_in_setup);
@@ -3226,38 +3218,34 @@ int dwc3_gadget_init(struct dwc3 *dwc)


	ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps);
	ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps);
	if (ret)
	if (ret)
		goto err6;
		goto err5;


	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
	if (ret) {
	if (ret) {
		dev_err(dwc->dev, "failed to register udc\n");
		dev_err(dwc->dev, "failed to register udc\n");
		goto err6;
		goto err5;
	}
	}


	return 0;
	return 0;
err6:
err5:
	dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
	dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
			dwc->bounce_addr);
			dwc->bounce_addr);


err5:
err4:
	kfree(dwc->zlp_buf);
	kfree(dwc->zlp_buf);


err4:
err3:
	dwc3_gadget_free_endpoints(dwc);
	dwc3_gadget_free_endpoints(dwc);
	dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE,
	dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE,
			dwc->ep0_bounce, dwc->ep0_bounce_addr);
			dwc->ep0_bounce, dwc->ep0_bounce_addr);


err3:
err2:
	kfree(dwc->setup_buf);
	kfree(dwc->setup_buf);


err2:
err1:
	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2,
	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2,
			dwc->ep0_trb, dwc->ep0_trb_addr);
			dwc->ep0_trb, dwc->ep0_trb_addr);


err1:
	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req),
			dwc->ctrl_req, dwc->ctrl_req_addr);

err0:
err0:
	return ret;
	return ret;
}
}
@@ -3280,9 +3268,6 @@ void dwc3_gadget_exit(struct dwc3 *dwc)


	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2,
	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2,
			dwc->ep0_trb, dwc->ep0_trb_addr);
			dwc->ep0_trb, dwc->ep0_trb_addr);

	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req),
			dwc->ctrl_req, dwc->ctrl_req_addr);
}
}


int dwc3_gadget_suspend(struct dwc3 *dwc)
int dwc3_gadget_suspend(struct dwc3 *dwc)