mlx4: Use port management change event instead of smp_snoop
[cascardo/linux.git] / drivers / infiniband / hw / mlx4 / main.c
index ee1c577..4f230c2 100644 (file)
@@ -50,7 +50,7 @@
 #include "mlx4_ib.h"
 #include "user.h"
 
-#define DRV_NAME       "mlx4_ib"
+#define DRV_NAME       MLX4_IB_DRV_NAME
 #define DRV_VERSION    "1.0"
 #define DRV_RELDATE    "April 4, 2008"
 
@@ -140,7 +140,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->max_mr_size         = ~0ull;
        props->page_size_cap       = dev->dev->caps.page_size_cap;
        props->max_qp              = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps;
-       props->max_qp_wr           = dev->dev->caps.max_wqes;
+       props->max_qp_wr           = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE;
        props->max_sge             = min(dev->dev->caps.max_sq_sg,
                                         dev->dev->caps.max_rq_sg);
        props->max_cq              = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs;
@@ -898,7 +898,6 @@ static void update_gids_task(struct work_struct *work)
        union ib_gid *gids;
        int err;
        struct mlx4_dev *dev = gw->dev->dev;
-       struct ib_event event;
 
        mailbox = mlx4_alloc_cmd_mailbox(dev);
        if (IS_ERR(mailbox)) {
@@ -916,10 +915,7 @@ static void update_gids_task(struct work_struct *work)
                pr_warn("set port command failed\n");
        else {
                memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
-               event.device = &gw->dev->ib_dev;
-               event.element.port_num = gw->port;
-               event.event    = IB_EVENT_GID_CHANGE;
-               ib_dispatch_event(&event);
+               mlx4_ib_dispatch_event(gw->dev, gw->port, IB_EVENT_GID_CHANGE);
        }
 
        mlx4_free_cmd_mailbox(dev, mailbox);
@@ -1084,12 +1080,9 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
        int total_eqs = 0;
        int i, j, eq;
 
-       /* Init eq table */
-       ibdev->eq_table = NULL;
-       ibdev->eq_added = 0;
-
-       /* Legacy mode? */
-       if (dev->caps.comp_pool == 0)
+       /* Legacy mode or comp_pool is not large enough */
+       if (dev->caps.comp_pool == 0 ||
+           dev->caps.num_ports > dev->caps.comp_pool)
                return;
 
        eq_per_port = rounddown_pow_of_two(dev->caps.comp_pool/
@@ -1135,7 +1128,10 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
 static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
 {
        int i;
-       int total_eqs;
+
+       /* no additional eqs were added */
+       if (!ibdev->eq_table)
+               return;
 
        /* Reset the advertised EQ number */
        ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors;
@@ -1148,12 +1144,7 @@ static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
                mlx4_release_eq(dev, ibdev->eq_table[i]);
        }
 
-       total_eqs = dev->caps.num_comp_vectors + ibdev->eq_added;
-       memset(ibdev->eq_table, 0, total_eqs * sizeof(int));
        kfree(ibdev->eq_table);
-
-       ibdev->eq_table = NULL;
-       ibdev->eq_added = 0;
 }
 
 static void *mlx4_ib_add(struct mlx4_dev *dev)
@@ -1388,10 +1379,18 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 }
 
 static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
-                         enum mlx4_dev_event event, int port)
+                         enum mlx4_dev_event event, unsigned long param)
 {
        struct ib_event ibev;
        struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr);
+       struct mlx4_eqe *eqe = NULL;
+       struct ib_event_work *ew;
+       int port = 0;
+
+       if (event == MLX4_DEV_EVENT_PORT_MGMT_CHANGE)
+               eqe = (struct mlx4_eqe *)param;
+       else
+               port = (u8)param;
 
        if (port > ibdev->num_ports)
                return;
@@ -1410,6 +1409,19 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
                ibev.event = IB_EVENT_DEVICE_FATAL;
                break;
 
+       case MLX4_DEV_EVENT_PORT_MGMT_CHANGE:
+               ew = kmalloc(sizeof *ew, GFP_ATOMIC);
+               if (!ew) {
+                       pr_err("failed to allocate memory for events work\n");
+                       break;
+               }
+
+               INIT_WORK(&ew->work, handle_port_mgmt_change_event);
+               memcpy(&ew->ib_eqe, eqe, sizeof *eqe);
+               ew->ib_dev = ibdev;
+               handle_port_mgmt_change_event(&ew->work);
+               return;
+
        default:
                return;
        }