|
@@ -30,96 +30,25 @@
|
|
|
* SOFTWARE.
|
|
|
*/
|
|
|
/* Crude resource management */
|
|
|
-#include <linux/kernel.h>
|
|
|
-#include <linux/random.h>
|
|
|
-#include <linux/slab.h>
|
|
|
-#include <linux/kfifo.h>
|
|
|
#include <linux/spinlock.h>
|
|
|
-#include <linux/errno.h>
|
|
|
#include <linux/genalloc.h>
|
|
|
#include <linux/ratelimit.h>
|
|
|
#include "iw_cxgb4.h"
|
|
|
|
|
|
-#define RANDOM_SIZE 16
|
|
|
-
|
|
|
-static int __c4iw_init_resource_fifo(struct kfifo *fifo,
|
|
|
- spinlock_t *fifo_lock,
|
|
|
- u32 nr, u32 skip_low,
|
|
|
- u32 skip_high,
|
|
|
- int random)
|
|
|
-{
|
|
|
- u32 i, j, entry = 0, idx;
|
|
|
- u32 random_bytes;
|
|
|
- u32 rarray[16];
|
|
|
- spin_lock_init(fifo_lock);
|
|
|
-
|
|
|
- if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL))
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- for (i = 0; i < skip_low + skip_high; i++)
|
|
|
- kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
|
|
|
- if (random) {
|
|
|
- j = 0;
|
|
|
- random_bytes = random32();
|
|
|
- for (i = 0; i < RANDOM_SIZE; i++)
|
|
|
- rarray[i] = i + skip_low;
|
|
|
- for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
|
|
|
- if (j >= RANDOM_SIZE) {
|
|
|
- j = 0;
|
|
|
- random_bytes = random32();
|
|
|
- }
|
|
|
- idx = (random_bytes >> (j * 2)) & 0xF;
|
|
|
- kfifo_in(fifo,
|
|
|
- (unsigned char *) &rarray[idx],
|
|
|
- sizeof(u32));
|
|
|
- rarray[idx] = i;
|
|
|
- j++;
|
|
|
- }
|
|
|
- for (i = 0; i < RANDOM_SIZE; i++)
|
|
|
- kfifo_in(fifo,
|
|
|
- (unsigned char *) &rarray[i],
|
|
|
- sizeof(u32));
|
|
|
- } else
|
|
|
- for (i = skip_low; i < nr - skip_high; i++)
|
|
|
- kfifo_in(fifo, (unsigned char *) &i, sizeof(u32));
|
|
|
-
|
|
|
- for (i = 0; i < skip_low + skip_high; i++)
|
|
|
- if (kfifo_out_locked(fifo, (unsigned char *) &entry,
|
|
|
- sizeof(u32), fifo_lock))
|
|
|
- break;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int c4iw_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock,
|
|
|
- u32 nr, u32 skip_low, u32 skip_high)
|
|
|
-{
|
|
|
- return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
|
|
|
- skip_high, 0);
|
|
|
-}
|
|
|
-
|
|
|
-static int c4iw_init_resource_fifo_random(struct kfifo *fifo,
|
|
|
- spinlock_t *fifo_lock,
|
|
|
- u32 nr, u32 skip_low, u32 skip_high)
|
|
|
-{
|
|
|
- return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
|
|
|
- skip_high, 1);
|
|
|
-}
|
|
|
-
|
|
|
-static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
|
|
|
+static int c4iw_init_qid_table(struct c4iw_rdev *rdev)
|
|
|
{
|
|
|
u32 i;
|
|
|
|
|
|
- spin_lock_init(&rdev->resource.qid_fifo_lock);
|
|
|
-
|
|
|
- if (kfifo_alloc(&rdev->resource.qid_fifo, rdev->lldi.vr->qp.size *
|
|
|
- sizeof(u32), GFP_KERNEL))
|
|
|
+ if (c4iw_id_table_alloc(&rdev->resource.qid_table,
|
|
|
+ rdev->lldi.vr->qp.start,
|
|
|
+ rdev->lldi.vr->qp.size,
|
|
|
+ rdev->lldi.vr->qp.size, 0))
|
|
|
return -ENOMEM;
|
|
|
|
|
|
for (i = rdev->lldi.vr->qp.start;
|
|
|
- i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
|
|
|
+ i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
|
|
|
if (!(i & rdev->qpmask))
|
|
|
- kfifo_in(&rdev->resource.qid_fifo,
|
|
|
- (unsigned char *) &i, sizeof(u32));
|
|
|
+ c4iw_id_free(&rdev->resource.qid_table, i);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -127,44 +56,42 @@ static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
|
|
|
int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid)
|
|
|
{
|
|
|
int err = 0;
|
|
|
- err = c4iw_init_resource_fifo_random(&rdev->resource.tpt_fifo,
|
|
|
- &rdev->resource.tpt_fifo_lock,
|
|
|
- nr_tpt, 1, 0);
|
|
|
+ err = c4iw_id_table_alloc(&rdev->resource.tpt_table, 0, nr_tpt, 1,
|
|
|
+ C4IW_ID_TABLE_F_RANDOM);
|
|
|
if (err)
|
|
|
goto tpt_err;
|
|
|
- err = c4iw_init_qid_fifo(rdev);
|
|
|
+ err = c4iw_init_qid_table(rdev);
|
|
|
if (err)
|
|
|
goto qid_err;
|
|
|
- err = c4iw_init_resource_fifo(&rdev->resource.pdid_fifo,
|
|
|
- &rdev->resource.pdid_fifo_lock,
|
|
|
- nr_pdid, 1, 0);
|
|
|
+ err = c4iw_id_table_alloc(&rdev->resource.pdid_table, 0,
|
|
|
+ nr_pdid, 1, 0);
|
|
|
if (err)
|
|
|
goto pdid_err;
|
|
|
return 0;
|
|
|
-pdid_err:
|
|
|
- kfifo_free(&rdev->resource.qid_fifo);
|
|
|
-qid_err:
|
|
|
- kfifo_free(&rdev->resource.tpt_fifo);
|
|
|
-tpt_err:
|
|
|
+ pdid_err:
|
|
|
+ c4iw_id_table_free(&rdev->resource.qid_table);
|
|
|
+ qid_err:
|
|
|
+ c4iw_id_table_free(&rdev->resource.tpt_table);
|
|
|
+ tpt_err:
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* returns 0 if no resource available
|
|
|
*/
|
|
|
-u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock)
|
|
|
+u32 c4iw_get_resource(struct c4iw_id_table *id_table)
|
|
|
{
|
|
|
u32 entry;
|
|
|
- if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock))
|
|
|
- return entry;
|
|
|
- else
|
|
|
+ entry = c4iw_id_alloc(id_table);
|
|
|
+ if (entry == (u32)(-1))
|
|
|
return 0;
|
|
|
+ return entry;
|
|
|
}
|
|
|
|
|
|
-void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock)
|
|
|
+void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry)
|
|
|
{
|
|
|
PDBG("%s entry 0x%x\n", __func__, entry);
|
|
|
- kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock);
|
|
|
+ c4iw_id_free(id_table, entry);
|
|
|
}
|
|
|
|
|
|
u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
|
|
@@ -181,8 +108,7 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
|
|
|
qid = entry->qid;
|
|
|
kfree(entry);
|
|
|
} else {
|
|
|
- qid = c4iw_get_resource(&rdev->resource.qid_fifo,
|
|
|
- &rdev->resource.qid_fifo_lock);
|
|
|
+ qid = c4iw_get_resource(&rdev->resource.qid_table);
|
|
|
if (!qid)
|
|
|
goto out;
|
|
|
mutex_lock(&rdev->stats.lock);
|
|
@@ -252,8 +178,7 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
|
|
|
qid = entry->qid;
|
|
|
kfree(entry);
|
|
|
} else {
|
|
|
- qid = c4iw_get_resource(&rdev->resource.qid_fifo,
|
|
|
- &rdev->resource.qid_fifo_lock);
|
|
|
+ qid = c4iw_get_resource(&rdev->resource.qid_table);
|
|
|
if (!qid)
|
|
|
goto out;
|
|
|
mutex_lock(&rdev->stats.lock);
|
|
@@ -311,9 +236,9 @@ void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qid,
|
|
|
|
|
|
void c4iw_destroy_resource(struct c4iw_resource *rscp)
|
|
|
{
|
|
|
- kfifo_free(&rscp->tpt_fifo);
|
|
|
- kfifo_free(&rscp->qid_fifo);
|
|
|
- kfifo_free(&rscp->pdid_fifo);
|
|
|
+ c4iw_id_table_free(&rscp->tpt_table);
|
|
|
+ c4iw_id_table_free(&rscp->qid_table);
|
|
|
+ c4iw_id_table_free(&rscp->pdid_table);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -326,16 +251,14 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
|
|
|
{
|
|
|
unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
|
|
|
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
|
|
|
- if (!addr)
|
|
|
- printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
|
|
|
- pci_name(rdev->lldi.pdev));
|
|
|
+ mutex_lock(&rdev->stats.lock);
|
|
|
if (addr) {
|
|
|
- mutex_lock(&rdev->stats.lock);
|
|
|
rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
|
|
|
if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
|
|
|
rdev->stats.pbl.max = rdev->stats.pbl.cur;
|
|
|
- mutex_unlock(&rdev->stats.lock);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ rdev->stats.pbl.fail++;
|
|
|
+ mutex_unlock(&rdev->stats.lock);
|
|
|
return (u32)addr;
|
|
|
}
|
|
|
|
|
@@ -401,13 +324,14 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
|
|
|
if (!addr)
|
|
|
printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
|
|
|
pci_name(rdev->lldi.pdev));
|
|
|
+ mutex_lock(&rdev->stats.lock);
|
|
|
if (addr) {
|
|
|
- mutex_lock(&rdev->stats.lock);
|
|
|
rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
|
|
|
if (rdev->stats.rqt.cur > rdev->stats.rqt.max)
|
|
|
rdev->stats.rqt.max = rdev->stats.rqt.cur;
|
|
|
- mutex_unlock(&rdev->stats.lock);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ rdev->stats.rqt.fail++;
|
|
|
+ mutex_unlock(&rdev->stats.lock);
|
|
|
return (u32)addr;
|
|
|
}
|
|
|
|