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

Commit 0d391f34 authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: rndis_ipa: Fix to incorrect state transition" into msm-4.9

parents 508067bf 93d96bff
Loading
Loading
Loading
Loading
+63 −1
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ enum rndis_ipa_operation {
 * This callback shall be called by the Netdev once the Netdev internal
 * state is changed to RNDIS_IPA_CONNECTED_AND_UP
 * @xmit_error_delayed_work: work item for cases where IPA driver Tx fails
 * @state_lock: used to protect the state variable.
 */
struct rndis_ipa_dev {
	struct net_device *net;
@@ -186,6 +187,7 @@ struct rndis_ipa_dev {
	u8 device_ethaddr[ETH_ALEN];
	void (*device_ready_notify)(void);
	struct delayed_work xmit_error_delayed_work;
	spinlock_t state_lock; /* Spinlock for the state variable.*/
};

/**
@@ -504,6 +506,8 @@ int rndis_ipa_init(struct ipa_usb_init_params *params)
	memset(rndis_ipa_ctx, 0, sizeof(*rndis_ipa_ctx));
	RNDIS_IPA_DEBUG("rndis_ipa_ctx (private)=%p\n", rndis_ipa_ctx);

	spin_lock_init(&rndis_ipa_ctx->state_lock);

	rndis_ipa_ctx->net = net;
	rndis_ipa_ctx->tx_filter = false;
	rndis_ipa_ctx->rx_filter = false;
@@ -656,11 +660,13 @@ int rndis_ipa_pipe_connect_notify(
	int next_state;
	int result;
	int ret;
	unsigned long flags;

	RNDIS_IPA_LOG_ENTRY();

	ret = 0;
	NULL_CHECK_RETVAL(private);

	if (ret)
		return ret;

@@ -675,13 +681,16 @@ int rndis_ipa_pipe_connect_notify(
		("max_xfer_sz_to_host=%d\n",
		max_xfer_size_bytes_to_host);

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);
	next_state = rndis_ipa_next_state
		(rndis_ipa_ctx->state,
		RNDIS_IPA_CONNECT);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("use init()/disconnect() before connect()\n");
		return -EPERM;
	}
	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	if (usb_to_ipa_hdl >= IPA_CLIENT_MAX) {
		RNDIS_IPA_ERROR
@@ -733,7 +742,17 @@ int rndis_ipa_pipe_connect_notify(
	}
	RNDIS_IPA_DEBUG("netif_carrier_on() was called\n");

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);
	next_state = rndis_ipa_next_state(rndis_ipa_ctx->state,
					  RNDIS_IPA_CONNECT);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("use init()/disconnect() before connect()\n");
		return -EPERM;
	}
	rndis_ipa_ctx->state = next_state;
	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx);

	if (next_state == RNDIS_IPA_CONNECTED_AND_UP)
@@ -770,18 +789,25 @@ static int rndis_ipa_open(struct net_device *net)
{
	struct rndis_ipa_dev *rndis_ipa_ctx;
	int next_state;
	unsigned long flags;

	RNDIS_IPA_LOG_ENTRY();

	rndis_ipa_ctx = netdev_priv(net);

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);

	next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_OPEN);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("can't bring driver up before initialize\n");
		return -EPERM;
	}

	rndis_ipa_ctx->state = next_state;

	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx);

	if (next_state == RNDIS_IPA_CONNECTED_AND_UP)
@@ -1123,19 +1149,26 @@ static int rndis_ipa_stop(struct net_device *net)
{
	struct rndis_ipa_dev *rndis_ipa_ctx = netdev_priv(net);
	int next_state;
	unsigned long flags;

	RNDIS_IPA_LOG_ENTRY();

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);

	next_state = rndis_ipa_next_state(rndis_ipa_ctx->state, RNDIS_IPA_STOP);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_DEBUG("can't do network interface down without up\n");
		return -EPERM;
	}

	rndis_ipa_ctx->state = next_state;

	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	netif_stop_queue(net);
	pr_info("RNDIS_IPA NetDev queue is stopped\n");

	rndis_ipa_ctx->state = next_state;
	RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx);

	RNDIS_IPA_LOG_EXIT();
@@ -1165,6 +1198,7 @@ int rndis_ipa_pipe_disconnect_notify(void *private)
	int outstanding_dropped_pkts;
	int retval;
	int ret;
	unsigned long flags;

	RNDIS_IPA_LOG_ENTRY();

@@ -1174,13 +1208,17 @@ int rndis_ipa_pipe_disconnect_notify(void *private)
		return ret;
	RNDIS_IPA_DEBUG("private=0x%p\n", private);

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);

	next_state = rndis_ipa_next_state
		(rndis_ipa_ctx->state,
		RNDIS_IPA_DISCONNECT);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("can't disconnect before connect\n");
		return -EPERM;
	}
	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	if (rndis_ipa_ctx->during_xmit_error) {
		RNDIS_IPA_DEBUG("canceling xmit-error delayed work\n");
@@ -1208,7 +1246,17 @@ int rndis_ipa_pipe_disconnect_notify(void *private)
	}
	RNDIS_IPA_DEBUG("RM was successfully destroyed\n");

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);
	next_state = rndis_ipa_next_state(rndis_ipa_ctx->state,
					  RNDIS_IPA_DISCONNECT);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("can't disconnect before connect\n");
		return -EPERM;
	}
	rndis_ipa_ctx->state = next_state;
	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx);

	pr_info("RNDIS_IPA NetDev pipes disconnected (%d outstanding clr)\n",
@@ -1247,6 +1295,7 @@ void rndis_ipa_cleanup(void *private)
	struct rndis_ipa_dev *rndis_ipa_ctx = private;
	int next_state;
	int retval;
	unsigned long flags;

	RNDIS_IPA_LOG_ENTRY();

@@ -1257,13 +1306,17 @@ void rndis_ipa_cleanup(void *private)
		return;
	}

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);
	next_state = rndis_ipa_next_state
		(rndis_ipa_ctx->state,
		RNDIS_IPA_CLEANUP);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("use disconnect()before clean()\n");
		return;
	}
	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);

	RNDIS_IPA_STATE_DEBUG(rndis_ipa_ctx);

	retval = rndis_ipa_deregister_properties(rndis_ipa_ctx->net->name);
@@ -1286,7 +1339,16 @@ void rndis_ipa_cleanup(void *private)
	unregister_netdev(rndis_ipa_ctx->net);
	RNDIS_IPA_DEBUG("netdev unregistered\n");

	spin_lock_irqsave(&rndis_ipa_ctx->state_lock, flags);
	next_state = rndis_ipa_next_state(rndis_ipa_ctx->state,
					  RNDIS_IPA_CLEANUP);
	if (next_state == RNDIS_IPA_INVALID) {
		spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
		RNDIS_IPA_ERROR("use disconnect()before clean()\n");
		return;
	}
	rndis_ipa_ctx->state = next_state;
	spin_unlock_irqrestore(&rndis_ipa_ctx->state_lock, flags);
	free_netdev(rndis_ipa_ctx->net);
	pr_info("RNDIS_IPA NetDev was cleaned\n");