linux/arch/arm/common/dmabounce.c
<<
>>
Prefs
   1/*
   2 *  arch/arm/common/dmabounce.c
   3 *
   4 *  Special dma_{map/unmap/dma_sync}_* routines for systems that have
   5 *  limited DMA windows. These functions utilize bounce buffers to
   6 *  copy data to/from buffers located outside the DMA region. This
   7 *  only works for systems in which DMA memory is at the bottom of
   8 *  RAM and the remainder of memory is at the top an the DMA memory
   9 *  can be marked as ZONE_DMA. Anything beyond that such as discontigous
  10 *  DMA windows will require custom implementations that reserve memory
  11 *  areas at early bootup.
  12 *
  13 *  Original version by Brad Parker (brad@heeltoe.com)
  14 *  Re-written by Christopher Hoover <ch@murgatroid.com>
  15 *  Made generic by Deepak Saxena <dsaxena@plexity.net>
  16 *
  17 *  Copyright (C) 2002 Hewlett Packard Company.
  18 *  Copyright (C) 2004 MontaVista Software, Inc.
  19 *
  20 *  This program is free software; you can redistribute it and/or
  21 *  modify it under the terms of the GNU General Public License
  22 *  version 2 as published by the Free Software Foundation.
  23 */
  24
  25#include <linux/module.h>
  26#include <linux/init.h>
  27#include <linux/slab.h>
  28#include <linux/device.h>
  29#include <linux/dma-mapping.h>
  30#include <linux/dmapool.h>
  31#include <linux/list.h>
  32
  33#undef DEBUG
  34
  35#undef STATS
  36#ifdef STATS
  37#define DO_STATS(X) do { X ; } while (0)
  38#else
  39#define DO_STATS(X) do { } while (0)
  40#endif
  41
  42/* ************************************************** */
  43
  44struct safe_buffer {
  45        struct list_head node;
  46
  47        /* original request */
  48        void            *ptr;
  49        size_t          size;
  50        int             direction;
  51
  52        /* safe buffer info */
  53        struct dma_pool *pool;
  54        void            *safe;
  55        dma_addr_t      safe_dma_addr;
  56};
  57
  58struct dmabounce_device_info {
  59        struct list_head node;
  60
  61        struct device *dev;
  62        struct dma_pool *small_buffer_pool;
  63        struct dma_pool *large_buffer_pool;
  64        struct list_head safe_buffers;
  65        unsigned long small_buffer_size, large_buffer_size;
  66#ifdef STATS
  67        unsigned long sbp_allocs;
  68        unsigned long lbp_allocs;
  69        unsigned long total_allocs;
  70        unsigned long map_op_count;
  71        unsigned long bounce_count;
  72#endif
  73};
  74
  75static LIST_HEAD(dmabounce_devs);
  76
  77#ifdef STATS
  78static void print_alloc_stats(struct dmabounce_device_info *device_info)
  79{
  80        printk(KERN_INFO
  81                "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
  82                device_info->dev->bus_id,
  83                device_info->sbp_allocs, device_info->lbp_allocs,
  84                device_info->total_allocs - device_info->sbp_allocs -
  85                        device_info->lbp_allocs,
  86                device_info->total_allocs);
  87}
  88#endif
  89
  90/* find the given device in the dmabounce device list */
  91static inline struct dmabounce_device_info *
  92find_dmabounce_dev(struct device *dev)
  93{
  94        struct list_head *entry;
  95
  96        list_for_each(entry, &dmabounce_devs) {
  97                struct dmabounce_device_info *d =
  98                        list_entry(entry, struct dmabounce_device_info, node);
  99
 100                if (d->dev == dev)
 101                        return d;
 102        }
 103        return NULL;
 104}
 105
 106
 107/* allocate a 'safe' buffer and keep track of it */
 108static inline struct safe_buffer *
 109alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 110                        size_t size, enum dma_data_direction dir)
 111{
 112        struct safe_buffer *buf;
 113        struct dma_pool *pool;
 114        struct device *dev = device_info->dev;
 115        void *safe;
 116        dma_addr_t safe_dma_addr;
 117
 118        dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n",
 119                __func__, ptr, size, dir);
 120
 121        DO_STATS ( device_info->total_allocs++ );
 122
 123        buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
 124        if (buf == NULL) {
 125                dev_warn(dev, "%s: kmalloc failed\n", __func__);
 126                return NULL;
 127        }
 128
 129        if (size <= device_info->small_buffer_size) {
 130                pool = device_info->small_buffer_pool;
 131                safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
 132
 133                DO_STATS ( device_info->sbp_allocs++ );
 134        } else if (size <= device_info->large_buffer_size) {
 135                pool = device_info->large_buffer_pool;
 136                safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
 137
 138                DO_STATS ( device_info->lbp_allocs++ );
 139        } else {
 140                pool = NULL;
 141                safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC);
 142        }
 143
 144        if (safe == NULL) {
 145                dev_warn(device_info->dev,
 146                        "%s: could not alloc dma memory (size=%d)\n",
 147                       __func__, size);
 148                kfree(buf);
 149                return NULL;
 150        }
 151
 152#ifdef STATS
 153        if (device_info->total_allocs % 1000 == 0)
 154                print_alloc_stats(device_info);
 155#endif
 156
 157        buf->ptr = ptr;
 158        buf->size = size;
 159        buf->direction = dir;
 160        buf->pool = pool;
 161        buf->safe = safe;
 162        buf->safe_dma_addr = safe_dma_addr;
 163
 164        list_add(&buf->node, &device_info->safe_buffers);
 165
 166        return buf;
 167}
 168
 169/* determine if a buffer is from our "safe" pool */
 170static inline struct safe_buffer *
 171find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
 172{
 173        struct list_head *entry;
 174
 175        list_for_each(entry, &device_info->safe_buffers) {
 176                struct safe_buffer *b =
 177                        list_entry(entry, struct safe_buffer, node);
 178
 179                if (b->safe_dma_addr == safe_dma_addr)
 180                        return b;
 181        }
 182
 183        return NULL;
 184}
 185
 186static inline void
 187free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf)
 188{
 189        dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);
 190
 191        list_del(&buf->node);
 192
 193        if (buf->pool)
 194                dma_pool_free(buf->pool, buf->safe, buf->safe_dma_addr);
 195        else
 196                dma_free_coherent(device_info->dev, buf->size, buf->safe,
 197                                    buf->safe_dma_addr);
 198
 199        kfree(buf);
 200}
 201
 202/* ************************************************** */
 203
 204#ifdef STATS
 205
 206static void print_map_stats(struct dmabounce_device_info *device_info)
 207{
 208        printk(KERN_INFO
 209                "%s: dmabounce: map_op_count=%lu, bounce_count=%lu\n",
 210                device_info->dev->bus_id,
 211                device_info->map_op_count, device_info->bounce_count);
 212}
 213#endif
 214
 215static inline dma_addr_t
 216map_single(struct device *dev, void *ptr, size_t size,
 217                enum dma_data_direction dir)
 218{
 219        struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
 220        dma_addr_t dma_addr;
 221        int needs_bounce = 0;
 222
 223        if (device_info)
 224                DO_STATS ( device_info->map_op_count++ );
 225
 226        dma_addr = virt_to_dma(dev, ptr);
 227
 228        if (dev->dma_mask) {
 229                unsigned long mask = *dev->dma_mask;
 230                unsigned long limit;
 231
 232                limit = (mask + 1) & ~mask;
 233                if (limit && size > limit) {
 234                        dev_err(dev, "DMA mapping too big (requested %#x "
 235                                "mask %#Lx)\n", size, *dev->dma_mask);
 236                        return ~0;
 237                }
 238
 239                /*
 240                 * Figure out if we need to bounce from the DMA mask.
 241                 */
 242                needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
 243        }
 244
 245        if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
 246                struct safe_buffer *buf;
 247
 248                buf = alloc_safe_buffer(device_info, ptr, size, dir);
 249                if (buf == 0) {
 250                        dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
 251                               __func__, ptr);
 252                        return 0;
 253                }
 254
 255                dev_dbg(dev,
 256                        "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
 257                        __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 258                        buf->safe, (void *) buf->safe_dma_addr);
 259
 260                if ((dir == DMA_TO_DEVICE) ||
 261                    (dir == DMA_BIDIRECTIONAL)) {
 262                        dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
 263                                __func__, ptr, buf->safe, size);
 264                        memcpy(buf->safe, ptr, size);
 265                }
 266                consistent_sync(buf->safe, size, dir);
 267
 268                dma_addr = buf->safe_dma_addr;
 269        } else {
 270                consistent_sync(ptr, size, dir);
 271        }
 272
 273        return dma_addr;
 274}
 275
 276static inline void
 277unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 278                enum dma_data_direction dir)
 279{
 280        struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
 281        struct safe_buffer *buf = NULL;
 282
 283        /*
 284         * Trying to unmap an invalid mapping
 285         */
 286        if (dma_addr == ~0) {
 287                dev_err(dev, "Trying to unmap invalid mapping\n");
 288                return;
 289        }
 290
 291        if (device_info)
 292                buf = find_safe_buffer(device_info, dma_addr);
 293
 294        if (buf) {
 295                BUG_ON(buf->size != size);
 296
 297                dev_dbg(dev,
 298                        "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
 299                        __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 300                        buf->safe, (void *) buf->safe_dma_addr);
 301
 302
 303                DO_STATS ( device_info->bounce_count++ );
 304
 305                if ((dir == DMA_FROM_DEVICE) ||
 306                    (dir == DMA_BIDIRECTIONAL)) {
 307                        dev_dbg(dev,
 308                                "%s: copy back safe %p to unsafe %p size %d\n",
 309                                __func__, buf->safe, buf->ptr, size);
 310                        memcpy(buf->ptr, buf->safe, size);
 311                }
 312                free_safe_buffer(device_info, buf);
 313        }
 314}
 315
 316static inline void
 317sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 318                enum dma_data_direction dir)
 319{
 320        struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
 321        struct safe_buffer *buf = NULL;
 322
 323        if (device_info)
 324                buf = find_safe_buffer(device_info, dma_addr);
 325
 326        if (buf) {
 327                /*
 328                 * Both of these checks from original code need to be
 329                 * commented out b/c some drivers rely on the following:
 330                 *
 331                 * 1) Drivers may map a large chunk of memory into DMA space
 332                 *    but only sync a small portion of it. Good example is
 333                 *    allocating a large buffer, mapping it, and then
 334                 *    breaking it up into small descriptors. No point
 335                 *    in syncing the whole buffer if you only have to
 336                 *    touch one descriptor.
 337                 *
 338                 * 2) Buffers that are mapped as DMA_BIDIRECTIONAL are
 339                 *    usually only synced in one dir at a time.
 340                 *
 341                 * See drivers/net/eepro100.c for examples of both cases.
 342                 *
 343                 * -ds
 344                 *
 345                 * BUG_ON(buf->size != size);
 346                 * BUG_ON(buf->direction != dir);
 347                 */
 348
 349                dev_dbg(dev,
 350                        "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
 351                        __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 352                        buf->safe, (void *) buf->safe_dma_addr);
 353
 354                DO_STATS ( device_info->bounce_count++ );
 355
 356                switch (dir) {
 357                case DMA_FROM_DEVICE:
 358                        dev_dbg(dev,
 359                                "%s: copy back safe %p to unsafe %p size %d\n",
 360                                __func__, buf->safe, buf->ptr, size);
 361                        memcpy(buf->ptr, buf->safe, size);
 362                        break;
 363                case DMA_TO_DEVICE:
 364                        dev_dbg(dev,
 365                                "%s: copy out unsafe %p to safe %p, size %d\n",
 366                                __func__,buf->ptr, buf->safe, size);
 367                        memcpy(buf->safe, buf->ptr, size);
 368                        break;
 369                case DMA_BIDIRECTIONAL:
 370                        BUG();  /* is this allowed?  what does it mean? */
 371                default:
 372                        BUG();
 373                }
 374                consistent_sync(buf->safe, size, dir);
 375        } else {
 376                consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
 377        }
 378}
 379
 380/* ************************************************** */
 381
 382/*
 383 * see if a buffer address is in an 'unsafe' range.  if it is
 384 * allocate a 'safe' buffer and copy the unsafe buffer into it.
 385 * substitute the safe buffer for the unsafe one.
 386 * (basically move the buffer from an unsafe area to a safe one)
 387 */
 388dma_addr_t
 389dma_map_single(struct device *dev, void *ptr, size_t size,
 390                enum dma_data_direction dir)
 391{
 392        unsigned long flags;
 393        dma_addr_t dma_addr;
 394
 395        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 396                __func__, ptr, size, dir);
 397
 398        BUG_ON(dir == DMA_NONE);
 399
 400        local_irq_save(flags);
 401
 402        dma_addr = map_single(dev, ptr, size, dir);
 403
 404        local_irq_restore(flags);
 405
 406        return dma_addr;
 407}
 408
 409/*
 410 * see if a mapped address was really a "safe" buffer and if so, copy
 411 * the data from the safe buffer back to the unsafe buffer and free up
 412 * the safe buffer.  (basically return things back to the way they
 413 * should be)
 414 */
 415
 416void
 417dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 418                        enum dma_data_direction dir)
 419{
 420        unsigned long flags;
 421
 422        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 423                __func__, (void *) dma_addr, size, dir);
 424
 425        BUG_ON(dir == DMA_NONE);
 426
 427        local_irq_save(flags);
 428
 429        unmap_single(dev, dma_addr, size, dir);
 430
 431        local_irq_restore(flags);
 432}
 433
 434int
 435dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 436                enum dma_data_direction dir)
 437{
 438        unsigned long flags;
 439        int i;
 440
 441        dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
 442                __func__, sg, nents, dir);
 443
 444        BUG_ON(dir == DMA_NONE);
 445
 446        local_irq_save(flags);
 447
 448        for (i = 0; i < nents; i++, sg++) {
 449                struct page *page = sg->page;
 450                unsigned int offset = sg->offset;
 451                unsigned int length = sg->length;
 452                void *ptr = page_address(page) + offset;
 453
 454                sg->dma_address =
 455                        map_single(dev, ptr, length, dir);
 456        }
 457
 458        local_irq_restore(flags);
 459
 460        return nents;
 461}
 462
 463void
 464dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 465                enum dma_data_direction dir)
 466{
 467        unsigned long flags;
 468        int i;
 469
 470        dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
 471                __func__, sg, nents, dir);
 472
 473        BUG_ON(dir == DMA_NONE);
 474
 475        local_irq_save(flags);
 476
 477        for (i = 0; i < nents; i++, sg++) {
 478                dma_addr_t dma_addr = sg->dma_address;
 479                unsigned int length = sg->length;
 480
 481                unmap_single(dev, dma_addr, length, dir);
 482        }
 483
 484        local_irq_restore(flags);
 485}
 486
 487void
 488dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
 489                                enum dma_data_direction dir)
 490{
 491        unsigned long flags;
 492
 493        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 494                __func__, (void *) dma_addr, size, dir);
 495
 496        local_irq_save(flags);
 497
 498        sync_single(dev, dma_addr, size, dir);
 499
 500        local_irq_restore(flags);
 501}
 502
 503void
 504dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
 505                                enum dma_data_direction dir)
 506{
 507        unsigned long flags;
 508
 509        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 510                __func__, (void *) dma_addr, size, dir);
 511
 512        local_irq_save(flags);
 513
 514        sync_single(dev, dma_addr, size, dir);
 515
 516        local_irq_restore(flags);
 517}
 518
 519void
 520dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
 521                        enum dma_data_direction dir)
 522{
 523        unsigned long flags;
 524        int i;
 525
 526        dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
 527                __func__, sg, nents, dir);
 528
 529        BUG_ON(dir == DMA_NONE);
 530
 531        local_irq_save(flags);
 532
 533        for (i = 0; i < nents; i++, sg++) {
 534                dma_addr_t dma_addr = sg->dma_address;
 535                unsigned int length = sg->length;
 536
 537                sync_single(dev, dma_addr, length, dir);
 538        }
 539
 540        local_irq_restore(flags);
 541}
 542
 543void
 544dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
 545                        enum dma_data_direction dir)
 546{
 547        unsigned long flags;
 548        int i;
 549
 550        dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
 551                __func__, sg, nents, dir);
 552
 553        BUG_ON(dir == DMA_NONE);
 554
 555        local_irq_save(flags);
 556
 557        for (i = 0; i < nents; i++, sg++) {
 558                dma_addr_t dma_addr = sg->dma_address;
 559                unsigned int length = sg->length;
 560
 561                sync_single(dev, dma_addr, length, dir);
 562        }
 563
 564        local_irq_restore(flags);
 565}
 566
 567int
 568dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
 569                        unsigned long large_buffer_size)
 570{
 571        struct dmabounce_device_info *device_info;
 572
 573        device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
 574        if (!device_info) {
 575                printk(KERN_ERR
 576                        "Could not allocated dmabounce_device_info for %s",
 577                        dev->bus_id);
 578                return -ENOMEM;
 579        }
 580
 581        device_info->small_buffer_pool =
 582                dma_pool_create("small_dmabounce_pool",
 583                                dev,
 584                                small_buffer_size,
 585                                0 /* byte alignment */,
 586                                0 /* no page-crossing issues */);
 587        if (!device_info->small_buffer_pool) {
 588                printk(KERN_ERR
 589                        "dmabounce: could not allocate small DMA pool for %s\n",
 590                        dev->bus_id);
 591                kfree(device_info);
 592                return -ENOMEM;
 593        }
 594
 595        if (large_buffer_size) {
 596                device_info->large_buffer_pool =
 597                        dma_pool_create("large_dmabounce_pool",
 598                                        dev,
 599                                        large_buffer_size,
 600                                        0 /* byte alignment */,
 601                                        0 /* no page-crossing issues */);
 602                if (!device_info->large_buffer_pool) {
 603                printk(KERN_ERR
 604                        "dmabounce: could not allocate large DMA pool for %s\n",
 605                        dev->bus_id);
 606                        dma_pool_destroy(device_info->small_buffer_pool);
 607
 608                        return -ENOMEM;
 609                }
 610        }
 611
 612        device_info->dev = dev;
 613        device_info->small_buffer_size = small_buffer_size;
 614        device_info->large_buffer_size = large_buffer_size;
 615        INIT_LIST_HEAD(&device_info->safe_buffers);
 616
 617#ifdef STATS
 618        device_info->sbp_allocs = 0;
 619        device_info->lbp_allocs = 0;
 620        device_info->total_allocs = 0;
 621        device_info->map_op_count = 0;
 622        device_info->bounce_count = 0;
 623#endif
 624
 625        list_add(&device_info->node, &dmabounce_devs);
 626
 627        printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
 628                dev->bus_id, dev->bus->name);
 629
 630        return 0;
 631}
 632
 633void
 634dmabounce_unregister_dev(struct device *dev)
 635{
 636        struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
 637
 638        if (!device_info) {
 639                printk(KERN_WARNING
 640                        "%s: Never registered with dmabounce but attempting" \
 641                        "to unregister!\n", dev->bus_id);
 642                return;
 643        }
 644
 645        if (!list_empty(&device_info->safe_buffers)) {
 646                printk(KERN_ERR
 647                        "%s: Removing from dmabounce with pending buffers!\n",
 648                        dev->bus_id);
 649                BUG();
 650        }
 651
 652        if (device_info->small_buffer_pool)
 653                dma_pool_destroy(device_info->small_buffer_pool);
 654        if (device_info->large_buffer_pool)
 655                dma_pool_destroy(device_info->large_buffer_pool);
 656
 657#ifdef STATS
 658        print_alloc_stats(device_info);
 659        print_map_stats(device_info);
 660#endif
 661
 662        list_del(&device_info->node);
 663
 664        kfree(device_info);
 665
 666        printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
 667                dev->bus_id, dev->bus->name);
 668}
 669
 670
 671EXPORT_SYMBOL(dma_map_single);
 672EXPORT_SYMBOL(dma_unmap_single);
 673EXPORT_SYMBOL(dma_map_sg);
 674EXPORT_SYMBOL(dma_unmap_sg);
 675EXPORT_SYMBOL(dma_sync_single);
 676EXPORT_SYMBOL(dma_sync_sg);
 677EXPORT_SYMBOL(dmabounce_register_dev);
 678EXPORT_SYMBOL(dmabounce_unregister_dev);
 679
 680MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>, Deepak Saxena <dsaxena@plexity.net>");
 681MODULE_DESCRIPTION("Special dma_{map/unmap/dma_sync}_* routines for systems with limited DMA windows");
 682MODULE_LICENSE("GPL");
 683
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.