@@ -1583,6 +1583,56 @@ void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev)
}
EXPORT_SYMBOL_GPL(mhi_unprepare_from_transfer);
+static int mhi_update_transfer_state(struct mhi_device *mhi_dev,
+ enum mhi_ch_state_type to_state)
+{
+ struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+ struct device *dev = &mhi_cntrl->mhi_dev->dev;
+ struct mhi_chan *mhi_chan;
+ struct mhi_chan_ctxt *chan_ctxt;
+ int dir, ret;
+
+ for (dir = 0; dir < 2; dir++) {
+ mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan;
+
+ if (!mhi_chan)
+ continue;
+
+ /*
+ * Bail out if one of the channels fails as client will reset
+ * both upon failure
+ */
+ mutex_lock(&mhi_chan->mutex);
+ chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan];
+ if (!(chan_ctxt->chcfg & CHAN_CTX_CHSTATE_MASK)) {
+ mutex_unlock(&mhi_chan->mutex);
+ dev_err(dev, "Channel %s(%u) context not initialized\n",
+ mhi_chan->name, mhi_chan->chan);
+ return -EINVAL;
+ }
+ ret = mhi_update_channel_state(mhi_cntrl, mhi_chan, to_state);
+ if (ret) {
+ mutex_unlock(&mhi_chan->mutex);
+ return ret;
+ }
+ mutex_unlock(&mhi_chan->mutex);
+ }
+
+ return 0;
+}
+
+int mhi_stop_transfer(struct mhi_device *mhi_dev)
+{
+ return mhi_update_transfer_state(mhi_dev, MHI_CH_STATE_TYPE_STOP);
+}
+EXPORT_SYMBOL_GPL(mhi_stop_transfer);
+
+int mhi_start_transfer(struct mhi_device *mhi_dev)
+{
+ return mhi_update_transfer_state(mhi_dev, MHI_CH_STATE_TYPE_START);
+}
+EXPORT_SYMBOL_GPL(mhi_start_transfer);
+
int mhi_poll(struct mhi_device *mhi_dev, u32 budget)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
@@ -715,6 +715,25 @@ int mhi_prepare_for_transfer(struct mhi_device *mhi_dev);
void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev);
/**
+ * mhi_stop_transfer - Pauses ongoing channel activity by issuing the STOP
+ * channel command to both UL and DL channels. This command
+ * does not reset the channel context and the client drivers
+ * can issue mhi_start_transfer to resume activity.
+ * @mhi_dev: Device associated with the channels
+ */
+int mhi_stop_transfer(struct mhi_device *mhi_dev);
+
+/**
+ * mhi_start_transfer - Resumes channel activity by issuing the START channel
+ * command to both UL and DL channels. This command assumes
+ * the channel context is already setup and the client
+ * drivers can issue mhi_stop_transfer to pause activity if
+ * required.
+ * @mhi_dev: Device associated with the channels
+ */
+int mhi_start_transfer(struct mhi_device *mhi_dev);
+
+/**
* mhi_poll - Poll for any available data in DL direction
* @mhi_dev: Device associated with the channels
* @budget: # of events to process