Fixes #3 for 4.12-rc
- 2 Fixes for OPA found by debug kernel - 1 Fix for user supplied input causing kernel problems - 1 Fix for the IPoIB fixes submitted around -rc4 -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZXVfPAAoJELgmozMOVy/dRRcP/AiN4wyEQ897se1fKXAktL1g a17tiSkK2MukAVHbM++9Ea/YXK66e2s7Ls8Pd230E85N3V48rSUhWZUIUQLOm+gS b98z53uNs6KkdBCezXABsHIi4PB6u1CfzaFaUfN5WI3ymAgsYqpQWMtNyO6GNe/R Dur3vDieXPNJ2x+F1jiNxHFBXLKofCG0y1FX88zqsQI5vVVq7ASKgaaSX3T1emQY 18l4Dd7pesrWj4QD9jaqQiYkruF5VC1NE8/he8Zzy6XjSgnUZZfjbjuMptbW4y3y Tvvd5bjMAkJhCbK1mhe1dZHPlYJhAguUBZfThjVSKtiMGwRhGA4SYkRtek3nZOga /OLhERgj0VomHx7o+Pwp74DWnsSv08EMoc4hXKHZPPyxok83r9czejqm7mC2VbGd Sa8LmVeLQp79e9MbGAj+PbNRHf9CE9dnLeFUmbj+qptXUVGvT8j9U1a9iTjTz0+2 NX/O4iWjtnt/CIkH9dhN9aWolswbmO2jSmmzb/x2EuCLv94GNtTyZLSifvxSYMnN IWO86aGQmuUkWJ3RI/5tzq+gVzI6bdKB9hG5DOPWN/uJVF9nWkq3c69Bv9djvUoM xi/rI0grxTqYHelRx3ja4ZqaI43R6YwL928XdtZJKQ/uNanq65Lyd6KKz3W7hT0l emCoqb2MjuzsNWIPkSgg =JEor -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
9871ab22f2
|
@ -1935,6 +1935,11 @@ static int modify_qp(struct ib_uverbs_file *file,
|
|||
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->cur_qp_state = cmd->base.cur_qp_state;
|
||||
attr->path_mtu = cmd->base.path_mtu;
|
||||
|
@ -2548,6 +2553,9 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
|
|||
if (copy_from_user(&cmd, buf, sizeof cmd))
|
||||
return -EFAULT;
|
||||
|
||||
if (!rdma_is_port_valid(ib_dev, cmd.attr.port_num))
|
||||
return -EINVAL;
|
||||
|
||||
INIT_UDATA(&udata, buf + sizeof(cmd),
|
||||
(unsigned long)cmd.response + sizeof(resp),
|
||||
in_len - sizeof(cmd), out_len - sizeof(resp));
|
||||
|
|
|
@ -1779,7 +1779,6 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
|
|||
ibdev->alloc_hw_stats = alloc_hw_stats;
|
||||
ibdev->get_hw_stats = get_hw_stats;
|
||||
ibdev->alloc_rdma_netdev = hfi1_vnic_alloc_rn;
|
||||
ibdev->free_rdma_netdev = hfi1_vnic_free_rn;
|
||||
|
||||
/* keep process mad in the driver */
|
||||
ibdev->process_mad = hfi1_process_mad;
|
||||
|
|
|
@ -176,7 +176,6 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
|
|||
const char *name,
|
||||
unsigned char name_assign_type,
|
||||
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,
|
||||
struct hfi1_vnic_vport_info *vinfo,
|
||||
struct sk_buff *skb, u64 pbc, u8 plen);
|
||||
|
|
|
@ -833,6 +833,15 @@ static const struct net_device_ops hfi1_netdev_ops = {
|
|||
.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,
|
||||
u8 port_num,
|
||||
enum rdma_netdev_t type,
|
||||
|
@ -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_rx_q = HFI1_NUM_VNIC_CTXT;
|
||||
vinfo->netdev = netdev;
|
||||
rn->free_rdma_netdev = hfi1_vnic_free_rn;
|
||||
rn->set_id = hfi1_vnic_set_vesw_id;
|
||||
|
||||
netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG;
|
||||
|
@ -892,12 +902,3 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
|
|||
free_netdev(netdev);
|
||||
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,
|
|||
return num_counters;
|
||||
}
|
||||
|
||||
static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
|
||||
{
|
||||
return mlx5_rdma_netdev_free(netdev);
|
||||
}
|
||||
|
||||
static struct net_device*
|
||||
mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
|
||||
u8 port_num,
|
||||
|
@ -3536,16 +3541,19 @@ mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
|
|||
unsigned char name_assign_type,
|
||||
void (*setup)(struct net_device *))
|
||||
{
|
||||
struct net_device *netdev;
|
||||
struct rdma_netdev *rn;
|
||||
|
||||
if (type != RDMA_NETDEV_IPOIB)
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
return mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
|
||||
name, setup);
|
||||
}
|
||||
|
||||
static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
|
||||
{
|
||||
return mlx5_rdma_netdev_free(netdev);
|
||||
netdev = mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
|
||||
name, setup);
|
||||
if (likely(!IS_ERR_OR_NULL(netdev))) {
|
||||
rn = netdev_priv(netdev);
|
||||
rn->free_rdma_netdev = mlx5_ib_free_rdma_netdev;
|
||||
}
|
||||
return netdev;
|
||||
}
|
||||
|
||||
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.get_port_immutable = mlx5_port_immutable;
|
||||
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.free_rdma_netdev = mlx5_ib_free_rdma_netdev;
|
||||
}
|
||||
|
||||
if (mlx5_core_is_pf(mdev)) {
|
||||
dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
|
||||
dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
|
||||
|
|
|
@ -1893,6 +1893,7 @@ static struct net_device
|
|||
rn->send = ipoib_send;
|
||||
rn->attach_mcast = ipoib_mcast_attach;
|
||||
rn->detach_mcast = ipoib_mcast_detach;
|
||||
rn->free_rdma_netdev = free_netdev;
|
||||
rn->hca = hca;
|
||||
|
||||
dev->netdev_ops = &ipoib_netdev_default_pf;
|
||||
|
@ -2288,6 +2289,8 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
|
|||
return;
|
||||
|
||||
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);
|
||||
flush_workqueue(ipoib_workqueue);
|
||||
|
||||
|
@ -2304,10 +2307,7 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
|
|||
flush_workqueue(priv->wq);
|
||||
|
||||
unregister_netdev(priv->dev);
|
||||
if (device->free_rdma_netdev)
|
||||
device->free_rdma_netdev(priv->dev);
|
||||
else
|
||||
free_netdev(priv->dev);
|
||||
rn->free_rdma_netdev(priv->dev);
|
||||
|
||||
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
|
||||
kfree(cpriv);
|
||||
|
|
|
@ -146,15 +146,15 @@ static void vnic_get_ethtool_stats(struct net_device *netdev,
|
|||
int i;
|
||||
|
||||
memset(&vstats, 0, sizeof(vstats));
|
||||
mutex_lock(&adapter->stats_lock);
|
||||
spin_lock(&adapter->stats_lock);
|
||||
adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats);
|
||||
spin_unlock(&adapter->stats_lock);
|
||||
for (i = 0; i < VNIC_STATS_LEN; i++) {
|
||||
char *p = (char *)&vstats + vnic_gstrings_stats[i].stat_offset;
|
||||
|
||||
data[i] = (vnic_gstrings_stats[i].sizeof_stat ==
|
||||
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
|
||||
}
|
||||
mutex_unlock(&adapter->stats_lock);
|
||||
}
|
||||
|
||||
/* vnic_get_strings - get strings */
|
||||
|
|
|
@ -214,7 +214,7 @@ struct opa_vnic_adapter {
|
|||
struct mutex mactbl_lock;
|
||||
|
||||
/* Lock used to protect access to vnic counters */
|
||||
struct mutex stats_lock;
|
||||
spinlock_t stats_lock;
|
||||
|
||||
u8 flow_tbl[OPA_VNIC_FLOW_TBL_SIZE];
|
||||
|
||||
|
|
|
@ -69,9 +69,9 @@ static void opa_vnic_get_stats64(struct net_device *netdev,
|
|||
struct opa_vnic_stats 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);
|
||||
mutex_unlock(&adapter->stats_lock);
|
||||
spin_unlock(&adapter->stats_lock);
|
||||
memcpy(stats, &vstats.netstats, sizeof(*stats));
|
||||
}
|
||||
|
||||
|
@ -323,13 +323,13 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
|
|||
else if (IS_ERR(netdev))
|
||||
return ERR_CAST(netdev);
|
||||
|
||||
rn = netdev_priv(netdev);
|
||||
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
|
||||
if (!adapter) {
|
||||
rc = -ENOMEM;
|
||||
goto adapter_err;
|
||||
}
|
||||
|
||||
rn = netdev_priv(netdev);
|
||||
rn->clnt_priv = adapter;
|
||||
rn->hca = ibdev;
|
||||
rn->port_num = port_num;
|
||||
|
@ -344,7 +344,7 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
|
|||
netdev->hard_header_len += OPA_VNIC_SKB_HEADROOM;
|
||||
mutex_init(&adapter->lock);
|
||||
mutex_init(&adapter->mactbl_lock);
|
||||
mutex_init(&adapter->stats_lock);
|
||||
spin_lock_init(&adapter->stats_lock);
|
||||
|
||||
SET_NETDEV_DEV(netdev, ibdev->dev.parent);
|
||||
|
||||
|
@ -364,10 +364,9 @@ struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
|
|||
netdev_err:
|
||||
mutex_destroy(&adapter->lock);
|
||||
mutex_destroy(&adapter->mactbl_lock);
|
||||
mutex_destroy(&adapter->stats_lock);
|
||||
kfree(adapter);
|
||||
adapter_err:
|
||||
ibdev->free_rdma_netdev(netdev);
|
||||
rn->free_rdma_netdev(netdev);
|
||||
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct ib_device *ibdev = adapter->ibdev;
|
||||
struct rdma_netdev *rn = netdev_priv(netdev);
|
||||
|
||||
v_info("removing\n");
|
||||
unregister_netdev(netdev);
|
||||
opa_vnic_release_mac_tbl(adapter);
|
||||
mutex_destroy(&adapter->lock);
|
||||
mutex_destroy(&adapter->mactbl_lock);
|
||||
mutex_destroy(&adapter->stats_lock);
|
||||
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,
|
|||
|
||||
send_buf = ib_create_send_mad(port->mad_agent, 1, pkey_idx, 0,
|
||||
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)) {
|
||||
c_err("%s:Couldn't allocate send buf\n", __func__);
|
||||
goto err_sndbuf;
|
||||
|
|
|
@ -89,9 +89,9 @@ void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter,
|
|||
u64 *src;
|
||||
|
||||
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);
|
||||
mutex_unlock(&adapter->stats_lock);
|
||||
spin_unlock(&adapter->stats_lock);
|
||||
|
||||
cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
|
||||
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,
|
|||
struct opa_vnic_stats 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);
|
||||
mutex_unlock(&adapter->stats_lock);
|
||||
spin_unlock(&adapter->stats_lock);
|
||||
|
||||
cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
|
||||
cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
|
||||
|
|
|
@ -1968,6 +1968,9 @@ struct rdma_netdev {
|
|||
struct ib_device *hca;
|
||||
u8 port_num;
|
||||
|
||||
/* cleanup function must be specified */
|
||||
void (*free_rdma_netdev)(struct net_device *netdev);
|
||||
|
||||
/* control functions */
|
||||
void (*set_id)(struct net_device *netdev, int id);
|
||||
/* send packet */
|
||||
|
@ -2243,7 +2246,7 @@ struct ib_device {
|
|||
struct ib_udata *udata);
|
||||
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
|
||||
* doesn't support the specified rdma netdev type.
|
||||
|
@ -2255,7 +2258,6 @@ struct ib_device {
|
|||
const char *name,
|
||||
unsigned char name_assign_type,
|
||||
void (*setup)(struct net_device *));
|
||||
void (*free_rdma_netdev)(struct net_device *netdev);
|
||||
|
||||
struct module *owner;
|
||||
struct device dev;
|
||||
|
|
Loading…
Reference in New Issue