IB/mlx4: Add IB counters table
[linux-2.6-block.git] / drivers / infiniband / hw / mlx4 / main.c
index efecdf0216d85179c05f6e949d0c7597cf7f4f70..232b104c1d041c1983102b0f026085b55c6b307a 100644 (file)
@@ -442,6 +442,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
        }
 
+       props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
+
        props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
                0xffffff;
        props->vendor_part_id      = dev->dev->persist->pdev->device;
@@ -1247,6 +1249,22 @@ static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
        return 0;
 }
 
+static void mlx4_ib_delete_counters_table(struct mlx4_ib_dev *ibdev,
+                                         struct mlx4_ib_counters *ctr_table)
+{
+       struct counter_index *counter, *tmp_count;
+
+       mutex_lock(&ctr_table->mutex);
+       list_for_each_entry_safe(counter, tmp_count, &ctr_table->counters_list,
+                                list) {
+               if (counter->allocated)
+                       mlx4_counter_free(ibdev->dev, counter->index);
+               list_del(&counter->list);
+               kfree(counter);
+       }
+       mutex_unlock(&ctr_table->mutex);
+}
+
 int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
                   union ib_gid *gid)
 {
@@ -2131,6 +2149,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        int num_req_counters;
        int allocated;
        u32 counter_index;
+       struct counter_index *new_counter_index = NULL;
 
        pr_info_once("%s", mlx4_ib_version);
 
@@ -2302,6 +2321,11 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        if (init_node_data(ibdev))
                goto err_map;
 
+       for (i = 0; i < ibdev->num_ports; ++i) {
+               mutex_init(&ibdev->counters_table[i].mutex);
+               INIT_LIST_HEAD(&ibdev->counters_table[i].counters_list);
+       }
+
        num_req_counters = mlx4_is_bonded(dev) ? 1 : ibdev->num_ports;
        for (i = 0; i < num_req_counters; ++i) {
                mutex_init(&ibdev->qp1_proxy_lock[i]);
@@ -2320,15 +2344,34 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                        counter_index = mlx4_get_default_counter_index(dev,
                                                                       i + 1);
                }
-               ibdev->counters[i].index = counter_index;
-               ibdev->counters[i].allocated = allocated;
+               new_counter_index = kmalloc(sizeof(*new_counter_index),
+                                           GFP_KERNEL);
+               if (!new_counter_index) {
+                       if (allocated)
+                               mlx4_counter_free(ibdev->dev, counter_index);
+                       goto err_counter;
+               }
+               new_counter_index->index = counter_index;
+               new_counter_index->allocated = allocated;
+               list_add_tail(&new_counter_index->list,
+                             &ibdev->counters_table[i].counters_list);
+               ibdev->counters_table[i].default_counter = counter_index;
                pr_info("counter index %d for port %d allocated %d\n",
                        counter_index, i + 1, allocated);
        }
        if (mlx4_is_bonded(dev))
                for (i = 1; i < ibdev->num_ports ; ++i) {
-                       ibdev->counters[i].index = ibdev->counters[0].index;
-                       ibdev->counters[i].allocated = 0;
+                       new_counter_index =
+                                       kmalloc(sizeof(struct counter_index),
+                                               GFP_KERNEL);
+                       if (!new_counter_index)
+                               goto err_counter;
+                       new_counter_index->index = counter_index;
+                       new_counter_index->allocated = 0;
+                       list_add_tail(&new_counter_index->list,
+                                     &ibdev->counters_table[i].counters_list);
+                       ibdev->counters_table[i].default_counter =
+                                                               counter_index;
                }
 
        mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
@@ -2437,12 +2480,9 @@ err_steer_qp_release:
                mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
                                      ibdev->steer_qpn_count);
 err_counter:
-       for (i = 0; i < ibdev->num_ports; ++i) {
-               if (ibdev->counters[i].index != -1 &&
-                   ibdev->counters[i].allocated)
-                       mlx4_counter_free(ibdev->dev,
-                                         ibdev->counters[i].index);
-       }
+       for (i = 0; i < ibdev->num_ports; ++i)
+               mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[i]);
+
 err_map:
        iounmap(ibdev->uar_map);
 
@@ -2546,9 +2586,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 
        iounmap(ibdev->uar_map);
        for (p = 0; p < ibdev->num_ports; ++p)
-               if (ibdev->counters[p].index != -1 &&
-                   ibdev->counters[p].allocated)
-                       mlx4_counter_free(ibdev->dev, ibdev->counters[p].index);
+               mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[p]);
+
        mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
                mlx4_CLOSE_PORT(dev, p);