Commit 9871ab22 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma

Pull rdma update from Doug Ledford:
 "This includes two bugs against the newly added opa vnic that were
  found by turning on the debug kernel options:

   - sleeping while holding a lock, so a one line fix where they
     switched it from GFP_KERNEL allocation to a GFP_ATOMIC allocation

   - a case where they had an isolated caller of their code that could
     call them in an atomic context so they had to switch their use of a
     mutex to a spinlock to be safe, so this was considerably more lines
     of diff because all uses of that lock had to be switched

  In addition, the bug that was discussed with you already about an out
  of bounds array access in ib_uverbs_modify_qp and ib_uverbs_create_ah
  and is only seven lines of diff.

  And finally, one fix to an earlier fix in the -rc cycle that broke
  hfi1 and qib in regards to IPoIB (this one is, unfortunately, larger
  than I would like for a -rc7 submission, but fixing the problem
  required that we not treat all devices as though they had allocated a
  netdev universally because it isn't true, and it took 70 lines of diff
  to resolve the issue, but the final patch has been vetted by Intel and
  Mellanox and they've both given their approval to the fix).

  Summary:

   - Two fixes for OPA found by debug kernel
   - Fix for user supplied input causing kernel problems
   - Fix for the IPoIB fixes submitted around -rc4"

[ Doug sent this having not noticed the 4.12 release, so I guess I'll be
  getting another rdma pull request with the actuakl merge window
  updates and not just fixes.

  Oh well - it would have been nice if this small update had been the
  merge window one.     - Linus ]

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma:
  IB/core, opa_vnic, hfi1, mlx5: Properly free rdma_netdev
  RDMA/uverbs: Check port number supplied by user verbs cmds
  IB/opa_vnic: Use spinlock instead of mutex for stats_lock
  IB/opa_vnic: Use GFP_ATOMIC while sending trap
parents ac7b7596 8e959601
...@@ -1935,6 +1935,11 @@ static int modify_qp(struct ib_uverbs_file *file, ...@@ -1935,6 +1935,11 @@ static int modify_qp(struct ib_uverbs_file *file,
goto out; goto out;
} }
if (!rdma_is_port_valid(qp->device, cmd->base.port_num)) {
ret = -EINVAL;
goto release_qp;
}
attr->qp_state = cmd->base.qp_state; attr->qp_state = cmd->base.qp_state;
attr->cur_qp_state = cmd->base.cur_qp_state; attr->cur_qp_state = cmd->base.cur_qp_state;
attr->path_mtu = cmd->base.path_mtu; attr->path_mtu = cmd->base.path_mtu;
...@@ -2548,6 +2553,9 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, ...@@ -2548,6 +2553,9 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd)) if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT; return -EFAULT;
if (!rdma_is_port_valid(ib_dev, cmd.attr.port_num))
return -EINVAL;
INIT_UDATA(&udata, buf + sizeof(cmd), INIT_UDATA(&udata, buf + sizeof(cmd),
(unsigned long)cmd.response + sizeof(resp), (unsigned long)cmd.response + sizeof(resp),
in_len - sizeof(cmd), out_len - sizeof(resp)); in_len - sizeof(cmd), out_len - sizeof(resp));
......
...@@ -1779,7 +1779,6 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd) ...@@ -1779,7 +1779,6 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
ibdev->alloc_hw_stats = alloc_hw_stats; ibdev->alloc_hw_stats = alloc_hw_stats;
ibdev->get_hw_stats = get_hw_stats; ibdev->get_hw_stats = get_hw_stats;
ibdev->alloc_rdma_netdev = hfi1_vnic_alloc_rn; ibdev->alloc_rdma_netdev = hfi1_vnic_alloc_rn;
ibdev->free_rdma_netdev = hfi1_vnic_free_rn;
/* keep process mad in the driver */ /* keep process mad in the driver */
ibdev->process_mad = hfi1_process_mad; ibdev->process_mad = hfi1_process_mad;
......
...@@ -176,7 +176,6 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, ...@@ -176,7 +176,6 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
const char *name, const char *name,
unsigned char name_assign_type, unsigned char name_assign_type,
void (*setup)(struct net_device *)); void (*setup)(struct net_device *));
void hfi1_vnic_free_rn(struct net_device *netdev);
int hfi1_vnic_send_dma(struct hfi1_devdata *dd, u8 q_idx, int hfi1_vnic_send_dma(struct hfi1_devdata *dd, u8 q_idx,
struct hfi1_vnic_vport_info *vinfo, struct hfi1_vnic_vport_info *vinfo,
struct sk_buff *skb, u64 pbc, u8 plen); struct sk_buff *skb, u64 pbc, u8 plen);
......
...@@ -833,6 +833,15 @@ static const struct net_device_ops hfi1_netdev_ops = { ...@@ -833,6 +833,15 @@ static const struct net_device_ops hfi1_netdev_ops = {
.ndo_get_stats64 = hfi1_vnic_get_stats64, .ndo_get_stats64 = hfi1_vnic_get_stats64,
}; };
static void hfi1_vnic_free_rn(struct net_device *netdev)
{
struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev);
hfi1_vnic_deinit(vinfo);
mutex_destroy(&vinfo->lock);
free_netdev(netdev);
}
struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
u8 port_num, u8 port_num,
enum rdma_netdev_t type, enum rdma_netdev_t type,
...@@ -864,6 +873,7 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, ...@@ -864,6 +873,7 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
vinfo->num_tx_q = dd->chip_sdma_engines; vinfo->num_tx_q = dd->chip_sdma_engines;
vinfo->num_rx_q = HFI1_NUM_VNIC_CTXT; vinfo->num_rx_q = HFI1_NUM_VNIC_CTXT;
vinfo->netdev = netdev; vinfo->netdev = netdev;
rn->free_rdma_netdev = hfi1_vnic_free_rn;
rn->set_id = hfi1_vnic_set_vesw_id; rn->set_id = hfi1_vnic_set_vesw_id;
netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG; netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG;
...@@ -892,12 +902,3 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device, ...@@ -892,12 +902,3 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
free_netdev(netdev); free_netdev(netdev);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
void hfi1_vnic_free_rn(struct net_device *netdev)
{
struct hfi1_vnic_vport_info *vinfo = opa_vnic_dev_priv(netdev);
hfi1_vnic_deinit(vinfo);
mutex_destroy(&vinfo->lock);
free_netdev(netdev);
}
...@@ -3528,6 +3528,11 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, ...@@ -3528,6 +3528,11 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
return num_counters; return num_counters;
} }
static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
{
return mlx5_rdma_netdev_free(netdev);
}
static struct net_device* static struct net_device*
mlx5_ib_alloc_rdma_netdev(struct ib_device *hca, mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
u8 port_num, u8 port_num,
...@@ -3536,16 +3541,19 @@ mlx5_ib_alloc_rdma_netdev(struct ib_device *hca, ...@@ -3536,16 +3541,19 @@ mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
unsigned char name_assign_type, unsigned char name_assign_type,
void (*setup)(struct net_device *)) void (*setup)(struct net_device *))
{ {
struct net_device *netdev;
struct rdma_netdev *rn;
if (type != RDMA_NETDEV_IPOIB) if (type != RDMA_NETDEV_IPOIB)
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
return mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca, netdev = mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
name, setup); name, setup);
} if (likely(!IS_ERR_OR_NULL(netdev))) {
rn = netdev_priv(netdev);
static void mlx5_ib_free_rdma_netdev(struct net_device *netdev) rn->free_rdma_netdev = mlx5_ib_free_rdma_netdev;
{ }
return mlx5_rdma_netdev_free(netdev); return netdev;
} }
static void *mlx5_ib_add(struct mlx5_core_dev *mdev) static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
...@@ -3678,10 +3686,9 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) ...@@ -3678,10 +3686,9 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status; dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
dev->ib_dev.get_port_immutable = mlx5_port_immutable; dev->ib_dev.get_port_immutable = mlx5_port_immutable;
dev->ib_dev.get_dev_fw_str = get_dev_fw_str; dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) { if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads))
dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev; dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev;
dev->ib_dev.free_rdma_netdev = mlx5_ib_free_rdma_netdev;
}
if (mlx5_core_is_pf(mdev)) { if (mlx5_core_is_pf(mdev)) {
dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config; dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state; dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
......
...@@ -1893,6 +1893,7 @@ static struct net_device ...@@ -1893,6 +1893,7 @@ static struct net_device
rn->send = ipoib_send; rn->send = ipoib_send;
rn->attach_mcast = ipoib_mcast_attach; rn->attach_mcast = ipoib_mcast_attach;
rn->detach_mcast = ipoib_mcast_detach; rn->detach_mcast = ipoib_mcast_detach;
rn->free_rdma_netdev = free_netdev;
rn->hca = hca; rn->hca = hca;
dev->netdev_ops = &ipoib_netdev_default_pf; dev->netdev_ops = &ipoib_netdev_default_pf;
...@@ -2288,6 +2289,8 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data) ...@@ -2288,6 +2289,8 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
return; return;
list_for_each_entry_safe(priv, tmp, dev_list, list) { list_for_each_entry_safe(priv, tmp, dev_list, list) {
struct rdma_netdev *rn = netdev_priv(priv->dev);
ib_unregister_event_handler(&priv->event_handler); ib_unregister_event_handler(&priv->event_handler);
flush_workqueue(ipoib_workqueue); flush_workqueue(ipoib_workqueue);
...@@ -2304,10 +2307,7 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data) ...@@ -2304,10 +2307,7 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
flush_workqueue(priv->wq); flush_workqueue(priv->wq);
unregister_netdev(priv->dev); unregister_netdev(priv->dev);
if (device->free_rdma_netdev) rn->free_rdma_netdev(priv->dev);
device->free_rdma_netdev(priv->dev);
else
free_netdev(priv->dev);
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
kfree(cpriv); kfree(cpriv);
......
...@@ -146,15 +146,15 @@ static void vnic_get_ethtool_stats(struct net_device *netdev, ...@@ -146,15 +146,15 @@ static void vnic_get_ethtool_stats(struct net_device *netdev,
int i; int i;
memset(&vstats, 0, sizeof(vstats)); memset(&vstats, 0, sizeof(vstats));
mutex_lock(&adapter->stats_lock); spin_lock(&adapter->stats_lock);
adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats); adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats);
spin_unlock(&adapter->stats_lock);
for (i = 0; i < VNIC_STATS_LEN; i++) { for (i = 0; i < VNIC_STATS_LEN; i++) {
char *p = (char *)&vstats + vnic_gstrings_stats[i].stat_offset; char *p = (char *)&vstats + vnic_gstrings_stats[i].stat_offset;
data[i] = (vnic_gstrings_stats[i].sizeof_stat == data[i] = (vnic_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p; sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
} }
mutex_unlock(&adapter->stats_lock);
} }
/* vnic_get_strings - get strings */ /* vnic_get_strings - get strings */
......
...@@ -214,7 +214,7 @@ struct opa_vnic_adapter { ...@@ -214,7 +214,7 @@ struct opa_vnic_adapter {
struct mutex mactbl_lock; struct mutex mactbl_lock;
/* Lock used to protect access to vnic counters */ /* Lock used to protect access to vnic counters */
struct mutex stats_lock; spinlock_t stats_lock;
u8 flow_tbl[OPA_VNIC_FLOW_TBL_SIZE]; u8 flow_tbl[OPA_VNIC_FLOW_TBL_SIZE];
......
...@@ -69,9 +69,9 @@ static void opa_vnic_get_stats64(struct net_device *netdev, ...@@ -69,9 +69,9 @@ static void opa_vnic_get_stats64(struct net_device *netdev,
struct opa_vnic_stats vstats; struct opa_vnic_stats vstats;
memset(&vstats, 0, sizeof(vstats)); memset(&vstats, 0, sizeof(vstats));
mutex_lock(&adapter->stats_lock); spin_lock(&adapter->stats_lock);
adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats); adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats);
mutex_unlock(&adapter->stats_lock); spin_unlock(&adapter->stats_lock);
memcpy(stats, &vstats.netstats, sizeof(*stats)); memcpy(stats, &vstats.netstats, sizeof(*stats));
} }
...@@ -323,13 +323,13 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev, ...@@ -323,13 +323,13 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
else if (IS_ERR(netdev)) else if (IS_ERR(netdev))
return ERR_CAST(netdev); return ERR_CAST(netdev);
rn = netdev_priv(netdev);
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
if (!adapter) { if (!adapter) {
rc = -ENOMEM; rc = -ENOMEM;
goto adapter_err; goto adapter_err;
} }
rn = netdev_priv(netdev);
rn->clnt_priv = adapter; rn->clnt_priv = adapter;
rn->hca = ibdev; rn->hca = ibdev;
rn->port_num = port_num; rn->port_num = port_num;
...@@ -344,7 +344,7 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev, ...@@ -344,7 +344,7 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
netdev->hard_header_len += OPA_VNIC_SKB_HEADROOM; netdev->hard_header_len += OPA_VNIC_SKB_HEADROOM;
mutex_init(&adapter->lock); mutex_init(&adapter->lock);
mutex_init(&adapter->mactbl_lock); mutex_init(&adapter->mactbl_lock);
mutex_init(&adapter->stats_lock); spin_lock_init(&adapter->stats_lock);
SET_NETDEV_DEV(netdev, ibdev->dev.parent); SET_NETDEV_DEV(netdev, ibdev->dev.parent);
...@@ -364,10 +364,9 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev, ...@@ -364,10 +364,9 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
netdev_err: netdev_err:
mutex_destroy(&adapter->lock); mutex_destroy(&adapter->lock);
mutex_destroy(&adapter->mactbl_lock); mutex_destroy(&adapter->mactbl_lock);
mutex_destroy(&adapter->stats_lock);
kfree(adapter); kfree(adapter);
adapter_err: adapter_err:
ibdev->free_rdma_netdev(netdev); rn->free_rdma_netdev(netdev);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
...@@ -376,14 +375,13 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev, ...@@ -376,14 +375,13 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
void opa_vnic_rem_netdev(struct opa_vnic_adapter *adapter) void opa_vnic_rem_netdev(struct opa_vnic_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct ib_device *ibdev = adapter->ibdev; struct rdma_netdev *rn = netdev_priv(netdev);
v_info("removing\n"); v_info("removing\n");
unregister_netdev(netdev); unregister_netdev(netdev);
opa_vnic_release_mac_tbl(adapter); opa_vnic_release_mac_tbl(adapter);
mutex_destroy(&adapter->lock); mutex_destroy(&adapter->lock);
mutex_destroy(&adapter->mactbl_lock); mutex_destroy(&adapter->mactbl_lock);
mutex_destroy(&adapter->stats_lock);
kfree(adapter); kfree(adapter);
ibdev->free_rdma_netdev(netdev); rn->free_rdma_netdev(netdev);
} }
...@@ -794,7 +794,7 @@ void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter, ...@@ -794,7 +794,7 @@ void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
send_buf = ib_create_send_mad(port->mad_agent, 1, pkey_idx, 0, send_buf = ib_create_send_mad(port->mad_agent, 1, pkey_idx, 0,
IB_MGMT_VENDOR_HDR, IB_MGMT_MAD_DATA, IB_MGMT_VENDOR_HDR, IB_MGMT_MAD_DATA,
GFP_KERNEL, OPA_MGMT_BASE_VERSION); GFP_ATOMIC, OPA_MGMT_BASE_VERSION);
if (IS_ERR(send_buf)) { if (IS_ERR(send_buf)) {
c_err("%s:Couldn't allocate send buf\n", __func__); c_err("%s:Couldn't allocate send buf\n", __func__);
goto err_sndbuf; goto err_sndbuf;
......
...@@ -89,9 +89,9 @@ void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter, ...@@ -89,9 +89,9 @@ void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter,
u64 *src; u64 *src;
memset(&vstats, 0, sizeof(vstats)); memset(&vstats, 0, sizeof(vstats));
mutex_lock(&adapter->stats_lock); spin_lock(&adapter->stats_lock);
adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats); adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats);
mutex_unlock(&adapter->stats_lock); spin_unlock(&adapter->stats_lock);
cntrs->vp_instance = cpu_to_be16(adapter->vport_num); cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id); cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
...@@ -128,9 +128,9 @@ void opa_vnic_get_error_counters(struct opa_vnic_adapter *adapter, ...@@ -128,9 +128,9 @@ void opa_vnic_get_error_counters(struct opa_vnic_adapter *adapter,
struct opa_vnic_stats vstats; struct opa_vnic_stats vstats;
memset(&vstats, 0, sizeof(vstats)); memset(&vstats, 0, sizeof(vstats));
mutex_lock(&adapter->stats_lock); spin_lock(&adapter->stats_lock);
adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats); adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats);
mutex_unlock(&adapter->stats_lock); spin_unlock(&adapter->stats_lock);
cntrs->vp_instance = cpu_to_be16(adapter->vport_num); cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id); cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
......
...@@ -1968,6 +1968,9 @@ struct rdma_netdev { ...@@ -1968,6 +1968,9 @@ struct rdma_netdev {
struct ib_device *hca; struct ib_device *hca;
u8 port_num; u8 port_num;
/* cleanup function must be specified */
void (*free_rdma_netdev)(struct net_device *netdev);
/* control functions */ /* control functions */
void (*set_id)(struct net_device *netdev, int id); void (*set_id)(struct net_device *netdev, int id);
/* send packet */ /* send packet */
...@@ -2243,7 +2246,7 @@ struct ib_device { ...@@ -2243,7 +2246,7 @@ struct ib_device {
struct ib_udata *udata); struct ib_udata *udata);
int (*destroy_rwq_ind_table)(struct ib_rwq_ind_table *wq_ind_table); int (*destroy_rwq_ind_table)(struct ib_rwq_ind_table *wq_ind_table);
/** /**
* rdma netdev operations * rdma netdev operation
* *
* Driver implementing alloc_rdma_netdev must return -EOPNOTSUPP if it * Driver implementing alloc_rdma_netdev must return -EOPNOTSUPP if it
* doesn't support the specified rdma netdev type. * doesn't support the specified rdma netdev type.
...@@ -2255,7 +2258,6 @@ struct ib_device { ...@@ -2255,7 +2258,6 @@ struct ib_device {
const char *name, const char *name,
unsigned char name_assign_type, unsigned char name_assign_type,
void (*setup)(struct net_device *)); void (*setup)(struct net_device *));
void (*free_rdma_netdev)(struct net_device *netdev);
struct module *owner; struct module *owner;
struct device dev; struct device dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment