summaryrefslogtreecommitdiff
path: root/drivers/md/persistent-data/dm-transaction-manager.c
diff options
context:
space:
mode:
authorKevin Hilman <khilman@linaro.org>2014-12-15 13:59:43 -0800
committerKevin Hilman <khilman@linaro.org>2014-12-15 13:59:43 -0800
commit1888d2fa314033755026ceddee1fff8f80659fe4 (patch)
treeb0085323f5db6dca5f259b92038e27843c5a43a6 /drivers/md/persistent-data/dm-transaction-manager.c
parent9d312cd12e89ce08add99fe66e8f6baeaca16d7d (diff)
parent661ea91b676bcca137c1c3fe838997925ce98060 (diff)
Merge tag 'omap-for-v3.19/fixes-for-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
From: Tony Lindgren <tony@atomide.com> Subject: [GIT PULL] few fixes for the v3.19 merge window Fixes for a few issues found that would be good to get into -rc1: - Update SoC revision detection for am43x es1.2 - Fix regression with GPMC timings on 2430sdp for some versions of u-boot - Fix dra7 watchdog compatible property - Fix am437x-sk-evm LCD timings - Fix dra7 DSS clock muxing - Fix dra7-evm voltages - Remove a unused function prototype for am33xx_clk_init - Enable AHCI in the omap2plus_defconfig * tag 'omap-for-v3.19/fixes-for-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (1601 commits) ARM: omap2plus_defconfig: Enable AHCI_PLATFORM driver ARM: dts: am437x-sk-evm.dts: fix LCD timings ARM: dts: dra7-evm: Update SMPS7 (VDD_CORE) max voltage to match DM ARM: dts: dra7-evm: Fix typo in SMPS6 (VDD_GPU) max voltage ARM: OMAP2+: AM43x: Add ID for ES1.2 ARM: dts: am437x-sk: fix lcd enable pin mux data ARM: dts: Fix gpmc regression for omap 2430sdp smc91x hwmon: (tmp401) Detect TMP435 on all addresses it supports mfd: rtsx: Add func to split u32 into register mmc: sdhci-msm: Convert to mmc_send_tuning() mmc: sdhci-esdhc-imx: Convert to mmc_send_tuning() mmc: core: Let mmc_send_tuning() to take struct mmc_host* as parameter nios2: Make NIOS2_CMDLINE_IGNORE_DTB depend on CMDLINE_BOOL nios2: Add missing NR_CPUS to Kconfig nios2: asm-offsets: Remove unused definition TI_TASK nios2: Remove write-only struct member from nios2_timer nios2: Remove unused extern declaration of shm_align_mask nios2: include linux/type.h in io.h nios2: move include asm-generic/io.h to end of file nios2: remove include asm-generic/iomap.h from io.h ...
Diffstat (limited to 'drivers/md/persistent-data/dm-transaction-manager.c')
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
index 3bc30a0ae3d6..9cb797d800cf 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.c
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -10,6 +10,8 @@
#include "dm-persistent-data-internal.h"
#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/hash.h>
#include <linux/slab.h>
#include <linux/device-mapper.h>
@@ -17,6 +19,61 @@
/*----------------------------------------------------------------*/
+#define PREFETCH_SIZE 128
+#define PREFETCH_BITS 7
+#define PREFETCH_SENTINEL ((dm_block_t) -1ULL)
+
+struct prefetch_set {
+ struct mutex lock;
+ dm_block_t blocks[PREFETCH_SIZE];
+};
+
+static unsigned prefetch_hash(dm_block_t b)
+{
+ return hash_64(b, PREFETCH_BITS);
+}
+
+static void prefetch_wipe(struct prefetch_set *p)
+{
+ unsigned i;
+ for (i = 0; i < PREFETCH_SIZE; i++)
+ p->blocks[i] = PREFETCH_SENTINEL;
+}
+
+static void prefetch_init(struct prefetch_set *p)
+{
+ mutex_init(&p->lock);
+ prefetch_wipe(p);
+}
+
+static void prefetch_add(struct prefetch_set *p, dm_block_t b)
+{
+ unsigned h = prefetch_hash(b);
+
+ mutex_lock(&p->lock);
+ if (p->blocks[h] == PREFETCH_SENTINEL)
+ p->blocks[h] = b;
+
+ mutex_unlock(&p->lock);
+}
+
+static void prefetch_issue(struct prefetch_set *p, struct dm_block_manager *bm)
+{
+ unsigned i;
+
+ mutex_lock(&p->lock);
+
+ for (i = 0; i < PREFETCH_SIZE; i++)
+ if (p->blocks[i] != PREFETCH_SENTINEL) {
+ dm_bm_prefetch(bm, p->blocks[i]);
+ p->blocks[i] = PREFETCH_SENTINEL;
+ }
+
+ mutex_unlock(&p->lock);
+}
+
+/*----------------------------------------------------------------*/
+
struct shadow_info {
struct hlist_node hlist;
dm_block_t where;
@@ -37,6 +94,8 @@ struct dm_transaction_manager {
spinlock_t lock;
struct hlist_head buckets[DM_HASH_SIZE];
+
+ struct prefetch_set prefetches;
};
/*----------------------------------------------------------------*/
@@ -117,6 +176,8 @@ static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm,
for (i = 0; i < DM_HASH_SIZE; i++)
INIT_HLIST_HEAD(tm->buckets + i);
+ prefetch_init(&tm->prefetches);
+
return tm;
}
@@ -268,8 +329,14 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
struct dm_block_validator *v,
struct dm_block **blk)
{
- if (tm->is_clone)
- return dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+ if (tm->is_clone) {
+ int r = dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+
+ if (r == -EWOULDBLOCK)
+ prefetch_add(&tm->real->prefetches, b);
+
+ return r;
+ }
return dm_bm_read_lock(tm->bm, b, v, blk);
}
@@ -317,6 +384,12 @@ struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm)
return tm->bm;
}
+void dm_tm_issue_prefetches(struct dm_transaction_manager *tm)
+{
+ prefetch_issue(&tm->prefetches, tm->bm);
+}
+EXPORT_SYMBOL_GPL(dm_tm_issue_prefetches);
+
/*----------------------------------------------------------------*/
static int dm_tm_create_internal(struct dm_block_manager *bm,