summaryrefslogtreecommitdiffstats
path: root/target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch
diff options
context:
space:
mode:
authorkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>2010-07-21 11:20:53 +0000
committerkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>2010-07-21 11:20:53 +0000
commit642064ae9a94b47054ea7fb39804776ae11fbc4e (patch)
treece5d36d1490a49f1a75c8b8aae051f7c1e077ac8 /target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch
parent9b743eb09d74b1807a1101f8537c06f618835126 (diff)
add support for the Gateworks Laguna family (Cavium Networks Econa CNS3xxx)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22323 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch')
-rw-r--r--target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch438
1 files changed, 438 insertions, 0 deletions
diff --git a/target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch b/target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch
new file mode 100644
index 000000000..d6a8bef58
--- /dev/null
+++ b/target/linux/cns3xxx/patches-2.6.31/206-cns3xxx_raid_support.patch
@@ -0,0 +1,438 @@
+--- a/crypto/xor.c
++++ b/crypto/xor.c
+@@ -25,6 +25,26 @@
+ /* The xor routines to use. */
+ static struct xor_block_template *active_template;
+
++#ifdef CONFIG_CNS3XXX_RAID
++extern void do_cns_rdma_xorgen(unsigned int src_no, unsigned int bytes,
++ void **bh_ptr, void *dst_ptr);
++/**
++ * xor_blocks - one pass xor
++ * @src_count: source count
++ * @bytes: length in bytes
++ * @dest: dest
++ * @srcs: srcs
++ *
++ * Desc:
++ * 1. dest = xor(srcs[0...src_count-1]) within one calc
++ * 2. don't care if dest also be placed in srcs list or not.
++ */
++void xor_blocks(unsigned int src_count, unsigned int bytes, void *dest,
++ void **srcs)
++{
++ do_cns_rdma_xorgen(src_count, bytes, srcs, dest);
++}
++#else
+ void
+ xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
+ {
+@@ -51,6 +71,7 @@ xor_blocks(unsigned int src_count, unsig
+ p4 = (unsigned long *) srcs[3];
+ active_template->do_5(bytes, dest, p1, p2, p3, p4);
+ }
++#endif /* CONFIG_CNS3XXX_RAID */
+ EXPORT_SYMBOL(xor_blocks);
+
+ /* Set of all registered templates. */
+@@ -95,7 +116,11 @@ do_xor_speed(struct xor_block_template *
+ speed / 1000, speed % 1000);
+ }
+
++#ifdef CONFIG_CNS3XXX_RAID
++int
++#else
+ static int __init
++#endif /* CONFIG_CNS3XXX_RAID */
+ calibrate_xor_blocks(void)
+ {
+ void *b1, *b2;
+@@ -139,7 +164,10 @@ calibrate_xor_blocks(void)
+ if (f->speed > fastest->speed)
+ fastest = f;
+ }
+-
++#ifdef CONFIG_CNS3XXX_RAID
++ /* preferred */
++ fastest = template_list;
++#endif /* CONFIG_CNS3XXX_RAID */
+ printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
+ fastest->name, fastest->speed / 1000, fastest->speed % 1000);
+
+@@ -151,10 +179,20 @@ calibrate_xor_blocks(void)
+ return 0;
+ }
+
+-static __exit void xor_exit(void) { }
++#ifndef CONFIG_CNS3XXX_RAID
++static __exit void xor_exit(void)
++{
++}
++#endif /* ! CONFIG_CNS3XXX_RAID */
+
+ MODULE_LICENSE("GPL");
+
++#ifdef CONFIG_CNS3XXX_RAID
++/*
++ * Calibrate in R5 init.
++ */
++#else
+ /* when built-in xor.o must initialize before drivers/md/md.o */
+ core_initcall(calibrate_xor_blocks);
+ module_exit(xor_exit);
++#endif /* ! CONFIG_CNS3XXX_RAID */
+--- a/drivers/md/Makefile
++++ b/drivers/md/Makefile
+@@ -17,7 +17,7 @@ raid6_pq-y += raid6algos.o raid6recov.o
+ raid6int8.o raid6int16.o raid6int32.o \
+ raid6altivec1.o raid6altivec2.o raid6altivec4.o \
+ raid6altivec8.o \
+- raid6mmx.o raid6sse1.o raid6sse2.o
++ raid6mmx.o raid6sse1.o raid6sse2.o raid6cns.o
+ hostprogs-y += mktables
+
+ # Note: link order is important. All raid personalities
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1817,11 +1817,30 @@ static void compute_block_2(struct strip
+ compute_parity6(sh, UPDATE_PARITY);
+ return;
+ } else {
++#ifdef CONFIG_CNS3XXX_RAID
++ void *ptrs[disks];
++
++ count = 0;
++ i = d0_idx;
++ do {
++ ptrs[count++] = page_address(sh->dev[i].page);
++ i = raid6_next_disk(i, disks);
++ if (i != dd_idx1 && i != dd_idx2 &&
++ !test_bit(R5_UPTODATE, &sh->dev[i].flags))
++ printk
++ ("compute_2 with missing block %d/%d\n",
++ count, i);
++ } while (i != d0_idx);
++
++ raid6_dataq_recov(disks, STRIPE_SIZE, faila, ptrs);
++#else
++
+ /* We're missing D+Q; recompute D from P */
+ compute_block_1(sh, ((dd_idx1 == sh->qd_idx) ?
+ dd_idx2 : dd_idx1),
+ 0);
+ compute_parity6(sh, UPDATE_PARITY); /* Is this necessary? */
++#endif /* CONFIG_CNS3XXX_RAID */
+ return;
+ }
+ }
+@@ -5412,8 +5431,21 @@ static struct mdk_personality raid4_pers
+ .quiesce = raid5_quiesce,
+ };
+
++#ifdef CONFIG_CNS3XXX_RAID
++extern int calibrate_xor_blocks(void);
++#endif /* CONFIG_CNS3XXX_RAID */
++
+ static int __init raid5_init(void)
+ {
++
++#ifdef CONFIG_CNS3XXX_RAID
++ /* Just execute calibrate xor blocks */
++ int e;
++ e = calibrate_xor_blocks();
++ if (e)
++ return e;
++#endif /* CONFIG_CNS3XXX_RAID */
++
+ register_md_personality(&raid6_personality);
+ register_md_personality(&raid5_personality);
+ register_md_personality(&raid4_personality);
+--- a/drivers/md/raid6algos.c
++++ b/drivers/md/raid6algos.c
+@@ -49,6 +49,9 @@ extern const struct raid6_calls raid6_al
+ extern const struct raid6_calls raid6_altivec2;
+ extern const struct raid6_calls raid6_altivec4;
+ extern const struct raid6_calls raid6_altivec8;
++#ifdef CONFIG_CNS3XXX_RAID
++extern const struct raid6_calls raid6_cns_raid;
++#endif /* CONFIG_CNS3XXX_RAID */
+
+ const struct raid6_calls * const raid6_algos[] = {
+ &raid6_intx1,
+@@ -78,6 +81,11 @@ const struct raid6_calls * const raid6_a
+ &raid6_altivec4,
+ &raid6_altivec8,
+ #endif
++#ifdef CONFIG_CNS3XXX_RAID
++ /* CNS3000 HW RAID acceleration */
++ &raid6_cns_raid,
++#endif /* CONFIG_CNS3XXX_RAID */
++
+ NULL
+ };
+
+@@ -125,7 +133,9 @@ int __init raid6_select_algo(void)
+ if ( !(*algo)->valid || (*algo)->valid() ) {
+ perf = 0;
+
++#ifndef CONFIG_CNS3XXX_RAID
+ preempt_disable();
++#endif
+ j0 = jiffies;
+ while ( (j1 = jiffies) == j0 )
+ cpu_relax();
+@@ -134,7 +144,9 @@ int __init raid6_select_algo(void)
+ (*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs);
+ perf++;
+ }
++#ifndef CONFIG_CNS3XXX_RAID
+ preempt_enable();
++#endif
+
+ if ( (*algo)->prefer > bestprefer ||
+ ((*algo)->prefer == bestprefer &&
+--- /dev/null
++++ b/drivers/md/raid6cns.c
+@@ -0,0 +1,38 @@
++/*
++ * raid6cns.c
++ *
++ * CNS3xxx xor & gen_syndrome functions
++ *
++ */
++
++#ifdef CONFIG_CNS3XXX_RAID
++
++#include <linux/raid/pq.h>
++
++extern void do_cns_rdma_gfgen(unsigned int src_no, unsigned int bytes, void **bh_ptr,
++ void *p_dst, void *q_dst);
++
++/**
++ * raid6_cnsraid_gen_syndrome - CNSRAID Syndrome Generate
++ *
++ * @disks: raid disks
++ * @bytes: length
++ * @ptrs: already arranged stripe ptrs,
++ * disk0=[0], diskNNN=[disks-3],
++ * P/Q=[z0+1] & [z0+2], or, [disks-2], [disks-1]
++ */
++static void raid6_cnsraid_gen_syndrome(int disks, size_t bytes, void **ptrs)
++{
++ do_cns_rdma_gfgen(disks - 2, bytes, ptrs, ptrs[disks-2], ptrs[disks-1]);
++}
++
++const struct raid6_calls raid6_cns_raid = {
++ raid6_cnsraid_gen_syndrome, /* callback */
++ NULL, /* always valid */
++ "CNS-RAID", /* name */
++ 1 /* preferred: revise it to "0" to compare/compete with others algos */
++};
++
++EXPORT_SYMBOL(raid6_cns_raid);
++
++#endif /* CONFIG_CNS3XXX_RAID */
+--- a/drivers/md/raid6recov.c
++++ b/drivers/md/raid6recov.c
+@@ -20,6 +20,136 @@
+
+ #include <linux/raid/pq.h>
+
++#ifdef CONFIG_CNS3XXX_RAID
++#define R6_RECOV_PD 1
++#define R6_RECOV_DD 2
++#define R6_RECOV_DQ 3
++extern void do_cns_rdma_gfgen_pd_dd_dq(unsigned int src_no, unsigned int bytes,
++ void **bh_ptr, void *w1_dst,
++ void *w2_dst, int pd_dd_qd,
++ unsigned int w1_idx, unsigned int w2_idx,
++ unsigned int *src_idx);
++
++/**
++ * @disks: nr_disks
++ * @bytes: len
++ * @faila: 1st failed DD
++ * @ptrs: ptrs by order {d0, d1, ..., da, ..., dn, P, Q}
++ *
++ * Desc:
++ * new_read_ptrs = {d0, d1, ... dn, Q}
++ * dd1 = faila
++ * p_dst = P
++ */
++void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
++{
++ int cnt = 0;
++ int count = 0;
++ void *p_dst, *q;
++ void *dd1_dst;
++ void *new_read_ptrs[disks - 2];
++ unsigned int read_idx[disks - 2];
++
++ q = ptrs[disks - 1];
++ p_dst = ptrs[disks - 2];
++ dd1_dst = ptrs[faila];
++
++ while (cnt < disks) {
++ if (cnt != faila && cnt != disks - 2) {
++ new_read_ptrs[count] = ptrs[cnt];
++ read_idx[count] = cnt;
++ count++;
++ }
++ cnt++;
++ }
++
++ do_cns_rdma_gfgen_pd_dd_dq(disks - 2, bytes,
++ new_read_ptrs, p_dst, dd1_dst,
++ R6_RECOV_PD, disks - 1, faila + 1, read_idx);
++}
++
++/**
++ * @disks: nr_disks
++ * @bytes: len
++ * @faila: 1st failed DD
++ * @failb: 2nd failed DD
++ * @ptrs: ptrs by order {d0, d1, ..., da, ..., db, ..., dn, P, Q}
++ *
++ * Desc:
++ * new_read_ptrs = {d0, d1, ... dn, P, Q}
++ * dd1_dst = faila
++ * dd2_dst = failb
++ */
++void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
++ void **ptrs)
++{
++
++ int cnt = 0;
++ int count = 0;
++ void *p, *q;
++ void *dd1_dst, *dd2_dst;
++ void *new_read_ptrs[disks - 2];
++ unsigned int read_idx[disks - 2];
++
++ q = ptrs[disks - 1];
++ p = ptrs[disks - 2];
++ dd1_dst = ptrs[faila];
++ dd2_dst = ptrs[failb];
++
++ while (cnt < disks) {
++ if (cnt != faila && cnt != failb) {
++ new_read_ptrs[count] = ptrs[cnt];
++ read_idx[count] = cnt;
++ count++;
++ }
++ cnt++;
++ }
++
++ do_cns_rdma_gfgen_pd_dd_dq(disks - 2, bytes,
++ new_read_ptrs, dd1_dst, dd2_dst,
++ R6_RECOV_DD, faila + 1, failb + 1, read_idx);
++}
++
++/**
++ * @disks: nr_disks
++ * @bytes: len
++ * @faila: 1st failed DD
++ * @ptrs: ptrs by order {d0, d1, ..., da, ..., dn, P, Q}
++ *
++ * Desc:
++ * new_read_ptrs = {d0, d1, ... dn, P}
++ * dd1 = faila
++ * q_dst = Q
++ */
++void raid6_dataq_recov(int disks, size_t bytes, int faila, void **ptrs)
++{
++ int cnt = 0;
++ int count = 0;
++ void *q_dst, *p;
++ void *dd1_dst;
++ void *new_read_ptrs[disks - 2];
++ unsigned int read_idx[disks - 2];
++
++ p = ptrs[disks - 2];
++ q_dst = ptrs[disks - 1];
++ dd1_dst = ptrs[faila];
++
++ while (cnt < disks) {
++ if (cnt != faila && cnt != disks - 1) {
++ new_read_ptrs[count] = ptrs[cnt];
++ read_idx[count] = cnt;
++ count++;
++ }
++ cnt++;
++ }
++
++ do_cns_rdma_gfgen_pd_dd_dq(disks - 2, bytes,
++ new_read_ptrs, dd1_dst, q_dst,
++ R6_RECOV_DQ, faila + 1, disks, read_idx);
++}
++
++#else /* CONFIG_CNS3XXX_RAID
++
+ /* Recover two failed data blocks. */
+ void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
+ void **ptrs)
+@@ -96,6 +226,7 @@ void raid6_datap_recov(int disks, size_t
+ }
+ }
+ EXPORT_SYMBOL_GPL(raid6_datap_recov);
++#endif /* CONFIG_CNS3XXX_RAID */
+
+ #ifndef __KERNEL__
+ /* Testing only */
+--- a/include/linux/raid/pq.h
++++ b/include/linux/raid/pq.h
+@@ -100,6 +100,9 @@ void raid6_2data_recov(int disks, size_t
+ void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs);
+ void raid6_dual_recov(int disks, size_t bytes, int faila, int failb,
+ void **ptrs);
++#ifdef CONFIG_CNS3XXX_RAID
++void raid6_dataq_recov(int disks, size_t bytes, int faila, void **ptrs);
++#endif /* CONFIG_CNS3XXX_RAID */
+
+ /* Some definitions to allow code to be compiled for testing in userspace */
+ #ifndef __KERNEL__
+--- a/include/linux/raid/xor.h
++++ b/include/linux/raid/xor.h
+@@ -1,7 +1,11 @@
+ #ifndef _XOR_H
+ #define _XOR_H
+
++#ifdef CONFIG_CNS3XXX_RAID
++#define MAX_XOR_BLOCKS 32
++#else
+ #define MAX_XOR_BLOCKS 4
++#endif /* CONFIG_CNS3XXX_RAID */
+
+ extern void xor_blocks(unsigned int count, unsigned int bytes,
+ void *dest, void **srcs);
+--- a/mm/mempool.c
++++ b/mm/mempool.c
+@@ -250,6 +250,28 @@ repeat_alloc:
+ }
+ EXPORT_SYMBOL(mempool_alloc);
+
++#ifdef CONFIG_CNS3XXX_RAID
++/**
++ * acs_mempool_alloc - allocate an element from a specific memory pool
++ * @pool: pointer to the memory pool which was allocated via
++ * mempool_create().
++ *
++ * this function differs from mempool_alloc by directly allocating an element
++ * from @pool without calling @pool->alloc().
++ */
++void *acs_mempool_alloc(mempool_t * pool)
++{
++ unsigned long flags;
++ void *element = NULL;
++
++ spin_lock_irqsave(&pool->lock, flags);
++ if (likely(pool->curr_nr))
++ element = remove_element(pool);
++ spin_unlock_irqrestore(&pool->lock, flags);
++ return element;
++}
++#endif /* CONFIG_CNS3XXX_RAID */
++
+ /**
+ * mempool_free - return an element to the pool.
+ * @element: pool element pointer.