/** * rvt_alloc_device - allocate rdi * @size: how big of a structure to allocate * @nports: number of ports to allocate array slots for * * Use IB core device alloc to allocate space for the rdi which is assumed to be * inside of the ib_device. Any extra space that drivers require should be * included in size. * * We also allocate a port array based on the number of ports. * * Return: pointer to allocated rdi
*/ struct rvt_dev_info *rvt_alloc_device(size_t size, int nports)
{ struct rvt_dev_info *rdi;
staticint rvt_modify_device(struct ib_device *device, int device_modify_mask, struct ib_device_modify *device_modify)
{ /* * There is currently no need to supply this based on qib and hfi1. * Future drivers may need to implement this though.
*/
return -EOPNOTSUPP;
}
/** * rvt_query_port - Passes the query port call to the driver * @ibdev: Verbs IB dev * @port_num: port number, 1 based from ib core * @props: structure to hold returned properties * * Return: 0 on success
*/ staticint rvt_query_port(struct ib_device *ibdev, u32 port_num, struct ib_port_attr *props)
{ struct rvt_dev_info *rdi = ib_to_rvt(ibdev); struct rvt_ibport *rvp;
u32 port_index = ibport_num_to_idx(ibdev, port_num);
rvp = rdi->ports[port_index]; /* props being zeroed by the caller, avoid zeroing it here */
props->sm_lid = rvp->sm_lid;
props->sm_sl = rvp->sm_sl;
props->port_cap_flags = rvp->port_cap_flags;
props->max_msg_sz = 0x80000000;
props->pkey_tbl_len = rvt_get_npkeys(rdi);
props->bad_pkey_cntr = rvp->pkey_violations;
props->qkey_viol_cntr = rvp->qkey_violations;
props->subnet_timeout = rvp->subnet_timeout;
props->init_type_reply = 0;
/* Populate the remaining ib_port_attr elements */ return rdi->driver_f.query_port_state(rdi, port_num, props);
}
/** * rvt_modify_port - modify port * @ibdev: Verbs IB dev * @port_num: Port number, 1 based from ib core * @port_modify_mask: How to change the port * @props: Structure to fill in * * Return: 0 on success
*/ staticint rvt_modify_port(struct ib_device *ibdev, u32 port_num, int port_modify_mask, struct ib_port_modify *props)
{ struct rvt_dev_info *rdi = ib_to_rvt(ibdev); struct rvt_ibport *rvp; int ret = 0;
u32 port_index = ibport_num_to_idx(ibdev, port_num);
if (props->set_port_cap_mask || props->clr_port_cap_mask)
rdi->driver_f.cap_mask_chg(rdi, port_num); if (port_modify_mask & IB_PORT_SHUTDOWN)
ret = rdi->driver_f.shut_down_port(rdi, port_num); if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR)
rvp->qkey_violations = 0;
return ret;
}
/** * rvt_query_pkey - Return a pkey from the table at a given index * @ibdev: Verbs IB dev * @port_num: Port number, 1 based from ib core * @index: Index into pkey table * @pkey: returned pkey from the port pkey table * * Return: 0 on failure pkey otherwise
*/ staticint rvt_query_pkey(struct ib_device *ibdev, u32 port_num, u16 index,
u16 *pkey)
{ /* * Driver will be responsible for keeping rvt_dev_info.pkey_table up to * date. This function will just return that value. There is no need to * lock, if a stale value is read and sent to the user so be it there is * no way to protect against that anyway.
*/ struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
u32 port_index;
/** * rvt_query_gid - Return a gid from the table * @ibdev: Verbs IB dev * @port_num: Port number, 1 based from ib core * @guid_index: Index in table * @gid: Gid to return * * Return: 0 on success
*/ staticint rvt_query_gid(struct ib_device *ibdev, u32 port_num, int guid_index, union ib_gid *gid)
{ struct rvt_dev_info *rdi; struct rvt_ibport *rvp;
u32 port_index;
/* * Driver is responsible for updating the guid table. Which will be used * to craft the return value. This will work similar to how query_pkey() * is being done.
*/
port_index = ibport_num_to_idx(ibdev, port_num);
static noinline int check_support(struct rvt_dev_info *rdi, int verb)
{ switch (verb) { case MISC: /* * These functions are not part of verbs specifically but are * required for rdmavt to function.
*/ if ((!rdi->ibdev.ops.port_groups) ||
(!rdi->driver_f.get_pci_dev)) return -EINVAL; break;
case MODIFY_DEVICE: /* * rdmavt does not support modify device currently drivers must * provide.
*/ if (!rdi->ibdev.ops.modify_device) return -EOPNOTSUPP; break;
case QUERY_PORT: if (!rdi->ibdev.ops.query_port) if (!rdi->driver_f.query_port_state) return -EINVAL; break;
case MODIFY_PORT: if (!rdi->ibdev.ops.modify_port) if (!rdi->driver_f.cap_mask_chg ||
!rdi->driver_f.shut_down_port) return -EINVAL; break;
case QUERY_GID: if (!rdi->ibdev.ops.query_gid) if (!rdi->driver_f.get_guid_be) return -EINVAL; break;
case CREATE_QP: if (!rdi->ibdev.ops.create_qp) if (!rdi->driver_f.qp_priv_alloc ||
!rdi->driver_f.qp_priv_free ||
!rdi->driver_f.notify_qp_reset ||
!rdi->driver_f.flush_qp_waiters ||
!rdi->driver_f.stop_send_queue ||
!rdi->driver_f.quiesce_qp) return -EINVAL; break;
case MODIFY_QP: if (!rdi->ibdev.ops.modify_qp) if (!rdi->driver_f.notify_qp_reset ||
!rdi->driver_f.schedule_send ||
!rdi->driver_f.get_pmtu_from_attr ||
!rdi->driver_f.flush_qp_waiters ||
!rdi->driver_f.stop_send_queue ||
!rdi->driver_f.quiesce_qp ||
!rdi->driver_f.notify_error_qp ||
!rdi->driver_f.mtu_from_qp ||
!rdi->driver_f.mtu_to_path_mtu) return -EINVAL; break;
case DESTROY_QP: if (!rdi->ibdev.ops.destroy_qp) if (!rdi->driver_f.qp_priv_free ||
!rdi->driver_f.notify_qp_reset ||
!rdi->driver_f.flush_qp_waiters ||
!rdi->driver_f.stop_send_queue ||
!rdi->driver_f.quiesce_qp) return -EINVAL; break;
case POST_SEND: if (!rdi->ibdev.ops.post_send) if (!rdi->driver_f.schedule_send ||
!rdi->driver_f.do_send ||
!rdi->post_parms) return -EINVAL; break;
}
return 0;
}
/** * rvt_register_device - register a driver * @rdi: main dev structure for all of rdmavt operations * * It is up to drivers to allocate the rdi and fill in the appropriate * information. * * Return: 0 on success otherwise an errno.
*/ int rvt_register_device(struct rvt_dev_info *rdi)
{ int ret = 0, i;
if (!rdi) return -EINVAL;
/* * Check to ensure drivers have setup the required helpers for the verbs * they want rdmavt to handle
*/ for (i = 0; i < _VERB_IDX_MAX; i++) if (check_support(rdi, i)) {
pr_err("Driver support req not met at %d\n", i); return -EINVAL;
}
ib_set_device_ops(&rdi->ibdev, &rvt_dev_ops);
/* Once we get past here we can use rvt_pr macros and tracepoints */
trace_rvt_dbg(rdi, "Driver attempting registration");
rvt_mmap_init(rdi);
/* Queue Pairs */
ret = rvt_driver_qp_init(rdi); if (ret) {
pr_err("Error in driver QP init.\n"); return -EINVAL;
}
/* * There are some things which could be set by underlying drivers but * really should be up to rdmavt to set. For instance drivers can't know * exactly which functions rdmavt supports, nor do they know the ABI * version, so we do all of this sort of stuff here.
*/
rdi->ibdev.uverbs_cmd_mask |=
(1ull << IB_USER_VERBS_CMD_POLL_CQ) |
(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
(1ull << IB_USER_VERBS_CMD_POST_SEND) |
(1ull << IB_USER_VERBS_CMD_POST_RECV) |
(1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
rdi->ibdev.node_type = RDMA_NODE_IB_CA; if (!rdi->ibdev.num_comp_vectors)
rdi->ibdev.num_comp_vectors = 1;
/* We are now good to announce we exist */
ret = ib_register_device(&rdi->ibdev, dev_name(&rdi->ibdev.dev), NULL); if (ret) {
rvt_pr_err(rdi, "Failed to register driver with ib core.\n"); goto bail_wss;
}
rvt_create_mad_agents(rdi);
rvt_pr_info(rdi, "Registration with rdmavt done.\n"); return ret;
/** * rvt_init_port - init internal data for driver port * @rdi: rvt_dev_info struct * @port: rvt port * @port_index: 0 based index of ports, different from IB core port num * @pkey_table: pkey_table for @port * * Keep track of a list of ports. No need to have a detach port. * They persist until the driver goes away. * * Return: always 0
*/ int rvt_init_port(struct rvt_dev_info *rdi, struct rvt_ibport *port, int port_index, u16 *pkey_table)
{
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.