printk(KERN_ERR "RDS/IB: failed to allocate vector memoru\n");
goto put_dev;
}
+ mutex_init(&rds_ibdev->vector_load_lock);
rds_ibdev->mr = ib_get_dma_mr(rds_ibdev->pd, IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(rds_ibdev->mr)) {
struct rds_ib_port *ports;
struct ib_event_handler event_handler;
int *vector_load;
+ /* Several TOS connections may invoke ibdev_get_unused_vector()
+ * concurrently, hence we need protection for vector_load
+ */
+ struct mutex vector_load_lock;
/* flag indicating ib_device is under freeing up or is freed up to make
* the race between rds_ib_remove_one() and rds_release() safe.
static inline int ibdev_get_unused_vector(struct rds_ib_device *rds_ibdev)
{
- int min = rds_ibdev->vector_load[rds_ibdev->dev->num_comp_vectors - 1];
- int index = rds_ibdev->dev->num_comp_vectors - 1;
+ int index;
+ int min;
int i;
+ mutex_lock(&rds_ibdev->vector_load_lock);
+ min = rds_ibdev->vector_load[rds_ibdev->dev->num_comp_vectors - 1];
+ index = rds_ibdev->dev->num_comp_vectors - 1;
+
for (i = rds_ibdev->dev->num_comp_vectors - 1; i >= 0; i--) {
if (rds_ibdev->vector_load[i] < min) {
index = i;
}
rds_ibdev->vector_load[index]++;
+ mutex_unlock(&rds_ibdev->vector_load_lock);
+
return index;
}
static inline void ibdev_put_vector(struct rds_ib_device *rds_ibdev, int index)
{
+ mutex_lock(&rds_ibdev->vector_load_lock);
rds_ibdev->vector_load[index]--;
+ mutex_unlock(&rds_ibdev->vector_load_lock);
}
/*