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

Commit 3b41576a authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3-msm: Use dummy buffer as doorbell until GSI is ready"

parents 680114f6 b8e40bd4
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -516,6 +516,19 @@

struct dwc3_trb;

/**
 * struct dwc3_gadget_ep_cmd_params - representation of endpoint command
 * parameters
 * @param2: third parameter
 * @param1: second parameter
 * @param0: first parameter
 */
struct dwc3_gadget_ep_cmd_params {
	u32	param2;
	u32	param1;
	u32	param0;
};

/**
 * struct dwc3_event_buffer - Software event buffer representation
 * @buf: _THE_ buffer
@@ -606,6 +619,7 @@ struct dwc3_ep_events {
 * @dbg_ep_events_diff: differential events counter for endpoint
 * @dbg_ep_events_ts: timestamp for previous event counters
 * @fifo_depth: allocated TXFIFO depth
 * @ep_cfg_init_params: Used by GSI EP to save EP_CFG init_cmd params
 */
struct dwc3_ep {
	struct usb_ep		endpoint;
@@ -661,6 +675,7 @@ struct dwc3_ep {
	struct dwc3_ep_events	dbg_ep_events_diff;
	struct timespec		dbg_ep_events_ts;
	int			fifo_depth;
	struct dwc3_gadget_ep_cmd_params ep_cfg_init_params;
};

enum dwc3_phy {
@@ -1306,19 +1321,6 @@ union dwc3_event {
	struct dwc3_event_gevt		gevt;
};

/**
 * struct dwc3_gadget_ep_cmd_params - representation of endpoint command
 * parameters
 * @param2: third parameter
 * @param1: second parameter
 * @param0: first parameter
 */
struct dwc3_gadget_ep_cmd_params {
	u32	param2;
	u32	param1;
	u32	param0;
};

/*
 * DWC3 Features to be used as Driver Data
 */
+109 −5
Original line number Diff line number Diff line
@@ -309,6 +309,9 @@ struct dwc3_msm {
	struct mutex suspend_resume_mutex;

	enum usb_device_speed override_usb_speed;

	u64			dummy_gsi_db;
	dma_addr_t		dummy_gsi_db_dma;
};

#define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -974,6 +977,12 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
		ep->name, request->db_reg_phs_addr_lsb,
		(unsigned long long)request->mapped_db_reg_phs_addr_lsb);

	/*
	 * Replace dummy doorbell address with real one as IPA connection
	 * is setup now and GSI must be ready to handle doorbell updates.
	 */
	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n), 0x0);

	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n),
			(u32)request->mapped_db_reg_phs_addr_lsb);
	dev_dbg(mdwc->dev, "Ring Base Addr %d: %x (LSB)\n", n,
@@ -1232,6 +1241,7 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	}
	sg_free_table(&req->sgt_trb_xfer_ring);
}

/*
* Configures GSI EPs. For GSI EPs we need to set interrupter numbers.
*
@@ -1246,9 +1256,20 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
	struct dwc3_gadget_ep_cmd_params params;
	const struct usb_endpoint_descriptor *desc = ep->desc;
	const struct usb_ss_ep_comp_descriptor *comp_desc = ep->comp_desc;
	int n = ep->ep_intr_num - 1;
	u32 reg;
	int ret;

	/* setup dummy doorbell as IPA connection isn't setup yet */
	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n),
			   (u32)((u64)mdwc->dummy_gsi_db_dma >> 32));

	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n),
			   (u32)mdwc->dummy_gsi_db_dma);
	dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx %x (LSB)\n",
		&mdwc->dummy_gsi_db, (unsigned long long)mdwc->dummy_gsi_db_dma,
		(u32)mdwc->dummy_gsi_db_dma);

	memset(&params, 0x00, sizeof(params));

	/* Configure GSI EP */
@@ -1274,10 +1295,8 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
	/* Set interrupter number for GSI endpoints */
	params.param1 |= DWC3_DEPCFG_INT_NUM(ep->ep_intr_num);

	/* Enable XferInProgress and XferComplete Interrupts */
	params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN;
	params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
	params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN;
	/* EP Events are enabled later once DBL_ADDR is updated */

	/*
	 * We must use the lower 16 TX FIFOs even though
	 * HW might have more
@@ -1291,6 +1310,9 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
	dev_dbg(mdwc->dev, "Set EP config to params = %x %x %x, for %s\n",
		params.param0, params.param1, params.param2, dep->name);

	/* params are used later when EP_CONFIG is modified to enable events */
	dep->ep_cfg_init_params = params;

	dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);

	/* Set XferRsc Index for GSI EP */
@@ -1315,6 +1337,57 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)

}

/*
 * Enables events for GSI EPs. Modify EP_CONFIG to enable EP events
 * after GSI wrapper is initialized for the endpoint.
 *
 * @usb_ep - pointer to usb_ep instance.
 */
static void gsi_enable_ep_events(struct usb_ep *ep)
{
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent);
	struct dwc3_gadget_ep_cmd_params params;

	/* EP is already configured, just update params to enable events */
	params = dep->ep_cfg_init_params;

	/* Enable XferInProgress and XferComplete Interrupts */
	params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN;
	params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
	params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN;

	params.param0 |= DWC3_DEPCFG_ACTION_MODIFY;

	dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n",
		params.param0, params.param1, params.param2, dep->name);

	dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);
}

/*
 * Disables events for GSI EPs. Modify EP_CONFIG to disable EP events
 * to prevent USB GSI wrapper from ringing any doorbell.
 *
 * @usb_ep - pointer to usb_ep instance.
 */
static void gsi_disable_ep_events(struct usb_ep *ep)
{
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent);
	struct dwc3_gadget_ep_cmd_params params;

	/* EP is already enabled, just restore init_params to disable events */
	params = dep->ep_cfg_init_params;

	params.param0 |= DWC3_DEPCFG_ACTION_MODIFY;

	dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n",
		params.param0, params.param1, params.param2, dep->name);

	dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);
}

/*
* Enables USB wrapper for GSI
*
@@ -1352,6 +1425,16 @@ static void gsi_set_clear_dbell(struct usb_ep *ep,
	struct dwc3 *dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);

	/*
	 * Disable EP events if doorbell needs to be blocked to avoid issues
	 * due to another GSI interface endpoint enabling doorbell say on resume
	 * as there is no control of doorbell per endpoint.
	 */
	if (block_db)
		gsi_disable_ep_events(ep);
	else
		gsi_enable_ep_events(ep);

	dwc3_msm_write_reg_field(mdwc->base,
		GSI_GENERAL_CFG_REG, BLOCK_GSI_WR_GO_MASK, block_db);
}
@@ -1462,7 +1545,9 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
		break;
	case GSI_EP_OP_SET_CLR_BLOCK_DBL:
		block_db = *((bool *)op_data);
		spin_lock_irqsave(&dwc->lock, flags);
		gsi_set_clear_dbell(ep, block_db);
		spin_unlock_irqrestore(&dwc->lock, flags);
		break;
	case GSI_EP_OP_CHECK_FOR_SUSPEND:
		ret = gsi_check_ready_to_suspend(mdwc);
@@ -1967,6 +2052,19 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
			}
			mdwc->gsi_ev_buff[i] = evt;
		}
		/*
		 * Set-up dummy buffer to use as doorbell while IPA GSI
		 * connection is in progress.
		 */
		mdwc->dummy_gsi_db_dma = dma_map_single(dwc->sysdev,
						&mdwc->dummy_gsi_db,
						sizeof(mdwc->dummy_gsi_db),
						DMA_FROM_DEVICE);

		if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gsi_db_dma)) {
			dev_err(dwc->dev, "failed to map dummy doorbell buffer\n");
			mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
		}
		break;
	case DWC3_GSI_EVT_BUF_SETUP:
		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2040,6 +2138,12 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
				dma_free_coherent(dwc->sysdev, evt->length,
							evt->buf, evt->dma);
		}
		if (mdwc->dummy_gsi_db_dma) {
			dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
					 sizeof(mdwc->dummy_gsi_db),
					 DMA_FROM_DEVICE);
			mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
		}
		break;
	case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
		dwc3_msm_dbm_disable_updxfer(dwc, value);
+36 −17
Original line number Diff line number Diff line
@@ -746,33 +746,34 @@ static void ipa_data_path_enable(struct gsi_data_port *d_port)
	bool block_db = false;

	log_event_dbg("IN: db_reg_phs_addr_lsb = %x",
			gsi->d_port.in_request.db_reg_phs_addr_lsb);
	usb_gsi_ep_op(gsi->d_port.in_ep,
			&gsi->d_port.in_request,
			d_port->in_request.db_reg_phs_addr_lsb);
	usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
			GSI_EP_OP_STORE_DBL_INFO);

	if (gsi->d_port.out_ep) {
	if (d_port->out_ep) {
		log_event_dbg("OUT: db_reg_phs_addr_lsb = %x",
				gsi->d_port.out_request.db_reg_phs_addr_lsb);
		usb_gsi_ep_op(gsi->d_port.out_ep,
				&gsi->d_port.out_request,
				d_port->out_request.db_reg_phs_addr_lsb);
		usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
				GSI_EP_OP_STORE_DBL_INFO);
	}

	usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
	usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
				GSI_EP_OP_ENABLE_GSI);

	/* Unblock doorbell to GSI */
	usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);

	usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
	usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
				GSI_EP_OP_RING_DB);

	if (gsi->d_port.out_ep)
		usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request,
	if (d_port->out_ep) {
		usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);
		usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
				GSI_EP_OP_RING_DB);
	}
}

static void ipa_disconnect_handler(struct gsi_data_port *d_port)
{
@@ -792,9 +793,12 @@ static void ipa_disconnect_handler(struct gsi_data_port *d_port)
				&gsi->d_port.in_request, GSI_EP_OP_DISABLE);
	}

	if (gsi->d_port.out_ep)
	if (gsi->d_port.out_ep) {
		usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);
		usb_gsi_ep_op(gsi->d_port.out_ep,
				&gsi->d_port.out_request, GSI_EP_OP_DISABLE);
	}

	gsi->d_port.net_ready_trigger = false;
}
@@ -846,6 +850,10 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
		block_db = false;
		usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);
		if (d_port->out_ep)
			usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);

		goto done;
	}

@@ -864,6 +872,9 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
		block_db = false;
		usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);
		if (d_port->out_ep)
			usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
				GSI_EP_OP_SET_CLR_BLOCK_DBL);
		gsi_wakeup_host(gsi);
	} else if (ret == -EINPROGRESS) {
		d_port->sm_state = STATE_SUSPEND_IN_PROGRESS;
@@ -895,6 +906,9 @@ static void ipa_resume_work_handler(struct gsi_data_port *d_port)
	block_db = false;
	usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
			GSI_EP_OP_SET_CLR_BLOCK_DBL);
	if (d_port->out_ep)
		usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
			GSI_EP_OP_SET_CLR_BLOCK_DBL);
}

static void ipa_work_handler(struct work_struct *w)
@@ -1059,9 +1073,11 @@ static void ipa_work_handler(struct work_struct *w)
				log_event_dbg("%s: ST_CON_HOST_NRDY\n",
								__func__);
				block_db = true;
				/* stop USB ringing doorbell to GSI(OUT_EP) */
				/* stop USB ringing doorbell to GSI(both EPs) */
				usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
						GSI_EP_OP_SET_CLR_BLOCK_DBL);
				usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
						GSI_EP_OP_SET_CLR_BLOCK_DBL);
				gsi_rndis_ipa_reset_trigger(d_port);
				usb_gsi_ep_op(d_port->in_ep, NULL,
						GSI_EP_OP_ENDXFER);
@@ -2637,6 +2653,9 @@ static void gsi_suspend(struct usb_function *f)
	block_db = true;
	usb_gsi_ep_op(gsi->d_port.in_ep, (void *)&block_db,
			GSI_EP_OP_SET_CLR_BLOCK_DBL);
	if (gsi->d_port.out_ep)
		usb_gsi_ep_op(gsi->d_port.out_ep, (void *)&block_db,
			GSI_EP_OP_SET_CLR_BLOCK_DBL);
	post_event(&gsi->d_port, EVT_SUSPEND);
	queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
	log_event_dbg("gsi suspended");