|
@@ -143,6 +143,7 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev)
|
|
|
if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
|
|
|
dev->caps.port_mask |= 1 << (i - 1);
|
|
|
}
|
|
|
+
|
|
|
static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
|
|
|
{
|
|
|
int err;
|
|
@@ -257,6 +258,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
|
|
|
|
|
|
mlx4_set_port_mask(dev);
|
|
|
|
|
|
+ dev->caps.max_counters = 1 << ilog2(dev_cap->max_counters);
|
|
|
+
|
|
|
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
|
|
|
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
|
|
|
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] =
|
|
@@ -834,6 +837,45 @@ err_stop_fw:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static int mlx4_init_counters_table(struct mlx4_dev *dev)
|
|
|
+{
|
|
|
+ struct mlx4_priv *priv = mlx4_priv(dev);
|
|
|
+ int nent;
|
|
|
+
|
|
|
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ nent = dev->caps.max_counters;
|
|
|
+ return mlx4_bitmap_init(&priv->counters_bitmap, nent, nent - 1, 0, 0);
|
|
|
+}
|
|
|
+
|
|
|
+static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
|
|
|
+{
|
|
|
+ mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap);
|
|
|
+}
|
|
|
+
|
|
|
+int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
|
|
|
+{
|
|
|
+ struct mlx4_priv *priv = mlx4_priv(dev);
|
|
|
+
|
|
|
+ if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ *idx = mlx4_bitmap_alloc(&priv->counters_bitmap);
|
|
|
+ if (*idx == -1)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
|
|
|
+
|
|
|
+void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
|
|
|
+{
|
|
|
+ mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
|
|
|
+ return;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(mlx4_counter_free);
|
|
|
+
|
|
|
static int mlx4_setup_hca(struct mlx4_dev *dev)
|
|
|
{
|
|
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
|
@@ -938,6 +980,12 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
|
|
|
goto err_qp_table_free;
|
|
|
}
|
|
|
|
|
|
+ err = mlx4_init_counters_table(dev);
|
|
|
+ if (err && err != -ENOENT) {
|
|
|
+ mlx4_err(dev, "Failed to initialize counters table, aborting.\n");
|
|
|
+ goto err_counters_table_free;
|
|
|
+ }
|
|
|
+
|
|
|
for (port = 1; port <= dev->caps.num_ports; port++) {
|
|
|
enum mlx4_port_type port_type = 0;
|
|
|
mlx4_SENSE_PORT(dev, port, &port_type);
|
|
@@ -964,6 +1012,9 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
|
|
|
err_mcg_table_free:
|
|
|
mlx4_cleanup_mcg_table(dev);
|
|
|
|
|
|
+err_counters_table_free:
|
|
|
+ mlx4_cleanup_counters_table(dev);
|
|
|
+
|
|
|
err_qp_table_free:
|
|
|
mlx4_cleanup_qp_table(dev);
|
|
|
|
|
@@ -1294,6 +1345,7 @@ err_port:
|
|
|
for (--port; port >= 1; --port)
|
|
|
mlx4_cleanup_port_info(&priv->port[port]);
|
|
|
|
|
|
+ mlx4_cleanup_counters_table(dev);
|
|
|
mlx4_cleanup_mcg_table(dev);
|
|
|
mlx4_cleanup_qp_table(dev);
|
|
|
mlx4_cleanup_srq_table(dev);
|
|
@@ -1354,6 +1406,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
|
|
|
mlx4_CLOSE_PORT(dev, p);
|
|
|
}
|
|
|
|
|
|
+ mlx4_cleanup_counters_table(dev);
|
|
|
mlx4_cleanup_mcg_table(dev);
|
|
|
mlx4_cleanup_qp_table(dev);
|
|
|
mlx4_cleanup_srq_table(dev);
|