uar = &dev->priv_uar;
}
- if (dev->eq_table)
- vector = dev->eq_table[vector % ibdev->num_comp_vectors];
+ if (dev->eq_table) {
+ vector = dev->eq_table[mlx4_choose_vector(dev->dev, vector,
+ ibdev->num_comp_vectors)];
+ }
+
+ cq->vector = vector;
err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
cq->db.dma, &cq->mcq, vector, 0, 0);
return &cq->ibcq;
err_dbmap:
+ mlx4_release_vector(dev->dev, cq->vector);
+
if (context)
mlx4_ib_db_unmap_user(to_mucontext(context), &cq->db);
mlx4_db_free(dev->dev, &mcq->db);
}
+ mlx4_release_vector(dev->dev, mcq->vector);
+
kfree(mcq);
return 0;
#include <linux/mlx4/device.h>
#include <linux/mlx4/doorbell.h>
+#include <linux/mlx4/driver.h>
#define MLX4_IB_DRV_NAME "mlx4_ib"
/* List of qps that it serves.*/
struct list_head send_qp_list;
struct list_head recv_qp_list;
+ int vector;
};
struct mlx4_ib_mr {
int err;
int i;
+ spin_lock_init(&dev->eq_accounting_lock);
priv->eq_table.uar_map = kcalloc(mlx4_num_eq_uar(dev),
sizeof *priv->eq_table.uar_map,
GFP_KERNEL);
}
EXPORT_SYMBOL(mlx4_release_eq);
+int mlx4_choose_vector(struct mlx4_dev *dev, int vector, int num_comp)
+{
+ struct mlx4_eq *chosen;
+ int k;
+
+ if (vector || smp_processor_id() == (vector % num_online_cpus())) {
+ spin_lock(&dev->eq_accounting_lock);
+ mlx4_priv(dev)->eq_table.eq[vector].ncqs++;
+ spin_unlock(&dev->eq_accounting_lock);
+ } else {
+ spin_lock(&dev->eq_accounting_lock);
+ chosen = &mlx4_priv(dev)->eq_table.eq[0];
+ for (k = 0; k < num_comp; k++) {
+ if (mlx4_priv(dev)->eq_table.eq[k].ncqs < chosen->ncqs) {
+ chosen = &mlx4_priv(dev)->eq_table.eq[k];
+ vector = k;
+ }
+ }
+ chosen->ncqs++;
+ spin_unlock(&dev->eq_accounting_lock);
+ }
+
+ return vector;
+}
+EXPORT_SYMBOL(mlx4_choose_vector);
+
+void mlx4_release_vector(struct mlx4_dev *dev, int vector)
+{
+ spin_lock(&dev->eq_accounting_lock);
+ mlx4_priv(dev)->eq_table.eq[vector].ncqs--;
+ spin_unlock(&dev->eq_accounting_lock);
+}
+EXPORT_SYMBOL(mlx4_release_vector);
struct mlx4_buf_list *page_list;
struct mlx4_mtt mtt;
struct mlx4_eq_tasklet tasklet_ctx;
+ u32 ncqs;
};
struct mlx4_slave_eqe {
u64 regid_promisc_array[MLX4_MAX_PORTS + 1];
u64 regid_allmulti_array[MLX4_MAX_PORTS + 1];
struct mlx4_vf_dev *dev_vfs;
+ spinlock_t eq_accounting_lock;
};
struct mlx4_eqe {
return mac;
}
+int mlx4_choose_vector(struct mlx4_dev *dev, int vector, int num_comp);
+void mlx4_release_vector(struct mlx4_dev *dev, int vector);
+
#endif /* MLX4_DRIVER_H */