root/drivers/mmc/core/sdio_irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sdio_get_pending_irqs
  2. process_sdio_pending_irqs
  3. sdio_run_irqs
  4. sdio_irq_work
  5. sdio_signal_irq
  6. sdio_irq_thread
  7. sdio_card_irq_get
  8. sdio_card_irq_put
  9. sdio_single_irq_set
  10. sdio_claim_irq
  11. sdio_release_irq

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

/* [<][>][^][v][top][bottom][index][help] */