int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn, int npsvs, u32 *sig_index) { struct mlx5_allocate_psv_in in; struct mlx5_allocate_psv_out out; int i, err; if (npsvs > MLX5_MAX_PSVS) return -EINVAL; memset(&in, 0, sizeof(in)); memset(&out, 0, sizeof(out)); in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_PSV); in.npsv_pd = cpu_to_be32((npsvs << 28) | pdn); err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); if (err) { mlx5_core_err(dev, "cmd exec failed %d\n", err); return err; } if (out.hdr.status) { mlx5_core_err(dev, "create_psv bad status %d\n", out.hdr.status); return mlx5_cmd_status_to_err(&out.hdr); } for (i = 0; i < npsvs; i++) sig_index[i] = be32_to_cpu(out.psv_idx[i]) & 0xffffff; return err; }
int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num) { struct mlx5_destroy_psv_in in; struct mlx5_destroy_psv_out out; int err; memset(&in, 0, sizeof(in)); memset(&out, 0, sizeof(out)); in.psv_number = cpu_to_be32(psv_num); in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_PSV); err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); if (err) { mlx5_core_err(dev, "destroy_psv cmd exec failed %d\n", err); goto out; } if (out.hdr.status) { mlx5_core_err(dev, "destroy_psv bad status %d\n", out.hdr.status); err = mlx5_cmd_status_to_err(&out.hdr); goto out; } out: return err; }
void mlx5_enter_error_state(struct mlx5_core_dev *dev) { if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) return; mlx5_core_err(dev, "start\n"); if (pci_channel_offline(dev->pdev) || in_fatal(dev)) dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; mlx5_core_event(dev, MLX5_DEV_EVENT_SYS_ERROR, 0); mlx5_core_err(dev, "end\n"); }
int mlx5i_create_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp) { u32 *in = NULL; void *addr_path; int ret = 0; int inlen; void *qpc; inlen = MLX5_ST_SZ_BYTES(create_qp_in); in = kvzalloc(inlen, GFP_KERNEL); if (!in) return -ENOMEM; qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD); MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, MLX5_QP_ENHANCED_ULP_STATELESS_MODE); addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path); MLX5_SET(ads, addr_path, vhca_port_num, 1); MLX5_SET(ads, addr_path, grh, 1); ret = mlx5_core_create_qp(mdev, qp, in, inlen); if (ret) { mlx5_core_err(mdev, "Failed creating IPoIB QP err : %d\n", ret); goto out; } out: kvfree(in); return ret; }
int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, int promisc_uc, int promisc_mc, int promisc_all) { void *in; int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); int err; in = mlx5_vzalloc(inlen); if (!in) { mlx5_core_err(mdev, "failed to allocate inbox\n"); return -ENOMEM; } MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1); MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.promisc_uc, promisc_uc); MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.promisc_mc, promisc_mc); MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.promisc_all, promisc_all); err = mlx5_modify_nic_vport_context(mdev, in, inlen); kvfree(in); return err; }
void mlx5_modify_lag(struct mlx5_lag *ldev, struct lag_tracker *tracker) { struct mlx5_core_dev *dev0 = ldev->pf[0].dev; u8 v2p_port1, v2p_port2; int err; mlx5_infer_tx_affinity_mapping(tracker, &v2p_port1, &v2p_port2); if (v2p_port1 != ldev->v2p_map[0] || v2p_port2 != ldev->v2p_map[1]) { ldev->v2p_map[0] = v2p_port1; ldev->v2p_map[1] = v2p_port2; mlx5_core_info(dev0, "modify lag map port 1:%d port 2:%d", ldev->v2p_map[0], ldev->v2p_map[1]); err = mlx5_cmd_modify_lag(dev0, v2p_port1, v2p_port2); if (err) mlx5_core_err(dev0, "Failed to modify LAG (%d)\n", err); } }
int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev) { u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0}; u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0}; int force_state; int ret; if (!MLX5_CAP_GEN(dev, force_teardown)) { mlx5_core_dbg(dev, "force teardown is not supported in the firmware\n"); return -EOPNOTSUPP; } MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA); MLX5_SET(teardown_hca_in, in, profile, MLX5_TEARDOWN_HCA_IN_PROFILE_FORCE_CLOSE); ret = mlx5_cmd_exec_polling(dev, in, sizeof(in), out, sizeof(out)); if (ret) return ret; force_state = MLX5_GET(teardown_hca_out, out, force_state); if (force_state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) { mlx5_core_err(dev, "teardown with force mode failed\n"); return -EIO; } return 0; }
int mlx5i_init_underlay_qp(struct mlx5e_priv *priv) { struct mlx5_core_dev *mdev = priv->mdev; struct mlx5i_priv *ipriv = priv->ppriv; struct mlx5_core_qp *qp = &ipriv->qp; struct mlx5_qp_context *context; int ret; /* QP states */ context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) return -ENOMEM; context->flags = cpu_to_be32(MLX5_QP_PM_MIGRATED << 11); context->pri_path.port = 1; context->pri_path.pkey_index = cpu_to_be16(ipriv->pkey_index); context->qkey = cpu_to_be32(IB_DEFAULT_Q_KEY); ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RST2INIT_QP, 0, context, qp); if (ret) { mlx5_core_err(mdev, "Failed to modify qp RST2INIT, err: %d\n", ret); goto err_qp_modify_to_err; } memset(context, 0, sizeof(*context)); ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_INIT2RTR_QP, 0, context, qp); if (ret) { mlx5_core_err(mdev, "Failed to modify qp INIT2RTR, err: %d\n", ret); goto err_qp_modify_to_err; } ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RTR2RTS_QP, 0, context, qp); if (ret) { mlx5_core_err(mdev, "Failed to modify qp RTR2RTS, err: %d\n", ret); goto err_qp_modify_to_err; } kfree(context); return 0; err_qp_modify_to_err: mlx5_core_qp_modify(mdev, MLX5_CMD_OP_2ERR_QP, 0, &context, qp); kfree(context); return ret; }
void mlx5_enter_error_state(struct mlx5_core_dev *dev) { mutex_lock(&dev->intf_state_mutex); if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) goto unlock; mlx5_core_err(dev, "start\n"); if (pci_channel_offline(dev->pdev) || in_fatal(dev)) { dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; trigger_cmd_completions(dev); } mlx5_core_event(dev, MLX5_DEV_EVENT_SYS_ERROR, 0); mlx5_core_err(dev, "end\n"); unlock: mutex_unlock(&dev->intf_state_mutex); }
void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force) { mutex_lock(&dev->intf_state_mutex); if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) goto unlock; mlx5_core_err(dev, "start\n"); if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) { dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; mlx5_cmd_flush(dev); } mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1); mlx5_core_err(dev, "end\n"); unlock: mutex_unlock(&dev->intf_state_mutex); }
void mlx5i_uninit_underlay_qp(struct mlx5e_priv *priv) { struct mlx5i_priv *ipriv = priv->ppriv; struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_qp_context context; int err; err = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_2RST_QP, 0, &context, &ipriv->qp); if (err) mlx5_core_err(mdev, "Failed to modify qp 2RST, err: %d\n", err); }
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, u16 offset, u16 size, u8 *data) { u32 out[MLX5_ST_SZ_DW(mcia_reg)]; u32 in[MLX5_ST_SZ_DW(mcia_reg)]; int module_num; u16 i2c_addr; int status; int err; void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); err = mlx5_query_module_num(dev, &module_num); if (err) return err; memset(in, 0, sizeof(in)); size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); if (offset < MLX5_EEPROM_PAGE_LENGTH && offset + size > MLX5_EEPROM_PAGE_LENGTH) /* Cross pages read, read until offset 256 in low page */ size -= offset + size - MLX5_EEPROM_PAGE_LENGTH; i2c_addr = MLX5_I2C_ADDR_LOW; if (offset >= MLX5_EEPROM_PAGE_LENGTH) { i2c_addr = MLX5_I2C_ADDR_HIGH; offset -= MLX5_EEPROM_PAGE_LENGTH; } MLX5_SET(mcia_reg, in, l, 0); MLX5_SET(mcia_reg, in, module, module_num); MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); MLX5_SET(mcia_reg, in, page_number, 0); MLX5_SET(mcia_reg, in, device_address, offset); MLX5_SET(mcia_reg, in, size, size); err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MCIA, 0, 0); if (err) return err; status = MLX5_GET(mcia_reg, out, status); if (status) { mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", status); return -EIO; } memcpy(data, ptr, size); return size; }
static int mlx5_deactivate_lag(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[0].dev; bool roce_lag = __mlx5_lag_is_roce(ldev); int err; ldev->flags &= ~MLX5_LAG_MODE_FLAGS; err = mlx5_cmd_destroy_lag(dev0); if (err) { if (roce_lag) { mlx5_core_err(dev0, "Failed to deactivate RoCE LAG; driver restart required\n"); } else { mlx5_core_err(dev0, "Failed to deactivate VF LAG; driver restart required\n" "Make sure all VFs are unbound prior to VF LAG activation or deactivation\n"); } } return err; }
int mlx5_activate_lag(struct mlx5_lag *ldev, struct lag_tracker *tracker, u8 flags) { bool roce_lag = !!(flags & MLX5_LAG_FLAG_ROCE); struct mlx5_core_dev *dev0 = ldev->pf[0].dev; int err; err = mlx5_create_lag(ldev, tracker); if (err) { if (roce_lag) { mlx5_core_err(dev0, "Failed to activate RoCE LAG\n"); } else { mlx5_core_err(dev0, "Failed to activate VF LAG\n" "Make sure all VFs are unbound prior to VF LAG activation or deactivation\n"); } return err; } ldev->flags |= flags; return 0; }
static int mlx5_create_lag(struct mlx5_lag *ldev, struct lag_tracker *tracker) { struct mlx5_core_dev *dev0 = ldev->pf[0].dev; int err; mlx5_infer_tx_affinity_mapping(tracker, &ldev->v2p_map[0], &ldev->v2p_map[1]); mlx5_core_info(dev0, "lag map port 1:%d port 2:%d", ldev->v2p_map[0], ldev->v2p_map[1]); err = mlx5_cmd_create_lag(dev0, ldev->v2p_map[0], ldev->v2p_map[1]); if (err) mlx5_core_err(dev0, "Failed to create LAG (%d)\n", err); return err; }
int mlx5_core_reserve_gids(struct mlx5_core_dev *dev, unsigned int count) { if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { mlx5_core_err(dev, "Cannot reserve GIDs when interfaces are up\n"); return -EPERM; } if (dev->roce.reserved_gids.start < count) { mlx5_core_warn(dev, "GID table exhausted attempting to reserve %d more GIDs\n", count); return -ENOMEM; } if (dev->roce.reserved_gids.count + count > MLX5_MAX_RESERVED_GIDS) { mlx5_core_warn(dev, "Unable to reserve %d more GIDs\n", count); return -ENOMEM; } dev->roce.reserved_gids.start -= count; dev->roce.reserved_gids.count += count; mlx5_core_dbg(dev, "Reserved %u GIDs starting at %u\n", dev->roce.reserved_gids.count, dev->roce.reserved_gids.start); return 0; }
void mlx5_eq_pagefault(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe) { struct mlx5_eqe_page_fault *pf_eqe = &eqe->data.page_fault; int qpn = be32_to_cpu(pf_eqe->flags_qpn) & MLX5_QPN_MASK; struct mlx5_core_rsc_common *common = mlx5_get_rsc(dev, qpn); struct mlx5_core_qp *qp = container_of(common, struct mlx5_core_qp, common); struct mlx5_pagefault pfault; if (!qp) { mlx5_core_warn(dev, "ODP event for non-existent QP %06x\n", qpn); return; } pfault.event_subtype = eqe->sub_type; pfault.flags = (be32_to_cpu(pf_eqe->flags_qpn) >> MLX5_QPN_BITS) & (MLX5_PFAULT_REQUESTOR | MLX5_PFAULT_WRITE | MLX5_PFAULT_RDMA); pfault.bytes_committed = be32_to_cpu( pf_eqe->bytes_committed); mlx5_core_dbg(dev, "PAGE_FAULT: subtype: 0x%02x, flags: 0x%02x,\n", eqe->sub_type, pfault.flags); switch (eqe->sub_type) { case MLX5_PFAULT_SUBTYPE_RDMA: /* RDMA based event */ pfault.rdma.r_key = be32_to_cpu(pf_eqe->rdma.r_key); pfault.rdma.packet_size = be16_to_cpu(pf_eqe->rdma.packet_length); pfault.rdma.rdma_op_len = be32_to_cpu(pf_eqe->rdma.rdma_op_len); pfault.rdma.rdma_va = be64_to_cpu(pf_eqe->rdma.rdma_va); mlx5_core_dbg(dev, "PAGE_FAULT: qpn: 0x%06x, r_key: 0x%08x,\n", qpn, pfault.rdma.r_key); mlx5_core_dbg(dev, "PAGE_FAULT: rdma_op_len: 0x%08x,\n", pfault.rdma.rdma_op_len); mlx5_core_dbg(dev, "PAGE_FAULT: rdma_va: 0x%016llx,\n", pfault.rdma.rdma_va); mlx5_core_dbg(dev, "PAGE_FAULT: bytes_committed: 0x%06x\n", pfault.bytes_committed); break; case MLX5_PFAULT_SUBTYPE_WQE: /* WQE based event */ pfault.wqe.wqe_index = be16_to_cpu(pf_eqe->wqe.wqe_index); pfault.wqe.packet_size = be16_to_cpu(pf_eqe->wqe.packet_length); mlx5_core_dbg(dev, "PAGE_FAULT: qpn: 0x%06x, wqe_index: 0x%04x,\n", qpn, pfault.wqe.wqe_index); mlx5_core_dbg(dev, "PAGE_FAULT: bytes_committed: 0x%06x\n", pfault.bytes_committed); break; default: mlx5_core_warn(dev, "Unsupported page fault event sub-type: 0x%02hhx, QP %06x\n", eqe->sub_type, qpn); /* Unsupported page faults should still be resolved by the * page fault handler */ } if (qp->pfault_handler) { qp->pfault_handler(qp, &pfault); } else { mlx5_core_err(dev, "ODP event for QP %08x, without a fault handler in QP\n", qpn); /* Page fault will remain unresolved. QP will hang until it is * destroyed */ } mlx5_core_put_rsc(common); }