summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/mmc_hsq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/mmc_hsq.c')
-rw-r--r--drivers/mmc/host/mmc_hsq.c64
1 files changed, 38 insertions, 26 deletions
diff --git a/drivers/mmc/host/mmc_hsq.c b/drivers/mmc/host/mmc_hsq.c
index a5e05ed0fda3..79836705c176 100644
--- a/drivers/mmc/host/mmc_hsq.c
+++ b/drivers/mmc/host/mmc_hsq.c
@@ -13,9 +13,6 @@
#include "mmc_hsq.h"
-#define HSQ_NUM_SLOTS 64
-#define HSQ_INVALID_TAG HSQ_NUM_SLOTS
-
static void mmc_hsq_retry_handler(struct work_struct *work)
{
struct mmc_hsq *hsq = container_of(work, struct mmc_hsq, retry_work);
@@ -24,6 +21,25 @@ static void mmc_hsq_retry_handler(struct work_struct *work)
mmc->ops->request(mmc, hsq->mrq);
}
+static void mmc_hsq_modify_threshold(struct mmc_hsq *hsq)
+{
+ struct mmc_host *mmc = hsq->mmc;
+ struct mmc_request *mrq;
+ unsigned int tag, need_change = 0;
+
+ mmc->hsq_depth = HSQ_NORMAL_DEPTH;
+ for (tag = 0; tag < HSQ_NUM_SLOTS; tag++) {
+ mrq = hsq->slot[tag].mrq;
+ if (mrq && mrq->data &&
+ (mrq->data->blksz * mrq->data->blocks == 4096) &&
+ (mrq->data->flags & MMC_DATA_WRITE) &&
+ (++need_change == 2)) {
+ mmc->hsq_depth = HSQ_PERFORMANCE_DEPTH;
+ break;
+ }
+ }
+}
+
static void mmc_hsq_pump_requests(struct mmc_hsq *hsq)
{
struct mmc_host *mmc = hsq->mmc;
@@ -34,7 +50,7 @@ static void mmc_hsq_pump_requests(struct mmc_hsq *hsq)
spin_lock_irqsave(&hsq->lock, flags);
/* Make sure we are not already running a request now */
- if (hsq->mrq) {
+ if (hsq->mrq || hsq->recovery_halt) {
spin_unlock_irqrestore(&hsq->lock, flags);
return;
}
@@ -45,6 +61,8 @@ static void mmc_hsq_pump_requests(struct mmc_hsq *hsq)
return;
}
+ mmc_hsq_modify_threshold(hsq);
+
slot = &hsq->slot[hsq->next_tag];
hsq->mrq = slot->mrq;
hsq->qcnt--;
@@ -73,7 +91,6 @@ static void mmc_hsq_pump_requests(struct mmc_hsq *hsq)
static void mmc_hsq_update_next_tag(struct mmc_hsq *hsq, int remains)
{
- struct hsq_slot *slot;
int tag;
/*
@@ -82,29 +99,12 @@ static void mmc_hsq_update_next_tag(struct mmc_hsq *hsq, int remains)
*/
if (!remains) {
hsq->next_tag = HSQ_INVALID_TAG;
+ hsq->tail_tag = HSQ_INVALID_TAG;
return;
}
- /*
- * Increasing the next tag and check if the corresponding request is
- * available, if yes, then we found a candidate request.
- */
- if (++hsq->next_tag != HSQ_INVALID_TAG) {
- slot = &hsq->slot[hsq->next_tag];
- if (slot->mrq)
- return;
- }
-
- /* Othersie we should iterate all slots to find a available tag. */
- for (tag = 0; tag < HSQ_NUM_SLOTS; tag++) {
- slot = &hsq->slot[tag];
- if (slot->mrq)
- break;
- }
-
- if (tag == HSQ_NUM_SLOTS)
- tag = HSQ_INVALID_TAG;
-
+ tag = hsq->tag_slot[hsq->next_tag];
+ hsq->tag_slot[hsq->next_tag] = HSQ_INVALID_TAG;
hsq->next_tag = tag;
}
@@ -233,8 +233,14 @@ static int mmc_hsq_request(struct mmc_host *mmc, struct mmc_request *mrq)
* Set the next tag as current request tag if no available
* next tag.
*/
- if (hsq->next_tag == HSQ_INVALID_TAG)
+ if (hsq->next_tag == HSQ_INVALID_TAG) {
hsq->next_tag = tag;
+ hsq->tail_tag = tag;
+ hsq->tag_slot[hsq->tail_tag] = HSQ_INVALID_TAG;
+ } else {
+ hsq->tag_slot[hsq->tail_tag] = tag;
+ hsq->tail_tag = tag;
+ }
hsq->qcnt++;
@@ -339,8 +345,10 @@ static const struct mmc_cqe_ops mmc_hsq_ops = {
int mmc_hsq_init(struct mmc_hsq *hsq, struct mmc_host *mmc)
{
+ int i;
hsq->num_slots = HSQ_NUM_SLOTS;
hsq->next_tag = HSQ_INVALID_TAG;
+ hsq->tail_tag = HSQ_INVALID_TAG;
hsq->slot = devm_kcalloc(mmc_dev(mmc), hsq->num_slots,
sizeof(struct hsq_slot), GFP_KERNEL);
@@ -350,6 +358,10 @@ int mmc_hsq_init(struct mmc_hsq *hsq, struct mmc_host *mmc)
hsq->mmc = mmc;
hsq->mmc->cqe_private = hsq;
mmc->cqe_ops = &mmc_hsq_ops;
+ mmc->hsq_depth = HSQ_NORMAL_DEPTH;
+
+ for (i = 0; i < HSQ_NUM_SLOTS; i++)
+ hsq->tag_slot[i] = HSQ_INVALID_TAG;
INIT_WORK(&hsq->retry_work, mmc_hsq_retry_handler);
spin_lock_init(&hsq->lock);