aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEyal Reizer2013-07-30 05:55:46 -0500
committerEyal Reizer2013-07-30 05:55:46 -0500
commit0bf1c31420f6b3cc84c6ff7d531f75b5f2c8630b (patch)
tree1002572f48baec6abc3114c7295111e23ef257a0
parent49439339361762a6cb037307fd139ba31e420d1b (diff)
downloadbuild-utilities-r8.a6.02-ibi-experimental.tar.gz
build-utilities-r8.a6.02-ibi-experimental.tar.xz
build-utilities-r8.a6.02-ibi-experimental.zip
patches: add ubuntu 12.04 lts kernel ibi supportr8.a6.02-ibi-experimental
Add a series of patches that should be applied tot the ubuntu 12.04-LTS kernel (linux 3.5.0) in order for working with the wilink8 r8.a6.02 sdio in-band interrupt support. This series of patches add new APIs to the sdio_irq driver that are used by the r8.a6.02 modified drivers. Without this patch set the driver would not build with the 12.04-LTS kernel. Note: The build script is not applying this patch set. It needs to be manually applied to the linux pc kernel source followed buy a build/install of the modified kernel to the Ubuntu PC. Signed-off-by: Eyal Reizer <eyalr@ti.com>
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0001-sdio-add-sdio_enable_irq-sdio_disable_irq-functions.patch100
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0002-mmc-Toggle-power-while-host-is-claimed.patch56
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0003-sdio-Add-support-for-lock-less-interrupt-handlers-EX.patch152
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0004-sdio-Add-lock-less-handlers-host-claiming-function-E.patch79
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0005-sdio-don-t-signal-sdio-irq-if-the-power-was-kept.patch31
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0006-sdio-add-sdio_flush_irq-function-HACK.patch169
-rw-r--r--patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/README.TXT23
7 files changed, 610 insertions, 0 deletions
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0001-sdio-add-sdio_enable_irq-sdio_disable_irq-functions.patch b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0001-sdio-add-sdio_enable_irq-sdio_disable_irq-functions.patch
new file mode 100644
index 0000000..877389b
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0001-sdio-add-sdio_enable_irq-sdio_disable_irq-functions.patch
@@ -0,0 +1,100 @@
1From 9be7b41e872e5245e37a0bbf1a3640e5c1b8e008 Mon Sep 17 00:00:00 2001
2From: Eliad Peller <eliad@wizery.com>
3Date: Sun, 22 Jan 2012 15:57:22 +0200
4Subject: [PATCH 1/6] sdio: add sdio_enable_irq/sdio_disable_irq functions
5
6In some cases, we'd like to disable the irq, without stopping
7the handler thread, as this is our own context (i.e. doing
8something similar to disable_irq_nosync).
9
10Add sdio_enable_irq/sdio_disable_irq functions, that only
11configure the irq, without touching the handler.
12
13(TODO: add the missing async stuff)
14
15Signed-off-by: Eliad Peller <eliad@wizery.com>
16---
17 drivers/mmc/core/sdio_irq.c | 56 +++++++++++++++++++++++++++++++++++++++++
18 include/linux/mmc/sdio_func.h | 2 ++
19 2 files changed, 58 insertions(+)
20
21diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
22index 3d8ceb4..1090ef3 100644
23--- a/drivers/mmc/core/sdio_irq.c
24+++ b/drivers/mmc/core/sdio_irq.c
25@@ -312,3 +312,59 @@ int sdio_release_irq(struct sdio_func *func)
26 }
27 EXPORT_SYMBOL_GPL(sdio_release_irq);
28
29+int sdio_enable_irq(struct sdio_func *func)
30+{
31+ int ret;
32+ unsigned char reg;
33+
34+ BUG_ON(!func);
35+ BUG_ON(!func->card);
36+
37+ pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func));
38+
39+ ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
40+ if (ret)
41+ return ret;
42+
43+ reg |= 1 << func->num;
44+
45+ reg |= 1; /* Master interrupt enable */
46+
47+ ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
48+ if (ret)
49+ return ret;
50+
51+ /* TODO: add async stuff */
52+
53+ return ret;
54+}
55+EXPORT_SYMBOL_GPL(sdio_enable_irq);
56+
57+int sdio_disable_irq(struct sdio_func *func)
58+{
59+ int ret;
60+ unsigned char reg;
61+
62+ BUG_ON(!func);
63+ BUG_ON(!func->card);
64+
65+ pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));
66+
67+ ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
68+ if (ret)
69+ return ret;
70+
71+ reg &= ~(1 << func->num);
72+
73+ /* Disable master interrupt with the last function interrupt */
74+ if (!(reg & 0xFE))
75+ reg = 0;
76+
77+ ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
78+ if (ret)
79+ return ret;
80+
81+ return 0;
82+}
83+EXPORT_SYMBOL_GPL(sdio_disable_irq);
84+
85diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
86index 50f0bc9..5bdfffc 100644
87--- a/include/linux/mmc/sdio_func.h
88+++ b/include/linux/mmc/sdio_func.h
89@@ -126,6 +126,8 @@ extern int sdio_set_block_size(struct sdio_func *func, unsigned blksz);
90
91 extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler);
92 extern int sdio_release_irq(struct sdio_func *func);
93+extern int sdio_enable_irq(struct sdio_func *func);
94+extern int sdio_disable_irq(struct sdio_func *func);
95
96 extern unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz);
97
98--
991.7.9.5
100
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0002-mmc-Toggle-power-while-host-is-claimed.patch b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0002-mmc-Toggle-power-while-host-is-claimed.patch
new file mode 100644
index 0000000..73e2141
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0002-mmc-Toggle-power-while-host-is-claimed.patch
@@ -0,0 +1,56 @@
1From 4d57fc441988755093fe62a37a5f009a30dae2ca Mon Sep 17 00:00:00 2001
2From: Ido Yariv <ido@wizery.com>
3Date: Thu, 22 Dec 2011 11:27:06 +0200
4Subject: [PATCH 2/6] mmc: Toggle power while host is claimed
5
6Runtime PM ops might be called when the host isn't claimed. This can be
7problematic, as the mmc disable/enable callbacks might be called
8concurrently.
9
10Fix this by claiming the host before calling mmc_power_*_host. Since
11it's perfectly fine to claim a host more than once by the same task, it
12should be safe to do even if the runtime PM functions are called with
13the host claimed.
14
15Signed-off-by: Ido Yariv <ido@wizery.com>
16Signed-off-by: Ido Reis <idor@ti.com>
17Signed-off-by: Eliad Peller <eliad@wizery.com>
18---
19 drivers/mmc/core/bus.c | 14 ++++++++++++--
20 1 file changed, 12 insertions(+), 2 deletions(-)
21
22diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
23index 9b68933..4a87c03 100644
24--- a/drivers/mmc/core/bus.c
25+++ b/drivers/mmc/core/bus.c
26@@ -151,15 +151,25 @@ static int mmc_bus_resume(struct device *dev)
27 static int mmc_runtime_suspend(struct device *dev)
28 {
29 struct mmc_card *card = mmc_dev_to_card(dev);
30+ int ret;
31+
32+ mmc_claim_host(card->host);
33+ ret = mmc_power_save_host(card->host);
34+ mmc_release_host(card->host);
35
36- return mmc_power_save_host(card->host);
37+ return ret;
38 }
39
40 static int mmc_runtime_resume(struct device *dev)
41 {
42 struct mmc_card *card = mmc_dev_to_card(dev);
43+ int ret;
44+
45+ mmc_claim_host(card->host);
46+ ret = mmc_power_restore_host(card->host);
47+ mmc_release_host(card->host);
48
49- return mmc_power_restore_host(card->host);
50+ return ret;
51 }
52
53 static int mmc_runtime_idle(struct device *dev)
54--
551.7.9.5
56
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0003-sdio-Add-support-for-lock-less-interrupt-handlers-EX.patch b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0003-sdio-Add-support-for-lock-less-interrupt-handlers-EX.patch
new file mode 100644
index 0000000..20b0d2c
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0003-sdio-Add-support-for-lock-less-interrupt-handlers-EX.patch
@@ -0,0 +1,152 @@
1From 18de2b81bbc84bc38be63bb865995d642cf8eb20 Mon Sep 17 00:00:00 2001
2From: Ido Yariv <ido@wizery.com>
3Date: Mon, 2 Jan 2012 21:38:21 +0200
4Subject: [PATCH 3/6] sdio: Add support for lock-less interrupt handlers
5 *EXPERIMENTAL*
6
7SDIO interrupt handlers are called with the host being claimed. Some
8drivers may normally claim the host after acquiring a different lock.
9This means that the interrupt handler may not acquire this lock, as the
10locking order will be incorrect.
11
12Add support for lock-less interrupt handlers, which will be called
13without the host being claimed.
14
15Signed-off-by: Ido Reis <idor@ti.com>
16Signed-off-by: Eliad Peller <eliad@wizery.com>
17---
18 drivers/mmc/core/sdio_irq.c | 55 +++++++++++++++++++++++++++++++++++++++----
19 include/linux/mmc/card.h | 1 +
20 2 files changed, 51 insertions(+), 5 deletions(-)
21
22diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
23index 1090ef3..ae37545 100644
24--- a/drivers/mmc/core/sdio_irq.c
25+++ b/drivers/mmc/core/sdio_irq.c
26@@ -32,7 +32,6 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
27 {
28 struct mmc_card *card = host->card;
29 int i, ret, count;
30- unsigned char pending;
31 struct sdio_func *func;
32
33 /*
34@@ -46,7 +45,9 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
35 return 1;
36 }
37
38- ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
39+ card->pending_int = 0;
40+ ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0,
41+ &card->pending_int);
42 if (ret) {
43 pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",
44 mmc_card_id(card), ret);
45@@ -55,7 +56,7 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
46
47 count = 0;
48 for (i = 1; i <= 7; i++) {
49- if (pending & (1 << i)) {
50+ if (card->pending_int & (1 << i)) {
51 func = card->sdio_func[i - 1];
52 if (!func) {
53 pr_warning("%s: pending IRQ for "
54@@ -65,7 +66,7 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
55 } else if (func->irq_handler) {
56 func->irq_handler(func);
57 count++;
58- } else {
59+ } else if (!func->irq_handler_ll) {
60 pr_warning("%s: pending IRQ with no handler\n",
61 sdio_func_id(func));
62 ret = -EINVAL;
63@@ -79,6 +80,20 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
64 return ret;
65 }
66
67+static void call_sdio_lockless_irqs(struct mmc_card *card)
68+{
69+ int i;
70+
71+ for (i = 1; i <= 7; i++) {
72+ if (card->pending_int & (1 << i)) {
73+ struct sdio_func *func = card->sdio_func[i - 1];
74+ if (func && func->irq_handler_ll) {
75+ func->irq_handler_ll(func);
76+ }
77+ }
78+ }
79+}
80+
81 static int sdio_irq_thread(void *_host)
82 {
83 struct mmc_host *host = _host;
84@@ -121,6 +136,7 @@ static int sdio_irq_thread(void *_host)
85 ret = process_sdio_pending_irqs(host);
86 host->sdio_irq_pending = false;
87 mmc_release_host(host);
88+ call_sdio_lockless_irqs(host->card);
89
90 /*
91 * Give other threads a chance to run in the presence of
92@@ -273,6 +289,34 @@ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
93 EXPORT_SYMBOL_GPL(sdio_claim_irq);
94
95 /**
96+ * sdio_claim_irq_lockless - claim the IRQ for a SDIO function
97+ * @func: SDIO function
98+ * @handler: IRQ handler callback
99+ *
100+ * Claim and activate the IRQ for the given SDIO function. The provided
101+ * handler will be called when that IRQ is asserted. The host is not
102+ * claimed when the handler is called so the handler might need to call
103+ * sdio_claim_host() and sdio_release_host().
104+ */
105+int sdio_claim_irq_lockless(struct sdio_func *func, sdio_irq_handler_t *handler)
106+{
107+ int ret;
108+
109+ if (func->irq_handler_ll) {
110+ pr_debug("SDIO: IRQ for %s already in use.\n", sdio_func_id(func));
111+ return -EBUSY;
112+ }
113+
114+ func->irq_handler_ll = handler;
115+ ret = sdio_claim_irq(func, NULL);
116+ if (ret)
117+ func->irq_handler_ll = NULL;
118+
119+ return ret;
120+}
121+EXPORT_SYMBOL_GPL(sdio_claim_irq_lockless);
122+
123+/**
124 * sdio_release_irq - release the IRQ for a SDIO function
125 * @func: SDIO function
126 *
127@@ -288,8 +332,9 @@ int sdio_release_irq(struct sdio_func *func)
128
129 pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));
130
131- if (func->irq_handler) {
132+ if (func->irq_handler || func->irq_handler_ll) {
133 func->irq_handler = NULL;
134+ func->irq_handler_ll = NULL;
135 sdio_card_irq_put(func->card);
136 sdio_single_irq_set(func->card);
137 }
138diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
139index d76513b..236bdb7 100644
140--- a/include/linux/mmc/card.h
141+++ b/include/linux/mmc/card.h
142@@ -272,6 +272,7 @@ struct mmc_card {
143 unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
144
145 struct dentry *debugfs_root;
146+ unsigned char pending_int; /* pending sdio interrupts */
147 struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
148 unsigned int nr_parts;
149 };
150--
1511.7.9.5
152
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0004-sdio-Add-lock-less-handlers-host-claiming-function-E.patch b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0004-sdio-Add-lock-less-handlers-host-claiming-function-E.patch
new file mode 100644
index 0000000..45eb043
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0004-sdio-Add-lock-less-handlers-host-claiming-function-E.patch
@@ -0,0 +1,79 @@
1From a1d9007707559841bac009a08a768abffc2f5e0e Mon Sep 17 00:00:00 2001
2From: Ido Yariv <ido@wizery.com>
3Date: Mon, 2 Jan 2012 21:42:04 +0200
4Subject: [PATCH 4/6] sdio: Add lock-less handlers host claiming function
5 *EXPERIMENTAL*
6
7Lock-less handlers which are called without the host being claimed
8probably need to claim the host by themselves. In order to avoid a
9race with sdio_release_irq, add support for claiming the host and
10aborting the claim when the sdio irq is freed.
11
12Signed-off-by: Eliad Peller <eliad@wizery.com>
13---
14 drivers/mmc/core/sdio_io.c | 19 +++++++++++++++++++
15 include/linux/mmc/sdio_func.h | 4 ++++
16 2 files changed, 23 insertions(+)
17
18diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
19index 8f6f5ac..dcc37d9 100644
20--- a/drivers/mmc/core/sdio_io.c
21+++ b/drivers/mmc/core/sdio_io.c
22@@ -34,6 +34,25 @@ void sdio_claim_host(struct sdio_func *func)
23 EXPORT_SYMBOL_GPL(sdio_claim_host);
24
25 /**
26+ * sdio_claim_host_irq - exclusively claim a bus for a certain SDIO function
27+ * @func: SDIO function that will be accessed
28+ *
29+ * Claim a bus for a set of operations. The SDIO function given
30+ * is used to figure out which bus is relevant.
31+ * The function may abort (returing a negative return value) if the sdio
32+ * irq is freed.
33+ */
34+int sdio_claim_host_irq(struct sdio_func *func)
35+{
36+ BUG_ON(!func);
37+ BUG_ON(!func->card);
38+
39+ return __mmc_claim_host(func->card->host,
40+ &func->card->host->sdio_irq_thread_abort);
41+}
42+EXPORT_SYMBOL_GPL(sdio_claim_host_irq);
43+
44+/**
45 * sdio_release_host - release a bus for a certain SDIO function
46 * @func: SDIO function that was accessed
47 *
48diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
49index 5bdfffc..b7db154 100644
50--- a/include/linux/mmc/sdio_func.h
51+++ b/include/linux/mmc/sdio_func.h
52@@ -39,6 +39,7 @@ struct sdio_func {
53 struct mmc_card *card; /* the card this device belongs to */
54 struct device dev; /* the device */
55 sdio_irq_handler_t *irq_handler; /* IRQ callback */
56+ sdio_irq_handler_t *irq_handler_ll;/* IRQ callback, called with the host unclaimed */
57 unsigned int num; /* function number */
58
59 unsigned char class; /* standard interface class */
60@@ -117,6 +118,7 @@ extern void sdio_unregister_driver(struct sdio_driver *);
61 * SDIO I/O operations
62 */
63 extern void sdio_claim_host(struct sdio_func *func);
64+extern int sdio_claim_host_irq(struct sdio_func *func);
65 extern void sdio_release_host(struct sdio_func *func);
66
67 extern int sdio_enable_func(struct sdio_func *func);
68@@ -125,6 +127,8 @@ extern int sdio_disable_func(struct sdio_func *func);
69 extern int sdio_set_block_size(struct sdio_func *func, unsigned blksz);
70
71 extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler);
72+extern int sdio_claim_irq_lockless(struct sdio_func *func,
73+ sdio_irq_handler_t *handler);
74 extern int sdio_release_irq(struct sdio_func *func);
75 extern int sdio_enable_irq(struct sdio_func *func);
76 extern int sdio_disable_irq(struct sdio_func *func);
77--
781.7.9.5
79
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0005-sdio-don-t-signal-sdio-irq-if-the-power-was-kept.patch b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0005-sdio-don-t-signal-sdio-irq-if-the-power-was-kept.patch
new file mode 100644
index 0000000..f3edba8
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0005-sdio-don-t-signal-sdio-irq-if-the-power-was-kept.patch
@@ -0,0 +1,31 @@
1From 1cfa523f70217372ad30e414c1ca27d167bf0a63 Mon Sep 17 00:00:00 2001
2From: Ido Reis <idor@ti.com>
3Date: Wed, 7 Nov 2012 12:05:06 +0200
4Subject: [PATCH 5/6] sdio: don't signal sdio irq if the power was kept
5
6if the power was kept during during suspend, the
7sdio_irq was operational all the time, and there
8is no reason to signal it (for pending irqs)
9
10Signed-off-by: Eliad Peller <eliad@wizery.com>
11Signed-off-by: Ido Reis <idor@ti.com>
12---
13 drivers/mmc/core/sdio.c | 2 +-
14 1 file changed, 1 insertion(+), 1 deletion(-)
15
16diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
17index 41c5fd8..2bfe627 100644
18--- a/drivers/mmc/core/sdio.c
19+++ b/drivers/mmc/core/sdio.c
20@@ -952,7 +952,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
21 }
22 }
23
24- if (!err && host->sdio_irqs)
25+ if (!err && !mmc_card_keep_power(host) && host->sdio_irqs)
26 wake_up_process(host->sdio_irq_thread);
27 mmc_release_host(host);
28
29--
301.7.9.5
31
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0006-sdio-add-sdio_flush_irq-function-HACK.patch b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0006-sdio-add-sdio_flush_irq-function-HACK.patch
new file mode 100644
index 0000000..82abcf8
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/0006-sdio-add-sdio_flush_irq-function-HACK.patch
@@ -0,0 +1,169 @@
1From 9b1c6f353fc43a71ab2044015b34b55df803f86c Mon Sep 17 00:00:00 2001
2From: Eliad Peller <eliad@wizery.com>
3Date: Tue, 6 Nov 2012 18:20:15 +0200
4Subject: [PATCH 6/6] sdio: add sdio_flush_irq function (HACK)
5
6add sdio_flush_irq function to allow flushing
7the sdio irq function.
8do it by setting a flag if an irq was signaled,
9and clear it after running the sdio_irq handlers.
10
11the function waits (on a waitqueue) for the flag
12to get cleared.
13
14Signed-off-by: Eliad Peller <eliad@wizery.com>
15---
16 drivers/mmc/core/host.c | 3 +++
17 drivers/mmc/core/sdio_irq.c | 54 +++++++++++++++++++++++++++++++++++++++++
18 include/linux/mmc/host.h | 10 +++++++-
19 include/linux/mmc/sdio_func.h | 1 +
20 4 files changed, 67 insertions(+), 1 deletion(-)
21
22diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
23index 91c84c7..90f359d 100644
24--- a/drivers/mmc/core/host.c
25+++ b/drivers/mmc/core/host.c
26@@ -345,6 +345,9 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
27 host->max_blk_size = 512;
28 host->max_blk_count = PAGE_CACHE_SIZE / 512;
29
30+ spin_lock_init(&host->sdio_irq_running_lock);
31+ init_waitqueue_head(&host->sdio_wq);
32+
33 return host;
34
35 free:
36diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
37index ae37545..143551b 100644
38--- a/drivers/mmc/core/sdio_irq.c
39+++ b/drivers/mmc/core/sdio_irq.c
40@@ -99,6 +99,7 @@ static int sdio_irq_thread(void *_host)
41 struct mmc_host *host = _host;
42 struct sched_param param = { .sched_priority = 1 };
43 unsigned long period, idle_period;
44+ unsigned long flags;
45 int ret;
46
47 sched_setscheduler(current, SCHED_FIFO, &param);
48@@ -148,6 +149,10 @@ static int sdio_irq_thread(void *_host)
49 schedule_timeout(HZ);
50 set_current_state(TASK_RUNNING);
51 }
52+ host->sdio_irq_running = false;
53+ spin_lock_irqsave(&host->sdio_irq_running_lock, flags);
54+ wake_up_all(&host->sdio_wq);
55+ spin_unlock_irqrestore(&host->sdio_irq_running_lock, flags);
56
57 /*
58 * Adaptive polling frequency based on the assumption
59@@ -166,6 +171,11 @@ static int sdio_irq_thread(void *_host)
60
61 set_current_state(TASK_INTERRUPTIBLE);
62 if (host->caps & MMC_CAP_SDIO_IRQ) {
63+ spin_lock_irqsave(&host->sdio_irq_running_lock, flags);
64+ host->sdio_irq_running = false;
65+ wake_up_all(&host->sdio_wq);
66+ spin_unlock_irqrestore(&host->sdio_irq_running_lock, flags);
67+
68 mmc_host_clk_hold(host);
69 host->ops->enable_sdio_irq(host, 1);
70 mmc_host_clk_release(host);
71@@ -179,6 +189,11 @@ static int sdio_irq_thread(void *_host)
72 mmc_host_clk_hold(host);
73 host->ops->enable_sdio_irq(host, 0);
74 mmc_host_clk_release(host);
75+
76+ spin_lock_irqsave(&host->sdio_irq_running_lock, flags);
77+ host->sdio_irq_running = false;
78+ wake_up_all(&host->sdio_wq);
79+ spin_unlock_irqrestore(&host->sdio_irq_running_lock, flags);
80 }
81
82 pr_debug("%s: IRQ thread exiting with code %d\n",
83@@ -413,3 +428,42 @@ int sdio_disable_irq(struct sdio_func *func)
84 }
85 EXPORT_SYMBOL_GPL(sdio_disable_irq);
86
87+static bool sdio_irq_running(struct mmc_host *host)
88+{
89+ unsigned long flags;
90+ bool running;
91+
92+ spin_lock_irqsave(&host->sdio_irq_running_lock, flags);
93+ running = host->sdio_irq_running;
94+ spin_unlock_irqrestore(&host->sdio_irq_running_lock, flags);
95+
96+ return running;
97+}
98+
99+int sdio_flush_irq(struct sdio_func *func)
100+{
101+ struct mmc_host *host;
102+
103+ BUG_ON(!func);
104+ BUG_ON(!func->card);
105+
106+ host = func->card->host;
107+
108+ while (sdio_irq_running(host)) {
109+ DEFINE_WAIT(wait);
110+
111+ prepare_to_wait(&host->sdio_wq, &wait, TASK_UNINTERRUPTIBLE);
112+ if (sdio_irq_running(host))
113+ schedule();
114+
115+ /*
116+ * we should check the condition again, but this might be
117+ * a problem as a new irq might have come in the meantime
118+ */
119+ finish_wait(&host->sdio_wq, &wait);
120+
121+ break;
122+ }
123+ return 0;
124+}
125+EXPORT_SYMBOL_GPL(sdio_flush_irq);
126diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
127index 0707d22..72dc1f4 100644
128--- a/include/linux/mmc/host.h
129+++ b/include/linux/mmc/host.h
130@@ -300,6 +300,10 @@ struct mmc_host {
131 bool sdio_irq_pending;
132 atomic_t sdio_irq_thread_abort;
133
134+ spinlock_t sdio_irq_running_lock;
135+ bool sdio_irq_running;
136+ wait_queue_head_t sdio_wq;
137+
138 mmc_pm_flag_t pm_flags; /* requested pm features */
139
140 #ifdef CONFIG_LEDS_TRIGGERS
141@@ -352,8 +356,12 @@ extern int mmc_cache_ctrl(struct mmc_host *, u8);
142
143 static inline void mmc_signal_sdio_irq(struct mmc_host *host)
144 {
145+ unsigned long flags;
146+
147 host->ops->enable_sdio_irq(host, 0);
148- host->sdio_irq_pending = true;
149+ spin_lock_irqsave(&host->sdio_irq_running_lock, flags);
150+ host->sdio_irq_running = true;
151+ spin_unlock_irqrestore(&host->sdio_irq_running_lock, flags);
152 wake_up_process(host->sdio_irq_thread);
153 }
154
155diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
156index b7db154..33271a6 100644
157--- a/include/linux/mmc/sdio_func.h
158+++ b/include/linux/mmc/sdio_func.h
159@@ -132,6 +132,7 @@ extern int sdio_claim_irq_lockless(struct sdio_func *func,
160 extern int sdio_release_irq(struct sdio_func *func);
161 extern int sdio_enable_irq(struct sdio_func *func);
162 extern int sdio_disable_irq(struct sdio_func *func);
163+extern int sdio_flush_irq(struct sdio_func *func);
164
165 extern unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz);
166
167--
1681.7.9.5
169
diff --git a/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/README.TXT b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/README.TXT
new file mode 100644
index 0000000..f50e876
--- /dev/null
+++ b/patches/ubuntu-12.04-LTS-3.5.0-kernel-patches/README.TXT
@@ -0,0 +1,23 @@
1patches: add ubuntu 12.04 lts kernel ibi support
2================================================
3
4This directory contains a series of patches that should be applied to the
5ubuntu 12.04-LTS kernel (linux 3.5.0) in order for working with the wilink8
6r8.a6.02 sdio in-band interrupt support.
7This series of patches add new APIs to the sdio_irq driver that are used
8by the r8.a6.02 modified drivers.
9
10Without this patch set the driver would not build with the 12.04-LTS kernel.
11
12Note: The build script is not applying this patch set. It needs to
13==== be manually applied to the linux pc kernel source followed buy a
14 build/install of the modified kernel to the Ubuntu PC.
15
16The following web page has instructions on obtaining/rebuilding
17the Ubuntu 12.04 linux kernel after applying this patch set:
18
19http://linuxtweaking.blogspot.co.uk/2012/08/ubuntu-1204-lts-kernel-compile-guide.html
20
21
22
23