• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * linux/drivers/mmc/core/sdio_irq.c
3  *
4  * Author:      Nicolas Pitre
5  * Created:     June 18, 2007
6  * Copyright:   MontaVista Software Inc.
7  *
8  * Copyright 2008 Pierre Ossman
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  */
15 
16 #include <linux/kernel.h>
17 #include <linux/sched.h>
18 #include <uapi/linux/sched/types.h>
19 #include <linux/kthread.h>
20 #include <linux/export.h>
21 #include <linux/wait.h>
22 #include <linux/delay.h>
23 
24 #include <linux/mmc/core.h>
25 #include <linux/mmc/host.h>
26 #include <linux/mmc/card.h>
27 #include <linux/mmc/sdio.h>
28 #include <linux/mmc/sdio_func.h>
29 
30 #include "sdio_ops.h"
31 #include "core.h"
32 #include "card.h"
33 
process_sdio_pending_irqs(struct mmc_host * host)34 static int process_sdio_pending_irqs(struct mmc_host *host)
35 {
36 	struct mmc_card *card = host->card;
37 	int i, ret, count;
38 	bool sdio_irq_pending = host->sdio_irq_pending;
39 	unsigned char pending;
40 	struct sdio_func *func;
41 
42 	/* Don't process SDIO IRQs if the card is suspended. */
43 	if (mmc_card_suspended(card))
44 		return 0;
45 
46 	/* Clear the flag to indicate that we have processed the IRQ. */
47 	host->sdio_irq_pending = false;
48 
49 	/*
50 	 * Optimization, if there is only 1 function interrupt registered
51 	 * and we know an IRQ was signaled then call irq handler directly.
52 	 * Otherwise do the full probe.
53 	 */
54 	func = card->sdio_single_irq;
55 	if (func && sdio_irq_pending) {
56 		func->irq_handler(func);
57 		return 1;
58 	}
59 
60 	ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
61 	if (ret) {
62 		pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",
63 		       mmc_card_id(card), ret);
64 		return ret;
65 	}
66 
67 	if (pending && mmc_card_broken_irq_polling(card) &&
68 	    !(host->caps & MMC_CAP_SDIO_IRQ)) {
69 		unsigned char dummy;
70 
71 		/* A fake interrupt could be created when we poll SDIO_CCCR_INTx
72 		 * register with a Marvell SD8797 card. A dummy CMD52 read to
73 		 * function 0 register 0xff can avoid this.
74 		 */
75 		mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy);
76 	}
77 
78 	count = 0;
79 	for (i = 1; i <= 7; i++) {
80 		if (pending & (1 << i)) {
81 			func = card->sdio_func[i - 1];
82 			if (!func) {
83 				pr_warn("%s: pending IRQ for non-existent function\n",
84 					mmc_card_id(card));
85 				ret = -EINVAL;
86 			} else if (func->irq_handler) {
87 				func->irq_handler(func);
88 				count++;
89 			} else {
90 				pr_warn("%s: pending IRQ with no handler\n",
91 					sdio_func_id(func));
92 				ret = -EINVAL;
93 			}
94 		}
95 	}
96 
97 	if (count)
98 		return count;
99 
100 	return ret;
101 }
102 
sdio_run_irqs(struct mmc_host * host)103 void sdio_run_irqs(struct mmc_host *host)
104 {
105 	mmc_claim_host(host);
106 	if (host->sdio_irqs) {
107 		process_sdio_pending_irqs(host);
108 		if (host->ops->ack_sdio_irq)
109 			host->ops->ack_sdio_irq(host);
110 	}
111 	mmc_release_host(host);
112 }
113 EXPORT_SYMBOL_GPL(sdio_run_irqs);
114 
sdio_irq_work(struct work_struct * work)115 void sdio_irq_work(struct work_struct *work)
116 {
117 	struct mmc_host *host =
118 		container_of(work, struct mmc_host, sdio_irq_work.work);
119 
120 	sdio_run_irqs(host);
121 }
122 
sdio_signal_irq(struct mmc_host * host)123 void sdio_signal_irq(struct mmc_host *host)
124 {
125 	host->sdio_irq_pending = true;
126 	queue_delayed_work(system_wq, &host->sdio_irq_work, 0);
127 }
128 EXPORT_SYMBOL_GPL(sdio_signal_irq);
129 
sdio_irq_thread(void * _host)130 static int sdio_irq_thread(void *_host)
131 {
132 	struct mmc_host *host = _host;
133 	struct sched_param param = { .sched_priority = 1 };
134 	unsigned long period, idle_period;
135 	int ret;
136 
137 	sched_setscheduler(current, SCHED_FIFO, &param);
138 
139 	/*
140 	 * We want to allow for SDIO cards to work even on non SDIO
141 	 * aware hosts.  One thing that non SDIO host cannot do is
142 	 * asynchronous notification of pending SDIO card interrupts
143 	 * hence we poll for them in that case.
144 	 */
145 	idle_period = msecs_to_jiffies(10);
146 	period = (host->caps & MMC_CAP_SDIO_IRQ) ?
147 		MAX_SCHEDULE_TIMEOUT : idle_period;
148 
149 	pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n",
150 		 mmc_hostname(host), period);
151 
152 	do {
153 		/*
154 		 * We claim the host here on drivers behalf for a couple
155 		 * reasons:
156 		 *
157 		 * 1) it is already needed to retrieve the CCCR_INTx;
158 		 * 2) we want the driver(s) to clear the IRQ condition ASAP;
159 		 * 3) we need to control the abort condition locally.
160 		 *
161 		 * Just like traditional hard IRQ handlers, we expect SDIO
162 		 * IRQ handlers to be quick and to the point, so that the
163 		 * holding of the host lock does not cover too much work
164 		 * that doesn't require that lock to be held.
165 		 */
166 		ret = __mmc_claim_host(host, NULL,
167 				       &host->sdio_irq_thread_abort);
168 		if (ret)
169 			break;
170 		ret = process_sdio_pending_irqs(host);
171 		mmc_release_host(host);
172 
173 		/*
174 		 * Give other threads a chance to run in the presence of
175 		 * errors.
176 		 */
177 		if (ret < 0) {
178 			set_current_state(TASK_INTERRUPTIBLE);
179 			if (!kthread_should_stop())
180 				schedule_timeout(HZ);
181 			set_current_state(TASK_RUNNING);
182 		}
183 
184 		/*
185 		 * Adaptive polling frequency based on the assumption
186 		 * that an interrupt will be closely followed by more.
187 		 * This has a substantial benefit for network devices.
188 		 */
189 		if (!(host->caps & MMC_CAP_SDIO_IRQ)) {
190 			if (ret > 0)
191 				period /= 2;
192 			else {
193 				period++;
194 				if (period > idle_period)
195 					period = idle_period;
196 			}
197 		}
198 
199 		set_current_state(TASK_INTERRUPTIBLE);
200 		if (host->caps & MMC_CAP_SDIO_IRQ)
201 			host->ops->enable_sdio_irq(host, 1);
202 		if (!kthread_should_stop())
203 			schedule_timeout(period);
204 		set_current_state(TASK_RUNNING);
205 	} while (!kthread_should_stop());
206 
207 	if (host->caps & MMC_CAP_SDIO_IRQ)
208 		host->ops->enable_sdio_irq(host, 0);
209 
210 	pr_debug("%s: IRQ thread exiting with code %d\n",
211 		 mmc_hostname(host), ret);
212 
213 	return ret;
214 }
215 
sdio_card_irq_get(struct mmc_card * card)216 static int sdio_card_irq_get(struct mmc_card *card)
217 {
218 	struct mmc_host *host = card->host;
219 
220 	WARN_ON(!host->claimed);
221 
222 	if (!host->sdio_irqs++) {
223 		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
224 			atomic_set(&host->sdio_irq_thread_abort, 0);
225 			host->sdio_irq_thread =
226 				kthread_run(sdio_irq_thread, host,
227 					    "ksdioirqd/%s", mmc_hostname(host));
228 			if (IS_ERR(host->sdio_irq_thread)) {
229 				int err = PTR_ERR(host->sdio_irq_thread);
230 				host->sdio_irqs--;
231 				return err;
232 			}
233 		} else if (host->caps & MMC_CAP_SDIO_IRQ) {
234 			host->ops->enable_sdio_irq(host, 1);
235 		}
236 	}
237 
238 	return 0;
239 }
240 
sdio_card_irq_put(struct mmc_card * card)241 static int sdio_card_irq_put(struct mmc_card *card)
242 {
243 	struct mmc_host *host = card->host;
244 
245 	WARN_ON(!host->claimed);
246 
247 	if (host->sdio_irqs < 1)
248 		return -EINVAL;
249 
250 	if (!--host->sdio_irqs) {
251 		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
252 			atomic_set(&host->sdio_irq_thread_abort, 1);
253 			kthread_stop(host->sdio_irq_thread);
254 		} else if (host->caps & MMC_CAP_SDIO_IRQ) {
255 			host->ops->enable_sdio_irq(host, 0);
256 		}
257 	}
258 
259 	return 0;
260 }
261 
262 /* If there is only 1 function registered set sdio_single_irq */
sdio_single_irq_set(struct mmc_card * card)263 static void sdio_single_irq_set(struct mmc_card *card)
264 {
265 	struct sdio_func *func;
266 	int i;
267 
268 	card->sdio_single_irq = NULL;
269 	if ((card->host->caps & MMC_CAP_SDIO_IRQ) &&
270 	    card->host->sdio_irqs == 1)
271 		for (i = 0; i < card->sdio_funcs; i++) {
272 		       func = card->sdio_func[i];
273 		       if (func && func->irq_handler) {
274 			       card->sdio_single_irq = func;
275 			       break;
276 		       }
277 	       }
278 }
279 
280 /**
281  *	sdio_claim_irq - claim the IRQ for a SDIO function
282  *	@func: SDIO function
283  *	@handler: IRQ handler callback
284  *
285  *	Claim and activate the IRQ for the given SDIO function. The provided
286  *	handler will be called when that IRQ is asserted.  The host is always
287  *	claimed already when the handler is called so the handler should not
288  *	call sdio_claim_host() or sdio_release_host().
289  */
sdio_claim_irq(struct sdio_func * func,sdio_irq_handler_t * handler)290 int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
291 {
292 	int ret;
293 	unsigned char reg;
294 
295 	if (!func)
296 		return -EINVAL;
297 
298 	pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func));
299 
300 	if (func->irq_handler) {
301 		pr_debug("SDIO: IRQ for %s already in use.\n", sdio_func_id(func));
302 		return -EBUSY;
303 	}
304 
305 	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
306 	if (ret)
307 		return ret;
308 
309 	reg |= 1 << func->num;
310 
311 	reg |= 1; /* Master interrupt enable */
312 
313 	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
314 	if (ret)
315 		return ret;
316 
317 	func->irq_handler = handler;
318 	ret = sdio_card_irq_get(func->card);
319 	if (ret)
320 		func->irq_handler = NULL;
321 	sdio_single_irq_set(func->card);
322 
323 	return ret;
324 }
325 EXPORT_SYMBOL_GPL(sdio_claim_irq);
326 
327 /**
328  *	sdio_release_irq - release the IRQ for a SDIO function
329  *	@func: SDIO function
330  *
331  *	Disable and release the IRQ for the given SDIO function.
332  */
sdio_release_irq(struct sdio_func * func)333 int sdio_release_irq(struct sdio_func *func)
334 {
335 	int ret;
336 	unsigned char reg;
337 
338 	if (!func)
339 		return -EINVAL;
340 
341 	pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));
342 
343 	if (func->irq_handler) {
344 		func->irq_handler = NULL;
345 		sdio_card_irq_put(func->card);
346 		sdio_single_irq_set(func->card);
347 	}
348 
349 	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
350 	if (ret)
351 		return ret;
352 
353 	reg &= ~(1 << func->num);
354 
355 	/* Disable master interrupt with the last function interrupt */
356 	if (!(reg & 0xFE))
357 		reg = 0;
358 
359 	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
360 	if (ret)
361 		return ret;
362 
363 	return 0;
364 }
365 EXPORT_SYMBOL_GPL(sdio_release_irq);
366 
367