msm: ipa3: Fix to avoid gsi/sys len stats mismatch
In suspend just before stopping the channel possible to receive the IEOB interrupt and xfer pointer will not be processed in this mode but gsi stats are updated. In resume after starting the channel will receive the IEOB interrupt and xfer pointer will be overwritten because of this observing the gsi/sys len stats are not matching and buffers won't be replinished properly leading to HW stall. To avoid this process all data in polling context, gsi/sys len stats are updated properly. Change-Id: Id665448165b6aa51b251cddd72573c6df64ee541 Signed-off-by: Ashok Vuyyuru <avuyyuru@codeaurora.org>
此提交包含在:
@@ -537,9 +537,14 @@ static void gsi_process_chan(struct gsi_xfer_compl_evt *evt,
|
||||
ch_ctx->ring.rp_local = rp;
|
||||
}
|
||||
|
||||
|
||||
/* the element at RP is also processed */
|
||||
gsi_incr_ring_rp(&ch_ctx->ring);
|
||||
/*
|
||||
* Increment RP local only in polling context to avoid
|
||||
* sys len mismatch.
|
||||
*/
|
||||
if (!(callback && ch_ctx->props.dir ==
|
||||
GSI_CHAN_DIR_FROM_GSI))
|
||||
/* the element at RP is also processed */
|
||||
gsi_incr_ring_rp(&ch_ctx->ring);
|
||||
|
||||
ch_ctx->ring.rp = ch_ctx->ring.rp_local;
|
||||
rp_idx = gsi_find_idx_from_addr(&ch_ctx->ring, rp);
|
||||
@@ -549,11 +554,20 @@ static void gsi_process_chan(struct gsi_xfer_compl_evt *evt,
|
||||
notify->veid = evt->veid;
|
||||
}
|
||||
|
||||
ch_ctx->stats.completed++;
|
||||
|
||||
WARN_ON(!ch_ctx->user_data[rp_idx].valid);
|
||||
notify->xfer_user_data = ch_ctx->user_data[rp_idx].p;
|
||||
ch_ctx->user_data[rp_idx].valid = false;
|
||||
/*
|
||||
* In suspend just before stopping the channel possible to receive
|
||||
* the IEOB interrupt and xfer pointer will not be processed in this
|
||||
* mode and moving channel poll mode. In resume after starting the
|
||||
* channel will receive the IEOB interrupt and xfer pointer will be
|
||||
* overwritten. To avoid this process all data in polling context.
|
||||
*/
|
||||
if (!(callback && ch_ctx->props.dir == GSI_CHAN_DIR_FROM_GSI)) {
|
||||
ch_ctx->stats.completed++;
|
||||
ch_ctx->user_data[rp_idx].valid = false;
|
||||
}
|
||||
|
||||
notify->chan_user_data = ch_ctx->props.chan_user_data;
|
||||
notify->evt_id = evt->code;
|
||||
@@ -572,10 +586,18 @@ static void gsi_process_evt_re(struct gsi_evt_ctx *ctx,
|
||||
struct gsi_chan_xfer_notify *notify, bool callback)
|
||||
{
|
||||
struct gsi_xfer_compl_evt *evt;
|
||||
struct gsi_chan_ctx *ch_ctx;
|
||||
|
||||
evt = (struct gsi_xfer_compl_evt *)(ctx->ring.base_va +
|
||||
ctx->ring.rp_local - ctx->ring.base);
|
||||
gsi_process_chan(evt, notify, callback);
|
||||
/*
|
||||
* Increment RP local only in polling context to avoid
|
||||
* sys len mismatch.
|
||||
*/
|
||||
ch_ctx = &gsi_ctx->chan[evt->chid];
|
||||
if (callback && ch_ctx->props.dir == GSI_CHAN_DIR_FROM_GSI)
|
||||
return;
|
||||
gsi_incr_ring_rp(&ctx->ring);
|
||||
/* recycle this element */
|
||||
gsi_incr_ring_wp(&ctx->ring);
|
||||
|
@@ -4594,8 +4594,14 @@ static void ipa_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify)
|
||||
|
||||
sys = (struct ipa3_sys_context *)notify->chan_user_data;
|
||||
|
||||
|
||||
sys->ep->xfer_notify_valid = true;
|
||||
/*
|
||||
* In suspend just before stopping the channel possible to receive
|
||||
* the IEOB interrupt and xfer pointer will not be processed in this
|
||||
* mode and moving channel poll mode. In resume after starting the
|
||||
* channel will receive the IEOB interrupt and xfer pointer will be
|
||||
* overwritten. To avoid this process all data in polling context.
|
||||
*/
|
||||
sys->ep->xfer_notify_valid = false;
|
||||
sys->ep->xfer_notify = *notify;
|
||||
|
||||
switch (notify->evt_id) {
|
||||
@@ -4630,7 +4636,7 @@ static void ipa_dma_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify)
|
||||
return;
|
||||
}
|
||||
|
||||
sys->ep->xfer_notify_valid = true;
|
||||
sys->ep->xfer_notify_valid = false;
|
||||
sys->ep->xfer_notify = *notify;
|
||||
|
||||
switch (notify->evt_id) {
|
||||
|
新增問題並參考
封鎖使用者