mlx5-updates-2019-04-02
This series provides misc updates to mlx5 driver 1) Aya Levin (1): Handle event of power detection in the PCIE slot 2) Eli Britstein (6): Some TC VLAN related updates and fixes to the previous VLAN modify action support patchset. Offload TC e-switch rules with egress/ingress VLAN devices 3) Max Gurtovoy (1): Fix double mutex initialization in esiwtch.c 4) Tariq Toukan (3): Misc small updates A write memory barrier is sufficient in EQ ci update Obsolete param field holding a constant value Unify logic of MTU boundaries 5) Tonghao Zhang (4): Misc updates to en_tc.c Make the log friendly when decapsulation offload not supported Remove 'parse_attr' argument in parse_tc_fdb_actions() Deletes unnecessary setting of esw_attr->parse_attr Return -EOPNOTSUPP when attempting to offload an unsupported action -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJcp8RLAAoJEEg/ir3gV/o+etQH/ArD5o0gKsQdro02oLIQ97t8 t3DrT07jv+C3sHzV1uVK76mikZdao7Dgjj132quB5HLEnZfpJ0HWbbQ1ZGAd124P 3vaONL47bDAxJM/5P4JM18dtQrLNJEJ9vPS3fK5HyR6qpnjbXSVKnwdN5cFtidoj B+CGxDFizx9WuYaRugrW5NVatHvZIgfigYf1LctrDyVV8yzJLwb+5xiDMJ9c6v28 QONVpvfuwk294T/Hs1mN3z1V4IrypV1ZuSKcbXIklFdabV+p0tdn6OYTOmtyQ0U7 XwIomQIn0QqU5CHPAMdgANymle2Qb+qx9fRZ+4hpuPdLIFM/BAP35ZEofVNVMfg= =2qTS -----END PGP SIGNATURE----- Merge tag 'mlx5-updates-2019-04-02' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux Saeed Mamameed says: ==================== mlx5-updates-2019-04-02 This series provides misc updates to mlx5 driver 1) Aya Levin (1): Handle event of power detection in the PCIE slot 2) Eli Britstein (6): Some TC VLAN related updates and fixes to the previous VLAN modify action support patchset. Offload TC e-switch rules with egress/ingress VLAN devices 3) Max Gurtovoy (1): Fix double mutex initialization in esiwtch.c 4) Tariq Toukan (3): Misc small updates A write memory barrier is sufficient in EQ ci update Obsolete param field holding a constant value Unify logic of MTU boundaries 5) Tonghao Zhang (4): Misc updates to en_tc.c Make the log friendly when decapsulation offload not supported Remove 'parse_attr' argument in parse_tc_fdb_actions() Deletes unnecessary setting of esw_attr->parse_attr Return -EOPNOTSUPP when attempting to offload an unsupported action ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
8bb309e67f
|
@ -148,7 +148,7 @@ int mlx5_cmd_alloc_memic(struct mlx5_memic *memic, phys_addr_t *addr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
*addr = pci_resource_start(dev->pdev, 0) +
|
||||
*addr = dev->bar_addr +
|
||||
MLX5_GET64(alloc_memic_out, out, memic_start_addr);
|
||||
|
||||
return 0;
|
||||
|
@ -167,7 +167,7 @@ int mlx5_cmd_dealloc_memic(struct mlx5_memic *memic, u64 addr, u64 length)
|
|||
u64 start_page_idx;
|
||||
int err;
|
||||
|
||||
addr -= pci_resource_start(dev->pdev, 0);
|
||||
addr -= dev->bar_addr;
|
||||
start_page_idx = (addr - hw_start_addr) >> PAGE_SHIFT;
|
||||
|
||||
MLX5_SET(dealloc_memic_in, in, opcode, MLX5_CMD_OP_DEALLOC_MEMIC);
|
||||
|
|
|
@ -2009,7 +2009,7 @@ static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,
|
|||
|
||||
fw_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? MLX5_UARS_IN_PAGE : 1;
|
||||
|
||||
return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) + uar_idx / fw_uars_per_page;
|
||||
return (dev->mdev->bar_addr >> PAGE_SHIFT) + uar_idx / fw_uars_per_page;
|
||||
}
|
||||
|
||||
static int get_command(unsigned long offset)
|
||||
|
@ -2199,7 +2199,7 @@ static int dm_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
|
|||
page_idx + npages)
|
||||
return -EINVAL;
|
||||
|
||||
pfn = ((pci_resource_start(dev->mdev->pdev, 0) +
|
||||
pfn = ((dev->mdev->bar_addr +
|
||||
MLX5_CAP64_DEV_MEM(dev->mdev, memic_bar_start_addr)) >>
|
||||
PAGE_SHIFT) +
|
||||
page_idx;
|
||||
|
@ -2283,7 +2283,7 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
|
|||
goto err_free;
|
||||
|
||||
start_offset = memic_addr & ~PAGE_MASK;
|
||||
page_idx = (memic_addr - pci_resource_start(memic->dev->pdev, 0) -
|
||||
page_idx = (memic_addr - memic->dev->bar_addr -
|
||||
MLX5_CAP64_DEV_MEM(memic->dev, memic_bar_start_addr)) >>
|
||||
PAGE_SHIFT;
|
||||
|
||||
|
@ -2326,7 +2326,7 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
page_idx = (dm->dev_addr - pci_resource_start(memic->dev->pdev, 0) -
|
||||
page_idx = (dm->dev_addr - memic->dev->bar_addr -
|
||||
MLX5_CAP64_DEV_MEM(memic->dev, memic_bar_start_addr)) >>
|
||||
PAGE_SHIFT;
|
||||
bitmap_clear(to_mucontext(ibdm->uobject->context)->dm_pages,
|
||||
|
|
|
@ -1194,8 +1194,7 @@ static struct ib_mr *mlx5_ib_get_memic_mr(struct ib_pd *pd, u64 memic_addr,
|
|||
MLX5_SET64(mkc, mkc, len, length);
|
||||
MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
|
||||
MLX5_SET(mkc, mkc, qpn, 0xffffff);
|
||||
MLX5_SET64(mkc, mkc, start_addr,
|
||||
memic_addr - pci_resource_start(dev->mdev->pdev, 0));
|
||||
MLX5_SET64(mkc, mkc, start_addr, memic_addr - dev->mdev->bar_addr);
|
||||
|
||||
err = mlx5_core_create_mkey(mdev, &mr->mmkey, in, inlen);
|
||||
if (err)
|
||||
|
|
|
@ -5119,7 +5119,7 @@ out:
|
|||
wmb();
|
||||
|
||||
/* currently we support only regular doorbells */
|
||||
mlx5_write64((__be32 *)ctrl, bf->bfreg->map + bf->offset, NULL);
|
||||
mlx5_write64((__be32 *)ctrl, bf->bfreg->map + bf->offset);
|
||||
/* Make sure doorbells don't leak out of SQ spinlock
|
||||
* and reach the HCA out of order.
|
||||
*/
|
||||
|
|
|
@ -1347,7 +1347,7 @@ static void set_wqname(struct mlx5_core_dev *dev)
|
|||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
|
||||
snprintf(cmd->wq_name, sizeof(cmd->wq_name), "mlx5_cmd_%s",
|
||||
dev_name(&dev->pdev->dev));
|
||||
dev->priv.name);
|
||||
}
|
||||
|
||||
static void clean_debug_files(struct mlx5_core_dev *dev)
|
||||
|
@ -1902,9 +1902,9 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
|||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd_if_rev = cmdif_rev(dev);
|
||||
if (cmd_if_rev != CMD_IF_REV) {
|
||||
dev_err(&dev->pdev->dev,
|
||||
"Driver cmdif rev(%d) differs from firmware's(%d)\n",
|
||||
CMD_IF_REV, cmd_if_rev);
|
||||
mlx5_core_err(dev,
|
||||
"Driver cmdif rev(%d) differs from firmware's(%d)\n",
|
||||
CMD_IF_REV, cmd_if_rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1921,14 +1921,14 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
|||
cmd->log_sz = cmd_l >> 4 & 0xf;
|
||||
cmd->log_stride = cmd_l & 0xf;
|
||||
if (1 << cmd->log_sz > MLX5_MAX_COMMANDS) {
|
||||
dev_err(&dev->pdev->dev, "firmware reports too many outstanding commands %d\n",
|
||||
1 << cmd->log_sz);
|
||||
mlx5_core_err(dev, "firmware reports too many outstanding commands %d\n",
|
||||
1 << cmd->log_sz);
|
||||
err = -EINVAL;
|
||||
goto err_free_page;
|
||||
}
|
||||
|
||||
if (cmd->log_sz + cmd->log_stride > MLX5_ADAPTER_PAGE_SHIFT) {
|
||||
dev_err(&dev->pdev->dev, "command queue size overflow\n");
|
||||
mlx5_core_err(dev, "command queue size overflow\n");
|
||||
err = -EINVAL;
|
||||
goto err_free_page;
|
||||
}
|
||||
|
@ -1939,8 +1939,8 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
|||
|
||||
cmd->cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16;
|
||||
if (cmd->cmdif_rev > CMD_IF_REV) {
|
||||
dev_err(&dev->pdev->dev, "driver does not support command interface version. driver %d, firmware %d\n",
|
||||
CMD_IF_REV, cmd->cmdif_rev);
|
||||
mlx5_core_err(dev, "driver does not support command interface version. driver %d, firmware %d\n",
|
||||
CMD_IF_REV, cmd->cmdif_rev);
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_free_page;
|
||||
}
|
||||
|
@ -1956,7 +1956,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
|||
cmd_h = (u32)((u64)(cmd->dma) >> 32);
|
||||
cmd_l = (u32)(cmd->dma);
|
||||
if (cmd_l & 0xfff) {
|
||||
dev_err(&dev->pdev->dev, "invalid command queue address\n");
|
||||
mlx5_core_err(dev, "invalid command queue address\n");
|
||||
err = -ENOMEM;
|
||||
goto err_free_page;
|
||||
}
|
||||
|
@ -1976,7 +1976,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
|||
set_wqname(dev);
|
||||
cmd->wq = create_singlethread_workqueue(cmd->wq_name);
|
||||
if (!cmd->wq) {
|
||||
dev_err(&dev->pdev->dev, "failed to create command workqueue\n");
|
||||
mlx5_core_err(dev, "failed to create command workqueue\n");
|
||||
err = -ENOMEM;
|
||||
goto err_cache;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ TRACE_EVENT(mlx5_fw,
|
|||
TP_ARGS(tracer, trace_timestamp, lost, event_id, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(dev_name, dev_name(&tracer->dev->pdev->dev))
|
||||
__string(dev_name, tracer->dev->priv.name)
|
||||
__field(u64, trace_timestamp)
|
||||
__field(bool, lost)
|
||||
__field(u8, event_id)
|
||||
|
@ -55,7 +55,7 @@ TRACE_EVENT(mlx5_fw,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(dev_name, dev_name(&tracer->dev->pdev->dev));
|
||||
__assign_str(dev_name, tracer->dev->priv.name);
|
||||
__entry->trace_timestamp = trace_timestamp;
|
||||
__entry->lost = lost;
|
||||
__entry->event_id = event_id;
|
||||
|
|
|
@ -241,7 +241,6 @@ struct mlx5e_params {
|
|||
struct net_dim_cq_moder rx_cq_moderation;
|
||||
struct net_dim_cq_moder tx_cq_moderation;
|
||||
bool lro_en;
|
||||
u32 lro_wqe_sz;
|
||||
u8 tx_min_inline_mode;
|
||||
bool vlan_strip_disable;
|
||||
bool scatter_fcs_en;
|
||||
|
@ -975,7 +974,7 @@ void mlx5e_notify_hw(struct mlx5_wq_cyc *wq, u16 pc,
|
|||
*/
|
||||
wmb();
|
||||
|
||||
mlx5_write64((__be32 *)ctrl, uar_map, NULL);
|
||||
mlx5_write64((__be32 *)ctrl, uar_map);
|
||||
}
|
||||
|
||||
static inline void mlx5e_cq_arm(struct mlx5e_cq *cq)
|
||||
|
@ -1087,6 +1086,7 @@ mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *prof
|
|||
int mlx5e_attach_netdev(struct mlx5e_priv *priv);
|
||||
void mlx5e_detach_netdev(struct mlx5e_priv *priv);
|
||||
void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
|
||||
void mlx5e_set_netdev_mtu_boundaries(struct mlx5e_priv *priv);
|
||||
void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
|
||||
struct mlx5e_rss_params *rss_params,
|
||||
struct mlx5e_params *params,
|
||||
|
|
|
@ -96,7 +96,7 @@ static const char *mlx5e_netdev_kind(struct net_device *dev)
|
|||
if (dev->rtnl_link_ops)
|
||||
return dev->rtnl_link_ops->kind;
|
||||
else
|
||||
return "";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv,
|
||||
|
@ -636,8 +636,10 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
|
|||
headers_c, headers_v);
|
||||
} else {
|
||||
netdev_warn(priv->netdev,
|
||||
"decapsulation offload is not supported for %s net device (%d)\n",
|
||||
mlx5e_netdev_kind(filter_dev), tunnel_type);
|
||||
"decapsulation offload is not supported for %s (kind: \"%s\")\n",
|
||||
netdev_name(filter_dev),
|
||||
mlx5e_netdev_kind(filter_dev));
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return err;
|
||||
|
|
|
@ -204,7 +204,6 @@ static u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev,
|
|||
void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev,
|
||||
struct mlx5e_params *params)
|
||||
{
|
||||
params->lro_wqe_sz = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
|
||||
params->log_rq_mtu_frames = is_kdump_kernel() ?
|
||||
MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE :
|
||||
MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE;
|
||||
|
@ -2637,7 +2636,7 @@ static void mlx5e_build_tir_ctx_lro(struct mlx5e_params *params, void *tirc)
|
|||
MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO |
|
||||
MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO);
|
||||
MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
|
||||
(params->lro_wqe_sz - ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
|
||||
(MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
|
||||
MLX5_SET(tirc, tirc, lro_timeout_period_usecs, params->lro_timeout);
|
||||
}
|
||||
|
||||
|
@ -2812,6 +2811,21 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mlx5e_set_netdev_mtu_boundaries(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_params *params = &priv->channels.params;
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u16 max_mtu;
|
||||
|
||||
/* MTU range: 68 - hw-specific max */
|
||||
netdev->min_mtu = ETH_MIN_MTU;
|
||||
|
||||
mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
|
||||
netdev->max_mtu = min_t(unsigned int, MLX5E_HW2SW_MTU(params, max_mtu),
|
||||
ETH_MAX_MTU);
|
||||
}
|
||||
|
||||
static void mlx5e_netdev_set_tcs(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
@ -4913,7 +4927,6 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
|
|||
{
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u16 max_mtu;
|
||||
|
||||
mlx5e_init_l2_addr(priv);
|
||||
|
||||
|
@ -4921,10 +4934,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
|
|||
if (!netif_running(netdev))
|
||||
mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
|
||||
|
||||
/* MTU range: 68 - hw-specific max */
|
||||
netdev->min_mtu = ETH_MIN_MTU;
|
||||
mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
|
||||
netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
|
||||
mlx5e_set_netdev_mtu_boundaries(priv);
|
||||
mlx5e_set_dev_port_mtu(priv);
|
||||
|
||||
mlx5_lag_add(mdev, netdev);
|
||||
|
|
|
@ -795,7 +795,8 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
|
|||
struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
|
||||
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
if (!mlx5e_tc_tun_device_to_offload(priv, netdev))
|
||||
if (!mlx5e_tc_tun_device_to_offload(priv, netdev) &&
|
||||
!is_vlan_dev(netdev))
|
||||
return NOTIFY_OK;
|
||||
|
||||
switch (event) {
|
||||
|
@ -1623,13 +1624,7 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
|
|||
|
||||
static void mlx5e_vf_rep_enable(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u16 max_mtu;
|
||||
|
||||
netdev->min_mtu = ETH_MIN_MTU;
|
||||
mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
|
||||
netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
|
||||
mlx5e_set_netdev_mtu_boundaries(priv);
|
||||
}
|
||||
|
||||
static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data)
|
||||
|
|
|
@ -1438,6 +1438,26 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void *get_match_headers_criteria(u32 flags,
|
||||
struct mlx5_flow_spec *spec)
|
||||
{
|
||||
return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
|
||||
MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
||||
inner_headers) :
|
||||
MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
||||
outer_headers);
|
||||
}
|
||||
|
||||
static void *get_match_headers_value(u32 flags,
|
||||
struct mlx5_flow_spec *spec)
|
||||
{
|
||||
return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
|
||||
MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
inner_headers) :
|
||||
MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
outer_headers);
|
||||
}
|
||||
|
||||
static int __parse_cls_flower(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_spec *spec,
|
||||
struct tc_cls_flower_offload *f,
|
||||
|
@ -1503,10 +1523,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||
/* In decap flow, header pointers should point to the inner
|
||||
* headers, outer header were already set by parse_tunnel_attr
|
||||
*/
|
||||
headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
||||
inner_headers);
|
||||
headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
inner_headers);
|
||||
headers_c = get_match_headers_criteria(MLX5_FLOW_CONTEXT_ACTION_DECAP,
|
||||
spec);
|
||||
headers_v = get_match_headers_value(MLX5_FLOW_CONTEXT_ACTION_DECAP,
|
||||
spec);
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
|
||||
|
@ -1521,11 +1541,23 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||
if (match.mask->n_proto)
|
||||
*match_level = MLX5_MATCH_L2;
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN) ||
|
||||
is_vlan_dev(filter_dev)) {
|
||||
struct flow_dissector_key_vlan filter_dev_mask;
|
||||
struct flow_dissector_key_vlan filter_dev_key;
|
||||
struct flow_match_vlan match;
|
||||
|
||||
flow_rule_match_vlan(rule, &match);
|
||||
if (is_vlan_dev(filter_dev)) {
|
||||
match.key = &filter_dev_key;
|
||||
match.key->vlan_id = vlan_dev_vlan_id(filter_dev);
|
||||
match.key->vlan_tpid = vlan_dev_vlan_proto(filter_dev);
|
||||
match.key->vlan_priority = 0;
|
||||
match.mask = &filter_dev_mask;
|
||||
memset(match.mask, 0xff, sizeof(*match.mask));
|
||||
match.mask->vlan_priority = 0;
|
||||
} else {
|
||||
flow_rule_match_vlan(rule, &match);
|
||||
}
|
||||
if (match.mask->vlan_id ||
|
||||
match.mask->vlan_priority ||
|
||||
match.mask->vlan_tpid) {
|
||||
|
@ -1875,39 +1907,73 @@ struct mlx5_fields {
|
|||
u8 field;
|
||||
u8 size;
|
||||
u32 offset;
|
||||
u32 match_offset;
|
||||
};
|
||||
|
||||
#define OFFLOAD(fw_field, size, field, off) \
|
||||
{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, offsetof(struct pedit_headers, field) + (off)}
|
||||
#define OFFLOAD(fw_field, size, field, off, match_field) \
|
||||
{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, \
|
||||
offsetof(struct pedit_headers, field) + (off), \
|
||||
MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}
|
||||
|
||||
static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
|
||||
void *matchmaskp, int size)
|
||||
{
|
||||
bool same = false;
|
||||
|
||||
switch (size) {
|
||||
case sizeof(u8):
|
||||
same = ((*(u8 *)valp) & (*(u8 *)maskp)) ==
|
||||
((*(u8 *)matchvalp) & (*(u8 *)matchmaskp));
|
||||
break;
|
||||
case sizeof(u16):
|
||||
same = ((*(u16 *)valp) & (*(u16 *)maskp)) ==
|
||||
((*(u16 *)matchvalp) & (*(u16 *)matchmaskp));
|
||||
break;
|
||||
case sizeof(u32):
|
||||
same = ((*(u32 *)valp) & (*(u32 *)maskp)) ==
|
||||
((*(u32 *)matchvalp) & (*(u32 *)matchmaskp));
|
||||
break;
|
||||
}
|
||||
|
||||
return same;
|
||||
}
|
||||
|
||||
static struct mlx5_fields fields[] = {
|
||||
OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0),
|
||||
OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0),
|
||||
OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0),
|
||||
OFFLOAD(SMAC_15_0, 2, eth.h_source[4], 0),
|
||||
OFFLOAD(ETHERTYPE, 2, eth.h_proto, 0),
|
||||
OFFLOAD(FIRST_VID, 2, vlan.h_vlan_TCI, 0),
|
||||
OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0, dmac_47_16),
|
||||
OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0, dmac_15_0),
|
||||
OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0, smac_47_16),
|
||||
OFFLOAD(SMAC_15_0, 2, eth.h_source[4], 0, smac_15_0),
|
||||
OFFLOAD(ETHERTYPE, 2, eth.h_proto, 0, ethertype),
|
||||
OFFLOAD(FIRST_VID, 2, vlan.h_vlan_TCI, 0, first_vid),
|
||||
|
||||
OFFLOAD(IP_TTL, 1, ip4.ttl, 0),
|
||||
OFFLOAD(SIPV4, 4, ip4.saddr, 0),
|
||||
OFFLOAD(DIPV4, 4, ip4.daddr, 0),
|
||||
OFFLOAD(IP_TTL, 1, ip4.ttl, 0, ttl_hoplimit),
|
||||
OFFLOAD(SIPV4, 4, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
|
||||
OFFLOAD(DIPV4, 4, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
|
||||
|
||||
OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0),
|
||||
OFFLOAD(SIPV6_95_64, 4, ip6.saddr.s6_addr32[1], 0),
|
||||
OFFLOAD(SIPV6_63_32, 4, ip6.saddr.s6_addr32[2], 0),
|
||||
OFFLOAD(SIPV6_31_0, 4, ip6.saddr.s6_addr32[3], 0),
|
||||
OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0),
|
||||
OFFLOAD(DIPV6_95_64, 4, ip6.daddr.s6_addr32[1], 0),
|
||||
OFFLOAD(DIPV6_63_32, 4, ip6.daddr.s6_addr32[2], 0),
|
||||
OFFLOAD(DIPV6_31_0, 4, ip6.daddr.s6_addr32[3], 0),
|
||||
OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0),
|
||||
OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0,
|
||||
src_ipv4_src_ipv6.ipv6_layout.ipv6[0]),
|
||||
OFFLOAD(SIPV6_95_64, 4, ip6.saddr.s6_addr32[1], 0,
|
||||
src_ipv4_src_ipv6.ipv6_layout.ipv6[4]),
|
||||
OFFLOAD(SIPV6_63_32, 4, ip6.saddr.s6_addr32[2], 0,
|
||||
src_ipv4_src_ipv6.ipv6_layout.ipv6[8]),
|
||||
OFFLOAD(SIPV6_31_0, 4, ip6.saddr.s6_addr32[3], 0,
|
||||
src_ipv4_src_ipv6.ipv6_layout.ipv6[12]),
|
||||
OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0,
|
||||
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]),
|
||||
OFFLOAD(DIPV6_95_64, 4, ip6.daddr.s6_addr32[1], 0,
|
||||
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]),
|
||||
OFFLOAD(DIPV6_63_32, 4, ip6.daddr.s6_addr32[2], 0,
|
||||
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]),
|
||||
OFFLOAD(DIPV6_31_0, 4, ip6.daddr.s6_addr32[3], 0,
|
||||
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
|
||||
OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0, ttl_hoplimit),
|
||||
|
||||
OFFLOAD(TCP_SPORT, 2, tcp.source, 0),
|
||||
OFFLOAD(TCP_DPORT, 2, tcp.dest, 0),
|
||||
OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5),
|
||||
OFFLOAD(TCP_SPORT, 2, tcp.source, 0, tcp_sport),
|
||||
OFFLOAD(TCP_DPORT, 2, tcp.dest, 0, tcp_dport),
|
||||
OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5, tcp_flags),
|
||||
|
||||
OFFLOAD(UDP_SPORT, 2, udp.source, 0),
|
||||
OFFLOAD(UDP_DPORT, 2, udp.dest, 0),
|
||||
OFFLOAD(UDP_SPORT, 2, udp.source, 0, udp_sport),
|
||||
OFFLOAD(UDP_DPORT, 2, udp.dest, 0, udp_dport),
|
||||
};
|
||||
|
||||
/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
|
||||
|
@ -1916,9 +1982,14 @@ static struct mlx5_fields fields[] = {
|
|||
*/
|
||||
static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
u32 *action_flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
|
||||
void *headers_c = get_match_headers_criteria(*action_flags,
|
||||
&parse_attr->spec);
|
||||
void *headers_v = get_match_headers_value(*action_flags,
|
||||
&parse_attr->spec);
|
||||
int i, action_size, nactions, max_actions, first, last, next_z;
|
||||
void *s_masks_p, *a_masks_p, *vals_p;
|
||||
struct mlx5_fields *f;
|
||||
|
@ -1942,6 +2013,8 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|||
nactions = parse_attr->num_mod_hdr_actions;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fields); i++) {
|
||||
bool skip;
|
||||
|
||||
f = &fields[i];
|
||||
/* avoid seeing bits set from previous iterations */
|
||||
s_mask = 0;
|
||||
|
@ -1970,19 +2043,34 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
skip = false;
|
||||
if (s_mask) {
|
||||
void *match_mask = headers_c + f->match_offset;
|
||||
void *match_val = headers_v + f->match_offset;
|
||||
|
||||
cmd = MLX5_ACTION_TYPE_SET;
|
||||
mask = s_mask;
|
||||
vals_p = (void *)set_vals + f->offset;
|
||||
/* don't rewrite if we have a match on the same value */
|
||||
if (cmp_val_mask(vals_p, s_masks_p, match_val,
|
||||
match_mask, f->size))
|
||||
skip = true;
|
||||
/* clear to denote we consumed this field */
|
||||
memset(s_masks_p, 0, f->size);
|
||||
} else {
|
||||
u32 zero = 0;
|
||||
|
||||
cmd = MLX5_ACTION_TYPE_ADD;
|
||||
mask = a_mask;
|
||||
vals_p = (void *)add_vals + f->offset;
|
||||
/* add 0 is no change */
|
||||
if (!memcmp(vals_p, &zero, f->size))
|
||||
skip = true;
|
||||
/* clear to denote we consumed this field */
|
||||
memset(a_masks_p, 0, f->size);
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
field_bsize = f->size * BITS_PER_BYTE;
|
||||
|
||||
|
@ -2029,6 +2117,15 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_flow_namespace_max_modify_action(struct mlx5_core_dev *mdev,
|
||||
int namespace)
|
||||
{
|
||||
if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
|
||||
return MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, max_modify_header_actions);
|
||||
else /* namespace is MLX5_FLOW_NAMESPACE_KERNEL - NIC offloading */
|
||||
return MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_modify_header_actions);
|
||||
}
|
||||
|
||||
static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
|
||||
struct pedit_headers_action *hdrs,
|
||||
int namespace,
|
||||
|
@ -2040,11 +2137,7 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
|
|||
hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits;
|
||||
action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
|
||||
|
||||
if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
|
||||
max_actions = MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, max_modify_header_actions);
|
||||
else /* namespace is MLX5_FLOW_NAMESPACE_KERNEL - NIC offloading */
|
||||
max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, max_modify_header_actions);
|
||||
|
||||
max_actions = mlx5e_flow_namespace_max_modify_action(priv->mdev, namespace);
|
||||
/* can get up to crazingly 16 HW actions in 32 bits pedit SW key */
|
||||
max_actions = min(max_actions, nkeys * 16);
|
||||
|
||||
|
@ -2077,6 +2170,12 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
if (!mlx5e_flow_namespace_max_modify_action(priv->mdev, namespace)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"The pedit offload action is not supported");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
mask = act->mangle.mask;
|
||||
val = act->mangle.val;
|
||||
offset = act->mangle.offset;
|
||||
|
@ -2095,6 +2194,7 @@ out_err:
|
|||
static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
struct pedit_headers_action *hdrs,
|
||||
u32 *action_flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct pedit_headers *cmd_masks;
|
||||
|
@ -2107,7 +2207,7 @@ static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
err = offload_pedit_fields(hdrs, parse_attr, extack);
|
||||
err = offload_pedit_fields(hdrs, parse_attr, action_flags, extack);
|
||||
if (err < 0)
|
||||
goto out_dealloc_parsed_actions;
|
||||
|
||||
|
@ -2219,11 +2319,7 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
|
|||
u8 ip_proto;
|
||||
int i;
|
||||
|
||||
if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP)
|
||||
headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers);
|
||||
else
|
||||
headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
|
||||
|
||||
headers_v = get_match_headers_value(actions, spec);
|
||||
ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
|
||||
|
||||
/* for non-IP we only re-write MACs, so we're okay */
|
||||
|
@ -2269,7 +2365,8 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
|
|||
actions = flow->nic_attr->action;
|
||||
|
||||
if (flow->flags & MLX5E_TC_FLOW_EGRESS &&
|
||||
!(actions & MLX5_FLOW_CONTEXT_ACTION_DECAP))
|
||||
!((actions & MLX5_FLOW_CONTEXT_ACTION_DECAP) ||
|
||||
(actions & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP)))
|
||||
return false;
|
||||
|
||||
if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
|
||||
|
@ -2309,10 +2406,25 @@ static int add_vlan_rewrite_action(struct mlx5e_priv *priv, int namespace,
|
|||
.mangle.mask = ~(u32)be16_to_cpu(*(__be16 *)&mask16),
|
||||
.mangle.val = (u32)be16_to_cpu(*(__be16 *)&val16),
|
||||
};
|
||||
u8 match_prio_mask, match_prio_val;
|
||||
void *headers_c, *headers_v;
|
||||
int err;
|
||||
|
||||
if (act->vlan.prio) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Setting VLAN prio is not supported");
|
||||
headers_c = get_match_headers_criteria(*action, &parse_attr->spec);
|
||||
headers_v = get_match_headers_value(*action, &parse_attr->spec);
|
||||
|
||||
if (!(MLX5_GET(fte_match_set_lyr_2_4, headers_c, cvlan_tag) &&
|
||||
MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag))) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"VLAN rewrite action must have VLAN protocol match");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
match_prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
|
||||
match_prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
|
||||
if (act->vlan.prio != (match_prio_val & match_prio_mask)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Changing VLAN prio is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
@ -2406,16 +2518,22 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
|
|||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
|
||||
hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
|
||||
err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
|
||||
parse_attr, hdrs, extack);
|
||||
parse_attr, hdrs, &action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
/* in case all pedit actions are skipped, remove the MOD_HDR
|
||||
* flag.
|
||||
*/
|
||||
if (parse_attr->num_mod_hdr_actions == 0)
|
||||
action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||
}
|
||||
|
||||
attr->action = action;
|
||||
|
@ -2593,15 +2711,60 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int add_vlan_push_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_esw_flow_attr *attr,
|
||||
struct net_device **out_dev,
|
||||
u32 *action)
|
||||
{
|
||||
struct net_device *vlan_dev = *out_dev;
|
||||
struct flow_action_entry vlan_act = {
|
||||
.id = FLOW_ACTION_VLAN_PUSH,
|
||||
.vlan.vid = vlan_dev_vlan_id(vlan_dev),
|
||||
.vlan.proto = vlan_dev_vlan_proto(vlan_dev),
|
||||
.vlan.prio = 0,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr, action);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*out_dev = dev_get_by_index_rcu(dev_net(vlan_dev),
|
||||
dev_get_iflink(vlan_dev));
|
||||
if (is_vlan_dev(*out_dev))
|
||||
err = add_vlan_push_action(priv, attr, out_dev, action);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int add_vlan_pop_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_esw_flow_attr *attr,
|
||||
u32 *action)
|
||||
{
|
||||
int nest_level = vlan_get_encap_level(attr->parse_attr->filter_dev);
|
||||
struct flow_action_entry vlan_act = {
|
||||
.id = FLOW_ACTION_VLAN_POP,
|
||||
};
|
||||
int err = 0;
|
||||
|
||||
while (nest_level--) {
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr, action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
||||
struct flow_action *flow_action,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
struct mlx5e_tc_flow *flow,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct pedit_headers_action hdrs[2] = {};
|
||||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
const struct ip_tunnel_info *info = NULL;
|
||||
const struct flow_action_entry *act;
|
||||
|
@ -2673,6 +2836,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||
uplink_upper == out_dev)
|
||||
out_dev = uplink_dev;
|
||||
|
||||
if (is_vlan_dev(out_dev)) {
|
||||
err = add_vlan_push_action(priv, attr,
|
||||
&out_dev,
|
||||
&action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (is_vlan_dev(parse_attr->filter_dev)) {
|
||||
err = add_vlan_pop_action(priv, attr,
|
||||
&action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!mlx5e_eswitch_rep(out_dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -2686,7 +2863,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||
out_dev->ifindex;
|
||||
parse_attr->tun_info[attr->out_count] = *info;
|
||||
encap = false;
|
||||
attr->parse_attr = parse_attr;
|
||||
attr->dests[attr->out_count].flags |=
|
||||
MLX5_ESW_DEST_ENCAP;
|
||||
attr->out_count++;
|
||||
|
@ -2765,16 +2941,27 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
|
||||
hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
|
||||
err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_FDB,
|
||||
parse_attr, hdrs, extack);
|
||||
parse_attr, hdrs, &action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
/* in case all pedit actions are skipped, remove the MOD_HDR
|
||||
* flag. we might have set split_count either by pedit or
|
||||
* pop/push. if there is no pop/push either, reset it too.
|
||||
*/
|
||||
if (parse_attr->num_mod_hdr_actions == 0) {
|
||||
action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||
if (!((action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) ||
|
||||
(action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH)))
|
||||
attr->split_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
attr->action = action;
|
||||
|
@ -2943,7 +3130,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
|
|||
if (err)
|
||||
goto err_free;
|
||||
|
||||
err = parse_tc_fdb_actions(priv, &rule->action, parse_attr, flow, extack);
|
||||
err = parse_tc_fdb_actions(priv, &rule->action, flow, extack);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
|
|
|
@ -707,7 +707,7 @@ void mlx5_eq_update_ci(struct mlx5_eq *eq, u32 cc, bool arm)
|
|||
|
||||
__raw_writel((__force u32)cpu_to_be32(val), addr);
|
||||
/* We still want ordering, just not swabbing, so add a barrier */
|
||||
mb();
|
||||
wmb();
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_eq_update_ci);
|
||||
|
||||
|
|
|
@ -1698,8 +1698,6 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports,
|
|||
{
|
||||
int err;
|
||||
|
||||
mutex_init(&esw->fdb_table.offloads.fdb_prio_lock);
|
||||
|
||||
err = esw_offloads_steering_init(esw, total_nvports);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -21,6 +21,7 @@ struct mlx5_event_nb {
|
|||
static int any_notifier(struct notifier_block *, unsigned long, void *);
|
||||
static int temp_warn(struct notifier_block *, unsigned long, void *);
|
||||
static int port_module(struct notifier_block *, unsigned long, void *);
|
||||
static int pcie_core(struct notifier_block *, unsigned long, void *);
|
||||
|
||||
/* handler which forwards the event to events->nh, driver notifiers */
|
||||
static int forward_event(struct notifier_block *, unsigned long, void *);
|
||||
|
@ -30,6 +31,7 @@ static struct mlx5_nb events_nbs_ref[] = {
|
|||
{.nb.notifier_call = any_notifier, .event_type = MLX5_EVENT_TYPE_NOTIFY_ANY },
|
||||
{.nb.notifier_call = temp_warn, .event_type = MLX5_EVENT_TYPE_TEMP_WARN_EVENT },
|
||||
{.nb.notifier_call = port_module, .event_type = MLX5_EVENT_TYPE_PORT_MODULE_EVENT },
|
||||
{.nb.notifier_call = pcie_core, .event_type = MLX5_EVENT_TYPE_GENERAL_EVENT },
|
||||
|
||||
/* Events to be forwarded (as is) to mlx5 core interfaces (mlx5e/mlx5_ib) */
|
||||
{.nb.notifier_call = forward_event, .event_type = MLX5_EVENT_TYPE_PORT_CHANGE },
|
||||
|
@ -51,11 +53,14 @@ static struct mlx5_nb events_nbs_ref[] = {
|
|||
|
||||
struct mlx5_events {
|
||||
struct mlx5_core_dev *dev;
|
||||
struct workqueue_struct *wq;
|
||||
struct mlx5_event_nb notifiers[ARRAY_SIZE(events_nbs_ref)];
|
||||
/* driver notifier chain */
|
||||
struct atomic_notifier_head nh;
|
||||
/* port module events stats */
|
||||
struct mlx5_pme_stats pme_stats;
|
||||
/*pcie_core*/
|
||||
struct work_struct pcie_core_work;
|
||||
};
|
||||
|
||||
static const char *eqe_type_str(u8 type)
|
||||
|
@ -249,6 +254,69 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
|
|||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
enum {
|
||||
MLX5_PCI_POWER_COULD_NOT_BE_READ = 0x0,
|
||||
MLX5_PCI_POWER_SUFFICIENT_REPORTED = 0x1,
|
||||
MLX5_PCI_POWER_INSUFFICIENT_REPORTED = 0x2,
|
||||
};
|
||||
|
||||
static void mlx5_pcie_event(struct work_struct *work)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(mpein_reg)] = {0};
|
||||
u32 in[MLX5_ST_SZ_DW(mpein_reg)] = {0};
|
||||
struct mlx5_events *events;
|
||||
struct mlx5_core_dev *dev;
|
||||
u8 power_status;
|
||||
u16 pci_power;
|
||||
|
||||
events = container_of(work, struct mlx5_events, pcie_core_work);
|
||||
dev = events->dev;
|
||||
|
||||
if (!MLX5_CAP_MCAM_FEATURE(dev, pci_status_and_power))
|
||||
return;
|
||||
|
||||
mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_MPEIN, 0, 0);
|
||||
power_status = MLX5_GET(mpein_reg, out, pwr_status);
|
||||
pci_power = MLX5_GET(mpein_reg, out, pci_power);
|
||||
|
||||
switch (power_status) {
|
||||
case MLX5_PCI_POWER_COULD_NOT_BE_READ:
|
||||
mlx5_core_info_rl(dev,
|
||||
"PCIe slot power capability was not advertised.\n");
|
||||
break;
|
||||
case MLX5_PCI_POWER_INSUFFICIENT_REPORTED:
|
||||
mlx5_core_warn_rl(dev,
|
||||
"Detected insufficient power on the PCIe slot (%uW).\n",
|
||||
pci_power);
|
||||
break;
|
||||
case MLX5_PCI_POWER_SUFFICIENT_REPORTED:
|
||||
mlx5_core_info_rl(dev,
|
||||
"PCIe slot advertised sufficient power (%uW).\n",
|
||||
pci_power);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int pcie_core(struct notifier_block *nb, unsigned long type, void *data)
|
||||
{
|
||||
struct mlx5_event_nb *event_nb = mlx5_nb_cof(nb,
|
||||
struct mlx5_event_nb,
|
||||
nb);
|
||||
struct mlx5_events *events = event_nb->ctx;
|
||||
struct mlx5_eqe *eqe = data;
|
||||
|
||||
switch (eqe->sub_type) {
|
||||
case MLX5_GENERAL_SUBTYPE_PCI_POWER_CHANGE_EVENT:
|
||||
queue_work(events->wq, &events->pcie_core_work);
|
||||
break;
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats)
|
||||
{
|
||||
*stats = dev->priv.events->pme_stats;
|
||||
|
@ -277,11 +345,17 @@ int mlx5_events_init(struct mlx5_core_dev *dev)
|
|||
ATOMIC_INIT_NOTIFIER_HEAD(&events->nh);
|
||||
events->dev = dev;
|
||||
dev->priv.events = events;
|
||||
events->wq = create_singlethread_workqueue("mlx5_events");
|
||||
if (!events->wq)
|
||||
return -ENOMEM;
|
||||
INIT_WORK(&events->pcie_core_work, mlx5_pcie_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5_events_cleanup(struct mlx5_core_dev *dev)
|
||||
{
|
||||
destroy_workqueue(dev->priv.events->wq);
|
||||
kvfree(dev->priv.events);
|
||||
}
|
||||
|
||||
|
@ -304,6 +378,7 @@ void mlx5_events_stop(struct mlx5_core_dev *dev)
|
|||
|
||||
for (i = ARRAY_SIZE(events_nbs_ref) - 1; i >= 0 ; i--)
|
||||
mlx5_eq_notifier_unregister(dev, &events->notifiers[i].nb);
|
||||
flush_workqueue(events->wq);
|
||||
}
|
||||
|
||||
int mlx5_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb)
|
||||
|
|
|
@ -135,7 +135,7 @@ static void mlx5_fpga_conn_notify_hw(struct mlx5_fpga_conn *conn, void *wqe)
|
|||
*conn->qp.wq.sq.db = cpu_to_be32(conn->qp.sq.pc);
|
||||
/* Make sure that doorbell record is visible before ringing */
|
||||
wmb();
|
||||
mlx5_write64(wqe, conn->fdev->conn_res.uar->map + MLX5_BF_OFFSET, NULL);
|
||||
mlx5_write64(wqe, conn->fdev->conn_res.uar->map + MLX5_BF_OFFSET);
|
||||
}
|
||||
|
||||
static void mlx5_fpga_conn_post_send(struct mlx5_fpga_conn *conn,
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <linux/mlx5/eq.h>
|
||||
|
||||
#include "mlx5_core.h"
|
||||
#include "lib/eq.h"
|
||||
#include "fpga/cmd.h"
|
||||
|
||||
|
@ -62,26 +63,26 @@ struct mlx5_fpga_device {
|
|||
};
|
||||
|
||||
#define mlx5_fpga_dbg(__adev, format, ...) \
|
||||
dev_dbg(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
mlx5_core_dbg((__adev)->mdev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_err(__adev, format, ...) \
|
||||
dev_err(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
mlx5_core_err((__adev)->mdev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_warn(__adev, format, ...) \
|
||||
dev_warn(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
mlx5_core_warn((__adev)->mdev, "FPGA: %s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_warn_ratelimited(__adev, format, ...) \
|
||||
dev_warn_ratelimited(&(__adev)->mdev->pdev->dev, "FPGA: %s:%d: " \
|
||||
format, __func__, __LINE__, ##__VA_ARGS__)
|
||||
mlx5_core_err_rl((__adev)->mdev, "FPGA: %s:%d: " \
|
||||
format, __func__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_notice(__adev, format, ...) \
|
||||
dev_notice(&(__adev)->mdev->pdev->dev, "FPGA: " format, ##__VA_ARGS__)
|
||||
mlx5_core_info((__adev)->mdev, "FPGA: " format, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_fpga_info(__adev, format, ...) \
|
||||
dev_info(&(__adev)->mdev->pdev->dev, "FPGA: " format, ##__VA_ARGS__)
|
||||
mlx5_core_info((__adev)->mdev, "FPGA: " format, ##__VA_ARGS__)
|
||||
|
||||
int mlx5_fpga_init(struct mlx5_core_dev *mdev);
|
||||
void mlx5_fpga_cleanup(struct mlx5_core_dev *mdev);
|
||||
|
|
|
@ -819,7 +819,7 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
|
|||
struct mlx5_flow_root_namespace *root = find_root(&prio->node);
|
||||
struct mlx5_ft_underlay_qp *uqp;
|
||||
int min_level = INT_MAX;
|
||||
int err;
|
||||
int err = 0;
|
||||
u32 qpn;
|
||||
|
||||
if (root->root_ft)
|
||||
|
|
|
@ -152,11 +152,11 @@ static void health_recover(struct work_struct *work)
|
|||
|
||||
nic_state = mlx5_get_nic_state(dev);
|
||||
if (nic_state == MLX5_NIC_IFC_INVALID) {
|
||||
dev_err(&dev->pdev->dev, "health recovery flow aborted since the nic state is invalid\n");
|
||||
mlx5_core_err(dev, "health recovery flow aborted since the nic state is invalid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_err(&dev->pdev->dev, "starting health recovery flow\n");
|
||||
mlx5_core_err(dev, "starting health recovery flow\n");
|
||||
mlx5_recover_device(dev);
|
||||
}
|
||||
|
||||
|
@ -180,8 +180,8 @@ static void health_care(struct work_struct *work)
|
|||
if (!test_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags))
|
||||
schedule_delayed_work(&health->recover_work, recover_delay);
|
||||
else
|
||||
dev_err(&dev->pdev->dev,
|
||||
"new health works are not permitted at this stage\n");
|
||||
mlx5_core_err(dev,
|
||||
"new health works are not permitted at this stage\n");
|
||||
spin_unlock_irqrestore(&health->wq_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -228,18 +228,22 @@ static void print_health_info(struct mlx5_core_dev *dev)
|
|||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(h->assert_var); i++)
|
||||
dev_err(&dev->pdev->dev, "assert_var[%d] 0x%08x\n", i, ioread32be(h->assert_var + i));
|
||||
mlx5_core_err(dev, "assert_var[%d] 0x%08x\n", i,
|
||||
ioread32be(h->assert_var + i));
|
||||
|
||||
dev_err(&dev->pdev->dev, "assert_exit_ptr 0x%08x\n", ioread32be(&h->assert_exit_ptr));
|
||||
dev_err(&dev->pdev->dev, "assert_callra 0x%08x\n", ioread32be(&h->assert_callra));
|
||||
mlx5_core_err(dev, "assert_exit_ptr 0x%08x\n",
|
||||
ioread32be(&h->assert_exit_ptr));
|
||||
mlx5_core_err(dev, "assert_callra 0x%08x\n",
|
||||
ioread32be(&h->assert_callra));
|
||||
sprintf(fw_str, "%d.%d.%d", fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev));
|
||||
dev_err(&dev->pdev->dev, "fw_ver %s\n", fw_str);
|
||||
dev_err(&dev->pdev->dev, "hw_id 0x%08x\n", ioread32be(&h->hw_id));
|
||||
dev_err(&dev->pdev->dev, "irisc_index %d\n", ioread8(&h->irisc_index));
|
||||
dev_err(&dev->pdev->dev, "synd 0x%x: %s\n", ioread8(&h->synd), hsynd_str(ioread8(&h->synd)));
|
||||
dev_err(&dev->pdev->dev, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd));
|
||||
mlx5_core_err(dev, "fw_ver %s\n", fw_str);
|
||||
mlx5_core_err(dev, "hw_id 0x%08x\n", ioread32be(&h->hw_id));
|
||||
mlx5_core_err(dev, "irisc_index %d\n", ioread8(&h->irisc_index));
|
||||
mlx5_core_err(dev, "synd 0x%x: %s\n", ioread8(&h->synd),
|
||||
hsynd_str(ioread8(&h->synd)));
|
||||
mlx5_core_err(dev, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd));
|
||||
fw = ioread32be(&h->fw_ver);
|
||||
dev_err(&dev->pdev->dev, "raw fw_ver 0x%08x\n", fw);
|
||||
mlx5_core_err(dev, "raw fw_ver 0x%08x\n", fw);
|
||||
}
|
||||
|
||||
static unsigned long get_next_poll_jiffies(void)
|
||||
|
@ -262,8 +266,7 @@ void mlx5_trigger_health_work(struct mlx5_core_dev *dev)
|
|||
if (!test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags))
|
||||
queue_work(health->wq, &health->work);
|
||||
else
|
||||
dev_err(&dev->pdev->dev,
|
||||
"new health works are not permitted at this stage\n");
|
||||
mlx5_core_err(dev, "new health works are not permitted at this stage\n");
|
||||
spin_unlock_irqrestore(&health->wq_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -284,7 +287,7 @@ static void poll_health(struct timer_list *t)
|
|||
|
||||
health->prev = count;
|
||||
if (health->miss_counter == MAX_MISSES) {
|
||||
dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n");
|
||||
mlx5_core_err(dev, "device's health compromised - reached miss count\n");
|
||||
print_health_info(dev);
|
||||
}
|
||||
|
||||
|
@ -352,6 +355,13 @@ void mlx5_drain_health_recovery(struct mlx5_core_dev *dev)
|
|||
cancel_delayed_work_sync(&dev->priv.health.recover_work);
|
||||
}
|
||||
|
||||
void mlx5_health_flush(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_core_health *health = &dev->priv.health;
|
||||
|
||||
flush_workqueue(health->wq);
|
||||
}
|
||||
|
||||
void mlx5_health_cleanup(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_core_health *health = &dev->priv.health;
|
||||
|
@ -370,7 +380,7 @@ int mlx5_health_init(struct mlx5_core_dev *dev)
|
|||
return -ENOMEM;
|
||||
|
||||
strcpy(name, "mlx5_health");
|
||||
strcat(name, dev_name(&dev->pdev->dev));
|
||||
strcat(name, dev->priv.name);
|
||||
health->wq = create_singlethread_workqueue(name);
|
||||
kfree(name);
|
||||
if (!health->wq)
|
||||
|
|
|
@ -77,15 +77,14 @@ int mlx5i_init(struct mlx5_core_dev *mdev,
|
|||
void *ppriv)
|
||||
{
|
||||
struct mlx5e_priv *priv = mlx5i_epriv(netdev);
|
||||
u16 max_mtu;
|
||||
int err;
|
||||
|
||||
err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
|
||||
netdev->mtu = max_mtu;
|
||||
mlx5e_set_netdev_mtu_boundaries(priv);
|
||||
netdev->mtu = netdev->max_mtu;
|
||||
|
||||
mlx5e_build_nic_params(mdev, &priv->rss_params, &priv->channels.params,
|
||||
mlx5e_get_netdev_max_channels(netdev),
|
||||
|
|
|
@ -567,24 +567,23 @@ query_ex:
|
|||
|
||||
static int set_hca_cap(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
int err;
|
||||
|
||||
err = handle_hca_cap(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "handle_hca_cap failed\n");
|
||||
mlx5_core_err(dev, "handle_hca_cap failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = handle_hca_cap_atomic(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "handle_hca_cap_atomic failed\n");
|
||||
mlx5_core_err(dev, "handle_hca_cap_atomic failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = handle_hca_cap_odp(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "handle_hca_cap_odp failed\n");
|
||||
mlx5_core_err(dev, "handle_hca_cap_odp failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -716,36 +715,29 @@ static int mlx5_core_set_issi(struct mlx5_core_dev *dev)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
||||
static int mlx5_pci_init(struct mlx5_core_dev *dev, struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
int err = 0;
|
||||
|
||||
dev->pdev = pdev;
|
||||
priv->pci_dev_data = id->driver_data;
|
||||
|
||||
pci_set_drvdata(dev->pdev, dev);
|
||||
strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN);
|
||||
priv->name[MLX5_MAX_NAME_LEN - 1] = 0;
|
||||
|
||||
mutex_init(&priv->pgdir_mutex);
|
||||
INIT_LIST_HEAD(&priv->pgdir_list);
|
||||
spin_lock_init(&priv->mkey_lock);
|
||||
|
||||
mutex_init(&priv->alloc_mutex);
|
||||
|
||||
dev->bar_addr = pci_resource_start(pdev, 0);
|
||||
priv->numa_node = dev_to_node(&dev->pdev->dev);
|
||||
|
||||
if (mlx5_debugfs_root)
|
||||
priv->dbg_root =
|
||||
debugfs_create_dir(pci_name(pdev), mlx5_debugfs_root);
|
||||
|
||||
err = mlx5_pci_enable_device(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
|
||||
goto err_dbg;
|
||||
mlx5_core_err(dev, "Cannot enable PCI device, aborting\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = request_bar(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "error requesting BARs, aborting\n");
|
||||
mlx5_core_err(dev, "error requesting BARs, aborting\n");
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
|
@ -753,7 +745,7 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
|||
|
||||
err = set_dma_caps(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed setting DMA capabilities mask, aborting\n");
|
||||
mlx5_core_err(dev, "Failed setting DMA capabilities mask, aborting\n");
|
||||
goto err_clr_master;
|
||||
}
|
||||
|
||||
|
@ -762,11 +754,11 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
|||
pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP128))
|
||||
mlx5_core_dbg(dev, "Enabling pci atomics failed\n");
|
||||
|
||||
dev->iseg_base = pci_resource_start(dev->pdev, 0);
|
||||
dev->iseg_base = dev->bar_addr;
|
||||
dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg));
|
||||
if (!dev->iseg) {
|
||||
err = -ENOMEM;
|
||||
dev_err(&pdev->dev, "Failed mapping initialization segment, aborting\n");
|
||||
mlx5_core_err(dev, "Failed mapping initialization segment, aborting\n");
|
||||
goto err_clr_master;
|
||||
}
|
||||
|
||||
|
@ -777,52 +769,47 @@ err_clr_master:
|
|||
release_bar(dev->pdev);
|
||||
err_disable:
|
||||
mlx5_pci_disable_device(dev);
|
||||
|
||||
err_dbg:
|
||||
debugfs_remove(priv->dbg_root);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
||||
static void mlx5_pci_close(struct mlx5_core_dev *dev)
|
||||
{
|
||||
iounmap(dev->iseg);
|
||||
pci_clear_master(dev->pdev);
|
||||
release_bar(dev->pdev);
|
||||
mlx5_pci_disable_device(dev);
|
||||
debugfs_remove_recursive(priv->dbg_root);
|
||||
}
|
||||
|
||||
static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
||||
static int mlx5_init_once(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
int err;
|
||||
|
||||
priv->devcom = mlx5_devcom_register_device(dev);
|
||||
if (IS_ERR(priv->devcom))
|
||||
dev_err(&pdev->dev, "failed to register with devcom (0x%p)\n",
|
||||
priv->devcom);
|
||||
dev->priv.devcom = mlx5_devcom_register_device(dev);
|
||||
if (IS_ERR(dev->priv.devcom))
|
||||
mlx5_core_err(dev, "failed to register with devcom (0x%p)\n",
|
||||
dev->priv.devcom);
|
||||
|
||||
err = mlx5_query_board_id(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "query board id failed\n");
|
||||
mlx5_core_err(dev, "query board id failed\n");
|
||||
goto err_devcom;
|
||||
}
|
||||
|
||||
err = mlx5_eq_table_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to initialize eq\n");
|
||||
mlx5_core_err(dev, "failed to initialize eq\n");
|
||||
goto err_devcom;
|
||||
}
|
||||
|
||||
err = mlx5_events_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to initialize events\n");
|
||||
mlx5_core_err(dev, "failed to initialize events\n");
|
||||
goto err_eq_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_cq_debugfs_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to initialize cq debugfs\n");
|
||||
mlx5_core_err(dev, "failed to initialize cq debugfs\n");
|
||||
goto err_events_cleanup;
|
||||
}
|
||||
|
||||
|
@ -838,31 +825,31 @@ static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
|
|||
|
||||
err = mlx5_init_rl_table(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init rate limiting\n");
|
||||
mlx5_core_err(dev, "Failed to init rate limiting\n");
|
||||
goto err_tables_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_mpfs_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init l2 table %d\n", err);
|
||||
mlx5_core_err(dev, "Failed to init l2 table %d\n", err);
|
||||
goto err_rl_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_eswitch_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init eswitch %d\n", err);
|
||||
mlx5_core_err(dev, "Failed to init eswitch %d\n", err);
|
||||
goto err_mpfs_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_sriov_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init sriov %d\n", err);
|
||||
mlx5_core_err(dev, "Failed to init sriov %d\n", err);
|
||||
goto err_eswitch_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_fpga_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init fpga device %d\n", err);
|
||||
mlx5_core_err(dev, "Failed to init fpga device %d\n", err);
|
||||
goto err_sriov_cleanup;
|
||||
}
|
||||
|
||||
|
@ -912,93 +899,78 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
|
|||
mlx5_devcom_unregister_device(dev->priv.devcom);
|
||||
}
|
||||
|
||||
static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
||||
bool boot)
|
||||
static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot)
|
||||
{
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
int err;
|
||||
|
||||
dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
|
||||
mutex_lock(&dev->intf_state_mutex);
|
||||
if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
|
||||
dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev),
|
||||
fw_rev_min(dev), fw_rev_sub(dev));
|
||||
mlx5_core_info(dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev),
|
||||
fw_rev_min(dev), fw_rev_sub(dev));
|
||||
|
||||
/* Only PFs hold the relevant PCIe information for this query */
|
||||
if (mlx5_core_is_pf(dev))
|
||||
pcie_print_link_status(dev->pdev);
|
||||
|
||||
/* on load removing any previous indication of internal error, device is
|
||||
* up
|
||||
*/
|
||||
dev->state = MLX5_DEVICE_STATE_UP;
|
||||
|
||||
/* wait for firmware to accept initialization segments configurations
|
||||
*/
|
||||
err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
|
||||
if (err) {
|
||||
dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
|
||||
FW_PRE_INIT_TIMEOUT_MILI);
|
||||
goto out_err;
|
||||
mlx5_core_err(dev, "Firmware over %d MS in pre-initializing state, aborting\n",
|
||||
FW_PRE_INIT_TIMEOUT_MILI);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mlx5_cmd_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
|
||||
goto out_err;
|
||||
mlx5_core_err(dev, "Failed initializing command interface, aborting\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI);
|
||||
if (err) {
|
||||
dev_err(&dev->pdev->dev, "Firmware over %d MS in initializing state, aborting\n",
|
||||
FW_INIT_TIMEOUT_MILI);
|
||||
mlx5_core_err(dev, "Firmware over %d MS in initializing state, aborting\n",
|
||||
FW_INIT_TIMEOUT_MILI);
|
||||
goto err_cmd_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_core_enable_hca(dev, 0);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "enable hca failed\n");
|
||||
mlx5_core_err(dev, "enable hca failed\n");
|
||||
goto err_cmd_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_core_set_issi(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to set issi\n");
|
||||
mlx5_core_err(dev, "failed to set issi\n");
|
||||
goto err_disable_hca;
|
||||
}
|
||||
|
||||
err = mlx5_satisfy_startup_pages(dev, 1);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to allocate boot pages\n");
|
||||
mlx5_core_err(dev, "failed to allocate boot pages\n");
|
||||
goto err_disable_hca;
|
||||
}
|
||||
|
||||
err = set_hca_ctrl(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "set_hca_ctrl failed\n");
|
||||
mlx5_core_err(dev, "set_hca_ctrl failed\n");
|
||||
goto reclaim_boot_pages;
|
||||
}
|
||||
|
||||
err = set_hca_cap(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "set_hca_cap failed\n");
|
||||
mlx5_core_err(dev, "set_hca_cap failed\n");
|
||||
goto reclaim_boot_pages;
|
||||
}
|
||||
|
||||
err = mlx5_satisfy_startup_pages(dev, 0);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to allocate init pages\n");
|
||||
mlx5_core_err(dev, "failed to allocate init pages\n");
|
||||
goto reclaim_boot_pages;
|
||||
}
|
||||
|
||||
err = mlx5_cmd_init_hca(dev, sw_owner_id);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "init hca failed\n");
|
||||
mlx5_core_err(dev, "init hca failed\n");
|
||||
goto reclaim_boot_pages;
|
||||
}
|
||||
|
||||
|
@ -1008,23 +980,50 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
|||
|
||||
err = mlx5_query_hca_caps(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "query hca failed\n");
|
||||
goto err_stop_poll;
|
||||
mlx5_core_err(dev, "query hca failed\n");
|
||||
goto stop_health;
|
||||
}
|
||||
|
||||
if (boot) {
|
||||
err = mlx5_init_once(dev, priv);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "sw objs init failed\n");
|
||||
goto err_stop_poll;
|
||||
}
|
||||
return 0;
|
||||
|
||||
stop_health:
|
||||
mlx5_stop_health_poll(dev, boot);
|
||||
reclaim_boot_pages:
|
||||
mlx5_reclaim_startup_pages(dev);
|
||||
err_disable_hca:
|
||||
mlx5_core_disable_hca(dev, 0);
|
||||
err_cmd_cleanup:
|
||||
mlx5_cmd_cleanup(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
|
||||
{
|
||||
int err;
|
||||
|
||||
mlx5_stop_health_poll(dev, boot);
|
||||
err = mlx5_cmd_teardown_hca(dev);
|
||||
if (err) {
|
||||
mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n");
|
||||
return err;
|
||||
}
|
||||
mlx5_reclaim_startup_pages(dev);
|
||||
mlx5_core_disable_hca(dev, 0);
|
||||
mlx5_cmd_cleanup(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_load(struct mlx5_core_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
dev->priv.uar = mlx5_get_uars_page(dev);
|
||||
if (IS_ERR(dev->priv.uar)) {
|
||||
dev_err(&pdev->dev, "Failed allocating uar, aborting\n");
|
||||
mlx5_core_err(dev, "Failed allocating uar, aborting\n");
|
||||
err = PTR_ERR(dev->priv.uar);
|
||||
goto err_get_uars;
|
||||
return err;
|
||||
}
|
||||
|
||||
mlx5_events_start(dev);
|
||||
|
@ -1032,64 +1031,131 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
|||
|
||||
err = mlx5_eq_table_create(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to create EQs\n");
|
||||
mlx5_core_err(dev, "Failed to create EQs\n");
|
||||
goto err_eq_table;
|
||||
}
|
||||
|
||||
err = mlx5_fw_tracer_init(dev->tracer);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init FW tracer\n");
|
||||
mlx5_core_err(dev, "Failed to init FW tracer\n");
|
||||
goto err_fw_tracer;
|
||||
}
|
||||
|
||||
err = mlx5_fpga_device_start(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "fpga device start failed %d\n", err);
|
||||
mlx5_core_err(dev, "fpga device start failed %d\n", err);
|
||||
goto err_fpga_start;
|
||||
}
|
||||
|
||||
err = mlx5_accel_ipsec_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "IPSec device start failed %d\n", err);
|
||||
mlx5_core_err(dev, "IPSec device start failed %d\n", err);
|
||||
goto err_ipsec_start;
|
||||
}
|
||||
|
||||
err = mlx5_accel_tls_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "TLS device start failed %d\n", err);
|
||||
mlx5_core_err(dev, "TLS device start failed %d\n", err);
|
||||
goto err_tls_start;
|
||||
}
|
||||
|
||||
err = mlx5_init_fs(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init flow steering\n");
|
||||
mlx5_core_err(dev, "Failed to init flow steering\n");
|
||||
goto err_fs;
|
||||
}
|
||||
|
||||
err = mlx5_core_set_hca_defaults(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to set hca defaults\n");
|
||||
mlx5_core_err(dev, "Failed to set hca defaults\n");
|
||||
goto err_fs;
|
||||
}
|
||||
|
||||
err = mlx5_sriov_attach(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "sriov init failed %d\n", err);
|
||||
mlx5_core_err(dev, "sriov init failed %d\n", err);
|
||||
goto err_sriov;
|
||||
}
|
||||
|
||||
err = mlx5_ec_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to init embedded CPU\n");
|
||||
mlx5_core_err(dev, "Failed to init embedded CPU\n");
|
||||
goto err_ec;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_ec:
|
||||
mlx5_sriov_detach(dev);
|
||||
err_sriov:
|
||||
mlx5_cleanup_fs(dev);
|
||||
err_fs:
|
||||
mlx5_accel_tls_cleanup(dev);
|
||||
err_tls_start:
|
||||
mlx5_accel_ipsec_cleanup(dev);
|
||||
err_ipsec_start:
|
||||
mlx5_fpga_device_stop(dev);
|
||||
err_fpga_start:
|
||||
mlx5_fw_tracer_cleanup(dev->tracer);
|
||||
err_fw_tracer:
|
||||
mlx5_eq_table_destroy(dev);
|
||||
err_eq_table:
|
||||
mlx5_pagealloc_stop(dev);
|
||||
mlx5_events_stop(dev);
|
||||
mlx5_put_uars_page(dev, dev->priv.uar);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5_unload(struct mlx5_core_dev *dev)
|
||||
{
|
||||
mlx5_ec_cleanup(dev);
|
||||
mlx5_sriov_detach(dev);
|
||||
mlx5_cleanup_fs(dev);
|
||||
mlx5_accel_ipsec_cleanup(dev);
|
||||
mlx5_accel_tls_cleanup(dev);
|
||||
mlx5_fpga_device_stop(dev);
|
||||
mlx5_fw_tracer_cleanup(dev->tracer);
|
||||
mlx5_eq_table_destroy(dev);
|
||||
mlx5_pagealloc_stop(dev);
|
||||
mlx5_events_stop(dev);
|
||||
mlx5_put_uars_page(dev, dev->priv.uar);
|
||||
}
|
||||
|
||||
static int mlx5_load_one(struct mlx5_core_dev *dev, bool boot)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
|
||||
mutex_lock(&dev->intf_state_mutex);
|
||||
if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
|
||||
mlx5_core_warn(dev, "interface is up, NOP\n");
|
||||
goto out;
|
||||
}
|
||||
/* remove any previous indication of internal error */
|
||||
dev->state = MLX5_DEVICE_STATE_UP;
|
||||
|
||||
err = mlx5_function_setup(dev, boot);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (boot) {
|
||||
err = mlx5_init_once(dev);
|
||||
if (err) {
|
||||
mlx5_core_err(dev, "sw objs init failed\n");
|
||||
goto function_teardown;
|
||||
}
|
||||
}
|
||||
|
||||
err = mlx5_load(dev);
|
||||
if (err)
|
||||
goto err_load;
|
||||
|
||||
if (mlx5_device_registered(dev)) {
|
||||
mlx5_attach_device(dev);
|
||||
} else {
|
||||
err = mlx5_register_device(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
|
||||
mlx5_core_err(dev, "register device failed %d\n", err);
|
||||
goto err_reg_dev;
|
||||
}
|
||||
}
|
||||
|
@ -1098,66 +1164,22 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
|||
out:
|
||||
mutex_unlock(&dev->intf_state_mutex);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
|
||||
err_reg_dev:
|
||||
mlx5_ec_cleanup(dev);
|
||||
|
||||
err_ec:
|
||||
mlx5_sriov_detach(dev);
|
||||
|
||||
err_sriov:
|
||||
mlx5_cleanup_fs(dev);
|
||||
|
||||
err_fs:
|
||||
mlx5_accel_tls_cleanup(dev);
|
||||
|
||||
err_tls_start:
|
||||
mlx5_accel_ipsec_cleanup(dev);
|
||||
|
||||
err_ipsec_start:
|
||||
mlx5_fpga_device_stop(dev);
|
||||
|
||||
err_fpga_start:
|
||||
mlx5_fw_tracer_cleanup(dev->tracer);
|
||||
|
||||
err_fw_tracer:
|
||||
mlx5_eq_table_destroy(dev);
|
||||
|
||||
err_eq_table:
|
||||
mlx5_pagealloc_stop(dev);
|
||||
mlx5_events_stop(dev);
|
||||
mlx5_put_uars_page(dev, priv->uar);
|
||||
|
||||
err_get_uars:
|
||||
mlx5_unload(dev);
|
||||
err_load:
|
||||
if (boot)
|
||||
mlx5_cleanup_once(dev);
|
||||
|
||||
err_stop_poll:
|
||||
mlx5_stop_health_poll(dev, boot);
|
||||
if (mlx5_cmd_teardown_hca(dev)) {
|
||||
dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
reclaim_boot_pages:
|
||||
mlx5_reclaim_startup_pages(dev);
|
||||
|
||||
err_disable_hca:
|
||||
mlx5_core_disable_hca(dev, 0);
|
||||
|
||||
err_cmd_cleanup:
|
||||
mlx5_cmd_cleanup(dev);
|
||||
|
||||
out_err:
|
||||
function_teardown:
|
||||
mlx5_function_teardown(dev, boot);
|
||||
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
|
||||
mutex_unlock(&dev->intf_state_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
||||
bool cleanup)
|
||||
static int mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
@ -1166,8 +1188,8 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
|||
|
||||
mutex_lock(&dev->intf_state_mutex);
|
||||
if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
|
||||
dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
|
||||
__func__);
|
||||
mlx5_core_warn(dev, "%s: interface is down, NOP\n",
|
||||
__func__);
|
||||
if (cleanup)
|
||||
mlx5_cleanup_once(dev);
|
||||
goto out;
|
||||
|
@ -1178,30 +1200,12 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
|||
if (mlx5_device_registered(dev))
|
||||
mlx5_detach_device(dev);
|
||||
|
||||
mlx5_ec_cleanup(dev);
|
||||
mlx5_sriov_detach(dev);
|
||||
mlx5_cleanup_fs(dev);
|
||||
mlx5_accel_ipsec_cleanup(dev);
|
||||
mlx5_accel_tls_cleanup(dev);
|
||||
mlx5_fpga_device_stop(dev);
|
||||
mlx5_fw_tracer_cleanup(dev->tracer);
|
||||
mlx5_eq_table_destroy(dev);
|
||||
mlx5_pagealloc_stop(dev);
|
||||
mlx5_events_stop(dev);
|
||||
mlx5_put_uars_page(dev, priv->uar);
|
||||
mlx5_unload(dev);
|
||||
|
||||
if (cleanup)
|
||||
mlx5_cleanup_once(dev);
|
||||
mlx5_stop_health_poll(dev, cleanup);
|
||||
|
||||
err = mlx5_cmd_teardown_hca(dev);
|
||||
if (err) {
|
||||
dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n");
|
||||
goto out;
|
||||
}
|
||||
mlx5_reclaim_startup_pages(dev);
|
||||
mlx5_core_disable_hca(dev, 0);
|
||||
mlx5_cmd_cleanup(dev);
|
||||
|
||||
mlx5_function_teardown(dev, cleanup);
|
||||
out:
|
||||
mutex_unlock(&dev->intf_state_mutex);
|
||||
return err;
|
||||
|
@ -1218,29 +1222,15 @@ static const struct devlink_ops mlx5_devlink_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define MLX5_IB_MOD "mlx5_ib"
|
||||
static int init_one(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
static int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx, const char *name)
|
||||
{
|
||||
struct mlx5_core_dev *dev;
|
||||
struct devlink *devlink;
|
||||
struct mlx5_priv *priv;
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
int err;
|
||||
|
||||
devlink = devlink_alloc(&mlx5_devlink_ops, sizeof(*dev));
|
||||
if (!devlink) {
|
||||
dev_err(&pdev->dev, "kzalloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
strncpy(priv->name, name, MLX5_MAX_NAME_LEN);
|
||||
priv->name[MLX5_MAX_NAME_LEN - 1] = 0;
|
||||
|
||||
dev = devlink_priv(devlink);
|
||||
priv = &dev->priv;
|
||||
priv->pci_dev_data = id->driver_data;
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
dev->pdev = pdev;
|
||||
dev->profile = &profile[prof_sel];
|
||||
dev->profile = &profile[profile_idx];
|
||||
|
||||
INIT_LIST_HEAD(&priv->ctx_list);
|
||||
spin_lock_init(&priv->ctx_lock);
|
||||
|
@ -1252,25 +1242,72 @@ static int init_one(struct pci_dev *pdev,
|
|||
INIT_LIST_HEAD(&priv->bfregs.reg_head.list);
|
||||
INIT_LIST_HEAD(&priv->bfregs.wc_head.list);
|
||||
|
||||
err = mlx5_pci_init(dev, priv);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "mlx5_pci_init failed with error code %d\n", err);
|
||||
goto clean_dev;
|
||||
mutex_init(&priv->alloc_mutex);
|
||||
mutex_init(&priv->pgdir_mutex);
|
||||
INIT_LIST_HEAD(&priv->pgdir_list);
|
||||
spin_lock_init(&priv->mkey_lock);
|
||||
|
||||
priv->dbg_root = debugfs_create_dir(name, mlx5_debugfs_root);
|
||||
if (!priv->dbg_root) {
|
||||
pr_err("mlx5_core: %s error, Cannot create debugfs dir, aborting\n", name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = mlx5_health_init(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "mlx5_health_init failed with error code %d\n", err);
|
||||
goto close_pci;
|
||||
}
|
||||
if (err)
|
||||
goto err_health_init;
|
||||
|
||||
err = mlx5_pagealloc_init(dev);
|
||||
if (err)
|
||||
goto err_pagealloc_init;
|
||||
|
||||
err = mlx5_load_one(dev, priv, true);
|
||||
return 0;
|
||||
|
||||
err_pagealloc_init:
|
||||
mlx5_health_cleanup(dev);
|
||||
err_health_init:
|
||||
debugfs_remove(dev->priv.dbg_root);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
|
||||
{
|
||||
mlx5_pagealloc_cleanup(dev);
|
||||
mlx5_health_cleanup(dev);
|
||||
debugfs_remove_recursive(dev->priv.dbg_root);
|
||||
}
|
||||
|
||||
#define MLX5_IB_MOD "mlx5_ib"
|
||||
static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct mlx5_core_dev *dev;
|
||||
struct devlink *devlink;
|
||||
int err;
|
||||
|
||||
devlink = devlink_alloc(&mlx5_devlink_ops, sizeof(*dev));
|
||||
if (!devlink) {
|
||||
dev_err(&pdev->dev, "kzalloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev = devlink_priv(devlink);
|
||||
|
||||
err = mlx5_mdev_init(dev, prof_sel, dev_name(&pdev->dev));
|
||||
if (err)
|
||||
goto mdev_init_err;
|
||||
|
||||
err = mlx5_pci_init(dev, pdev, id);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "mlx5_load_one failed with error code %d\n", err);
|
||||
mlx5_core_err(dev, "mlx5_pci_init failed with error code %d\n",
|
||||
err);
|
||||
goto pci_init_err;
|
||||
}
|
||||
|
||||
err = mlx5_load_one(dev, true);
|
||||
if (err) {
|
||||
mlx5_core_err(dev, "mlx5_load_one failed with error code %d\n",
|
||||
err);
|
||||
goto err_load_one;
|
||||
}
|
||||
|
||||
|
@ -1284,14 +1321,13 @@ static int init_one(struct pci_dev *pdev,
|
|||
return 0;
|
||||
|
||||
clean_load:
|
||||
mlx5_unload_one(dev, priv, true);
|
||||
mlx5_unload_one(dev, true);
|
||||
|
||||
err_load_one:
|
||||
mlx5_pagealloc_cleanup(dev);
|
||||
err_pagealloc_init:
|
||||
mlx5_health_cleanup(dev);
|
||||
close_pci:
|
||||
mlx5_pci_close(dev, priv);
|
||||
clean_dev:
|
||||
mlx5_pci_close(dev);
|
||||
pci_init_err:
|
||||
mlx5_mdev_uninit(dev);
|
||||
mdev_init_err:
|
||||
devlink_free(devlink);
|
||||
|
||||
return err;
|
||||
|
@ -1301,20 +1337,18 @@ static void remove_one(struct pci_dev *pdev)
|
|||
{
|
||||
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
|
||||
struct devlink *devlink = priv_to_devlink(dev);
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
|
||||
devlink_unregister(devlink);
|
||||
mlx5_unregister_device(dev);
|
||||
|
||||
if (mlx5_unload_one(dev, priv, true)) {
|
||||
dev_err(&dev->pdev->dev, "mlx5_unload_one failed\n");
|
||||
mlx5_health_cleanup(dev);
|
||||
if (mlx5_unload_one(dev, true)) {
|
||||
mlx5_core_err(dev, "mlx5_unload_one failed\n");
|
||||
mlx5_health_flush(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
mlx5_pagealloc_cleanup(dev);
|
||||
mlx5_health_cleanup(dev);
|
||||
mlx5_pci_close(dev, priv);
|
||||
mlx5_pci_close(dev);
|
||||
mlx5_mdev_uninit(dev);
|
||||
devlink_free(devlink);
|
||||
}
|
||||
|
||||
|
@ -1322,12 +1356,11 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
|
|||
pci_channel_state_t state)
|
||||
{
|
||||
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
|
||||
dev_info(&pdev->dev, "%s was called\n", __func__);
|
||||
mlx5_core_info(dev, "%s was called\n", __func__);
|
||||
|
||||
mlx5_enter_error_state(dev, false);
|
||||
mlx5_unload_one(dev, priv, false);
|
||||
mlx5_unload_one(dev, false);
|
||||
/* In case of kernel call drain the health wq */
|
||||
if (state) {
|
||||
mlx5_drain_health_wq(dev);
|
||||
|
@ -1354,7 +1387,9 @@ static int wait_vital(struct pci_dev *pdev)
|
|||
count = ioread32be(health->health_counter);
|
||||
if (count && count != 0xffffffff) {
|
||||
if (last_count && last_count != count) {
|
||||
dev_info(&pdev->dev, "Counter value 0x%x after %d iterations\n", count, i);
|
||||
mlx5_core_info(dev,
|
||||
"wait vital counter value 0x%x after %d iterations\n",
|
||||
count, i);
|
||||
return 0;
|
||||
}
|
||||
last_count = count;
|
||||
|
@ -1370,12 +1405,12 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
|
|||
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
|
||||
int err;
|
||||
|
||||
dev_info(&pdev->dev, "%s was called\n", __func__);
|
||||
mlx5_core_info(dev, "%s was called\n", __func__);
|
||||
|
||||
err = mlx5_pci_enable_device(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "%s: mlx5_pci_enable_device failed with error code: %d\n"
|
||||
, __func__, err);
|
||||
mlx5_core_err(dev, "%s: mlx5_pci_enable_device failed with error code: %d\n",
|
||||
__func__, err);
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
|
@ -1384,7 +1419,7 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
|
|||
pci_save_state(pdev);
|
||||
|
||||
if (wait_vital(pdev)) {
|
||||
dev_err(&pdev->dev, "%s: wait_vital timed out\n", __func__);
|
||||
mlx5_core_err(dev, "%s: wait_vital timed out\n", __func__);
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
|
@ -1394,17 +1429,16 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
|
|||
static void mlx5_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
int err;
|
||||
|
||||
dev_info(&pdev->dev, "%s was called\n", __func__);
|
||||
mlx5_core_info(dev, "%s was called\n", __func__);
|
||||
|
||||
err = mlx5_load_one(dev, priv, false);
|
||||
err = mlx5_load_one(dev, false);
|
||||
if (err)
|
||||
dev_err(&pdev->dev, "%s: mlx5_load_one failed with error code: %d\n"
|
||||
, __func__, err);
|
||||
mlx5_core_err(dev, "%s: mlx5_load_one failed with error code: %d\n",
|
||||
__func__, err);
|
||||
else
|
||||
dev_info(&pdev->dev, "%s: device recovered\n", __func__);
|
||||
mlx5_core_info(dev, "%s: device recovered\n", __func__);
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers mlx5_err_handler = {
|
||||
|
@ -1466,13 +1500,12 @@ succeed:
|
|||
static void shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
|
||||
struct mlx5_priv *priv = &dev->priv;
|
||||
int err;
|
||||
|
||||
dev_info(&pdev->dev, "Shutdown was called\n");
|
||||
mlx5_core_info(dev, "Shutdown was called\n");
|
||||
err = mlx5_try_fast_unload(dev);
|
||||
if (err)
|
||||
mlx5_unload_one(dev, priv, false);
|
||||
mlx5_unload_one(dev, false);
|
||||
mlx5_pci_disable_device(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,12 +48,12 @@
|
|||
extern uint mlx5_core_debug_mask;
|
||||
|
||||
#define mlx5_core_dbg(__dev, format, ...) \
|
||||
dev_dbg(&(__dev)->pdev->dev, "%s:%d:(pid %d): " format, \
|
||||
pr_debug("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_dbg_once(__dev, format, ...) \
|
||||
dev_dbg_once(&(__dev)->pdev->dev, "%s:%d:(pid %d): " format, \
|
||||
pr_debug_once("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
|
@ -64,28 +64,37 @@ do { \
|
|||
} while (0)
|
||||
|
||||
#define mlx5_core_err(__dev, format, ...) \
|
||||
dev_err(&(__dev)->pdev->dev, "%s:%d:(pid %d): " format, \
|
||||
pr_err("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_err_rl(__dev, format, ...) \
|
||||
dev_err_ratelimited(&(__dev)->pdev->dev, \
|
||||
"%s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
#define mlx5_core_err_rl(__dev, format, ...) \
|
||||
pr_err_ratelimited("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_warn(__dev, format, ...) \
|
||||
dev_warn(&(__dev)->pdev->dev, "%s:%d:(pid %d): " format, \
|
||||
pr_warn("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_warn_once(__dev, format, ...) \
|
||||
dev_warn_once(&(__dev)->pdev->dev, "%s:%d:(pid %d): " format, \
|
||||
pr_warn_once("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_warn_rl(__dev, format, ...) \
|
||||
pr_warn_ratelimited("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_info(__dev, format, ...) \
|
||||
dev_info(&(__dev)->pdev->dev, format, ##__VA_ARGS__)
|
||||
pr_info("%s " format, (__dev)->priv.name, ##__VA_ARGS__)
|
||||
|
||||
#define mlx5_core_info_rl(__dev, format, ...) \
|
||||
pr_info_ratelimited("%s:%s:%d:(pid %d): " format, (__dev)->priv.name, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
enum {
|
||||
MLX5_CMD_DATA, /* print command payload only */
|
||||
|
|
|
@ -79,7 +79,7 @@ static u64 uar2pfn(struct mlx5_core_dev *mdev, u32 index)
|
|||
else
|
||||
system_page_index = index;
|
||||
|
||||
return (pci_resource_start(mdev->pdev, 0) >> PAGE_SHIFT) + system_page_index;
|
||||
return (mdev->bar_addr >> PAGE_SHIFT) + system_page_index;
|
||||
}
|
||||
|
||||
static void up_rel_func(struct kref *kref)
|
||||
|
|
|
@ -170,7 +170,7 @@ static inline void mlx5_cq_arm(struct mlx5_core_cq *cq, u32 cmd,
|
|||
doorbell[0] = cpu_to_be32(sn << 28 | cmd | ci);
|
||||
doorbell[1] = cpu_to_be32(cq->cqn);
|
||||
|
||||
mlx5_write64(doorbell, uar_page + MLX5_CQ_DOORBELL, NULL);
|
||||
mlx5_write64(doorbell, uar_page + MLX5_CQ_DOORBELL);
|
||||
}
|
||||
|
||||
static inline void mlx5_cq_hold(struct mlx5_core_cq *cq)
|
||||
|
|
|
@ -361,6 +361,7 @@ enum {
|
|||
|
||||
enum {
|
||||
MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT = 0x1,
|
||||
MLX5_GENERAL_SUBTYPE_PCI_POWER_CHANGE_EVENT = 0x5,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -36,46 +36,25 @@
|
|||
#define MLX5_BF_OFFSET 0x800
|
||||
#define MLX5_CQ_DOORBELL 0x20
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
/* Assume that we can just write a 64-bit doorbell atomically. s390
|
||||
* actually doesn't have writeq() but S/390 systems don't even have
|
||||
* PCI so we won't worry about it.
|
||||
*
|
||||
* Note that the write is not atomic on 32-bit systems! In contrast to 64-bit
|
||||
* ones, it requires proper locking. mlx5_write64 doesn't do any locking, so use
|
||||
* it at your own discretion, protected by some kind of lock on 32 bits.
|
||||
*
|
||||
* TODO: use write{q,l}_relaxed()
|
||||
*/
|
||||
|
||||
#define MLX5_DECLARE_DOORBELL_LOCK(name)
|
||||
#define MLX5_INIT_DOORBELL_LOCK(ptr) do { } while (0)
|
||||
#define MLX5_GET_DOORBELL_LOCK(ptr) (NULL)
|
||||
|
||||
static inline void mlx5_write64(__be32 val[2], void __iomem *dest,
|
||||
spinlock_t *doorbell_lock)
|
||||
static inline void mlx5_write64(__be32 val[2], void __iomem *dest)
|
||||
{
|
||||
#if BITS_PER_LONG == 64
|
||||
__raw_writeq(*(u64 *)val, dest);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Just fall back to a spinlock to protect the doorbell if
|
||||
* BITS_PER_LONG is 32 -- there's no portable way to do atomic 64-bit
|
||||
* MMIO writes.
|
||||
*/
|
||||
|
||||
#define MLX5_DECLARE_DOORBELL_LOCK(name) spinlock_t name;
|
||||
#define MLX5_INIT_DOORBELL_LOCK(ptr) spin_lock_init(ptr)
|
||||
#define MLX5_GET_DOORBELL_LOCK(ptr) (ptr)
|
||||
|
||||
static inline void mlx5_write64(__be32 val[2], void __iomem *dest,
|
||||
spinlock_t *doorbell_lock)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (doorbell_lock)
|
||||
spin_lock_irqsave(doorbell_lock, flags);
|
||||
__raw_writel((__force u32) val[0], dest);
|
||||
__raw_writel((__force u32) val[1], dest + 4);
|
||||
if (doorbell_lock)
|
||||
spin_unlock_irqrestore(doorbell_lock, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* MLX5_DOORBELL_H */
|
||||
|
|
|
@ -133,6 +133,7 @@ enum {
|
|||
MLX5_REG_MTRC_CONF = 0x9041,
|
||||
MLX5_REG_MTRC_STDB = 0x9042,
|
||||
MLX5_REG_MTRC_CTRL = 0x9043,
|
||||
MLX5_REG_MPEIN = 0x9050,
|
||||
MLX5_REG_MPCNT = 0x9051,
|
||||
MLX5_REG_MTPPS = 0x9053,
|
||||
MLX5_REG_MTPPSE = 0x9054,
|
||||
|
@ -662,6 +663,7 @@ struct mlx5_core_dev {
|
|||
u64 sys_image_guid;
|
||||
phys_addr_t iseg_base;
|
||||
struct mlx5_init_seg __iomem *iseg;
|
||||
phys_addr_t bar_addr;
|
||||
enum mlx5_device_state state;
|
||||
/* sync interface state */
|
||||
struct mutex intf_state_mutex;
|
||||
|
@ -887,6 +889,7 @@ void mlx5_cmd_mbox_status(void *out, u8 *status, u32 *syndrome);
|
|||
int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type);
|
||||
int mlx5_cmd_alloc_uar(struct mlx5_core_dev *dev, u32 *uarn);
|
||||
int mlx5_cmd_free_uar(struct mlx5_core_dev *dev, u32 uarn);
|
||||
void mlx5_health_flush(struct mlx5_core_dev *dev);
|
||||
void mlx5_health_cleanup(struct mlx5_core_dev *dev);
|
||||
int mlx5_health_init(struct mlx5_core_dev *dev);
|
||||
void mlx5_start_health_poll(struct mlx5_core_dev *dev);
|
||||
|
|
|
@ -8027,6 +8027,52 @@ struct mlx5_ifc_ppcnt_reg_bits {
|
|||
union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits counter_set;
|
||||
};
|
||||
|
||||
struct mlx5_ifc_mpein_reg_bits {
|
||||
u8 reserved_at_0[0x2];
|
||||
u8 depth[0x6];
|
||||
u8 pcie_index[0x8];
|
||||
u8 node[0x8];
|
||||
u8 reserved_at_18[0x8];
|
||||
|
||||
u8 capability_mask[0x20];
|
||||
|
||||
u8 reserved_at_40[0x8];
|
||||
u8 link_width_enabled[0x8];
|
||||
u8 link_speed_enabled[0x10];
|
||||
|
||||
u8 lane0_physical_position[0x8];
|
||||
u8 link_width_active[0x8];
|
||||
u8 link_speed_active[0x10];
|
||||
|
||||
u8 num_of_pfs[0x10];
|
||||
u8 num_of_vfs[0x10];
|
||||
|
||||
u8 bdf0[0x10];
|
||||
u8 reserved_at_b0[0x10];
|
||||
|
||||
u8 max_read_request_size[0x4];
|
||||
u8 max_payload_size[0x4];
|
||||
u8 reserved_at_c8[0x5];
|
||||
u8 pwr_status[0x3];
|
||||
u8 port_type[0x4];
|
||||
u8 reserved_at_d4[0xb];
|
||||
u8 lane_reversal[0x1];
|
||||
|
||||
u8 reserved_at_e0[0x14];
|
||||
u8 pci_power[0xc];
|
||||
|
||||
u8 reserved_at_100[0x20];
|
||||
|
||||
u8 device_status[0x10];
|
||||
u8 port_state[0x8];
|
||||
u8 reserved_at_138[0x8];
|
||||
|
||||
u8 reserved_at_140[0x10];
|
||||
u8 receiver_detect_result[0x10];
|
||||
|
||||
u8 reserved_at_160[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_mpcnt_reg_bits {
|
||||
u8 reserved_at_0[0x8];
|
||||
u8 pcie_index[0x8];
|
||||
|
@ -8346,7 +8392,9 @@ struct mlx5_ifc_pcam_reg_bits {
|
|||
};
|
||||
|
||||
struct mlx5_ifc_mcam_enhanced_features_bits {
|
||||
u8 reserved_at_0[0x74];
|
||||
u8 reserved_at_0[0x6e];
|
||||
u8 pci_status_and_power[0x1];
|
||||
u8 reserved_at_6f[0x5];
|
||||
u8 mark_tx_action_cnp[0x1];
|
||||
u8 mark_tx_action_cqe[0x1];
|
||||
u8 dynamic_tx_overflow[0x1];
|
||||
|
@ -8954,6 +9002,7 @@ union mlx5_ifc_ports_control_registers_document_bits {
|
|||
struct mlx5_ifc_pmtu_reg_bits pmtu_reg;
|
||||
struct mlx5_ifc_ppad_reg_bits ppad_reg;
|
||||
struct mlx5_ifc_ppcnt_reg_bits ppcnt_reg;
|
||||
struct mlx5_ifc_mpein_reg_bits mpein_reg;
|
||||
struct mlx5_ifc_mpcnt_reg_bits mpcnt_reg;
|
||||
struct mlx5_ifc_pplm_reg_bits pplm_reg;
|
||||
struct mlx5_ifc_pplr_reg_bits pplr_reg;
|
||||
|
|
Загрузка…
Ссылка в новой задаче