/* * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE.
*/
/* * Key check traps can't be generated unless we have in_wc to * tell us where to send the trap.
*/ if ((mad_ifc_flags & MLX4_MAD_IFC_IGNORE_MKEY) || !in_wc)
op_modifier |= 0x1; if ((mad_ifc_flags & MLX4_MAD_IFC_IGNORE_BKEY) || !in_wc)
op_modifier |= 0x2; if (mlx4_is_mfunc(dev->dev) &&
(mad_ifc_flags & MLX4_MAD_IFC_NET_VIEW || in_wc))
op_modifier |= 0x8;
if (pinfo->clientrereg_resv_subnetto & 0x80)
handle_client_rereg_event(dev, port_num);
if (prev_lid != lid)
handle_lid_change_event(dev, port_num); break;
case IB_SMP_ATTR_PKEY_TABLE: if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV) return; if (!mlx4_is_mfunc(dev->dev)) {
mlx4_ib_dispatch_event(dev, port_num,
IB_EVENT_PKEY_CHANGE); break;
}
/* at this point, we are running in the master. * Slaves do not receive SMPs.
*/
bn = be32_to_cpu(((struct ib_smp *)mad)->attr_mod) & 0xFFFF;
base = (__be16 *) &(((struct ib_smp *)mad)->data[0]);
pkey_change_bitmap = 0; for (i = 0; i < 32; i++) {
pr_debug("PKEY[%d] = x%x\n",
i + bn*32, be16_to_cpu(base[i])); if (be16_to_cpu(base[i]) !=
dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32]) {
pkey_change_bitmap |= (1 << i);
dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32] =
be16_to_cpu(base[i]);
}
}
pr_debug("PKEY Change event: port=%u, " "block=0x%x, change_bitmap=0x%x\n",
port_num, bn, pkey_change_bitmap);
if (pkey_change_bitmap) {
mlx4_ib_dispatch_event(dev, port_num,
IB_EVENT_PKEY_CHANGE); if (!dev->sriov.is_going_down)
__propagate_pkey_ev(dev, port_num, bn,
pkey_change_bitmap);
} break;
case IB_SMP_ATTR_GUID_INFO: if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV) return; /* paravirtualized master's guid is guid 0 -- does not change */ if (!mlx4_is_master(dev->dev))
mlx4_ib_dispatch_event(dev, port_num,
IB_EVENT_GID_CHANGE); /*if master, notify relevant slaves*/ if (mlx4_is_master(dev->dev) &&
!dev->sriov.is_going_down) {
bn = be32_to_cpu(((struct ib_smp *)mad)->attr_mod);
mlx4_ib_update_cache_on_guid_change(dev, bn, port_num,
(u8 *)(&((struct ib_smp *)mad)->data));
mlx4_ib_notify_slaves_on_guid_change(dev, bn, port_num,
(u8 *)(&((struct ib_smp *)mad)->data));
} break;
case IB_SMP_ATTR_SL_TO_VL_TABLE: /* cache sl to vl mapping changes for use in * filling QP1 LRH VL field when sending packets
*/ if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV &&
dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SL_TO_VL_CHANGE_EVENT) return; if (!mlx4_is_slave(dev->dev)) { union sl2vl_tbl_to_u64 sl2vl64; int jj;
if (agent) {
send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
IB_MGMT_MAD_DATA, GFP_ATOMIC,
IB_MGMT_BASE_VERSION); if (IS_ERR(send_buf)) return; /* * We rely here on the fact that MLX QPs don't use the * address handle after the send is posted (this is * wrong following the IB spec strictly, but we know * it's OK for our devices).
*/
spin_lock_irqsave(&dev->sm_lock, flags);
memcpy(send_buf->mad, mad, sizeof *mad); if ((send_buf->ah = dev->sm_ah[port_num - 1]))
ret = ib_post_send_mad(send_buf, NULL); else
ret = -EINVAL;
spin_unlock_irqrestore(&dev->sm_lock, flags);
if (ret)
ib_free_send_mad(send_buf);
}
}
staticint mlx4_ib_demux_sa_handler(struct ib_device *ibdev, int port, int slave, struct ib_sa_mad *sa_mad)
{ int ret = 0;
/* dispatch to different sa handlers */ switch (be16_to_cpu(sa_mad->mad_hdr.attr_id)) { case IB_SA_ATTR_MC_MEMBER_REC:
ret = mlx4_ib_mcg_demux_handler(ibdev, port, slave, sa_mad); break; default: break;
} return ret;
}
int mlx4_ib_find_real_gid(struct ib_device *ibdev, u32 port, __be64 guid)
{ struct mlx4_ib_dev *dev = to_mdev(ibdev); int i;
for (i = 0; i < dev->dev->caps.sqp_demux; i++) { if (dev->sriov.demux[port - 1].guid_cache[i] == guid) return i;
} return -1;
}
staticint find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave,
u32 port, u16 pkey, u16 *ix)
{ int i, ret;
u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF;
u16 slot_pkey;
if (slave == mlx4_master_func_num(dev->dev)) return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix);
staticint get_gids_from_l3_hdr(struct ib_grh *grh, union ib_gid *sgid, union ib_gid *dgid)
{ int version = ib_get_rdma_header_version((constunion rdma_network_hdr *)grh); enum rdma_network_type net_type;
/* check if proxy qp created */ if (!tun_ctx || tun_ctx->state != DEMUX_PV_STATE_ACTIVE) return -EAGAIN;
if (!dest_qpt)
tun_qp = &tun_ctx->qp[0]; else
tun_qp = &tun_ctx->qp[1];
/* compute P_Key index to put in tunnel header for slave */ if (dest_qpt) {
u16 pkey_ix;
ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey); if (ret) {
pr_debug("unable to get %s cached pkey for index %d, ret %d\n",
is_proxy_qp0(dev, wc->src_qp, slave) ? "SMI" : "GSI",
wc->pkey_index, ret); return -EINVAL;
}
ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix); if (ret) {
pr_debug("unable to get %s pkey ix for pkey 0x%x, ret %d\n",
is_proxy_qp0(dev, wc->src_qp, slave) ? "SMI" : "GSI",
cached_pkey, ret); return -EINVAL;
}
tun_pkey_ix = pkey_ix;
} else
tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
/* get tunnel tx data buf for slave */
src_qp = tun_qp->qp;
/* create ah. Just need an empty one with the port num for the post send.
* The driver will set the force loopback bit in post_send */
memset(&attr, 0, sizeof attr);
attr.type = rdma_ah_find_type(&dev->ib_dev, port);
rdma_ah_set_port_num(&attr, port); if (is_eth) { union ib_gid sgid; union ib_gid dgid;
if (is_eth) {
u16 vlan = 0; if (mlx4_get_slave_default_vlan(dev->dev, port, slave, &vlan,
NULL)) { /* VST mode */ if (vlan != wc->vlan_id) /* Packet vlan is not the VST-assigned vlan. * Drop the packet.
*/ goto out; else /* Remove the vlan tag before forwarding * the packet to the VF.
*/
vlan = 0xffff;
} else {
vlan = wc->vlan_id;
}
/* Initially assume that this mad is for us */
slave = mlx4_master_func_num(dev->dev);
/* See if the slave id is encoded in a response mad */ if (mad->mad_hdr.method & 0x80) {
slave_id = (u8 *) &mad->mad_hdr.tid;
slave = *slave_id; if (slave != 255) /*255 indicates the dom0*/
*slave_id = 0; /* remap tid */
}
/* If a grh is present, we demux according to it */ if (wc->wc_flags & IB_WC_GRH) { if (grh->dgid.global.interface_id ==
cpu_to_be64(IB_SA_WELL_KNOWN_GUID) &&
grh->dgid.global.subnet_prefix == cpu_to_be64(
atomic64_read(&dev->sriov.demux[port - 1].subnet_prefix))) {
slave = 0;
} else {
slave = mlx4_ib_find_real_gid(ibdev, port,
grh->dgid.global.interface_id); if (slave < 0) {
mlx4_ib_warn(ibdev, "failed matching grh\n"); return -ENOENT;
}
}
} /* Class-specific handling */ switch (mad->mad_hdr.mgmt_class) { case IB_MGMT_CLASS_SUBN_LID_ROUTED: case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: /* 255 indicates the dom0 */ if (slave != 255 && slave != mlx4_master_func_num(dev->dev)) { if (!mlx4_vf_smi_enabled(dev->dev, slave, port)) return -EPERM; /* for a VF. drop unsolicited MADs */ if (!(mad->mad_hdr.method & IB_MGMT_METHOD_RESP)) {
mlx4_ib_warn(ibdev, "demux QP0. rejecting unsolicited mad for slave %d class 0x%x, method 0x%x\n",
slave, mad->mad_hdr.mgmt_class,
mad->mad_hdr.method); return -EINVAL;
}
} break; case IB_MGMT_CLASS_SUBN_ADM: if (mlx4_ib_demux_sa_handler(ibdev, port, slave,
(struct ib_sa_mad *) mad)) return 0; break; case IB_MGMT_CLASS_CM: if (mlx4_ib_demux_cm_handler(ibdev, port, &slave, mad)) return 0; break; case IB_MGMT_CLASS_DEVICE_MGMT: if (mad->mad_hdr.method != IB_MGMT_METHOD_GET_RESP) return 0; break; default: /* Drop unsupported classes for slaves in tunnel mode */ if (slave != mlx4_master_func_num(dev->dev)) {
pr_debug("dropping unsupported ingress mad from class:%d " "for slave:%d\n", mad->mad_hdr.mgmt_class, slave); return 0;
}
} /*make sure that no slave==255 was not handled yet.*/ if (slave >= dev->dev->caps.sqp_demux) {
mlx4_ib_warn(ibdev, "slave id: %d is bigger than allowed:%d\n",
slave, dev->dev->caps.sqp_demux); return -ENOENT;
}
if (!out_mad->mad_hdr.status) {
smp_snoop(ibdev, port_num, in_mad, prev_lid); /* slaves get node desc from FW */ if (!mlx4_is_slave(to_mdev(ibdev)->dev))
node_desc_override(ibdev, out_mad);
}
/* set return bit in status of directed route responses */ if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
out_mad->mad_hdr.status |= cpu_to_be16(1 << 15);
if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) /* no response for trap repress */ return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
/* iboe_process_mad() which uses the HCA flow-counters to implement IB PMA * queries, should be called only by VFs and for that specific purpose
*/ if (link == IB_LINK_LAYER_INFINIBAND) { if (mlx4_is_slave(dev->dev) &&
(in->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT &&
(in->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS ||
in->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT ||
in->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO))) return iboe_process_mad(ibdev, mad_flags, port_num,
in_wc, in_grh, in, out);
return ib_process_mad(ibdev, mad_flags, port_num, in_wc, in_grh,
in, out);
}
if (link == IB_LINK_LAYER_ETHERNET) return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
in_grh, in, out);
/* Update the sl to vl table from inside client rereg * only if in secure-host mode (snooping is not possible) * and the sl-to-vl change event is not generated by FW.
*/ if (!mlx4_is_slave(dev->dev) &&
dev->dev->flags & MLX4_FLAG_SECURE_HOST &&
!(dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SL_TO_VL_CHANGE_EVENT)) { if (mlx4_is_master(dev->dev)) /* already in work queue from mlx4_ib_event queueing * mlx4_handle_port_mgmt_change_event, which calls * this procedure. Therefore, call sl2vl_update directly.
*/
mlx4_ib_sl2vl_update(dev, port_num); else
mlx4_sched_ib_sl2vl_update_work(dev, port_num);
}
mlx4_ib_dispatch_event(dev, port_num, IB_EVENT_CLIENT_REREGISTER);
}
switch (eqe->subtype) { case MLX4_DEV_PMC_SUBTYPE_PORT_INFO:
changed_attr = be32_to_cpu(eqe->event.port_mgmt_change.params.port_info.changed_attr);
/* Update the SM ah - This should be done before handling
the other changed attributes so that MADs can be sent to the SM */ if (changed_attr & MSTR_SM_CHANGE_MASK) {
u16 lid = be16_to_cpu(eqe->event.port_mgmt_change.params.port_info.mstr_sm_lid);
u8 sl = eqe->event.port_mgmt_change.params.port_info.mstr_sm_sl & 0xf;
update_sm_ah(dev, port, lid, sl);
}
/* Check if it is a lid change event */ if (changed_attr & MLX4_EQ_PORT_INFO_LID_CHANGE_MASK)
handle_lid_change_event(dev, port);
/* Generate GUID changed event */ if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) { if (mlx4_is_master(dev->dev)) { union ib_gid gid; int err = 0;
if (!eqe->event.port_mgmt_change.params.port_info.gid_prefix)
err = __mlx4_ib_query_gid(&dev->ib_dev, port, 0, &gid, 1); else
gid.global.subnet_prefix =
eqe->event.port_mgmt_change.params.port_info.gid_prefix; if (err) {
pr_warn("Could not change QP1 subnet prefix for port %d: query_gid error (%d)\n",
port, err);
} else {
pr_debug("Changing QP1 subnet prefix for port %d. old=0x%llx. new=0x%llx\n",
port,
(u64)atomic64_read(&dev->sriov.demux[port - 1].subnet_prefix),
be64_to_cpu(gid.global.subnet_prefix));
atomic64_set(&dev->sriov.demux[port - 1].subnet_prefix,
be64_to_cpu(gid.global.subnet_prefix));
}
}
mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); /*if master, notify all slaves*/ if (mlx4_is_master(dev->dev))
mlx4_gen_slaves_port_mgt_ev(dev->dev, port,
MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK);
}
if (changed_attr & MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK)
handle_client_rereg_event(dev, port); break;
case MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE:
mlx4_ib_dispatch_event(dev, port, IB_EVENT_PKEY_CHANGE); if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down)
propagate_pkey_ev(dev, port, eqe); break; case MLX4_DEV_PMC_SUBTYPE_GUID_INFO: /* paravirtualized master's guid is guid 0 -- does not change */ if (!mlx4_is_master(dev->dev))
mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); /*if master, notify relevant slaves*/ elseif (!dev->sriov.is_going_down) {
tbl_block = GET_BLK_PTR_FROM_EQE(eqe);
change_bitmap = GET_MASK_FROM_EQE(eqe);
handle_slaves_guid_change(dev, port, tbl_block, change_bitmap);
} break;
case MLX4_DEV_PMC_SUBTYPE_SL_TO_VL_MAP: /* cache sl to vl mapping changes for use in * filling QP1 LRH VL field when sending packets
*/ if (!mlx4_is_slave(dev->dev)) { union sl2vl_tbl_to_u64 sl2vl64; int jj;
staticint mlx4_ib_multiplex_sa_handler(struct ib_device *ibdev, int port, int slave, struct ib_sa_mad *sa_mad)
{ int ret = 0;
/* dispatch to different sa handlers */ switch (be16_to_cpu(sa_mad->mad_hdr.attr_id)) { case IB_SA_ATTR_MC_MEMBER_REC:
ret = mlx4_ib_mcg_multiplex_handler(ibdev, port, slave, sa_mad); break; default: break;
} return ret;
}
/* Get slave that sent this packet */ if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
wc->src_qp >= dev->dev->phys_caps.base_proxy_sqpn + 8 * MLX4_MFUNC_MAX ||
(wc->src_qp & 0x1) != ctx->port - 1 ||
wc->src_qp & 0x4) {
mlx4_ib_warn(ctx->ib_dev, "can't multiplex bad sqp:%d\n", wc->src_qp); return;
}
slave = ((wc->src_qp & ~0x7) - dev->dev->phys_caps.base_proxy_sqpn) / 8; if (slave != ctx->slave) {
mlx4_ib_warn(ctx->ib_dev, "can't multiplex bad sqp:%d: " "belongs to another slave\n", wc->src_qp); return;
}
/* Map transaction ID */
ib_dma_sync_single_for_cpu(ctx->ib_dev, tun_qp->ring[wr_ix].map, sizeof (struct mlx4_tunnel_mad),
DMA_FROM_DEVICE); switch (tunnel->mad.mad_hdr.method) { case IB_MGMT_METHOD_SET: case IB_MGMT_METHOD_GET: case IB_MGMT_METHOD_REPORT: case IB_SA_METHOD_GET_TABLE: case IB_SA_METHOD_DELETE: case IB_SA_METHOD_GET_MULTI: case IB_SA_METHOD_GET_TRACE_TBL:
slave_id = (u8 *) &tunnel->mad.mad_hdr.tid; if (*slave_id) {
mlx4_ib_warn(ctx->ib_dev, "egress mad has non-null tid msb:%d " "class:%d slave:%d\n", *slave_id,
tunnel->mad.mad_hdr.mgmt_class, slave); return;
} else
*slave_id = slave; break; default: /* nothing */;
}
/* Class-specific handling */ switch (tunnel->mad.mad_hdr.mgmt_class) { case IB_MGMT_CLASS_SUBN_LID_ROUTED: case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: if (slave != mlx4_master_func_num(dev->dev) &&
!mlx4_vf_smi_enabled(dev->dev, slave, ctx->port)) return; break; case IB_MGMT_CLASS_SUBN_ADM: if (mlx4_ib_multiplex_sa_handler(ctx->ib_dev, ctx->port, slave,
(struct ib_sa_mad *) &tunnel->mad)) return; break; case IB_MGMT_CLASS_CM: if (mlx4_ib_multiplex_cm_handler(ctx->ib_dev, ctx->port, slave,
(struct ib_mad *) &tunnel->mad)) return; break; case IB_MGMT_CLASS_DEVICE_MGMT: if (tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_GET &&
tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_SET) return; break; default: /* Drop unsupported classes for slaves in tunnel mode */ if (slave != mlx4_master_func_num(dev->dev)) {
mlx4_ib_warn(ctx->ib_dev, "dropping unsupported egress mad from class:%d " "for slave:%d\n", tunnel->mad.mad_hdr.mgmt_class, slave); return;
}
}
/* We are using standard ib_core services to send the mad, so generate a
* stadard address handle by decoding the tunnelled mlx4_ah fields */
memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av));
ah.ibah.device = ctx->ib_dev;
port = be32_to_cpu(ah.av.ib.port_pd) >> 24;
port = mlx4_slave_convert_port(dev->dev, slave, port); if (port < 0) return;
ah.av.ib.port_pd = cpu_to_be32(port << 24 | (be32_to_cpu(ah.av.ib.port_pd) & 0xffffff));
ah.ibah.type = rdma_ah_find_type(&dev->ib_dev, port);
mlx4_ib_query_ah(&ah.ibah, &ah_attr); if (rdma_ah_get_ah_flags(&ah_attr) & IB_AH_GRH)
fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);
dmac = rdma_ah_retrieve_dmac(&ah_attr); if (dmac)
memcpy(dmac, tunnel->hdr.mac, ETH_ALEN);
vlan_id = be16_to_cpu(tunnel->hdr.vlan); /* if slave have default vlan use it */ if (mlx4_get_slave_default_vlan(dev->dev, ctx->port, slave,
&vlan_id, &qos))
rdma_ah_set_sl(&ah_attr, qos);
staticvoid free_pv_object(struct mlx4_ib_dev *dev, int slave, int port)
{ if (dev->sriov.demux[port - 1].tun[slave]) {
kfree(dev->sriov.demux[port - 1].tun[slave]);
dev->sriov.demux[port - 1].tun[slave] = NULL;
}
}
staticint create_pv_resources(struct ib_device *ibdev, int slave, int port, int create_tun, struct mlx4_ib_demux_pv_ctx *ctx)
{ int ret, cq_size; struct ib_cq_init_attr cq_attr = {}; constint nmbr_bufs = create_tun ? MLX4_NUM_TUNNEL_BUFS : MLX4_NUM_WIRE_BUFS;
if (ctx->state != DEMUX_PV_STATE_DOWN) return -EEXIST;
ctx->state = DEMUX_PV_STATE_STARTING; /* have QP0 only if link layer is IB */ if (rdma_port_get_link_layer(ibdev, ctx->port) ==
IB_LINK_LAYER_INFINIBAND)
ctx->has_smi = 1;
if (ctx->has_smi) {
ret = mlx4_ib_alloc_pv_bufs(ctx, IB_QPT_SMI, create_tun); if (ret) {
pr_err("Failed allocating qp0 tunnel bufs (%d)\n", ret); goto err_out;
}
}
ret = mlx4_ib_alloc_pv_bufs(ctx, IB_QPT_GSI, create_tun); if (ret) {
pr_err("Failed allocating qp1 tunnel bufs (%d)\n", ret); goto err_out_qp0;
}
cq_size = 2 * nmbr_bufs; if (ctx->has_smi)
cq_size *= 2;
for (i = 0;
i < min(dev->dev->caps.sqp_demux,
(u16)(dev->dev->persist->num_vfs + 1));
i++) { struct mlx4_active_ports actv_ports =
mlx4_get_active_ports(dev->dev, i);
if (!test_bit(port - 1, actv_ports.ports)) continue;
ret = alloc_pv_object(dev, i, port, &ctx->tun[i]); if (ret) {
ret = -ENOMEM; goto err_mcg;
}
}
ret = mlx4_ib_mcg_port_init(ctx); if (ret) {
pr_err("Failed initializing mcg para-virt (%d)\n", ret); goto err_mcg;
}
ctx->wq = alloc_ordered_workqueue("mlx4_ibt%d", WQ_MEM_RECLAIM, port); if (!ctx->wq) {
pr_err("Failed to create tunnelling WQ for port %d\n", port);
ret = -ENOMEM; goto err_wq;
}
ctx->wi_wq = alloc_ordered_workqueue("mlx4_ibwi%d", WQ_MEM_RECLAIM, port); if (!ctx->wi_wq) {
pr_err("Failed to create wire WQ for port %d\n", port);
ret = -ENOMEM; goto err_wiwq;
}
ctx->ud_wq = alloc_ordered_workqueue("mlx4_ibud%d", WQ_MEM_RECLAIM, port); if (!ctx->ud_wq) {
pr_err("Failed to create up/down WQ for port %d\n", port);
ret = -ENOMEM; goto err_udwq;
}
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.