LCOV - code coverage report
Current view: top level - drivers/mmc/card - queue.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 248 0.0 %
Date: 2014-02-18 Functions: 0 15 0.0 %
Branches: 0 130 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  linux/drivers/mmc/card/queue.c
       3                 :            :  *
       4                 :            :  *  Copyright (C) 2003 Russell King, All Rights Reserved.
       5                 :            :  *  Copyright 2006-2007 Pierre Ossman
       6                 :            :  *
       7                 :            :  * This program is free software; you can redistribute it and/or modify
       8                 :            :  * it under the terms of the GNU General Public License version 2 as
       9                 :            :  * published by the Free Software Foundation.
      10                 :            :  *
      11                 :            :  */
      12                 :            : #include <linux/slab.h>
      13                 :            : #include <linux/module.h>
      14                 :            : #include <linux/blkdev.h>
      15                 :            : #include <linux/freezer.h>
      16                 :            : #include <linux/kthread.h>
      17                 :            : #include <linux/scatterlist.h>
      18                 :            : #include <linux/dma-mapping.h>
      19                 :            : 
      20                 :            : #include <linux/mmc/card.h>
      21                 :            : #include <linux/mmc/host.h>
      22                 :            : #include "queue.h"
      23                 :            : 
      24                 :            : #define MMC_QUEUE_BOUNCESZ      65536
      25                 :            : 
      26                 :            : /*
      27                 :            :  * Prepare a MMC request. This just filters out odd stuff.
      28                 :            :  */
      29                 :          0 : static int mmc_prep_request(struct request_queue *q, struct request *req)
      30                 :            : {
      31                 :          0 :         struct mmc_queue *mq = q->queuedata;
      32                 :            : 
      33                 :            :         /*
      34                 :            :          * We only like normal block requests and discards.
      35                 :            :          */
      36 [ #  # ][ #  # ]:          0 :         if (req->cmd_type != REQ_TYPE_FS && !(req->cmd_flags & REQ_DISCARD)) {
      37                 :          0 :                 blk_dump_rq_flags(req, "MMC bad request");
      38                 :          0 :                 return BLKPREP_KILL;
      39                 :            :         }
      40                 :            : 
      41 [ #  # ][ #  # ]:          0 :         if (mq && mmc_card_removed(mq->card))
                 [ #  # ]
      42                 :            :                 return BLKPREP_KILL;
      43                 :            : 
      44                 :          0 :         req->cmd_flags |= REQ_DONTPREP;
      45                 :            : 
      46                 :          0 :         return BLKPREP_OK;
      47                 :            : }
      48                 :            : 
      49                 :          0 : static int mmc_queue_thread(void *d)
      50                 :            : {
      51                 :            :         struct mmc_queue *mq = d;
      52                 :          0 :         struct request_queue *q = mq->queue;
      53                 :            : 
      54                 :          0 :         current->flags |= PF_MEMALLOC;
      55                 :            : 
      56                 :          0 :         down(&mq->thread_sem);
      57                 :            :         do {
      58                 :            :                 struct request *req = NULL;
      59                 :            :                 struct mmc_queue_req *tmp;
      60                 :            :                 unsigned int cmd_flags = 0;
      61                 :            : 
      62                 :          0 :                 spin_lock_irq(q->queue_lock);
      63                 :          0 :                 set_current_state(TASK_INTERRUPTIBLE);
      64                 :          0 :                 req = blk_fetch_request(q);
      65                 :          0 :                 mq->mqrq_cur->req = req;
      66                 :          0 :                 spin_unlock_irq(q->queue_lock);
      67                 :            : 
      68 [ #  # ][ #  # ]:          0 :                 if (req || mq->mqrq_prev->req) {
      69                 :          0 :                         set_current_state(TASK_RUNNING);
      70         [ #  # ]:          0 :                         cmd_flags = req ? req->cmd_flags : 0;
      71                 :          0 :                         mq->issue_fn(mq, req);
      72         [ #  # ]:          0 :                         if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
      73                 :          0 :                                 mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
      74                 :          0 :                                 continue; /* fetch again */
      75                 :            :                         }
      76                 :            : 
      77                 :            :                         /*
      78                 :            :                          * Current request becomes previous request
      79                 :            :                          * and vice versa.
      80                 :            :                          * In case of special requests, current request
      81                 :            :                          * has been finished. Do not assign it to previous
      82                 :            :                          * request.
      83                 :            :                          */
      84         [ #  # ]:          0 :                         if (cmd_flags & MMC_REQ_SPECIAL_MASK)
      85                 :          0 :                                 mq->mqrq_cur->req = NULL;
      86                 :            : 
      87                 :          0 :                         mq->mqrq_prev->brq.mrq.data = NULL;
      88                 :          0 :                         mq->mqrq_prev->req = NULL;
      89                 :          0 :                         tmp = mq->mqrq_prev;
      90                 :          0 :                         mq->mqrq_prev = mq->mqrq_cur;
      91                 :          0 :                         mq->mqrq_cur = tmp;
      92                 :            :                 } else {
      93         [ #  # ]:          0 :                         if (kthread_should_stop()) {
      94                 :          0 :                                 set_current_state(TASK_RUNNING);
      95                 :            :                                 break;
      96                 :            :                         }
      97                 :          0 :                         up(&mq->thread_sem);
      98                 :          0 :                         schedule();
      99                 :          0 :                         down(&mq->thread_sem);
     100                 :            :                 }
     101                 :            :         } while (1);
     102                 :          0 :         up(&mq->thread_sem);
     103                 :            : 
     104                 :          0 :         return 0;
     105                 :            : }
     106                 :            : 
     107                 :            : /*
     108                 :            :  * Generic MMC request handler.  This is called for any queue on a
     109                 :            :  * particular host.  When the host is not busy, we look for a request
     110                 :            :  * on any queue on this host, and attempt to issue it.  This may
     111                 :            :  * not be the queue we were asked to process.
     112                 :            :  */
     113                 :          0 : static void mmc_request_fn(struct request_queue *q)
     114                 :            : {
     115                 :          0 :         struct mmc_queue *mq = q->queuedata;
     116                 :            :         struct request *req;
     117                 :            :         unsigned long flags;
     118                 :            :         struct mmc_context_info *cntx;
     119                 :            : 
     120         [ #  # ]:          0 :         if (!mq) {
     121         [ #  # ]:          0 :                 while ((req = blk_fetch_request(q)) != NULL) {
     122                 :          0 :                         req->cmd_flags |= REQ_QUIET;
     123                 :          0 :                         __blk_end_request_all(req, -EIO);
     124                 :            :                 }
     125                 :          0 :                 return;
     126                 :            :         }
     127                 :            : 
     128                 :          0 :         cntx = &mq->card->host->context_info;
     129 [ #  # ][ #  # ]:          0 :         if (!mq->mqrq_cur->req && mq->mqrq_prev->req) {
     130                 :            :                 /*
     131                 :            :                  * New MMC request arrived when MMC thread may be
     132                 :            :                  * blocked on the previous request to be complete
     133                 :            :                  * with no current request fetched
     134                 :            :                  */
     135                 :          0 :                 spin_lock_irqsave(&cntx->lock, flags);
     136         [ #  # ]:          0 :                 if (cntx->is_waiting_last_req) {
     137                 :          0 :                         cntx->is_new_req = true;
     138                 :          0 :                         wake_up_interruptible(&cntx->wait);
     139                 :            :                 }
     140                 :            :                 spin_unlock_irqrestore(&cntx->lock, flags);
     141 [ #  # ][ #  # ]:          0 :         } else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
     142                 :          0 :                 wake_up_process(mq->thread);
     143                 :            : }
     144                 :            : 
     145                 :          0 : static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
     146                 :            : {
     147                 :            :         struct scatterlist *sg;
     148                 :            : 
     149                 :          0 :         sg = kmalloc(sizeof(struct scatterlist)*sg_len, GFP_KERNEL);
     150         [ #  # ]:          0 :         if (!sg)
     151                 :          0 :                 *err = -ENOMEM;
     152                 :            :         else {
     153                 :          0 :                 *err = 0;
     154                 :          0 :                 sg_init_table(sg, sg_len);
     155                 :            :         }
     156                 :            : 
     157                 :          0 :         return sg;
     158                 :            : }
     159                 :            : 
     160                 :          0 : static void mmc_queue_setup_discard(struct request_queue *q,
     161                 :            :                                     struct mmc_card *card)
     162                 :            : {
     163                 :            :         unsigned max_discard;
     164                 :            : 
     165                 :          0 :         max_discard = mmc_calc_max_discard(card);
     166         [ #  # ]:          0 :         if (!max_discard)
     167                 :          0 :                 return;
     168                 :            : 
     169                 :            :         queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
     170                 :          0 :         q->limits.max_discard_sectors = max_discard;
     171 [ #  # ][ #  # ]:          0 :         if (card->erased_byte == 0 && !mmc_can_discard(card))
     172                 :          0 :                 q->limits.discard_zeroes_data = 1;
     173                 :          0 :         q->limits.discard_granularity = card->pref_erase << 9;
     174                 :            :         /* granularity must not be greater than max. discard */
     175         [ #  # ]:          0 :         if (card->pref_erase > max_discard)
     176                 :          0 :                 q->limits.discard_granularity = 0;
     177         [ #  # ]:          0 :         if (mmc_can_secure_erase_trim(card))
     178                 :            :                 queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
     179                 :            : }
     180                 :            : 
     181                 :            : /**
     182                 :            :  * mmc_init_queue - initialise a queue structure.
     183                 :            :  * @mq: mmc queue
     184                 :            :  * @card: mmc card to attach this queue
     185                 :            :  * @lock: queue lock
     186                 :            :  * @subname: partition subname
     187                 :            :  *
     188                 :            :  * Initialise a MMC card request queue.
     189                 :            :  */
     190                 :          0 : int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
     191                 :            :                    spinlock_t *lock, const char *subname)
     192                 :            : {
     193                 :          0 :         struct mmc_host *host = card->host;
     194                 :          0 :         u64 limit = BLK_BOUNCE_HIGH;
     195                 :            :         int ret;
     196                 :          0 :         struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
     197                 :          0 :         struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
     198                 :            : 
     199 [ #  # ][ #  # ]:          0 :         if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
     200                 :          0 :                 limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
     201                 :            : 
     202                 :          0 :         mq->card = card;
     203                 :          0 :         mq->queue = blk_init_queue(mmc_request_fn, lock);
     204         [ #  # ]:          0 :         if (!mq->queue)
     205                 :            :                 return -ENOMEM;
     206                 :            : 
     207                 :          0 :         mq->mqrq_cur = mqrq_cur;
     208                 :          0 :         mq->mqrq_prev = mqrq_prev;
     209                 :          0 :         mq->queue->queuedata = mq;
     210                 :            : 
     211                 :          0 :         blk_queue_prep_rq(mq->queue, mmc_prep_request);
     212                 :          0 :         queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
     213         [ #  # ]:          0 :         if (mmc_can_erase(card))
     214                 :          0 :                 mmc_queue_setup_discard(mq->queue, card);
     215                 :            : 
     216                 :            : #ifdef CONFIG_MMC_BLOCK_BOUNCE
     217         [ #  # ]:          0 :         if (host->max_segs == 1) {
     218                 :            :                 unsigned int bouncesz;
     219                 :            : 
     220                 :            :                 bouncesz = MMC_QUEUE_BOUNCESZ;
     221                 :            : 
     222         [ #  # ]:          0 :                 if (bouncesz > host->max_req_size)
     223                 :            :                         bouncesz = host->max_req_size;
     224         [ #  # ]:          0 :                 if (bouncesz > host->max_seg_size)
     225                 :            :                         bouncesz = host->max_seg_size;
     226         [ #  # ]:          0 :                 if (bouncesz > (host->max_blk_count * 512))
     227                 :            :                         bouncesz = host->max_blk_count * 512;
     228                 :            : 
     229         [ #  # ]:          0 :                 if (bouncesz > 512) {
     230                 :          0 :                         mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
     231         [ #  # ]:          0 :                         if (!mqrq_cur->bounce_buf) {
     232                 :          0 :                                 pr_warning("%s: unable to "
     233                 :            :                                         "allocate bounce cur buffer\n",
     234                 :            :                                         mmc_card_name(card));
     235                 :            :                         }
     236                 :          0 :                         mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
     237         [ #  # ]:          0 :                         if (!mqrq_prev->bounce_buf) {
     238                 :          0 :                                 pr_warning("%s: unable to "
     239                 :            :                                         "allocate bounce prev buffer\n",
     240                 :            :                                         mmc_card_name(card));
     241                 :          0 :                                 kfree(mqrq_cur->bounce_buf);
     242                 :          0 :                                 mqrq_cur->bounce_buf = NULL;
     243                 :            :                         }
     244                 :            :                 }
     245                 :            : 
     246 [ #  # ][ #  # ]:          0 :                 if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) {
     247                 :          0 :                         blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
     248                 :          0 :                         blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
     249                 :          0 :                         blk_queue_max_segments(mq->queue, bouncesz / 512);
     250                 :          0 :                         blk_queue_max_segment_size(mq->queue, bouncesz);
     251                 :            : 
     252                 :          0 :                         mqrq_cur->sg = mmc_alloc_sg(1, &ret);
     253         [ #  # ]:          0 :                         if (ret)
     254                 :            :                                 goto cleanup_queue;
     255                 :            : 
     256                 :          0 :                         mqrq_cur->bounce_sg =
     257                 :          0 :                                 mmc_alloc_sg(bouncesz / 512, &ret);
     258         [ #  # ]:          0 :                         if (ret)
     259                 :            :                                 goto cleanup_queue;
     260                 :            : 
     261                 :          0 :                         mqrq_prev->sg = mmc_alloc_sg(1, &ret);
     262         [ #  # ]:          0 :                         if (ret)
     263                 :            :                                 goto cleanup_queue;
     264                 :            : 
     265                 :          0 :                         mqrq_prev->bounce_sg =
     266                 :          0 :                                 mmc_alloc_sg(bouncesz / 512, &ret);
     267         [ #  # ]:          0 :                         if (ret)
     268                 :            :                                 goto cleanup_queue;
     269                 :            :                 }
     270                 :            :         }
     271                 :            : #endif
     272                 :            : 
     273 [ #  # ][ #  # ]:          0 :         if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
     274                 :          0 :                 blk_queue_bounce_limit(mq->queue, limit);
     275                 :          0 :                 blk_queue_max_hw_sectors(mq->queue,
     276                 :          0 :                         min(host->max_blk_count, host->max_req_size / 512));
     277                 :          0 :                 blk_queue_max_segments(mq->queue, host->max_segs);
     278                 :          0 :                 blk_queue_max_segment_size(mq->queue, host->max_seg_size);
     279                 :            : 
     280                 :          0 :                 mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret);
     281         [ #  # ]:          0 :                 if (ret)
     282                 :            :                         goto cleanup_queue;
     283                 :            : 
     284                 :            : 
     285                 :          0 :                 mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
     286         [ #  # ]:          0 :                 if (ret)
     287                 :            :                         goto cleanup_queue;
     288                 :            :         }
     289                 :            : 
     290                 :            :         sema_init(&mq->thread_sem, 1);
     291                 :            : 
     292 [ #  # ][ #  # ]:          0 :         mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
     293                 :            :                 host->index, subname ? subname : "");
     294                 :            : 
     295         [ #  # ]:          0 :         if (IS_ERR(mq->thread)) {
     296                 :          0 :                 ret = PTR_ERR(mq->thread);
     297                 :            :                 goto free_bounce_sg;
     298                 :            :         }
     299                 :            : 
     300                 :            :         return 0;
     301                 :            :  free_bounce_sg:
     302                 :          0 :         kfree(mqrq_cur->bounce_sg);
     303                 :          0 :         mqrq_cur->bounce_sg = NULL;
     304                 :          0 :         kfree(mqrq_prev->bounce_sg);
     305                 :          0 :         mqrq_prev->bounce_sg = NULL;
     306                 :            : 
     307                 :            :  cleanup_queue:
     308                 :          0 :         kfree(mqrq_cur->sg);
     309                 :          0 :         mqrq_cur->sg = NULL;
     310                 :          0 :         kfree(mqrq_cur->bounce_buf);
     311                 :          0 :         mqrq_cur->bounce_buf = NULL;
     312                 :            : 
     313                 :          0 :         kfree(mqrq_prev->sg);
     314                 :          0 :         mqrq_prev->sg = NULL;
     315                 :          0 :         kfree(mqrq_prev->bounce_buf);
     316                 :          0 :         mqrq_prev->bounce_buf = NULL;
     317                 :            : 
     318                 :          0 :         blk_cleanup_queue(mq->queue);
     319                 :          0 :         return ret;
     320                 :            : }
     321                 :            : 
     322                 :          0 : void mmc_cleanup_queue(struct mmc_queue *mq)
     323                 :            : {
     324                 :          0 :         struct request_queue *q = mq->queue;
     325                 :            :         unsigned long flags;
     326                 :          0 :         struct mmc_queue_req *mqrq_cur = mq->mqrq_cur;
     327                 :          0 :         struct mmc_queue_req *mqrq_prev = mq->mqrq_prev;
     328                 :            : 
     329                 :            :         /* Make sure the queue isn't suspended, as that will deadlock */
     330                 :          0 :         mmc_queue_resume(mq);
     331                 :            : 
     332                 :            :         /* Then terminate our worker thread */
     333                 :          0 :         kthread_stop(mq->thread);
     334                 :            : 
     335                 :            :         /* Empty the queue */
     336                 :          0 :         spin_lock_irqsave(q->queue_lock, flags);
     337                 :          0 :         q->queuedata = NULL;
     338                 :          0 :         blk_start_queue(q);
     339                 :          0 :         spin_unlock_irqrestore(q->queue_lock, flags);
     340                 :            : 
     341                 :          0 :         kfree(mqrq_cur->bounce_sg);
     342                 :          0 :         mqrq_cur->bounce_sg = NULL;
     343                 :            : 
     344                 :          0 :         kfree(mqrq_cur->sg);
     345                 :          0 :         mqrq_cur->sg = NULL;
     346                 :            : 
     347                 :          0 :         kfree(mqrq_cur->bounce_buf);
     348                 :          0 :         mqrq_cur->bounce_buf = NULL;
     349                 :            : 
     350                 :          0 :         kfree(mqrq_prev->bounce_sg);
     351                 :          0 :         mqrq_prev->bounce_sg = NULL;
     352                 :            : 
     353                 :          0 :         kfree(mqrq_prev->sg);
     354                 :          0 :         mqrq_prev->sg = NULL;
     355                 :            : 
     356                 :          0 :         kfree(mqrq_prev->bounce_buf);
     357                 :          0 :         mqrq_prev->bounce_buf = NULL;
     358                 :            : 
     359                 :          0 :         mq->card = NULL;
     360                 :          0 : }
     361                 :            : EXPORT_SYMBOL(mmc_cleanup_queue);
     362                 :            : 
     363                 :          0 : int mmc_packed_init(struct mmc_queue *mq, struct mmc_card *card)
     364                 :            : {
     365                 :            :         struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
     366                 :            :         struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
     367                 :            :         int ret = 0;
     368                 :            : 
     369                 :            : 
     370                 :          0 :         mqrq_cur->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL);
     371         [ #  # ]:          0 :         if (!mqrq_cur->packed) {
     372                 :          0 :                 pr_warn("%s: unable to allocate packed cmd for mqrq_cur\n",
     373                 :            :                         mmc_card_name(card));
     374                 :            :                 ret = -ENOMEM;
     375                 :          0 :                 goto out;
     376                 :            :         }
     377                 :            : 
     378                 :          0 :         mqrq_prev->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL);
     379         [ #  # ]:          0 :         if (!mqrq_prev->packed) {
     380                 :          0 :                 pr_warn("%s: unable to allocate packed cmd for mqrq_prev\n",
     381                 :            :                         mmc_card_name(card));
     382                 :          0 :                 kfree(mqrq_cur->packed);
     383                 :          0 :                 mqrq_cur->packed = NULL;
     384                 :            :                 ret = -ENOMEM;
     385                 :          0 :                 goto out;
     386                 :            :         }
     387                 :            : 
     388                 :          0 :         INIT_LIST_HEAD(&mqrq_cur->packed->list);
     389                 :          0 :         INIT_LIST_HEAD(&mqrq_prev->packed->list);
     390                 :            : 
     391                 :            : out:
     392                 :          0 :         return ret;
     393                 :            : }
     394                 :            : 
     395                 :          0 : void mmc_packed_clean(struct mmc_queue *mq)
     396                 :            : {
     397                 :            :         struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
     398                 :            :         struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
     399                 :            : 
     400                 :          0 :         kfree(mqrq_cur->packed);
     401                 :          0 :         mqrq_cur->packed = NULL;
     402                 :          0 :         kfree(mqrq_prev->packed);
     403                 :          0 :         mqrq_prev->packed = NULL;
     404                 :          0 : }
     405                 :            : 
     406                 :            : /**
     407                 :            :  * mmc_queue_suspend - suspend a MMC request queue
     408                 :            :  * @mq: MMC queue to suspend
     409                 :            :  *
     410                 :            :  * Stop the block request queue, and wait for our thread to
     411                 :            :  * complete any outstanding requests.  This ensures that we
     412                 :            :  * won't suspend while a request is being processed.
     413                 :            :  */
     414                 :          0 : void mmc_queue_suspend(struct mmc_queue *mq)
     415                 :            : {
     416                 :          0 :         struct request_queue *q = mq->queue;
     417                 :            :         unsigned long flags;
     418                 :            : 
     419         [ #  # ]:          0 :         if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
     420                 :          0 :                 mq->flags |= MMC_QUEUE_SUSPENDED;
     421                 :            : 
     422                 :          0 :                 spin_lock_irqsave(q->queue_lock, flags);
     423                 :          0 :                 blk_stop_queue(q);
     424                 :          0 :                 spin_unlock_irqrestore(q->queue_lock, flags);
     425                 :            : 
     426                 :          0 :                 down(&mq->thread_sem);
     427                 :            :         }
     428                 :          0 : }
     429                 :            : 
     430                 :            : /**
     431                 :            :  * mmc_queue_resume - resume a previously suspended MMC request queue
     432                 :            :  * @mq: MMC queue to resume
     433                 :            :  */
     434                 :          0 : void mmc_queue_resume(struct mmc_queue *mq)
     435                 :            : {
     436                 :          0 :         struct request_queue *q = mq->queue;
     437                 :            :         unsigned long flags;
     438                 :            : 
     439         [ #  # ]:          0 :         if (mq->flags & MMC_QUEUE_SUSPENDED) {
     440                 :          0 :                 mq->flags &= ~MMC_QUEUE_SUSPENDED;
     441                 :            : 
     442                 :          0 :                 up(&mq->thread_sem);
     443                 :            : 
     444                 :          0 :                 spin_lock_irqsave(q->queue_lock, flags);
     445                 :          0 :                 blk_start_queue(q);
     446                 :          0 :                 spin_unlock_irqrestore(q->queue_lock, flags);
     447                 :            :         }
     448                 :          0 : }
     449                 :            : 
     450                 :          0 : static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq,
     451                 :            :                                             struct mmc_packed *packed,
     452                 :            :                                             struct scatterlist *sg,
     453                 :            :                                             enum mmc_packed_type cmd_type)
     454                 :            : {
     455                 :            :         struct scatterlist *__sg = sg;
     456                 :            :         unsigned int sg_len = 0;
     457                 :            :         struct request *req;
     458                 :            : 
     459         [ #  # ]:          0 :         if (mmc_packed_wr(cmd_type)) {
     460         [ #  # ]:          0 :                 unsigned int hdr_sz = mmc_large_sector(mq->card) ? 4096 : 512;
     461                 :          0 :                 unsigned int max_seg_sz = queue_max_segment_size(mq->queue);
     462                 :            :                 unsigned int len, remain, offset = 0;
     463                 :          0 :                 u8 *buf = (u8 *)packed->cmd_hdr;
     464                 :            : 
     465                 :            :                 remain = hdr_sz;
     466                 :            :                 do {
     467                 :          0 :                         len = min(remain, max_seg_sz);
     468                 :          0 :                         sg_set_buf(__sg, buf + offset, len);
     469                 :          0 :                         offset += len;
     470                 :          0 :                         remain -= len;
     471                 :          0 :                         (__sg++)->page_link &= ~0x02;
     472                 :          0 :                         sg_len++;
     473         [ #  # ]:          0 :                 } while (remain);
     474                 :            :         }
     475                 :            : 
     476         [ #  # ]:          0 :         list_for_each_entry(req, &packed->list, queuelist) {
     477                 :          0 :                 sg_len += blk_rq_map_sg(mq->queue, req, __sg);
     478                 :          0 :                 __sg = sg + (sg_len - 1);
     479                 :          0 :                 (__sg++)->page_link &= ~0x02;
     480                 :            :         }
     481                 :          0 :         sg_mark_end(sg + (sg_len - 1));
     482                 :          0 :         return sg_len;
     483                 :            : }
     484                 :            : 
     485                 :            : /*
     486                 :            :  * Prepare the sg list(s) to be handed of to the host driver
     487                 :            :  */
     488                 :          0 : unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
     489                 :            : {
     490                 :            :         unsigned int sg_len;
     491                 :            :         size_t buflen;
     492                 :            :         struct scatterlist *sg;
     493                 :            :         enum mmc_packed_type cmd_type;
     494                 :            :         int i;
     495                 :            : 
     496                 :          0 :         cmd_type = mqrq->cmd_type;
     497                 :            : 
     498         [ #  # ]:          0 :         if (!mqrq->bounce_buf) {
     499         [ #  # ]:          0 :                 if (mmc_packed_cmd(cmd_type))
     500                 :          0 :                         return mmc_queue_packed_map_sg(mq, mqrq->packed,
     501                 :            :                                                        mqrq->sg, cmd_type);
     502                 :            :                 else
     503                 :          0 :                         return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
     504                 :            :         }
     505                 :            : 
     506         [ #  # ]:          0 :         BUG_ON(!mqrq->bounce_sg);
     507                 :            : 
     508         [ #  # ]:          0 :         if (mmc_packed_cmd(cmd_type))
     509                 :          0 :                 sg_len = mmc_queue_packed_map_sg(mq, mqrq->packed,
     510                 :            :                                                  mqrq->bounce_sg, cmd_type);
     511                 :            :         else
     512                 :          0 :                 sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
     513                 :            : 
     514                 :          0 :         mqrq->bounce_sg_len = sg_len;
     515                 :            : 
     516                 :            :         buflen = 0;
     517         [ #  # ]:          0 :         for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
     518                 :          0 :                 buflen += sg->length;
     519                 :            : 
     520                 :          0 :         sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
     521                 :            : 
     522                 :          0 :         return 1;
     523                 :            : }
     524                 :            : 
     525                 :            : /*
     526                 :            :  * If writing, bounce the data to the buffer before the request
     527                 :            :  * is sent to the host driver
     528                 :            :  */
     529                 :          0 : void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
     530                 :            : {
     531         [ #  # ]:          0 :         if (!mqrq->bounce_buf)
     532                 :            :                 return;
     533                 :            : 
     534         [ #  # ]:          0 :         if (rq_data_dir(mqrq->req) != WRITE)
     535                 :            :                 return;
     536                 :            : 
     537                 :          0 :         sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
     538                 :          0 :                 mqrq->bounce_buf, mqrq->sg[0].length);
     539                 :            : }
     540                 :            : 
     541                 :            : /*
     542                 :            :  * If reading, bounce the data from the buffer after the request
     543                 :            :  * has been handled by the host driver
     544                 :            :  */
     545                 :          0 : void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
     546                 :            : {
     547         [ #  # ]:          0 :         if (!mqrq->bounce_buf)
     548                 :            :                 return;
     549                 :            : 
     550         [ #  # ]:          0 :         if (rq_data_dir(mqrq->req) != READ)
     551                 :            :                 return;
     552                 :            : 
     553                 :          0 :         sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
     554                 :          0 :                 mqrq->bounce_buf, mqrq->sg[0].length);
     555                 :            : }

Generated by: LCOV version 1.9