aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2012-08-03 04:40:54 -0400
committerRoland Dreier <roland@purestorage.com>2012-09-30 23:33:41 -0400
commit992e8e6e8781b71fd475bd1fd0555da7dba59966 (patch)
tree1b84b49303a9f4eff3644b90cf20848bca7beabc
parent980e90010f15362b3b02ed4875ef2758aee3de72 (diff)
IB/mlx4: Miscellaneous adjustments for SR-IOV IB support
1. Allow only master to change node description. 2. Prevent AH leakage in send mads. 3. Take device part number from PCI structure, so that guests see the VF part number (and not the PF part number). 4. Place the device revision ID into caps structure at startup. 5. SET_PORT in update_gids_task needs to go through wrapper on master. 6. In mlx4_ib_event(), PORT_MGMT_EVENT needs be handled in a work queue on the master, since it propagates events to slaves using GEN_EQE. 7. Do not support FMR on slaves. 8. Add spinlock to slave_event(), since it is called both in interrupt context and in process context (due to 6 above, and also if smp_snoop is used). This fix was found and implemented by Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c6
-rw-r--r--drivers/infiniband/hw/mlx4/main.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h1
5 files changed, 31 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index b689dbd6d8f6..b91b4865d635 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -709,7 +709,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
709 if (!out_mad->mad_hdr.status) { 709 if (!out_mad->mad_hdr.status) {
710 if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV)) 710 if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV))
711 smp_snoop(ibdev, port_num, in_mad, prev_lid); 711 smp_snoop(ibdev, port_num, in_mad, prev_lid);
712 node_desc_override(ibdev, out_mad); 712 /* slaves get node desc from FW */
713 if (!mlx4_is_slave(to_mdev(ibdev)->dev))
714 node_desc_override(ibdev, out_mad);
713 } 715 }
714 716
715 /* set return bit in status of directed route responses */ 717 /* set return bit in status of directed route responses */
@@ -792,6 +794,8 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
792static void send_handler(struct ib_mad_agent *agent, 794static void send_handler(struct ib_mad_agent *agent,
793 struct ib_mad_send_wc *mad_send_wc) 795 struct ib_mad_send_wc *mad_send_wc)
794{ 796{
797 if (mad_send_wc->send_buf->context[0])
798 ib_destroy_ah(mad_send_wc->send_buf->context[0]);
795 ib_free_send_mad(mad_send_wc->send_buf); 799 ib_free_send_mad(mad_send_wc->send_buf);
796} 800}
797 801
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 7d97578fbbaa..46303b209ce6 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -138,7 +138,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
138 138
139 props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & 139 props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
140 0xffffff; 140 0xffffff;
141 props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); 141 props->vendor_part_id = dev->dev->pdev->device;
142 props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); 142 props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32));
143 memcpy(&props->sys_image_guid, out_mad->data + 4, 8); 143 memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
144 144
@@ -478,6 +478,9 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
478 if (!(mask & IB_DEVICE_MODIFY_NODE_DESC)) 478 if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
479 return 0; 479 return 0;
480 480
481 if (mlx4_is_slave(to_mdev(ibdev)->dev))
482 return -EOPNOTSUPP;
483
481 spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags); 484 spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags);
482 memcpy(ibdev->node_desc, props->node_desc, 64); 485 memcpy(ibdev->node_desc, props->node_desc, 64);
483 spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags); 486 spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags);
@@ -493,7 +496,7 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
493 memset(mailbox->buf, 0, 256); 496 memset(mailbox->buf, 0, 256);
494 memcpy(mailbox->buf, props->node_desc, 64); 497 memcpy(mailbox->buf, props->node_desc, 64);
495 mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0, 498 mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0,
496 MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 499 MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
497 500
498 mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox); 501 mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox);
499 502
@@ -921,6 +924,7 @@ static int init_node_data(struct mlx4_ib_dev *dev)
921 if (err) 924 if (err)
922 goto out; 925 goto out;
923 926
927 dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
924 memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); 928 memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
925 929
926out: 930out:
@@ -1009,7 +1013,7 @@ static void update_gids_task(struct work_struct *work)
1009 1013
1010 err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port, 1014 err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
1011 1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 1015 1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
1012 MLX4_CMD_NATIVE); 1016 MLX4_CMD_WRAPPED);
1013 if (err) 1017 if (err)
1014 pr_warn("set port command failed\n"); 1018 pr_warn("set port command failed\n");
1015 else { 1019 else {
@@ -1400,10 +1404,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
1400 ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; 1404 ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
1401 ibdev->ib_dev.process_mad = mlx4_ib_process_mad; 1405 ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
1402 1406
1403 ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc; 1407 if (!mlx4_is_slave(ibdev->dev)) {
1404 ibdev->ib_dev.map_phys_fmr = mlx4_ib_map_phys_fmr; 1408 ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc;
1405 ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr; 1409 ibdev->ib_dev.map_phys_fmr = mlx4_ib_map_phys_fmr;
1406 ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc; 1410 ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr;
1411 ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc;
1412 }
1407 1413
1408 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) { 1414 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
1409 ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd; 1415 ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
@@ -1615,7 +1621,11 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
1615 INIT_WORK(&ew->work, handle_port_mgmt_change_event); 1621 INIT_WORK(&ew->work, handle_port_mgmt_change_event);
1616 memcpy(&ew->ib_eqe, eqe, sizeof *eqe); 1622 memcpy(&ew->ib_eqe, eqe, sizeof *eqe);
1617 ew->ib_dev = ibdev; 1623 ew->ib_dev = ibdev;
1618 handle_port_mgmt_change_event(&ew->work); 1624 /* need to queue only for port owner, which uses GEN_EQE */
1625 if (mlx4_is_master(dev))
1626 queue_work(wq, &ew->work);
1627 else
1628 handle_port_mgmt_change_event(&ew->work);
1619 return; 1629 return;
1620 1630
1621 case MLX4_DEV_EVENT_SLAVE_INIT: 1631 case MLX4_DEV_EVENT_SLAVE_INIT:
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index ea5c884ab899..78fdbd653fa9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1757,6 +1757,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
1757 INIT_WORK(&priv->mfunc.master.slave_flr_event_work, 1757 INIT_WORK(&priv->mfunc.master.slave_flr_event_work,
1758 mlx4_master_handle_slave_flr); 1758 mlx4_master_handle_slave_flr);
1759 spin_lock_init(&priv->mfunc.master.slave_state_lock); 1759 spin_lock_init(&priv->mfunc.master.slave_state_lock);
1760 spin_lock_init(&priv->mfunc.master.slave_eq.event_lock);
1760 priv->mfunc.master.comm_wq = 1761 priv->mfunc.master.comm_wq =
1761 create_singlethread_workqueue("mlx4_comm"); 1762 create_singlethread_workqueue("mlx4_comm");
1762 if (!priv->mfunc.master.comm_wq) 1763 if (!priv->mfunc.master.comm_wq)
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index c425826b1fc0..51c764901ad2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -164,13 +164,16 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
164{ 164{
165 struct mlx4_priv *priv = mlx4_priv(dev); 165 struct mlx4_priv *priv = mlx4_priv(dev);
166 struct mlx4_slave_event_eq *slave_eq = &priv->mfunc.master.slave_eq; 166 struct mlx4_slave_event_eq *slave_eq = &priv->mfunc.master.slave_eq;
167 struct mlx4_eqe *s_eqe = 167 struct mlx4_eqe *s_eqe;
168 &slave_eq->event_eqe[slave_eq->prod & (SLAVE_EVENT_EQ_SIZE - 1)]; 168 unsigned long flags;
169 169
170 spin_lock_irqsave(&slave_eq->event_lock, flags);
171 s_eqe = &slave_eq->event_eqe[slave_eq->prod & (SLAVE_EVENT_EQ_SIZE - 1)];
170 if ((!!(s_eqe->owner & 0x80)) ^ 172 if ((!!(s_eqe->owner & 0x80)) ^
171 (!!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE))) { 173 (!!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE))) {
172 mlx4_warn(dev, "Master failed to generate an EQE for slave: %d. " 174 mlx4_warn(dev, "Master failed to generate an EQE for slave: %d. "
173 "No free EQE on slave events queue\n", slave); 175 "No free EQE on slave events queue\n", slave);
176 spin_unlock_irqrestore(&slave_eq->event_lock, flags);
174 return; 177 return;
175 } 178 }
176 179
@@ -183,6 +186,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
183 186
184 queue_work(priv->mfunc.master.comm_wq, 187 queue_work(priv->mfunc.master.comm_wq,
185 &priv->mfunc.master.slave_event_work); 188 &priv->mfunc.master.slave_event_work);
189 spin_unlock_irqrestore(&slave_eq->event_lock, flags);
186} 190}
187 191
188static void mlx4_slave_event(struct mlx4_dev *dev, int slave, 192static void mlx4_slave_event(struct mlx4_dev *dev, int slave,
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 23f74759f403..399793a23457 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -473,6 +473,7 @@ struct mlx4_slave_event_eq {
473 u32 eqn; 473 u32 eqn;
474 u32 cons; 474 u32 cons;
475 u32 prod; 475 u32 prod;
476 spinlock_t event_lock;
476 struct mlx4_eqe event_eqe[SLAVE_EVENT_EQ_SIZE]; 477 struct mlx4_eqe event_eqe[SLAVE_EVENT_EQ_SIZE];
477}; 478};
478 479