/* SPDX-License-Identifier: Apache-2.0
 * Copyright (c) 2023 Cisco Systems, Inc.
 */

#ifndef _VNET_DEV_FUNCS_H_
#define _VNET_DEV_FUNCS_H_

#include <vppinfra/clib.h>
#include <vnet/dev/dev.h>

static_always_inline void *
vnet_dev_get_data (vnet_dev_t *dev)
{
  return dev->data;
}

static_always_inline vnet_dev_t *
vnet_dev_from_data (void *p)
{
  return (void *) ((u8 *) p - STRUCT_OFFSET_OF (vnet_dev_t, data));
}

static_always_inline void *
vnet_dev_get_port_data (vnet_dev_port_t *port)
{
  return port->data;
}

static_always_inline void *
vnet_dev_get_rx_queue_data (vnet_dev_rx_queue_t *rxq)
{
  return rxq->data;
}

static_always_inline void *
vnet_dev_get_tx_queue_data (vnet_dev_tx_queue_t *txq)
{
  return txq->data;
}

static_always_inline vnet_dev_t *
vnet_dev_get_by_index (u32 index)
{
  vnet_dev_main_t *dm = &vnet_dev_main;
  return pool_elt_at_index (dm->devices, index)[0];
}

static_always_inline vnet_dev_port_t *
vnet_dev_get_port_by_index (vnet_dev_t *dev, u32 index)
{
  return pool_elt_at_index (dev->ports, index)[0];
}

static_always_inline vnet_dev_port_t *
vnet_dev_get_port_from_dev_instance (u32 dev_instance)
{
  vnet_dev_main_t *dm = &vnet_dev_main;
  if (pool_is_free_index (dm->ports_by_dev_instance, dev_instance))
    return 0;
  return pool_elt_at_index (dm->ports_by_dev_instance, dev_instance)[0];
}

static_always_inline vnet_dev_port_t *
vnet_dev_get_port_from_hw_if_index (u32 hw_if_index)
{
  vnet_hw_interface_t *hw;
  vnet_dev_port_t *port;
  hw = vnet_get_hw_interface (vnet_get_main (), hw_if_index);
  port = vnet_dev_get_port_from_dev_instance (hw->dev_instance);

  if (!port || port->intf.hw_if_index != hw_if_index)
    return 0;

  return port;
}

static_always_inline vnet_dev_t *
vnet_dev_by_id (char *id)
{
  vnet_dev_main_t *dm = &vnet_dev_main;
  uword *p = hash_get (dm->device_index_by_id, id);
  if (p)
    return *pool_elt_at_index (dm->devices, p[0]);
  return 0;
}

static_always_inline uword
vnet_dev_get_dma_addr (vlib_main_t *vm, vnet_dev_t *dev, void *p)
{
  return dev->va_dma ? pointer_to_uword (p) : vlib_physmem_get_pa (vm, p);
}

static_always_inline void *
vnet_dev_get_bus_data (vnet_dev_t *dev)
{
  return (void *) dev->bus_data;
}

static_always_inline vnet_dev_bus_t *
vnet_dev_get_bus (vnet_dev_t *dev)
{
  vnet_dev_main_t *dm = &vnet_dev_main;
  return pool_elt_at_index (dm->buses, dev->bus_index);
}

static_always_inline void
vnet_dev_validate (vlib_main_t *vm, vnet_dev_t *dev)
{
  ASSERT (dev->process_node_index == vlib_get_current_process_node_index (vm));
  ASSERT (vm->thread_index == 0);
}

static_always_inline void
vnet_dev_port_validate (vlib_main_t *vm, vnet_dev_port_t *port)
{
  ASSERT (port->dev->process_node_index ==
	  vlib_get_current_process_node_index (vm));
  ASSERT (vm->thread_index == 0);
}

static_always_inline u32
vnet_dev_port_get_sw_if_index (vnet_dev_port_t *port)
{
  return port->intf.sw_if_index;
}

static_always_inline vnet_dev_port_t *
vnet_dev_get_port_by_id (vnet_dev_t *dev, vnet_dev_port_id_t port_id)
{
  foreach_vnet_dev_port (p, dev)
    if (p->port_id == port_id)
      return p;
  return 0;
}

static_always_inline vnet_dev_rx_queue_t *
vnet_dev_port_get_rx_queue_by_id (vnet_dev_port_t *port,
				  vnet_dev_queue_id_t queue_id)
{
  foreach_vnet_dev_port_rx_queue (q, port)
    if (q->queue_id == queue_id)
      return q;
  return 0;
}

static_always_inline vnet_dev_tx_queue_t *
vnet_dev_port_get_tx_queue_by_id (vnet_dev_port_t *port,
				  vnet_dev_queue_id_t queue_id)
{
  foreach_vnet_dev_port_tx_queue (q, port)
    if (q->queue_id == queue_id)
      return q;
  return 0;
}

static_always_inline void *
vnet_dev_alloc_with_data (u32 sz, u32 data_sz)
{
  void *p;
  sz += data_sz;
  sz = round_pow2 (sz, CLIB_CACHE_LINE_BYTES);
  p = clib_mem_alloc_aligned (sz, CLIB_CACHE_LINE_BYTES);
  clib_memset (p, 0, sz);
  return p;
}

static_always_inline void
vnet_dev_tx_queue_lock_if_needed (vnet_dev_tx_queue_t *txq)
{
  u8 free = 0;

  if (!txq->lock_needed)
    return;

  while (!__atomic_compare_exchange_n (&txq->lock, &free, 1, 0,
				       __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
    {
      while (__atomic_load_n (&txq->lock, __ATOMIC_RELAXED))
	CLIB_PAUSE ();
      free = 0;
    }
}

static_always_inline void
vnet_dev_tx_queue_unlock_if_needed (vnet_dev_tx_queue_t *txq)
{
  if (!txq->lock_needed)
    return;
  __atomic_store_n (&txq->lock, 0, __ATOMIC_RELEASE);
}

static_always_inline u8
vnet_dev_get_rx_queue_buffer_pool_index (vnet_dev_rx_queue_t *rxq)
{
  return rxq->buffer_template.buffer_pool_index;
}

static_always_inline u32
vnet_dev_get_rx_queue_buffer_data_size (vlib_main_t *vm,
					vnet_dev_rx_queue_t *rxq)
{
  u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq);
  return vlib_get_buffer_pool (vm, bpi)->data_size;
}

static_always_inline void
vnet_dev_rx_queue_rt_request (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq,
			      vnet_dev_rx_queue_rt_req_t req)
{
  __atomic_fetch_or (&rxq->runtime_request.as_number, req.as_number,
		     __ATOMIC_RELEASE);
}

static_always_inline vnet_dev_rx_node_runtime_t *
vnet_dev_get_rx_node_runtime (vlib_node_runtime_t *node)
{
  return (void *) node->runtime_data;
}

static_always_inline vnet_dev_tx_node_runtime_t *
vnet_dev_get_tx_node_runtime (vlib_node_runtime_t *node)
{
  return (void *) node->runtime_data;
}

static_always_inline vnet_dev_rx_queue_t *
foreach_vnet_dev_rx_queue_runtime_helper (vlib_node_runtime_t *node,
					  vnet_dev_rx_queue_t *rxq)
{
  vnet_dev_port_t *port;
  vnet_dev_rx_queue_rt_req_t req;

  if (rxq == 0)
    rxq = vnet_dev_get_rx_node_runtime (node)->first_rx_queue;
  else
  next:
    rxq = rxq->next_on_thread;

  if (PREDICT_FALSE (rxq == 0))
    return 0;

  if (PREDICT_TRUE (rxq->runtime_request.as_number == 0))
    return rxq;

  req.as_number =
    __atomic_exchange_n (&rxq->runtime_request.as_number, 0, __ATOMIC_ACQUIRE);

  port = rxq->port;
  if (req.update_next_index)
    rxq->next_index = port->intf.rx_next_index;

  if (req.update_feature_arc)
    {
      vlib_buffer_template_t *bt = &rxq->buffer_template;
      bt->current_config_index = port->intf.current_config_index;
      vnet_buffer (bt)->feature_arc_index = port->intf.feature_arc_index;
    }

  if (req.suspend_on)
    {
      rxq->suspended = 1;
      goto next;
    }

  if (req.suspend_off)
    rxq->suspended = 0;

  return rxq;
}

#define foreach_vnet_dev_rx_queue_runtime(q, node)                            \
  for (vnet_dev_rx_queue_t * (q) =                                            \
	 foreach_vnet_dev_rx_queue_runtime_helper (node, 0);                  \
       q; (q) = foreach_vnet_dev_rx_queue_runtime_helper (node, q))

static_always_inline void *
vnet_dev_get_rt_temp_space (vlib_main_t *vm)
{
  return vnet_dev_main.runtime_temp_spaces +
	 ((uword) vm->thread_index
	  << vnet_dev_main.log2_runtime_temp_space_sz);
}

static_always_inline void
vnet_dev_set_hw_addr_eth_mac (vnet_dev_hw_addr_t *addr, const u8 *eth_mac_addr)
{
  vnet_dev_hw_addr_t ha = {};
  clib_memcpy_fast (&ha.eth_mac, eth_mac_addr, sizeof (ha.eth_mac));
  *addr = ha;
}

static_always_inline vnet_dev_arg_t *
vnet_dev_get_port_arg_by_id (vnet_dev_port_t *port, u32 id)
{
  foreach_vnet_dev_port_args (a, port)
    if (a->id == id)
      return a;
  return 0;
}

static_always_inline int
vnet_dev_arg_get_bool (vnet_dev_arg_t *arg)
{
  ASSERT (arg->type == VNET_DEV_ARG_TYPE_BOOL);
  return arg->val_set ? arg->val.boolean : arg->default_val.boolean;
}

static_always_inline u32
vnet_dev_arg_get_uint32 (vnet_dev_arg_t *arg)
{
  ASSERT (arg->type == VNET_DEV_ARG_TYPE_UINT32);
  return arg->val_set ? arg->val.uint32 : arg->default_val.uint32;
}

static_always_inline u8 *
vnet_dev_arg_get_string (vnet_dev_arg_t *arg)
{
  ASSERT (arg->type == VNET_DEV_ARG_TYPE_STRING);
  return arg->val_set ? arg->val.string : arg->default_val.string;
}

#endif /* _VNET_DEV_FUNCS_H_ */
