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

Commit 7ab91b27 authored by Mayank Rana's avatar Mayank Rana
Browse files

usb: gadget: gsi: Fix handling of MSG PACKET FILTER



When USB RNDIS network device is bridged with other network device
on windows host machine, it has been observed that many MSG PACKET
FILTER packet with zero and non-zero value are send from host to
device. USB GSI state machines handles those and results into case
where TRB buffer's address is updated wrongly causing bus error
with IPA GSI. Fix this issue as below:
- Move MSG PACKET FILTER handling as part of ipa_work_handler()
- Add blocking USB3 ringing doorbell on receiving MSG PACKET FILTER
with non-zero value.
- Before processing HOST_NRDY event, see already posted event. If it
is HOST_READY event, then ignore HOST_NRDY and HOST_READY to avoid
performing operations related to HOST_NRDY and HOST_READY again.

CRs-Fixed: 1059577
Change-Id: I3ac8f740d7b84212da1d799b563a6e8ef1c9b493
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent f2304aea
Loading
Loading
Loading
Loading
+28 −7
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ struct usb_gsi_debugfs {

static struct usb_gsi_debugfs debugfs;

static void gsi_rndis_ipa_reset_trigger(void);
static void ipa_disconnect_handler(struct gsi_data_port *d_port);
static int gsi_ctrl_send_notification(struct f_gsi *gsi,
		enum gsi_ctrl_notify_state);
@@ -756,6 +757,7 @@ static void ipa_work_handler(struct work_struct *w)
	struct device *dev;
	struct device *gad_dev;
	struct f_gsi *gsi;
	bool block_db;

	event = read_event(d_port);

@@ -868,7 +870,27 @@ static void ipa_work_handler(struct work_struct *w)
		}
		break;
	case STATE_CONNECTED:
		if (event == EVT_DISCONNECTED) {
		if (event == EVT_DISCONNECTED || event == EVT_HOST_NRDY) {
			if (peek_event(d_port) == EVT_HOST_READY) {
				read_event(d_port);
				log_event_dbg("%s: NO_OP NRDY_RDY", __func__);
				break;
			}

			if (event == EVT_HOST_NRDY) {
				log_event_dbg("%s: ST_CON_HOST_NRDY\n",
								__func__);
				block_db = true;
				/* stop USB ringing doorbell to GSI(OUT_EP) */
				usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
						GSI_EP_OP_SET_CLR_BLOCK_DBL);
				gsi_rndis_ipa_reset_trigger();
				usb_gsi_ep_op(d_port->in_ep, NULL,
						GSI_EP_OP_ENDXFER);
				usb_gsi_ep_op(d_port->out_ep, NULL,
						GSI_EP_OP_ENDXFER);
			}

			ipa_disconnect_work_handler(d_port);
			d_port->sm_state = STATE_INITIALIZED;
			usb_gadget_autopm_put_async(d_port->gadget);
@@ -1463,7 +1485,7 @@ static void gsi_rndis_open(struct f_gsi *rndis)
	rndis_signal_connect(rndis->config);
}

void gsi_rndis_ipa_reset_trigger(void)
static void gsi_rndis_ipa_reset_trigger(void)
{
	struct f_gsi *rndis = gsi_prot_ctx[IPA_USB_RNDIS];
	unsigned long flags;
@@ -1497,11 +1519,10 @@ void gsi_rndis_flow_ctrl_enable(bool enable)
	d_port = &rndis->d_port;

	if (enable) {
		gsi_rndis_ipa_reset_trigger();
		usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_ENDXFER);
		usb_gsi_ep_op(d_port->out_ep, NULL, GSI_EP_OP_ENDXFER);
		post_event(d_port, EVT_DISCONNECTED);
		log_event_dbg("%s: posting HOST_NRDY\n", __func__);
		post_event(d_port, EVT_HOST_NRDY);
	} else {
		log_event_dbg("%s: posting HOST_READY\n", __func__);
		post_event(d_port, EVT_HOST_READY);
	}