0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #include <linux/bitmap.h>
0047 #include <linux/errno.h>
0048 #include <linux/slab.h>
0049
0050 #include "pvrdma.h"
0051
0052 int pvrdma_uar_table_init(struct pvrdma_dev *dev)
0053 {
0054 u32 num = dev->dsr->caps.max_uar;
0055 u32 mask = num - 1;
0056 struct pvrdma_id_table *tbl = &dev->uar_table.tbl;
0057
0058 if (!is_power_of_2(num))
0059 return -EINVAL;
0060
0061 tbl->last = 0;
0062 tbl->top = 0;
0063 tbl->max = num;
0064 tbl->mask = mask;
0065 spin_lock_init(&tbl->lock);
0066 tbl->table = bitmap_zalloc(num, GFP_KERNEL);
0067 if (!tbl->table)
0068 return -ENOMEM;
0069
0070
0071 __set_bit(0, tbl->table);
0072
0073 return 0;
0074 }
0075
0076 void pvrdma_uar_table_cleanup(struct pvrdma_dev *dev)
0077 {
0078 struct pvrdma_id_table *tbl = &dev->uar_table.tbl;
0079
0080 bitmap_free(tbl->table);
0081 }
0082
0083 int pvrdma_uar_alloc(struct pvrdma_dev *dev, struct pvrdma_uar_map *uar)
0084 {
0085 struct pvrdma_id_table *tbl;
0086 unsigned long flags;
0087 u32 obj;
0088
0089 tbl = &dev->uar_table.tbl;
0090
0091 spin_lock_irqsave(&tbl->lock, flags);
0092 obj = find_next_zero_bit(tbl->table, tbl->max, tbl->last);
0093 if (obj >= tbl->max) {
0094 tbl->top = (tbl->top + tbl->max) & tbl->mask;
0095 obj = find_first_zero_bit(tbl->table, tbl->max);
0096 }
0097
0098 if (obj >= tbl->max) {
0099 spin_unlock_irqrestore(&tbl->lock, flags);
0100 return -ENOMEM;
0101 }
0102
0103 __set_bit(obj, tbl->table);
0104 obj |= tbl->top;
0105
0106 spin_unlock_irqrestore(&tbl->lock, flags);
0107
0108 uar->index = obj;
0109 uar->pfn = (pci_resource_start(dev->pdev, PVRDMA_PCI_RESOURCE_UAR) >>
0110 PAGE_SHIFT) + uar->index;
0111
0112 return 0;
0113 }
0114
0115 void pvrdma_uar_free(struct pvrdma_dev *dev, struct pvrdma_uar_map *uar)
0116 {
0117 struct pvrdma_id_table *tbl = &dev->uar_table.tbl;
0118 unsigned long flags;
0119 u32 obj;
0120
0121 obj = uar->index & (tbl->max - 1);
0122 spin_lock_irqsave(&tbl->lock, flags);
0123 __clear_bit(obj, tbl->table);
0124 tbl->last = min(tbl->last, obj);
0125 tbl->top = (tbl->top + tbl->max) & tbl->mask;
0126 spin_unlock_irqrestore(&tbl->lock, flags);
0127 }