@@ -873,23 +873,30 @@ static void gsi_channel_deprogram(struct gsi_channel *channel)
/* Nothing to do */
}
+static int __gsi_channel_start(struct gsi_channel *channel, bool start)
+{
+ struct gsi *gsi = channel->gsi;
+ int ret;
+
+ mutex_lock(&gsi->mutex);
+
+ ret = start ? gsi_channel_start_command(channel) : 0;
+
+ mutex_unlock(&gsi->mutex);
+
+ /* Thaw the channel if successful */
+ if (!ret)
+ gsi_channel_thaw(channel);
+
+ return ret;
+}
+
/* Start an allocated GSI channel */
int gsi_channel_start(struct gsi *gsi, u32 channel_id)
{
struct gsi_channel *channel = &gsi->channel[channel_id];
- int ret;
- mutex_lock(&gsi->mutex);
-
- ret = gsi_channel_start_command(channel);
-
- mutex_unlock(&gsi->mutex);
-
- /* Thaw the channel if successful */
- if (!ret)
- gsi_channel_thaw(channel);
-
- return ret;
+ return __gsi_channel_start(channel, true);
}
static int gsi_channel_stop_retry(struct gsi_channel *channel)
@@ -912,21 +919,27 @@ static int gsi_channel_stop_retry(struct gsi_channel *channel)
return ret;
}
+static int __gsi_channel_stop(struct gsi_channel *channel, bool stop)
+{
+ int ret;
+
+ gsi_channel_freeze(channel);
+
+ ret = stop ? gsi_channel_stop_retry(channel) : 0;
+
+ /* Re-thaw the channel if an error occurred while stopping */
+ if (ret)
+ gsi_channel_thaw(channel);
+
+ return ret;
+}
+
/* Stop a started channel */
int gsi_channel_stop(struct gsi *gsi, u32 channel_id)
{
struct gsi_channel *channel = &gsi->channel[channel_id];
- int ret;
- gsi_channel_freeze(channel);
-
- ret = gsi_channel_stop_retry(channel);
-
- /* Re-thaw the channel if an error occurred while stopping */
- if (ret)
- gsi_channel_thaw(channel);
-
- return ret;
+ return __gsi_channel_stop(channel, true);
}
/* Reset and reconfigure a channel, (possibly) enabling the doorbell engine */
@@ -952,12 +965,7 @@ int gsi_channel_suspend(struct gsi *gsi, u32 channel_id, bool stop)
{
struct gsi_channel *channel = &gsi->channel[channel_id];
- if (stop)
- return gsi_channel_stop(gsi, channel_id);
-
- gsi_channel_freeze(channel);
-
- return 0;
+ return __gsi_channel_stop(channel, stop);
}
/* Resume a suspended channel (starting will be requested if STOPPED) */
@@ -965,12 +973,7 @@ int gsi_channel_resume(struct gsi *gsi, u32 channel_id, bool start)
{
struct gsi_channel *channel = &gsi->channel[channel_id];
- if (start)
- return gsi_channel_start(gsi, channel_id);
-
- gsi_channel_thaw(channel);
-
- return 0;
+ return __gsi_channel_start(channel, start);
}
/**
Create a new function that does most of the work of starting a channel. What's different is that it takes a flag indicating whether the channel should really be stopped or not. When doing a "normal" channel start, the flag is true. Create another new function __gsi_channel_stop() that behaves similarly. IPA v3.5.1 implements suspend using a special SUSPEND endpoint setting. If the endpoint is suspended when an I/O completes on the underlying GSI channel, a SUSPEND interrupt is generated. Newer versions of IPA do not implement the SUSPEND endpoint mode. Instead, endpoint suspend is implemented by simply stopping the underlying GSI channel. In this case, an I/O completion on a *stopped* channel causes the SUSPEND interrupt condition. These new functions put all activity related to starting or stopping a channel (including "thawing/freezing" the channel) in one place, whether or not the channel is actually started or stopped. Signed-off-by: Alex Elder <elder@linaro.org> --- drivers/net/ipa/gsi.c | 71 ++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 34 deletions(-) -- 2.27.0