static int _gb_connection_enable()

in connection.c [671:735]


static int _gb_connection_enable(struct gb_connection *connection, bool rx)
{
	int ret;

	/* Handle ENABLED_TX -> ENABLED transitions. */
	if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) {
		if (!(connection->handler && rx))
			return 0;

		spin_lock_irq(&connection->lock);
		connection->state = GB_CONNECTION_STATE_ENABLED;
		spin_unlock_irq(&connection->lock);

		return 0;
	}

	ret = gb_connection_hd_cport_enable(connection);
	if (ret)
		return ret;

	ret = gb_connection_svc_connection_create(connection);
	if (ret)
		goto err_hd_cport_clear;

	ret = gb_connection_hd_cport_connected(connection);
	if (ret)
		goto err_svc_connection_destroy;

	spin_lock_irq(&connection->lock);
	if (connection->handler && rx)
		connection->state = GB_CONNECTION_STATE_ENABLED;
	else
		connection->state = GB_CONNECTION_STATE_ENABLED_TX;
	spin_unlock_irq(&connection->lock);

	ret = gb_connection_control_connected(connection);
	if (ret)
		goto err_control_disconnecting;

	return 0;

err_control_disconnecting:
	spin_lock_irq(&connection->lock);
	connection->state = GB_CONNECTION_STATE_DISCONNECTING;
	gb_connection_cancel_operations(connection, -ESHUTDOWN);
	spin_unlock_irq(&connection->lock);

	/* Transmit queue should already be empty. */
	gb_connection_hd_cport_flush(connection);

	gb_connection_control_disconnecting(connection);
	gb_connection_cport_shutdown_phase_1(connection);
	gb_connection_hd_cport_quiesce(connection);
	gb_connection_cport_shutdown_phase_2(connection);
	gb_connection_control_disconnected(connection);
	connection->state = GB_CONNECTION_STATE_DISABLED;
err_svc_connection_destroy:
	gb_connection_svc_connection_destroy(connection);
err_hd_cport_clear:
	gb_connection_hd_cport_clear(connection);

	gb_connection_hd_cport_disable(connection);

	return ret;
}