Revert rpmh and usb changes

8aafbcb usb: dwc3: gadget: Properly handle failed kick_transfer
c646369 soc: qcom: rpmh: Dirt can only make you dirtier, not cleaner
a91f874 soc: qcom: rpmh-rsc: Allow using free WAKE TCS for active request
c15a40c soc: qcom: rpmh-rsc: Clear active mode configuration for wake TCS
8644121 soc: qcom: rpmh: Invalidate SLEEP and WAKE TCSes before flushing new data
d504699 soc: qcom: rpmh: Update dirty flag only when data changes

Change-Id: I0d919e1b658c8195230444ef118f7f1fe8e63b47
Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
This commit is contained in:
Srinivasarao P 2020-08-06 18:43:27 +05:30
parent 204dd19a9b
commit 73abf3a00c
3 changed files with 71 additions and 107 deletions

View File

@ -148,7 +148,7 @@ int rpmh_rsc_invalidate(struct rsc_drv *drv)
static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv,
const struct tcs_request *msg)
{
int type;
int type, ret;
struct tcs_group *tcs;
switch (msg->state) {
@ -169,10 +169,19 @@ static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv,
* If we are making an active request on a RSC that does not have a
* dedicated TCS for active state use, then re-purpose a wake TCS to
* send active votes.
* NOTE: The driver must be aware that this RSC does not have a
* dedicated AMC, and therefore would invalidate the sleep and wake
* TCSes before making an active state request.
*/
tcs = get_tcs_of_type(drv, type);
if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs)
if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs) {
tcs = get_tcs_of_type(drv, WAKE_TCS);
if (tcs->num_tcs) {
ret = rpmh_rsc_invalidate(drv);
if (ret)
return ERR_PTR(ret);
}
}
return tcs;
}
@ -192,42 +201,6 @@ static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv,
return NULL;
}
static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger)
{
u32 enable;
/*
* HW req: Clear the DRV_CONTROL and enable TCS again
* While clearing ensure that the AMC mode trigger is cleared
* and then the mode enable is cleared.
*/
enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0);
enable &= ~TCS_AMC_MODE_TRIGGER;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
enable &= ~TCS_AMC_MODE_ENABLE;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
if (trigger) {
/* Enable the AMC mode on the TCS and then trigger the TCS */
enable = TCS_AMC_MODE_ENABLE;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
enable |= TCS_AMC_MODE_TRIGGER;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
}
}
static void enable_tcs_irq(struct rsc_drv *drv, int tcs_id, bool enable)
{
u32 data;
data = read_tcs_reg(drv, RSC_DRV_IRQ_ENABLE, 0, 0);
if (enable)
data |= BIT(tcs_id);
else
data &= ~BIT(tcs_id);
write_tcs_reg(drv, RSC_DRV_IRQ_ENABLE, 0, data);
}
/**
* tcs_tx_done: TX Done interrupt handler
*/
@ -264,14 +237,6 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
}
trace_rpmh_tx_done(drv, i, req, err);
/*
* If wake tcs was re-purposed for sending active
* votes, clear AMC trigger & enable modes and
* disable interrupt for this TCS
*/
if (!drv->tcs[ACTIVE_TCS].num_tcs)
__tcs_set_trigger(drv, i, false);
skip:
/* Reclaim the TCS */
write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0);
@ -279,13 +244,6 @@ skip:
write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i));
spin_lock(&drv->lock);
clear_bit(i, drv->tcs_in_use);
/*
* Disable interrupt for WAKE TCS to avoid being
* spammed with interrupts coming when the solver
* sends its wake votes.
*/
if (!drv->tcs[ACTIVE_TCS].num_tcs)
enable_tcs_irq(drv, i, false);
spin_unlock(&drv->lock);
if (req)
rpmh_tx_done(req, err);
@ -327,6 +285,28 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable);
}
static void __tcs_trigger(struct rsc_drv *drv, int tcs_id)
{
u32 enable;
/*
* HW req: Clear the DRV_CONTROL and enable TCS again
* While clearing ensure that the AMC mode trigger is cleared
* and then the mode enable is cleared.
*/
enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0);
enable &= ~TCS_AMC_MODE_TRIGGER;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
enable &= ~TCS_AMC_MODE_ENABLE;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
/* Enable the AMC mode on the TCS and then trigger the TCS */
enable = TCS_AMC_MODE_ENABLE;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
enable |= TCS_AMC_MODE_TRIGGER;
write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable);
}
static int check_for_req_inflight(struct rsc_drv *drv, struct tcs_group *tcs,
const struct tcs_request *msg)
{
@ -397,20 +377,10 @@ static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
tcs->req[tcs_id - tcs->offset] = msg;
set_bit(tcs_id, drv->tcs_in_use);
if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS) {
/*
* Clear previously programmed WAKE commands in selected
* repurposed TCS to avoid triggering them. tcs->slots will be
* cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
*/
write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0);
write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0);
enable_tcs_irq(drv, tcs_id, true);
}
spin_unlock(&drv->lock);
__tcs_buffer_write(drv, tcs_id, 0, msg);
__tcs_set_trigger(drv, tcs_id, true);
__tcs_trigger(drv, tcs_id);
done_write:
spin_unlock_irqrestore(&tcs->lock, flags);

View File

@ -119,7 +119,6 @@ static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr,
{
struct cache_req *req;
unsigned long flags;
u32 old_sleep_val, old_wake_val;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
req = __find_req(ctrlr, cmd->addr);
@ -134,27 +133,26 @@ static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr,
req->addr = cmd->addr;
req->sleep_val = req->wake_val = UINT_MAX;
INIT_LIST_HEAD(&req->list);
list_add_tail(&req->list, &ctrlr->cache);
existing:
old_sleep_val = req->sleep_val;
old_wake_val = req->wake_val;
switch (state) {
case RPMH_ACTIVE_ONLY_STATE:
if (req->sleep_val != UINT_MAX)
req->wake_val = cmd->data;
break;
case RPMH_WAKE_ONLY_STATE:
req->wake_val = cmd->data;
break;
case RPMH_SLEEP_STATE:
req->sleep_val = cmd->data;
break;
default:
break;
}
ctrlr->dirty |= (req->sleep_val != old_sleep_val ||
req->wake_val != old_wake_val) &&
req->sleep_val != UINT_MAX &&
req->wake_val != UINT_MAX;
ctrlr->dirty = true;
unlock:
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
@ -290,7 +288,6 @@ static void cache_batch(struct rpmh_ctrlr *ctrlr, struct batch_cache_req *req)
spin_lock_irqsave(&ctrlr->cache_lock, flags);
list_add_tail(&req->list, &ctrlr->batch_cache);
ctrlr->dirty = true;
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
}
@ -318,6 +315,18 @@ static int flush_batch(struct rpmh_ctrlr *ctrlr)
return ret;
}
static void invalidate_batch(struct rpmh_ctrlr *ctrlr)
{
struct batch_cache_req *req, *tmp;
unsigned long flags;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
list_for_each_entry_safe(req, tmp, &ctrlr->batch_cache, list)
kfree(req);
INIT_LIST_HEAD(&ctrlr->batch_cache);
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
}
/**
* rpmh_write_batch: Write multiple sets of RPMH commands and wait for the
* batch to finish.
@ -457,13 +466,6 @@ int rpmh_flush(const struct device *dev)
return 0;
}
/* Invalidate the TCSes first to avoid stale data */
do {
ret = rpmh_rsc_invalidate(ctrlr_to_drv(ctrlr));
} while (ret == -EAGAIN);
if (ret)
return ret;
/* First flush the cached batch requests */
ret = flush_batch(ctrlr);
if (ret)
@ -495,25 +497,25 @@ int rpmh_flush(const struct device *dev)
EXPORT_SYMBOL(rpmh_flush);
/**
* rpmh_invalidate: Invalidate sleep and wake sets in batch_cache
* rpmh_invalidate: Invalidate all sleep and active sets
* sets.
*
* @dev: The device making the request
*
* Invalidate the sleep and wake values in batch_cache.
* Invalidate the sleep and active values in the TCS blocks.
*/
int rpmh_invalidate(const struct device *dev)
{
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
struct batch_cache_req *req, *tmp;
unsigned long flags;
int ret;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
list_for_each_entry_safe(req, tmp, &ctrlr->batch_cache, list)
kfree(req);
INIT_LIST_HEAD(&ctrlr->batch_cache);
invalidate_batch(ctrlr);
ctrlr->dirty = true;
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
return 0;
do {
ret = rpmh_rsc_invalidate(ctrlr_to_drv(ctrlr));
} while (ret == -EAGAIN);
return ret;
}
EXPORT_SYMBOL(rpmh_invalidate);

View File

@ -1217,8 +1217,6 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
}
}
static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep);
static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
{
struct dwc3_gadget_ep_cmd_params params;
@ -1255,20 +1253,14 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
if (ret < 0) {
struct dwc3_request *tmp;
if (ret == -EAGAIN)
return ret;
dwc3_stop_active_transfer(dep, true, true);
list_for_each_entry_safe(req, tmp, &dep->started_list, list)
dwc3_gadget_move_cancelled_request(req);
/* If ep isn't started, then there's no end transfer pending */
if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
dwc3_gadget_ep_cleanup_cancelled_requests(dep);
/*
* FIXME we need to iterate over the list of requests
* here and stop, unmap, free and del each of the linked
* requests instead of what we do now.
*/
if (req->trb)
memset(req->trb, 0, sizeof(struct dwc3_trb));
dwc3_gadget_del_and_unmap_request(dep, req, ret);
return ret;
}