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

Commit 069f7c58 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: Mark usb gsi driver dma memory as cached"

parents 7352dd66 23cc3652
Loading
Loading
Loading
Loading
+59 −9
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ struct dwc3_msm {
	enum usb_device_speed override_usb_speed;
	u32			*gsi_reg;
	int			gsi_reg_offset_cnt;
	bool			gsi_io_coherency_disabled;

	struct notifier_block	dpdm_nb;
	struct regulator	*dpdm_reg;
@@ -1110,7 +1111,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,23 +1121,49 @@ 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;
	unsigned long dma_attr;
	dma_addr_t buffer_addr;
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3		*dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
	struct dwc3_trb *trb;
	int num_trbs = (dep->direction) ? (2 * (req->num_bufs) + 2)
					: (req->num_bufs + 2);
	struct scatterlist *sg;
	struct sg_table *sgt;

	dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
	if (mdwc->gsi_io_coherency_disabled)
		dma_attr = DMA_ATTR_FORCE_NON_COHERENT;
	else
		dma_attr = DMA_ATTR_FORCE_COHERENT;

	/* Allocate TRB buffers */

	len = req->buf_len * req->num_bufs;
	req->buf_base_addr = dma_alloc_attrs(dwc->sysdev, len, &req->dma,
					GFP_KERNEL, dma_attr);
	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_alloc_attrs(dwc->sysdev,
				num_trbs * sizeof(struct dwc3_trb),
				&dep->trb_pool_dma, GFP_KERNEL);
				&dep->trb_pool_dma, GFP_KERNEL, dma_attr);

	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 +1260,17 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	}

	return 0;

free_trb_buffer:
	dma_free_attrs(dwc->sysdev, len, req->buf_base_addr, req->dma,
			dma_attr);
	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.
 *
@@ -1245,20 +1279,32 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
{
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3 *dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
	unsigned long dma_attr;

	if (dep->endpoint.ep_type == EP_TYPE_NORMAL)
		return;

	if (mdwc->gsi_io_coherency_disabled)
		dma_attr = DMA_ATTR_FORCE_NON_COHERENT;
	else
		dma_attr = DMA_ATTR_FORCE_COHERENT;

	/*  Free TRBs and TRB pool for EP */
	if (dep->trb_pool_dma) {
		dma_free_coherent(dwc->sysdev,
		dma_free_attrs(dwc->sysdev,
			dep->num_trbs * sizeof(struct dwc3_trb),
			dep->trb_pool,
			dep->trb_pool_dma);
			dep->trb_pool, dep->trb_pool_dma, dma_attr);
		dep->trb_pool = NULL;
		dep->trb_pool_dma = 0;
	}
	sg_free_table(&req->sgt_trb_xfer_ring);

	/* free TRB buffers */
	dma_free_attrs(dwc->sysdev, req->buf_len * req->num_bufs,
		req->buf_base_addr, req->dma, dma_attr);
	req->buf_base_addr = NULL;
	sg_free_table(&req->sgt_data_buff);
}
/**
 * Configures GSI EPs. For GSI EPs we need to set interrupter numbers.
@@ -3585,6 +3631,10 @@ static int dwc3_msm_probe(struct platform_device *pdev)

	mdwc->use_pdc_interrupts = of_property_read_bool(node,
				"qcom,use-pdc-interrupts");

	mdwc->gsi_io_coherency_disabled = of_property_read_bool(node,
				"qcom,gsi-disable-io-coherency");

	dwc3_set_notifier(&dwc3_msm_notify_event);

	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
+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)
{