mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
RDMA: Update the query_device() op
This op hasn't followed the normal pattern of passing NULL for udata when invoked by the kernel. Instead the kernel caller creates a dummy ib_udata on the stack and passes that in. It does not seem to currently be a bug, but this flow should be modernized to use the new API flow and in the process accept NULL as well. Only mlx4 uses an input request structure, have every other driver call ib_is_udata_in_empty() to enforce the lack of request structs. Use ib_respond_empty_udata() in every driver that does not use a response struct. Ensure a check for NULL udata before calling ib_respond_udata() in bnxt_re, efa, and mlx5. Make mlx4 safe to be called with NULL. Link: https://patch.msgid.link/r/2-v1-922fa8e828ba+f7-ib_udata_stack_jgg@nvidia.com Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
43b57d73eb
commit
bad4e98893
|
|
@ -1246,7 +1246,6 @@ static int assign_name(struct ib_device *device, const char *name)
|
|||
*/
|
||||
static int setup_device(struct ib_device *device)
|
||||
{
|
||||
struct ib_udata uhw = {.outlen = 0, .inlen = 0};
|
||||
int ret;
|
||||
|
||||
ib_device_check_mandatory(device);
|
||||
|
|
@ -1258,7 +1257,7 @@ static int setup_device(struct ib_device *device)
|
|||
}
|
||||
|
||||
memset(&device->attrs, 0, sizeof(device->attrs));
|
||||
ret = device->ops.query_device(device, &device->attrs, &uhw);
|
||||
ret = device->ops.query_device(device, &device->attrs, NULL);
|
||||
if (ret) {
|
||||
dev_warn(&device->dev,
|
||||
"Couldn't query the device attributes\n");
|
||||
|
|
|
|||
|
|
@ -265,7 +265,10 @@ int bnxt_re_query_device(struct ib_device *ibdev,
|
|||
resp.packet_pacing_caps.supported_qpts =
|
||||
1 << IB_QPT_RC;
|
||||
}
|
||||
return ib_respond_udata(udata, resp);
|
||||
|
||||
if (udata)
|
||||
return ib_respond_udata(udata, resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_re_modify_device(struct ib_device *ibdev,
|
||||
|
|
|
|||
|
|
@ -259,11 +259,13 @@ static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *pro
|
|||
{
|
||||
|
||||
struct c4iw_dev *dev;
|
||||
int err;
|
||||
|
||||
pr_debug("ibdev %p\n", ibdev);
|
||||
|
||||
if (uhw->inlen || uhw->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev = to_c4iw_dev(ibdev);
|
||||
addrconf_addr_eui48((u8 *)&props->sys_image_guid,
|
||||
|
|
@ -298,7 +300,7 @@ static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *pro
|
|||
props->max_fast_reg_page_list_len =
|
||||
t4_max_fr_depth(dev->rdev.lldi.ulptx_memwrite_dsgl && use_dsgl);
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
static int c4iw_query_port(struct ib_device *ibdev, u32 port,
|
||||
|
|
|
|||
|
|
@ -315,9 +315,14 @@ erdma_user_mmap_entry_insert(struct erdma_ucontext *uctx, void *address,
|
|||
}
|
||||
|
||||
int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
|
||||
struct ib_udata *unused)
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct erdma_dev *dev = to_edev(ibdev);
|
||||
int err;
|
||||
|
||||
err = ib_is_udata_in_empty(udata);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(attr, 0, sizeof(*attr));
|
||||
|
||||
|
|
@ -358,7 +363,7 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
|
|||
addrconf_addr_eui48((u8 *)&attr->sys_image_guid,
|
||||
dev->netdev->dev_addr);
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(udata);
|
||||
}
|
||||
|
||||
int erdma_query_gid(struct ib_device *ibdev, u32 port, int idx,
|
||||
|
|
|
|||
|
|
@ -221,6 +221,11 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
|
|||
struct ib_udata *uhw)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
|
||||
int ret;
|
||||
|
||||
ret = ib_is_udata_in_empty(uhw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(props, 0, sizeof(*props));
|
||||
|
||||
|
|
@ -274,7 +279,7 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
|
|||
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_XRC)
|
||||
props->device_cap_flags |= IB_DEVICE_XRC;
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
static int hns_roce_query_port(struct ib_device *ib_dev, u32 port_num,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ static int ionic_query_device(struct ib_device *ibdev,
|
|||
{
|
||||
struct ionic_ibdev *dev = to_ionic_ibdev(ibdev);
|
||||
struct net_device *ndev;
|
||||
int err;
|
||||
|
||||
err = ib_is_udata_in_empty(udata);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ndev = ib_device_get_netdev(ibdev, 1);
|
||||
addrconf_ifid_eui48((u8 *)&attr->sys_image_guid, ndev);
|
||||
|
|
@ -69,7 +74,7 @@ static int ionic_query_device(struct ib_device *ibdev,
|
|||
attr->max_fast_reg_page_list_len = dev->lif_cfg.npts_per_lif / 2;
|
||||
attr->max_pkeys = IONIC_PKEY_TBL_LEN;
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(udata);
|
||||
}
|
||||
|
||||
static int ionic_query_port(struct ib_device *ibdev, u32 port,
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@ static int irdma_query_device(struct ib_device *ibdev,
|
|||
struct irdma_pci_f *rf = iwdev->rf;
|
||||
struct pci_dev *pcidev = iwdev->rf->pcidev;
|
||||
struct irdma_hw_attrs *hw_attrs = &rf->sc_dev.hw_attrs;
|
||||
int err;
|
||||
|
||||
if (udata->inlen || udata->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(udata);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(props, 0, sizeof(*props));
|
||||
addrconf_addr_eui48((u8 *)&props->sys_image_guid,
|
||||
|
|
@ -74,7 +76,7 @@ static int irdma_query_device(struct ib_device *ibdev,
|
|||
if (hw_attrs->uk_attrs.hw_rev >= IRDMA_GEN_3)
|
||||
props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B;
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(udata);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -549,6 +549,11 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
|
|||
{
|
||||
struct mana_ib_dev *dev = container_of(ibdev, struct mana_ib_dev, ib_dev);
|
||||
struct pci_dev *pdev = to_pci_dev(mdev_to_gc(dev)->dev);
|
||||
int err;
|
||||
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(props, 0, sizeof(*props));
|
||||
props->vendor_id = pdev->vendor;
|
||||
|
|
@ -576,7 +581,7 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
|
|||
if (!mana_ib_is_rnic(dev))
|
||||
props->raw_packet_caps = IB_RAW_PACKET_CAP_IP_CSUM;
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
int mana_ib_query_port(struct ib_device *ibdev, u32 port,
|
||||
|
|
|
|||
|
|
@ -444,8 +444,9 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
|
|||
struct mlx4_uverbs_ex_query_device cmd;
|
||||
struct mlx4_uverbs_ex_query_device_resp resp = {};
|
||||
struct mlx4_clock_params clock_params;
|
||||
size_t uhw_outlen = uhw ? uhw->outlen : 0;
|
||||
|
||||
if (uhw->inlen) {
|
||||
if (uhw && uhw->inlen) {
|
||||
err = ib_copy_validate_udata_in_cm(uhw, cmd, reserved, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -572,7 +573,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
|
|||
props->cq_caps.max_cq_moderation_count = MLX4_MAX_CQ_COUNT;
|
||||
props->cq_caps.max_cq_moderation_period = MLX4_MAX_CQ_PERIOD;
|
||||
|
||||
if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
|
||||
if (uhw_outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
|
||||
resp.response_length += sizeof(resp.hca_core_clock_offset);
|
||||
if (!mlx4_get_internal_clock_params(dev->dev, &clock_params)) {
|
||||
resp.comp_mask |= MLX4_IB_QUERY_DEV_RESP_MASK_CORE_CLOCK_OFFSET;
|
||||
|
|
@ -580,14 +581,14 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
|
|||
}
|
||||
}
|
||||
|
||||
if (uhw->outlen >= resp.response_length +
|
||||
if (uhw_outlen >= resp.response_length +
|
||||
sizeof(resp.max_inl_recv_sz)) {
|
||||
resp.response_length += sizeof(resp.max_inl_recv_sz);
|
||||
resp.max_inl_recv_sz = dev->dev->caps.max_rq_sg *
|
||||
sizeof(struct mlx4_wqe_data_seg);
|
||||
}
|
||||
|
||||
if (offsetofend(typeof(resp), rss_caps) <= uhw->outlen) {
|
||||
if (offsetofend(typeof(resp), rss_caps) <= uhw_outlen) {
|
||||
if (props->rss_caps.supported_qpts) {
|
||||
resp.rss_caps.rx_hash_function =
|
||||
MLX4_IB_RX_HASH_FUNC_TOEPLITZ;
|
||||
|
|
@ -611,7 +612,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
|
|||
sizeof(resp.rss_caps);
|
||||
}
|
||||
|
||||
if (offsetofend(typeof(resp), tso_caps) <= uhw->outlen) {
|
||||
if (offsetofend(typeof(resp), tso_caps) <= uhw_outlen) {
|
||||
if (dev->dev->caps.max_gso_sz &&
|
||||
((mlx4_ib_port_link_layer(ibdev, 1) ==
|
||||
IB_LINK_LAYER_ETHERNET) ||
|
||||
|
|
@ -625,7 +626,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
|
|||
sizeof(resp.tso_caps);
|
||||
}
|
||||
|
||||
if (uhw->outlen) {
|
||||
if (uhw_outlen) {
|
||||
err = ib_respond_udata(uhw, resp);
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -55,16 +55,19 @@ static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *pr
|
|||
{
|
||||
struct ib_smp *in_mad;
|
||||
struct ib_smp *out_mad;
|
||||
int err = -ENOMEM;
|
||||
int err;
|
||||
struct mthca_dev *mdev = to_mdev(ibdev);
|
||||
|
||||
if (uhw->inlen || uhw->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
in_mad = kzalloc_obj(*in_mad);
|
||||
out_mad = kmalloc_obj(*out_mad);
|
||||
if (!in_mad || !out_mad)
|
||||
if (!in_mad || !out_mad) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(props, 0, sizeof *props);
|
||||
|
||||
|
|
@ -111,7 +114,7 @@ static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *pr
|
|||
props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
|
||||
props->max_mcast_grp;
|
||||
|
||||
err = 0;
|
||||
err = ib_respond_empty_udata(uhw);
|
||||
out:
|
||||
kfree(in_mad);
|
||||
kfree(out_mad);
|
||||
|
|
|
|||
|
|
@ -68,9 +68,11 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
|
|||
struct ib_udata *uhw)
|
||||
{
|
||||
struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
|
||||
int err;
|
||||
|
||||
if (uhw->inlen || uhw->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(attr, 0, sizeof *attr);
|
||||
memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
|
||||
|
|
@ -110,7 +112,7 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
|
|||
attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay;
|
||||
attr->max_fast_reg_page_list_len = dev->attr.max_pages_per_frmr;
|
||||
attr->max_pkeys = 1;
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
static inline void get_link_speed_and_width(struct ocrdma_dev *dev,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ int qedr_query_device(struct ib_device *ibdev,
|
|||
{
|
||||
struct qedr_dev *dev = get_qedr_dev(ibdev);
|
||||
struct qedr_device_attr *qattr = &dev->attr;
|
||||
int rc;
|
||||
|
||||
if (!dev->rdma_ctx) {
|
||||
DP_ERR(dev,
|
||||
|
|
@ -113,6 +114,10 @@ int qedr_query_device(struct ib_device *ibdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = ib_is_udata_in_empty(udata);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
memset(attr, 0, sizeof(*attr));
|
||||
|
||||
attr->fw_ver = qattr->fw_ver;
|
||||
|
|
@ -155,7 +160,7 @@ int qedr_query_device(struct ib_device *ibdev,
|
|||
attr->max_pkeys = qattr->max_pkey;
|
||||
attr->max_ah = qattr->max_ah;
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(udata);
|
||||
}
|
||||
|
||||
static inline void get_link_speed_and_width(int speed, u16 *ib_speed,
|
||||
|
|
|
|||
|
|
@ -275,10 +275,12 @@ int usnic_ib_query_device(struct ib_device *ibdev,
|
|||
union ib_gid gid;
|
||||
struct ethtool_drvinfo info;
|
||||
int qp_per_vf;
|
||||
int err;
|
||||
|
||||
usnic_dbg("\n");
|
||||
if (uhw->inlen || uhw->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&us_ibdev->usdev_lock);
|
||||
us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
|
||||
|
|
@ -322,7 +324,7 @@ int usnic_ib_query_device(struct ib_device *ibdev,
|
|||
* max_qp_wr, max_sge, max_sge_rd, max_cqe */
|
||||
mutex_unlock(&us_ibdev->usdev_lock);
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
int usnic_ib_query_port(struct ib_device *ibdev, u32 port,
|
||||
|
|
|
|||
|
|
@ -67,9 +67,11 @@ int pvrdma_query_device(struct ib_device *ibdev,
|
|||
struct ib_udata *uhw)
|
||||
{
|
||||
struct pvrdma_dev *dev = to_vdev(ibdev);
|
||||
int err;
|
||||
|
||||
if (uhw->inlen || uhw->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
props->fw_ver = dev->dsr->caps.fw_ver;
|
||||
props->sys_image_guid = dev->dsr->caps.sys_image_guid;
|
||||
|
|
@ -114,7 +116,7 @@ int pvrdma_query_device(struct ib_device *ibdev,
|
|||
props->device_cap_flags |= IB_DEVICE_PORT_ACTIVE_EVENT |
|
||||
IB_DEVICE_RC_RNR_NAK_GEN;
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <rdma/uverbs_ioctl.h>
|
||||
#include "vt.h"
|
||||
#include "cq.h"
|
||||
#include "trace.h"
|
||||
|
|
@ -79,14 +80,16 @@ static int rvt_query_device(struct ib_device *ibdev,
|
|||
struct ib_udata *uhw)
|
||||
{
|
||||
struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
|
||||
int err;
|
||||
|
||||
if (uhw->inlen || uhw->outlen)
|
||||
return -EINVAL;
|
||||
err = ib_is_udata_in_empty(uhw);
|
||||
if (err)
|
||||
return err;
|
||||
/*
|
||||
* Return rvt_dev_info.dparms.props contents
|
||||
*/
|
||||
*props = rdi->dparms.props;
|
||||
return 0;
|
||||
return ib_respond_empty_udata(uhw);
|
||||
}
|
||||
|
||||
static int rvt_get_numa_node(struct ib_device *ibdev)
|
||||
|
|
|
|||
|
|
@ -22,19 +22,13 @@ static int rxe_query_device(struct ib_device *ibdev,
|
|||
struct rxe_dev *rxe = to_rdev(ibdev);
|
||||
int err;
|
||||
|
||||
if (udata->inlen || udata->outlen) {
|
||||
rxe_dbg_dev(rxe, "malformed udata\n");
|
||||
err = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
err = ib_is_udata_in_empty(udata);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memcpy(attr, &rxe->attr, sizeof(*attr));
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
rxe_err_dev(rxe, "returned err = %d\n", err);
|
||||
return err;
|
||||
return ib_respond_empty_udata(udata);
|
||||
}
|
||||
|
||||
static int rxe_query_port(struct ib_device *ibdev,
|
||||
|
|
|
|||
|
|
@ -130,9 +130,11 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
|
|||
struct ib_udata *udata)
|
||||
{
|
||||
struct siw_device *sdev = to_siw_dev(base_dev);
|
||||
int rv;
|
||||
|
||||
if (udata->inlen || udata->outlen)
|
||||
return -EINVAL;
|
||||
rv = ib_is_udata_in_empty(udata);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
memset(attr, 0, sizeof(*attr));
|
||||
|
||||
|
|
@ -165,7 +167,7 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
|
|||
addrconf_addr_eui48((u8 *)&attr->sys_image_guid,
|
||||
sdev->raw_gid);
|
||||
|
||||
return 0;
|
||||
return ib_respond_empty_udata(udata);
|
||||
}
|
||||
|
||||
int siw_query_port(struct ib_device *base_dev, u32 port,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user