Loading drivers/mmc/card/queue.c +31 −66 Original line number Diff line number Diff line Loading @@ -148,7 +148,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock printk(KERN_WARNING "%s: unable to allocate " "bounce buffer\n", mmc_card_name(card)); } else { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH); blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_sectors(mq->queue, bouncesz / 512); blk_queue_max_phys_segments(mq->queue, bouncesz / 512); blk_queue_max_hw_segments(mq->queue, bouncesz / 512); Loading Loading @@ -290,55 +290,15 @@ void mmc_queue_resume(struct mmc_queue *mq) } } static void copy_sg(struct scatterlist *dst, unsigned int dst_len, struct scatterlist *src, unsigned int src_len) { unsigned int chunk; char *dst_buf, *src_buf; unsigned int dst_size, src_size; dst_buf = NULL; src_buf = NULL; dst_size = 0; src_size = 0; while (src_len) { BUG_ON(dst_len == 0); if (dst_size == 0) { dst_buf = sg_virt(dst); dst_size = dst->length; } if (src_size == 0) { src_buf = sg_virt(src); src_size = src->length; } chunk = min(dst_size, src_size); memcpy(dst_buf, src_buf, chunk); dst_buf += chunk; src_buf += chunk; dst_size -= chunk; src_size -= chunk; if (dst_size == 0) { dst++; dst_len--; } if (src_size == 0) { src++; src_len--; } } } /* * Prepare the sg list(s) to be handed of to the host driver */ unsigned int mmc_queue_map_sg(struct mmc_queue *mq) { unsigned int sg_len; size_t buflen; struct scatterlist *sg; int i; if (!mq->bounce_buf) return blk_rq_map_sg(mq->queue, mq->req, mq->sg); Loading @@ -349,47 +309,52 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq) mq->bounce_sg_len = sg_len; /* * Shortcut in the event we only get a single entry. */ if (sg_len == 1) { memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist)); return 1; } buflen = 0; for_each_sg(mq->bounce_sg, sg, sg_len, i) buflen += sg->length; sg_init_one(mq->sg, mq->bounce_buf, 0); while (sg_len) { mq->sg[0].length += mq->bounce_sg[sg_len - 1].length; sg_len--; } sg_init_one(mq->sg, mq->bounce_buf, buflen); return 1; } /* * If writing, bounce the data to the buffer before the request * is sent to the host driver */ void mmc_queue_bounce_pre(struct mmc_queue *mq) { unsigned long flags; if (!mq->bounce_buf) return; if (mq->bounce_sg_len == 1) return; if (rq_data_dir(mq->req) != WRITE) return; copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len); local_irq_save(flags); sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len, mq->bounce_buf, mq->sg[0].length); local_irq_restore(flags); } /* * If reading, bounce the data from the buffer after the request * has been handled by the host driver */ void mmc_queue_bounce_post(struct mmc_queue *mq) { unsigned long flags; if (!mq->bounce_buf) return; if (mq->bounce_sg_len == 1) return; if (rq_data_dir(mq->req) != READ) return; copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1); local_irq_save(flags); sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len, mq->bounce_buf, mq->sg[0].length); local_irq_restore(flags); } Loading
drivers/mmc/card/queue.c +31 −66 Original line number Diff line number Diff line Loading @@ -148,7 +148,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock printk(KERN_WARNING "%s: unable to allocate " "bounce buffer\n", mmc_card_name(card)); } else { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH); blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_sectors(mq->queue, bouncesz / 512); blk_queue_max_phys_segments(mq->queue, bouncesz / 512); blk_queue_max_hw_segments(mq->queue, bouncesz / 512); Loading Loading @@ -290,55 +290,15 @@ void mmc_queue_resume(struct mmc_queue *mq) } } static void copy_sg(struct scatterlist *dst, unsigned int dst_len, struct scatterlist *src, unsigned int src_len) { unsigned int chunk; char *dst_buf, *src_buf; unsigned int dst_size, src_size; dst_buf = NULL; src_buf = NULL; dst_size = 0; src_size = 0; while (src_len) { BUG_ON(dst_len == 0); if (dst_size == 0) { dst_buf = sg_virt(dst); dst_size = dst->length; } if (src_size == 0) { src_buf = sg_virt(src); src_size = src->length; } chunk = min(dst_size, src_size); memcpy(dst_buf, src_buf, chunk); dst_buf += chunk; src_buf += chunk; dst_size -= chunk; src_size -= chunk; if (dst_size == 0) { dst++; dst_len--; } if (src_size == 0) { src++; src_len--; } } } /* * Prepare the sg list(s) to be handed of to the host driver */ unsigned int mmc_queue_map_sg(struct mmc_queue *mq) { unsigned int sg_len; size_t buflen; struct scatterlist *sg; int i; if (!mq->bounce_buf) return blk_rq_map_sg(mq->queue, mq->req, mq->sg); Loading @@ -349,47 +309,52 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq) mq->bounce_sg_len = sg_len; /* * Shortcut in the event we only get a single entry. */ if (sg_len == 1) { memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist)); return 1; } buflen = 0; for_each_sg(mq->bounce_sg, sg, sg_len, i) buflen += sg->length; sg_init_one(mq->sg, mq->bounce_buf, 0); while (sg_len) { mq->sg[0].length += mq->bounce_sg[sg_len - 1].length; sg_len--; } sg_init_one(mq->sg, mq->bounce_buf, buflen); return 1; } /* * If writing, bounce the data to the buffer before the request * is sent to the host driver */ void mmc_queue_bounce_pre(struct mmc_queue *mq) { unsigned long flags; if (!mq->bounce_buf) return; if (mq->bounce_sg_len == 1) return; if (rq_data_dir(mq->req) != WRITE) return; copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len); local_irq_save(flags); sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len, mq->bounce_buf, mq->sg[0].length); local_irq_restore(flags); } /* * If reading, bounce the data from the buffer after the request * has been handled by the host driver */ void mmc_queue_bounce_post(struct mmc_queue *mq) { unsigned long flags; if (!mq->bounce_buf) return; if (mq->bounce_sg_len == 1) return; if (rq_data_dir(mq->req) != READ) return; copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1); local_irq_save(flags); sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len, mq->bounce_buf, mq->sg[0].length); local_irq_restore(flags); }