linux/drivers/net/ethernet/mellanox/mlx4/alloc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
   3 * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
   4 *
   5 * This software is available to you under a choice of one of two
   6 * licenses.  You may choose to be licensed under the terms of the GNU
   7 * General Public License (GPL) Version 2, available from the file
   8 * COPYING in the main directory of this source tree, or the
   9 * OpenIB.org BSD license below:
  10 *
  11 *     Redistribution and use in source and binary forms, with or
  12 *     without modification, are permitted provided that the following
  13 *     conditions are met:
  14 *
  15 *      - Redistributions of source code must retain the above
  16 *        copyright notice, this list of conditions and the following
  17 *        disclaimer.
  18 *
  19 *      - Redistributions in binary form must reproduce the above
  20 *        copyright notice, this list of conditions and the following
  21 *        disclaimer in the documentation and/or other materials
  22 *        provided with the distribution.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31 * SOFTWARE.
  32 */
  33
  34#include <linux/errno.h>
  35#include <linux/slab.h>
  36#include <linux/mm.h>
  37#include <linux/export.h>
  38#include <linux/bitmap.h>
  39#include <linux/dma-mapping.h>
  40#include <linux/vmalloc.h>
  41
  42#include "mlx4.h"
  43
  44u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
  45{
  46        u32 obj;
  47
  48        spin_lock(&bitmap->lock);
  49
  50        obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
  51        if (obj >= bitmap->max) {
  52                bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
  53                                & bitmap->mask;
  54                obj = find_first_zero_bit(bitmap->table, bitmap->max);
  55        }
  56
  57        if (obj < bitmap->max) {
  58                set_bit(obj, bitmap->table);
  59                bitmap->last = (obj + 1);
  60                if (bitmap->last == bitmap->max)
  61                        bitmap->last = 0;
  62                obj |= bitmap->top;
  63        } else
  64                obj = -1;
  65
  66        if (obj != -1)
  67                --bitmap->avail;
  68
  69        spin_unlock(&bitmap->lock);
  70
  71        return obj;
  72}
  73
  74void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr)
  75{
  76        mlx4_bitmap_free_range(bitmap, obj, 1, use_rr);
  77}
  78
  79static unsigned long find_aligned_range(unsigned long *bitmap,
  80                                        u32 start, u32 nbits,
  81                                        int len, int align, u32 skip_mask)
  82{
  83        unsigned long end, i;
  84
  85again:
  86        start = ALIGN(start, align);
  87
  88        while ((start < nbits) && (test_bit(start, bitmap) ||
  89                                   (start & skip_mask)))
  90                start += align;
  91
  92        if (start >= nbits)
  93                return -1;
  94
  95        end = start+len;
  96        if (end > nbits)
  97                return -1;
  98
  99        for (i = start + 1; i < end; i++) {
 100                if (test_bit(i, bitmap) || ((u32)i & skip_mask)) {
 101                        start = i + 1;
 102                        goto again;
 103                }
 104        }
 105
 106        return start;
 107}
 108
 109u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt,
 110                            int align, u32 skip_mask)
 111{
 112        u32 obj;
 113
 114        if (likely(cnt == 1 && align == 1 && !skip_mask))
 115                return mlx4_bitmap_alloc(bitmap);
 116
 117        spin_lock(&bitmap->lock);
 118
 119        obj = find_aligned_range(bitmap->table, bitmap->last,
 120                                 bitmap->max, cnt, align, skip_mask);
 121        if (obj >= bitmap->max) {
 122                bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
 123                                & bitmap->mask;
 124                obj = find_aligned_range(bitmap->table, 0, bitmap->max,
 125                                         cnt, align, skip_mask);
 126        }
 127
 128        if (obj < bitmap->max) {
 129                bitmap_set(bitmap->table, obj, cnt);
 130                if (obj == bitmap->last) {
 131                        bitmap->last = (obj + cnt);
 132                        if (bitmap->last >= bitmap->max)
 133                                bitmap->last = 0;
 134                }
 135                obj |= bitmap->top;
 136        } else
 137                obj = -1;
 138
 139        if (obj != -1)
 140                bitmap->avail -= cnt;
 141
 142        spin_unlock(&bitmap->lock);
 143
 144        return obj;
 145}
 146
 147u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap)
 148{
 149        return bitmap->avail;
 150}
 151
 152static u32 mlx4_bitmap_masked_value(struct mlx4_bitmap *bitmap, u32 obj)
 153{
 154        return obj & (bitmap->max + bitmap->reserved_top - 1);
 155}
 156
 157void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
 158                            int use_rr)
 159{
 160        obj &= bitmap->max + bitmap->reserved_top - 1;
 161
 162        spin_lock(&bitmap->lock);
 163        if (!use_rr) {
 164                bitmap->last = min(bitmap->last, obj);
 165                bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
 166                                & bitmap->mask;
 167        }
 168        bitmap_clear(bitmap->table, obj, cnt);
 169        bitmap->avail += cnt;
 170        spin_unlock(&bitmap->lock);
 171}
 172
 173int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
 174                     u32 reserved_bot, u32 reserved_top)
 175{
 176        /* num must be a power of 2 */
 177        if (num != roundup_pow_of_two(num))
 178                return -EINVAL;
 179
 180        bitmap->last = 0;
 181        bitmap->top  = 0;
 182        bitmap->max  = num - reserved_top;
 183        bitmap->mask = mask;
 184        bitmap->reserved_top = reserved_top;
 185        bitmap->avail = num - reserved_top - reserved_bot;
 186        bitmap->effective_len = bitmap->avail;
 187        spin_lock_init(&bitmap->lock);
 188        bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
 189                                sizeof (long), GFP_KERNEL);
 190        if (!bitmap->table)
 191                return -ENOMEM;
 192
 193        bitmap_set(bitmap->table, 0, reserved_bot);
 194
 195        return 0;
 196}
 197
 198void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap)
 199{
 200        kfree(bitmap->table);
 201}
 202
 203struct mlx4_zone_allocator {
 204        struct list_head                entries;
 205        struct list_head                prios;
 206        u32                             last_uid;
 207        u32                             mask;
 208        /* protect the zone_allocator from concurrent accesses */
 209        spinlock_t                      lock;
 210        enum mlx4_zone_alloc_flags      flags;
 211};
 212
 213struct mlx4_zone_entry {
 214        struct list_head                list;
 215        struct list_head                prio_list;
 216        u32                             uid;
 217        struct mlx4_zone_allocator      *allocator;
 218        struct mlx4_bitmap              *bitmap;
 219        int                             use_rr;
 220        int                             priority;
 221        int                             offset;
 222        enum mlx4_zone_flags            flags;
 223};
 224
 225struct mlx4_zone_allocator *mlx4_zone_allocator_create(enum mlx4_zone_alloc_flags flags)
 226{
 227        struct mlx4_zone_allocator *zones = kmalloc(sizeof(*zones), GFP_KERNEL);
 228
 229        if (NULL == zones)
 230                return NULL;
 231
 232        INIT_LIST_HEAD(&zones->entries);
 233        INIT_LIST_HEAD(&zones->prios);
 234        spin_lock_init(&zones->lock);
 235        zones->last_uid = 0;
 236        zones->mask = 0;
 237        zones->flags = flags;
 238
 239        return zones;
 240}
 241
 242int mlx4_zone_add_one(struct mlx4_zone_allocator *zone_alloc,
 243                      struct mlx4_bitmap *bitmap,
 244                      u32 flags,
 245                      int priority,
 246                      int offset,
 247                      u32 *puid)
 248{
 249        u32 mask = mlx4_bitmap_masked_value(bitmap, (u32)-1);
 250        struct mlx4_zone_entry *it;
 251        struct mlx4_zone_entry *zone = kmalloc(sizeof(*zone), GFP_KERNEL);
 252
 253        if (NULL == zone)
 254                return -ENOMEM;
 255
 256        zone->flags = flags;
 257        zone->bitmap = bitmap;
 258        zone->use_rr = (flags & MLX4_ZONE_USE_RR) ? MLX4_USE_RR : 0;
 259        zone->priority = priority;
 260        zone->offset = offset;
 261
 262        spin_lock(&zone_alloc->lock);
 263
 264        zone->uid = zone_alloc->last_uid++;
 265        zone->allocator = zone_alloc;
 266
 267        if (zone_alloc->mask < mask)
 268                zone_alloc->mask = mask;
 269
 270        list_for_each_entry(it, &zone_alloc->prios, prio_list)
 271                if (it->priority >= priority)
 272                        break;
 273
 274        if (&it->prio_list == &zone_alloc->prios || it->priority > priority)
 275                list_add_tail(&zone->prio_list, &it->prio_list);
 276        list_add_tail(&zone->list, &it->list);
 277
 278        spin_unlock(&zone_alloc->lock);
 279
 280        *puid = zone->uid;
 281
 282        return 0;
 283}
 284
 285/* Should be called under a lock */
 286static int __mlx4_zone_remove_one_entry(struct mlx4_zone_entry *entry)
 287{
 288        struct mlx4_zone_allocator *zone_alloc = entry->allocator;
 289
 290        if (!list_empty(&entry->prio_list)) {
 291                /* Check if we need to add an alternative node to the prio list */
 292                if (!list_is_last(&entry->list, &zone_alloc->entries)) {
 293                        struct mlx4_zone_entry *next = list_first_entry(&entry->list,
 294                                                                        typeof(*next),
 295                                                                        list);
 296
 297                        if (next->priority == entry->priority)
 298                                list_add_tail(&next->prio_list, &entry->prio_list);
 299                }
 300
 301                list_del(&entry->prio_list);
 302        }
 303
 304        list_del(&entry->list);
 305
 306        if (zone_alloc->flags & MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP) {
 307                u32 mask = 0;
 308                struct mlx4_zone_entry *it;
 309
 310                list_for_each_entry(it, &zone_alloc->prios, prio_list) {
 311                        u32 cur_mask = mlx4_bitmap_masked_value(it->bitmap, (u32)-1);
 312
 313                        if (mask < cur_mask)
 314                                mask = cur_mask;
 315                }
 316                zone_alloc->mask = mask;
 317        }
 318
 319        return 0;
 320}
 321
 322void mlx4_zone_allocator_destroy(struct mlx4_zone_allocator *zone_alloc)
 323{
 324        struct mlx4_zone_entry *zone, *tmp;
 325
 326        spin_lock(&zone_alloc->lock);
 327
 328        list_for_each_entry_safe(zone, tmp, &zone_alloc->entries, list) {
 329                list_del(&zone->list);
 330                list_del(&zone->prio_list);
 331                kfree(zone);
 332        }
 333
 334        spin_unlock(&zone_alloc->lock);
 335        kfree(zone_alloc);
 336}
 337
 338/* Should be called under a lock */
 339static u32 __mlx4_alloc_from_zone(struct mlx4_zone_entry *zone, int count,
 340                                  int align, u32 skip_mask, u32 *puid)
 341{
 342        u32 uid;
 343        u32 res;
 344        struct mlx4_zone_allocator *zone_alloc = zone->allocator;
 345        struct mlx4_zone_entry *curr_node;
 346
 347        res = mlx4_bitmap_alloc_range(zone->bitmap, count,
 348                                      align, skip_mask);
 349
 350        if (res != (u32)-1) {
 351                res += zone->offset;
 352                uid = zone->uid;
 353                goto out;
 354        }
 355
 356        list_for_each_entry(curr_node, &zone_alloc->prios, prio_list) {
 357                if (unlikely(curr_node->priority == zone->priority))
 358                        break;
 359        }
 360
 361        if (zone->flags & MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO) {
 362                struct mlx4_zone_entry *it = curr_node;
 363
 364                list_for_each_entry_continue_reverse(it, &zone_alloc->entries, list) {
 365                        res = mlx4_bitmap_alloc_range(it->bitmap, count,
 366                                                      align, skip_mask);
 367                        if (res != (u32)-1) {
 368                                res += it->offset;
 369                                uid = it->uid;
 370                                goto out;
 371                        }
 372                }
 373        }
 374
 375        if (zone->flags & MLX4_ZONE_ALLOW_ALLOC_FROM_EQ_PRIO) {
 376                struct mlx4_zone_entry *it = curr_node;
 377
 378                list_for_each_entry_from(it, &zone_alloc->entries, list) {
 379                        if (unlikely(it == zone))
 380                                continue;
 381
 382                        if (unlikely(it->priority != curr_node->priority))
 383                                break;
 384
 385                        res = mlx4_bitmap_alloc_range(it->bitmap, count,
 386                                                      align, skip_mask);
 387                        if (res != (u32)-1) {
 388                                res += it->offset;
 389                                uid = it->uid;
 390                                goto out;
 391                        }
 392                }
 393        }
 394
 395        if (zone->flags & MLX4_ZONE_FALLBACK_TO_HIGHER_PRIO) {
 396                if (list_is_last(&curr_node->prio_list, &zone_alloc->prios))
 397                        goto out;
 398
 399                curr_node = list_first_entry(&curr_node->prio_list,
 400                                             typeof(*curr_node),
 401                                             prio_list);
 402
 403                list_for_each_entry_from(curr_node, &zone_alloc->entries, list) {
 404                        res = mlx4_bitmap_alloc_range(curr_node->bitmap, count,
 405                                                      align, skip_mask);
 406                        if (res != (u32)-1) {
 407                                res += curr_node->offset;
 408                                uid = curr_node->uid;
 409                                goto out;
 410                        }
 411                }
 412        }
 413
 414out:
 415        if (NULL != puid && res != (u32)-1)
 416                *puid = uid;
 417        return res;
 418}
 419
 420/* Should be called under a lock */
 421static void __mlx4_free_from_zone(struct mlx4_zone_entry *zone, u32 obj,
 422                                  u32 count)
 423{
 424        mlx4_bitmap_free_range(zone->bitmap, obj - zone->offset, count, zone->use_rr);
 425}
 426
 427/* Should be called under a lock */
 428static struct mlx4_zone_entry *__mlx4_find_zone_by_uid(
 429                struct mlx4_zone_allocator *zones, u32 uid)
 430{
 431        struct mlx4_zone_entry *zone;
 432
 433        list_for_each_entry(zone, &zones->entries, list) {
 434                if (zone->uid == uid)
 435                        return zone;
 436        }
 437
 438        return NULL;
 439}
 440
 441struct mlx4_bitmap *mlx4_zone_get_bitmap(struct mlx4_zone_allocator *zones, u32 uid)
 442{
 443        struct mlx4_zone_entry *zone;
 444        struct mlx4_bitmap *bitmap;
 445
 446        spin_lock(&zones->lock);
 447
 448        zone = __mlx4_find_zone_by_uid(zones, uid);
 449
 450        bitmap = zone == NULL ? NULL : zone->bitmap;
 451
 452        spin_unlock(&zones->lock);
 453
 454        return bitmap;
 455}
 456
 457int mlx4_zone_remove_one(struct mlx4_zone_allocator *zones, u32 uid)
 458{
 459        struct mlx4_zone_entry *zone;
 460        int res;
 461
 462        spin_lock(&zones->lock);
 463
 464        zone = __mlx4_find_zone_by_uid(zones, uid);
 465
 466        if (NULL == zone) {
 467                res = -1;
 468                goto out;
 469        }
 470
 471        res = __mlx4_zone_remove_one_entry(zone);
 472
 473out:
 474        spin_unlock(&zones->lock);
 475        kfree(zone);
 476
 477        return res;
 478}
 479
 480/* Should be called under a lock */
 481static struct mlx4_zone_entry *__mlx4_find_zone_by_uid_unique(
 482                struct mlx4_zone_allocator *zones, u32 obj)
 483{
 484        struct mlx4_zone_entry *zone, *zone_candidate = NULL;
 485        u32 dist = (u32)-1;
 486
 487        /* Search for the smallest zone that this obj could be
 488         * allocated from. This is done in order to handle
 489         * situations when small bitmaps are allocated from bigger
 490         * bitmaps (and the allocated space is marked as reserved in
 491         * the bigger bitmap.
 492         */
 493        list_for_each_entry(zone, &zones->entries, list) {
 494                if (obj >= zone->offset) {
 495                        u32 mobj = (obj - zone->offset) & zones->mask;
 496
 497                        if (mobj < zone->bitmap->max) {
 498                                u32 curr_dist = zone->bitmap->effective_len;
 499
 500                                if (curr_dist < dist) {
 501                                        dist = curr_dist;
 502                                        zone_candidate = zone;
 503                                }
 504                        }
 505                }
 506        }
 507
 508        return zone_candidate;
 509}
 510
 511u32 mlx4_zone_alloc_entries(struct mlx4_zone_allocator *zones, u32 uid, int count,
 512                            int align, u32 skip_mask, u32 *puid)
 513{
 514        struct mlx4_zone_entry *zone;
 515        int res = -1;
 516
 517        spin_lock(&zones->lock);
 518
 519        zone = __mlx4_find_zone_by_uid(zones, uid);
 520
 521        if (NULL == zone)
 522                goto out;
 523
 524        res = __mlx4_alloc_from_zone(zone, count, align, skip_mask, puid);
 525
 526out:
 527        spin_unlock(&zones->lock);
 528
 529        return res;
 530}
 531
 532u32 mlx4_zone_free_entries(struct mlx4_zone_allocator *zones, u32 uid, u32 obj, u32 count)
 533{
 534        struct mlx4_zone_entry *zone;
 535        int res = 0;
 536
 537        spin_lock(&zones->lock);
 538
 539        zone = __mlx4_find_zone_by_uid(zones, uid);
 540
 541        if (NULL == zone) {
 542                res = -1;
 543                goto out;
 544        }
 545
 546        __mlx4_free_from_zone(zone, obj, count);
 547
 548out:
 549        spin_unlock(&zones->lock);
 550
 551        return res;
 552}
 553
 554u32 mlx4_zone_free_entries_unique(struct mlx4_zone_allocator *zones, u32 obj, u32 count)
 555{
 556        struct mlx4_zone_entry *zone;
 557        int res;
 558
 559        if (!(zones->flags & MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP))
 560                return -EFAULT;
 561
 562        spin_lock(&zones->lock);
 563
 564        zone = __mlx4_find_zone_by_uid_unique(zones, obj);
 565
 566        if (NULL == zone) {
 567                res = -1;
 568                goto out;
 569        }
 570
 571        __mlx4_free_from_zone(zone, obj, count);
 572        res = 0;
 573
 574out:
 575        spin_unlock(&zones->lock);
 576
 577        return res;
 578}
 579
 580static int mlx4_buf_direct_alloc(struct mlx4_dev *dev, int size,
 581                                 struct mlx4_buf *buf, gfp_t gfp)
 582{
 583        dma_addr_t t;
 584
 585        buf->nbufs        = 1;
 586        buf->npages       = 1;
 587        buf->page_shift   = get_order(size) + PAGE_SHIFT;
 588        buf->direct.buf   =
 589                dma_zalloc_coherent(&dev->persist->pdev->dev,
 590                                    size, &t, gfp);
 591        if (!buf->direct.buf)
 592                return -ENOMEM;
 593
 594        buf->direct.map = t;
 595
 596        while (t & ((1 << buf->page_shift) - 1)) {
 597                --buf->page_shift;
 598                buf->npages *= 2;
 599        }
 600
 601        return 0;
 602}
 603
 604/* Handling for queue buffers -- we allocate a bunch of memory and
 605 * register it in a memory region at HCA virtual address 0. If the
 606 *  requested size is > max_direct, we split the allocation into
 607 *  multiple pages, so we don't require too much contiguous memory.
 608 */
 609int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
 610                   struct mlx4_buf *buf, gfp_t gfp)
 611{
 612        if (size <= max_direct) {
 613                return mlx4_buf_direct_alloc(dev, size, buf, gfp);
 614        } else {
 615                dma_addr_t t;
 616                int i;
 617
 618                buf->direct.buf = NULL;
 619                buf->nbufs      = (size + PAGE_SIZE - 1) / PAGE_SIZE;
 620                buf->npages     = buf->nbufs;
 621                buf->page_shift  = PAGE_SHIFT;
 622                buf->page_list   = kcalloc(buf->nbufs, sizeof(*buf->page_list),
 623                                           gfp);
 624                if (!buf->page_list)
 625                        return -ENOMEM;
 626
 627                for (i = 0; i < buf->nbufs; ++i) {
 628                        buf->page_list[i].buf =
 629                                dma_zalloc_coherent(&dev->persist->pdev->dev,
 630                                                    PAGE_SIZE, &t, gfp);
 631                        if (!buf->page_list[i].buf)
 632                                goto err_free;
 633
 634                        buf->page_list[i].map = t;
 635                }
 636        }
 637
 638        return 0;
 639
 640err_free:
 641        mlx4_buf_free(dev, size, buf);
 642
 643        return -ENOMEM;
 644}
 645EXPORT_SYMBOL_GPL(mlx4_buf_alloc);
 646
 647void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
 648{
 649        if (buf->nbufs == 1) {
 650                dma_free_coherent(&dev->persist->pdev->dev, size,
 651                                  buf->direct.buf, buf->direct.map);
 652        } else {
 653                int i;
 654
 655                for (i = 0; i < buf->nbufs; ++i)
 656                        if (buf->page_list[i].buf)
 657                                dma_free_coherent(&dev->persist->pdev->dev,
 658                                                  PAGE_SIZE,
 659                                                  buf->page_list[i].buf,
 660                                                  buf->page_list[i].map);
 661                kfree(buf->page_list);
 662        }
 663}
 664EXPORT_SYMBOL_GPL(mlx4_buf_free);
 665
 666static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device,
 667                                                 gfp_t gfp)
 668{
 669        struct mlx4_db_pgdir *pgdir;
 670
 671        pgdir = kzalloc(sizeof *pgdir, gfp);
 672        if (!pgdir)
 673                return NULL;
 674
 675        bitmap_fill(pgdir->order1, MLX4_DB_PER_PAGE / 2);
 676        pgdir->bits[0] = pgdir->order0;
 677        pgdir->bits[1] = pgdir->order1;
 678        pgdir->db_page = dma_alloc_coherent(dma_device, PAGE_SIZE,
 679                                            &pgdir->db_dma, gfp);
 680        if (!pgdir->db_page) {
 681                kfree(pgdir);
 682                return NULL;
 683        }
 684
 685        return pgdir;
 686}
 687
 688static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir,
 689                                    struct mlx4_db *db, int order)
 690{
 691        int o;
 692        int i;
 693
 694        for (o = order; o <= 1; ++o) {
 695                i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o);
 696                if (i < MLX4_DB_PER_PAGE >> o)
 697                        goto found;
 698        }
 699
 700        return -ENOMEM;
 701
 702found:
 703        clear_bit(i, pgdir->bits[o]);
 704
 705        i <<= o;
 706
 707        if (o > order)
 708                set_bit(i ^ 1, pgdir->bits[order]);
 709
 710        db->u.pgdir = pgdir;
 711        db->index   = i;
 712        db->db      = pgdir->db_page + db->index;
 713        db->dma     = pgdir->db_dma  + db->index * 4;
 714        db->order   = order;
 715
 716        return 0;
 717}
 718
 719int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order, gfp_t gfp)
 720{
 721        struct mlx4_priv *priv = mlx4_priv(dev);
 722        struct mlx4_db_pgdir *pgdir;
 723        int ret = 0;
 724
 725        mutex_lock(&priv->pgdir_mutex);
 726
 727        list_for_each_entry(pgdir, &priv->pgdir_list, list)
 728                if (!mlx4_alloc_db_from_pgdir(pgdir, db, order))
 729                        goto out;
 730
 731        pgdir = mlx4_alloc_db_pgdir(&dev->persist->pdev->dev, gfp);
 732        if (!pgdir) {
 733                ret = -ENOMEM;
 734                goto out;
 735        }
 736
 737        list_add(&pgdir->list, &priv->pgdir_list);
 738
 739        /* This should never fail -- we just allocated an empty page: */
 740        WARN_ON(mlx4_alloc_db_from_pgdir(pgdir, db, order));
 741
 742out:
 743        mutex_unlock(&priv->pgdir_mutex);
 744
 745        return ret;
 746}
 747EXPORT_SYMBOL_GPL(mlx4_db_alloc);
 748
 749void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db)
 750{
 751        struct mlx4_priv *priv = mlx4_priv(dev);
 752        int o;
 753        int i;
 754
 755        mutex_lock(&priv->pgdir_mutex);
 756
 757        o = db->order;
 758        i = db->index;
 759
 760        if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
 761                clear_bit(i ^ 1, db->u.pgdir->order0);
 762                ++o;
 763        }
 764        i >>= o;
 765        set_bit(i, db->u.pgdir->bits[o]);
 766
 767        if (bitmap_full(db->u.pgdir->order1, MLX4_DB_PER_PAGE / 2)) {
 768                dma_free_coherent(&dev->persist->pdev->dev, PAGE_SIZE,
 769                                  db->u.pgdir->db_page, db->u.pgdir->db_dma);
 770                list_del(&db->u.pgdir->list);
 771                kfree(db->u.pgdir);
 772        }
 773
 774        mutex_unlock(&priv->pgdir_mutex);
 775}
 776EXPORT_SYMBOL_GPL(mlx4_db_free);
 777
 778int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
 779                       int size)
 780{
 781        int err;
 782
 783        err = mlx4_db_alloc(dev, &wqres->db, 1, GFP_KERNEL);
 784        if (err)
 785                return err;
 786
 787        *wqres->db.db = 0;
 788
 789        err = mlx4_buf_direct_alloc(dev, size, &wqres->buf, GFP_KERNEL);
 790        if (err)
 791                goto err_db;
 792
 793        err = mlx4_mtt_init(dev, wqres->buf.npages, wqres->buf.page_shift,
 794                            &wqres->mtt);
 795        if (err)
 796                goto err_buf;
 797
 798        err = mlx4_buf_write_mtt(dev, &wqres->mtt, &wqres->buf, GFP_KERNEL);
 799        if (err)
 800                goto err_mtt;
 801
 802        return 0;
 803
 804err_mtt:
 805        mlx4_mtt_cleanup(dev, &wqres->mtt);
 806err_buf:
 807        mlx4_buf_free(dev, size, &wqres->buf);
 808err_db:
 809        mlx4_db_free(dev, &wqres->db);
 810
 811        return err;
 812}
 813EXPORT_SYMBOL_GPL(mlx4_alloc_hwq_res);
 814
 815void mlx4_free_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
 816                       int size)
 817{
 818        mlx4_mtt_cleanup(dev, &wqres->mtt);
 819        mlx4_buf_free(dev, size, &wqres->buf);
 820        mlx4_db_free(dev, &wqres->db);
 821}
 822EXPORT_SYMBOL_GPL(mlx4_free_hwq_res);
 823