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

Commit 76382194 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: dwc3: Allocate and free TRB buffers from ep ops



Move TRB buffer allocation under GSI_EP_OP_PREPARE_TRBS
ep operation. Similarly free TRB buffers under
GSI_EP_OP_FREE_TRBS ep operation. This simplifies to
make decision if TRB and buffer allocation needs to come
from cached or non-cached memory region.

Change-Id: Ife4203060ea8092c16a9d2cd92016fa7f6afb563
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent db92782e
Loading
Loading
Loading
Loading
+35 −4
Original line number Diff line number Diff line
@@ -1110,7 +1110,7 @@ static void gsi_endxfer_for_ep(struct usb_ep *ep)
}

/**
 * Allocates and configures TRBs for GSI EPs.
 * Allocates Buffers and TRBs. Configures TRBs for GSI EPs.
 *
 * @usb_ep - pointer to usb_ep instance.
 * @request - pointer to GSI request.
@@ -1120,7 +1120,8 @@ static void gsi_endxfer_for_ep(struct usb_ep *ep)
static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
{
	int i = 0;
	dma_addr_t buffer_addr = req->dma;
	size_t len;
	dma_addr_t buffer_addr;
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3		*dwc = dep->dwc;
	struct dwc3_trb *trb;
@@ -1129,6 +1130,24 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	struct scatterlist *sg;
	struct sg_table *sgt;

	/* Allocate TRB buffers */

	len = req->buf_len * req->num_bufs;
	req->buf_base_addr = dma_zalloc_coherent(dwc->sysdev, len, &req->dma,
					GFP_KERNEL);
	if (!req->buf_base_addr) {
		dev_err(dwc->dev, "%s: buf_base_addr allocate failed %s\n",
				dep->name);
		return -ENOMEM;
	}

	dma_get_sgtable(dwc->sysdev, &req->sgt_data_buff, req->buf_base_addr,
			req->dma, len);

	buffer_addr = req->dma;

	/* Allocate and configgure TRBs */

	dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
				num_trbs * sizeof(struct dwc3_trb),
				&dep->trb_pool_dma, GFP_KERNEL);
@@ -1136,7 +1155,7 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	if (!dep->trb_pool) {
		dev_err(dep->dwc->dev, "failed to alloc trb dma pool for %s\n",
				dep->name);
		return -ENOMEM;
		goto free_trb_buffer;
	}

	dep->num_trbs = num_trbs;
@@ -1233,10 +1252,16 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	}

	return 0;

free_trb_buffer:
	dma_free_coherent(dwc->sysdev, len, req->buf_base_addr, req->dma);
	req->buf_base_addr = NULL;
	sg_free_table(&req->sgt_data_buff);
	return -ENOMEM;
}

/**
 * Frees TRBs for GSI EPs.
 * Frees TRBs and buffers for GSI EPs.
 *
 * @usb_ep - pointer to usb_ep instance.
 *
@@ -1259,6 +1284,12 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
		dep->trb_pool_dma = 0;
	}
	sg_free_table(&req->sgt_trb_xfer_ring);

	/* free TRB buffers */
	dma_free_coherent(dwc->sysdev, req->buf_len * req->num_bufs,
		req->buf_base_addr, req->dma);
	req->buf_base_addr = NULL;
	sg_free_table(&req->sgt_data_buff);
}
/**
 * Configures GSI EPs. For GSI EPs we need to set interrupter numbers.
+6 −121
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@ static DEFINE_IDA(gsi_ida);
static void gsi_inst_clean(struct gsi_opts *opts);
static void gsi_rndis_ipa_reset_trigger(struct gsi_data_port *d_port);
static int gsi_ctrl_send_notification(struct f_gsi *gsi);
static int gsi_alloc_trb_buffer(struct f_gsi *gsi);
static void gsi_free_trb_buffer(struct f_gsi *gsi);
static struct gsi_ctrl_pkt *gsi_ctrl_pkt_alloc(unsigned int len, gfp_t flags);
static void gsi_ctrl_pkt_free(struct gsi_ctrl_pkt *pkt);

@@ -486,7 +484,9 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
	struct ipa_req_chan_out_params ipa_in_channel_out_params;
	struct ipa_req_chan_out_params ipa_out_channel_out_params;

	log_event_dbg("%s: USB GSI IN OPS", __func__);
	log_event_dbg("IN: num_bufs:=%zu, buf_len=%zu\n",
		d_port->in_request.num_bufs, d_port->in_request.buf_len);

	usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
		GSI_EP_OP_PREPARE_TRBS);
	usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
@@ -530,7 +530,9 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
		gsi_channel_info.depcmd_hi_addr;

	if (d_port->out_ep) {
		log_event_dbg("%s: USB GSI OUT OPS", __func__);
		log_event_dbg("OUT: num_bufs:=%zu, buf_len=%zu\n",
			d_port->out_request.num_bufs,
			d_port->out_request.buf_len);
		usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
			GSI_EP_OP_PREPARE_TRBS);
		usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
@@ -721,9 +723,6 @@ static void ipa_disconnect_channel(struct gsi_data_port *d_port)
	if (gsi->d_port.out_ep)
		usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request,
							GSI_EP_OP_FREE_TRBS);

	/* free buffers allocated with each TRB */
	gsi_free_trb_buffer(gsi);
}

static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
@@ -883,13 +882,6 @@ static void ipa_work_handler(struct work_struct *w)
				break;
			}

			/* allocate buffers used with each TRB */
			ret = gsi_alloc_trb_buffer(gsi);
			if (ret) {
				log_event_err("%s: gsi_alloc_trb_failed\n",
								__func__);
				break;
			}
			ipa_connect_channels(d_port);
			d_port->sm_state = STATE_WAIT_FOR_IPA_RDY;
			log_event_dbg("%s: ST_INIT_EVT_SET_ALT",
@@ -1028,13 +1020,6 @@ static void ipa_work_handler(struct work_struct *w)
			usb_gadget_autopm_get(d_port->gadget);
			log_event_dbg("%s: get = %d", __func__,
				atomic_read(&gad_dev->power.usage_count));
			/* allocate buffers used with each TRB */
			ret = gsi_alloc_trb_buffer(gsi);
			if (ret) {
				log_event_err("%s: gsi_alloc_trb_failed\n",
								__func__);
				break;
			}

			ipa_connect_channels(d_port);
			ipa_data_path_enable(d_port);
@@ -2260,106 +2245,6 @@ static int gsi_get_alt(struct usb_function *f, unsigned int intf)
	return -EINVAL;
}

static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
{
	u32 len_in = 0, len_out = 0;
	int ret = 0;
	struct device *dev;

	log_event_dbg("allocate trb's buffer\n");

	dev = gsi->d_port.gadget->dev.parent;
	if (gsi->d_port.in_ep && !gsi->d_port.in_request.buf_base_addr) {
		log_event_dbg("IN: num_bufs:=%zu, buf_len=%zu\n",
			gsi->d_port.in_request.num_bufs,
			gsi->d_port.in_request.buf_len);

		len_in = gsi->d_port.in_request.buf_len *
				gsi->d_port.in_request.num_bufs;
		gsi->d_port.in_request.buf_base_addr =
			dma_zalloc_coherent(dev->parent,
			len_in, &gsi->d_port.in_request.dma, GFP_KERNEL);
		if (!gsi->d_port.in_request.buf_base_addr) {
			dev_err(&gsi->d_port.gadget->dev,
					"IN buf_base_addr allocate failed %s\n",
					gsi->function.name);
			ret = -ENOMEM;
			goto fail1;
		}

		dma_get_sgtable(dev->parent,
			&gsi->d_port.in_request.sgt_data_buff,
			gsi->d_port.in_request.buf_base_addr,
			gsi->d_port.in_request.dma, len_in);
	}

	if (gsi->d_port.out_ep && !gsi->d_port.out_request.buf_base_addr) {
		log_event_dbg("OUT: num_bufs:=%zu, buf_len=%zu\n",
			gsi->d_port.out_request.num_bufs,
			gsi->d_port.out_request.buf_len);

		len_out = gsi->d_port.out_request.buf_len *
				gsi->d_port.out_request.num_bufs;
		gsi->d_port.out_request.buf_base_addr =
			dma_zalloc_coherent(dev->parent,
			len_out, &gsi->d_port.out_request.dma, GFP_KERNEL);
		if (!gsi->d_port.out_request.buf_base_addr) {
			dev_err(&gsi->d_port.gadget->dev,
					"OUT buf_base_addr allocate failed %s\n",
					gsi->function.name);
			ret = -ENOMEM;
			goto fail;
		}

		dma_get_sgtable(dev->parent,
			&gsi->d_port.out_request.sgt_data_buff,
			gsi->d_port.out_request.buf_base_addr,
			gsi->d_port.out_request.dma, len_out);
	}

	log_event_dbg("finished allocating trb's buffer\n");
	return ret;

fail:
	if (len_in && gsi->d_port.in_request.buf_base_addr) {
		dma_free_coherent(dev->parent, len_in,
				gsi->d_port.in_request.buf_base_addr,
				gsi->d_port.in_request.dma);
		gsi->d_port.in_request.buf_base_addr = NULL;
	}
fail1:
	return ret;
}

static void gsi_free_trb_buffer(struct f_gsi *gsi)
{
	u32 len;

	log_event_dbg("freeing trb's buffer\n");

	if (gsi->d_port.out_ep &&
			gsi->d_port.out_request.buf_base_addr) {
		len = gsi->d_port.out_request.buf_len *
			gsi->d_port.out_request.num_bufs;
		dma_free_coherent(gsi->d_port.gadget->dev.parent->parent, len,
			gsi->d_port.out_request.buf_base_addr,
			gsi->d_port.out_request.dma);
		gsi->d_port.out_request.buf_base_addr = NULL;
		sg_free_table(&gsi->d_port.out_request.sgt_data_buff);
	}

	if (gsi->d_port.in_ep &&
			gsi->d_port.in_request.buf_base_addr) {
		len = gsi->d_port.in_request.buf_len *
			gsi->d_port.in_request.num_bufs;
		dma_free_coherent(gsi->d_port.gadget->dev.parent->parent, len,
			gsi->d_port.in_request.buf_base_addr,
			gsi->d_port.in_request.dma);
		gsi->d_port.in_request.buf_base_addr = NULL;
		sg_free_table(&gsi->d_port.in_request.sgt_data_buff);
	}
}

static int gsi_set_alt(struct usb_function *f, unsigned int intf,
						unsigned int alt)
{