From 096c42657adbf3bee9e817e67fc1f6ee8f43093a Mon Sep 17 00:00:00 2001 From: Yuval Shaia Date: Sat, 31 Jan 2015 16:53:26 -0800 Subject: [PATCH] mlx4_vnic: Skip fip discover restart if pkey index not changed Driver receives MAD on any change made to partition table. This fix aim to cover the case where driver shouldn't restart net interface when receiving PKEY_CHANGE event but pkey index was not changed. Ported from UEK3 commit: 7f56a9b2252e732b0d9e2621303b0c2b781bddfc Orabug: 21446728 Signed-off-by: Yuval Shaia Reviewed-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx4_vnic/vnic.h | 7 ++++ .../mellanox/mlx4_vnic/vnic_fip_discover.c | 2 +- .../mellanox/mlx4_vnic/vnic_fip_main.c | 38 +++++++++++++++++++ .../ethernet/mellanox/mlx4_vnic/vnic_port.c | 5 ++- 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic.h b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic.h index afdb7b73c2d4..5cf0edf4ef25 100644 --- a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic.h +++ b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic.h @@ -458,6 +458,12 @@ enum { MCAST_ATTACH_RUNNING, }; +/* Flags to pass to port_fip_discover_restart */ +enum { + DISCOVER_RESTART_TEST = 0, /* If needed - restart */ + DISCOVER_RESTART_FORCE = 1 /* Force restart */ +}; + struct vnic_port_mcast { struct rb_node rb_node; struct list_head list; @@ -990,6 +996,7 @@ struct vnic_port { struct delayed_work event_task; struct delayed_work event_task_light; struct delayed_work discover_restart_task; + long discover_restart_task_data; struct ib_event_handler event_handler; struct ib_port_attr attr; union ib_gid gid; diff --git a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_discover.c b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_discover.c index 86f5cc78ce83..df9b3e9781c6 100644 --- a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_discover.c +++ b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_discover.c @@ -909,7 +909,7 @@ static int fip_free_gw_done(struct fip_discover *discover, enum fip_flush flush) } list_for_each_entry(curr_gw, &discover->gw_list, list) { - if (curr_gw->flush != FIP_NO_FLUSH) { + if (curr_gw->flush != FIP_NO_FLUSH) { up_read(&discover->l_rwsem); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_main.c b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_main.c index 07a6f2ebe54d..ac376287dec3 100644 --- a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_main.c +++ b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_fip_main.c @@ -69,14 +69,49 @@ void port_fip_discover_restart(struct work_struct *work) container_of(work, struct vnic_port, discover_restart_task.work); struct fip_discover *discover; struct vnic_login *login; + u16 new_index; + int flush_needed = list_empty(&port->login_list); vnic_dbg_mark(); mutex_lock(&port->start_stop_lock); vnic_dbg_mark(); mutex_lock(&port->mlock); + + /* If force restart - skip test */ + if (port->discover_restart_task_data == DISCOVER_RESTART_FORCE) + goto flush; + if (vnic_port_query(port)) vnic_warn(port->name, "vnic_port_query failed\n"); + vnic_dbg(port->name, "login list is%sempty\n", + list_empty(&port->login_list) ? " " : " not "); + list_for_each_entry(login, &port->login_list, list) { + vnic_dbg(port->name, + "Checking login, dev=%s: pkey=0x%x, pkey_index=0x%x\n", + login->dev->name, login->pkey, login->pkey_index); + new_index = 0; + if (login->pkey && !ib_find_pkey(port->dev->ca, + port->num, login->pkey, + &new_index)) + flush_needed = flush_needed || + (new_index != login->pkey_index); + else + flush_needed = 1; + vnic_dbg(port->name, "new_index=0x%x\n", new_index); + login->pkey_index = new_index; + } + + vnic_info("%s: Flush %sneeded\n", port->name, + flush_needed ? "" : "is not "); + + if (!flush_needed) { + mutex_unlock(&port->mlock); + goto out; + } + +flush: + vnic_dbg(port->name, "Flushing\n"); /* bring vnics links down */ list_for_each_entry(login, &port->login_list, list) vnic_mcast_del_all(&login->mcast_tree); @@ -95,6 +130,9 @@ void port_fip_discover_restart(struct work_struct *work) } } out: + /* Reset to default behavior */ + port->discover_restart_task_data = DISCOVER_RESTART_TEST; + mutex_unlock(&port->start_stop_lock); return; } diff --git a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_port.c b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_port.c index a973deb7aecd..b838ff883bce 100644 --- a/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_port.c +++ b/drivers/net/ethernet/mellanox/mlx4_vnic/vnic_port.c @@ -62,8 +62,9 @@ static void vnic_port_event(struct ib_event_handler *handler, /* calls vnic_port_event_task() */ queue_delayed_work(fip_wq, &port->event_task, msecs_to_jiffies(VNIC_SM_HEADSTART)); break; - case IB_EVENT_PKEY_CHANGE: case IB_EVENT_LID_CHANGE: + port->discover_restart_task_data = DISCOVER_RESTART_FORCE; + case IB_EVENT_PKEY_CHANGE: /* calls port_fip_discover_restart() */ if (no_bxm) queue_delayed_work(fip_wq, &port->event_task, 0); @@ -227,6 +228,8 @@ struct vnic_port *vnic_port_alloc(struct vnic_ib_dev *vnic_dev, u8 num) INIT_DELAYED_WORK(&port->event_task, vnic_port_event_task); INIT_DELAYED_WORK(&port->event_task_light, vnic_port_event_task_light); INIT_DELAYED_WORK(&port->discover_restart_task, port_fip_discover_restart); + /* Set to default behavior */ + port->discover_restart_task_data = DISCOVER_RESTART_TEST; INIT_IB_EVENT_HANDLER(&port->event_handler, vnic_dev->ca, vnic_port_event); mutex_init(&port->mlock); -- 2.50.1