예제 #1
0
파일: xport_rpm.c 프로젝트: KortanZ/linux
/*=========================================================================*/
glink_err_type xport_rpm_ssr(glink_transport_if_type *if_ptr)
{
  xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;

  glink_os_cs_acquire(ctx_ptr->tx_link_lock);
  glink_os_cs_acquire(ctx_ptr->rx_link_lock);
  ctx_ptr->tx_desc->write_ind = 0;
  ctx_ptr->tx_desc->read_ind = 0;
  ctx_ptr->rx_desc->write_ind = 0;
  ctx_ptr->rx_desc->read_ind = 0;
  ctx_ptr->reset = TRUE;
  glink_os_cs_release(ctx_ptr->rx_link_lock);
  glink_os_cs_release(ctx_ptr->tx_link_lock);

  return GLINK_STATUS_SUCCESS;
}
예제 #2
0
/*===========================================================================
FUNCTION      glink_init

DESCRIPTION   Initializes the GLink core library.

ARGUMENTS     None

RETURN VALUE  None

SIDE EFFECTS  None
===========================================================================*/
void glink_init(void)
{
  uint32 i;

  glink_mem_log_cs = glink_os_cs_create();

  glink_core_status = GLINK_INITIALIZED;

  /* Create/Initalize crtitical sections */
  glink_transport_q_cs = glink_os_cs_create();
  if(glink_transport_q_cs == NULL) {
    return;
  }

  glink_os_cs_acquire(glink_transport_q_cs);
  for(i= 0; i < sizeof(glink_registered_transports)/sizeof(smem_list_type);
      i++)
  {
    smem_list_init(&glink_registered_transports[i]);
  }
  glink_os_cs_release(glink_transport_q_cs);
}
예제 #3
0
void glinki_scan_channels_and_notify_discon
(
  glink_transport_if_type *if_ptr
)
{
  glink_channel_ctx_type *open_ch_ctx;
  glink_core_xport_ctx_type  *xport_ctx;

  ASSERT(if_ptr != NULL);

  xport_ctx = if_ptr->glink_core_priv;

  /* Find channel in the open_list */
  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
  while(open_ch_ctx != NULL)
  {
    /* Found channel, transition it to appropriate state based
     * on current state */
    if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
      open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN;

      /* Inform the client */
      open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
          GLINK_REMOTE_DISCONNECTED);
    } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
      /* Local side never opened the channel */
      /* Free channel resources */
      xport_ctx->channel_cleanup(open_ch_ctx);

      smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);

      glink_os_free(open_ch_ctx);
    }
    open_ch_ctx = smem_list_next(open_ch_ctx);
  }/* end while */
  glink_os_cs_release(&xport_ctx->channel_q_cs);
}
예제 #4
0
/**
 * Opens a logical GLink based on the specified config params
 *
 * @param[in]    cfg_ptr  Pointer to the configuration structure for the
 *                        GLink. See glink.h
 * @param[out]   handle   GLink handle associated with the logical channel
 *
 * @return       Standard GLink error codes
 *
 * @sideeffects  Allocates channel resources and informs remote host about
 *               channel open.
 */
glink_err_type glink_open
(
  glink_open_config_type *cfg_ptr,
  glink_handle_type      *handle
)
{
  glink_transport_if_type *if_ptr, *req_if_ptr;
  glink_channel_ctx_type  *ch_ctx;
  unsigned int            remote_host;

  /* Param validation */
  if(cfg_ptr == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  if(cfg_ptr->remote_ss == NULL             ||
     cfg_ptr->name == NULL                  ||
     cfg_ptr->notify_state == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  /* Evaluate the equivalent edge name->enum for future use */
  remote_host = glinki_find_remote_host(cfg_ptr->remote_ss);

  if(remote_host == GLINK_NUM_HOSTS ) {
    /* Unknown transport name trying to register with GLink */
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, cfg_ptr->name, "",
        cfg_ptr->remote_ss, GLINK_STATUS_INVALID_PARAM);

    return GLINK_STATUS_INVALID_PARAM;
  }

  /* Allocate and initialize channel info structure */
  ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
  if(ch_ctx == NULL) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, "",
        "", GLINK_STATUS_OUT_OF_RESOURCES);
    return GLINK_STATUS_OUT_OF_RESOURCES;
  }

  /* Fill in the channel info structure */
  glink_os_string_copy(ch_ctx->name, cfg_ptr->name, sizeof(ch_ctx->name));
  ch_ctx->priv = cfg_ptr->priv;
  ch_ctx->notify_rx = cfg_ptr->notify_rx;
  ch_ctx->notify_rxv = cfg_ptr->notify_rxv;
  ch_ctx->notify_tx_done = cfg_ptr->notify_tx_done;
  ch_ctx->notify_state = cfg_ptr->notify_state;
  ch_ctx->notify_rx_intent_req = cfg_ptr->notify_rx_intent_req;
  ch_ctx->notify_rx_intent = cfg_ptr->notify_rx_intent;
  ch_ctx->notify_rx_sigs = cfg_ptr->notify_rx_sigs;
  ch_ctx->ch_open_options = cfg_ptr->options;
  ch_ctx->notify_rx_abort = cfg_ptr->notify_rx_abort;
  ch_ctx->notify_tx_abort = cfg_ptr->notify_tx_abort;

  if (ch_ctx->notify_rx_sigs == NULL) {
    /* set default callback */
    ch_ctx->notify_rx_sigs = glink_default_notify_rx_sigs;
  }

  glink_os_cs_acquire(glink_transport_q_cs);

  /* Check to see if requested transport is available */
  for (if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
       if_ptr != NULL;
       if_ptr = smem_list_next(if_ptr))
  {
    glink_core_xport_ctx_type *xport_ctx = if_ptr->glink_core_priv;
    glink_channel_ctx_type    *allocated_ch_ctx;

    if (xport_ctx->status == GLINK_XPORT_LINK_UP &&
        (cfg_ptr->transport == NULL ||
         0 == strcmp(cfg_ptr->transport, xport_ctx->xport)) &&
        xport_ctx->verify_open_cfg(ch_ctx))
    {
      glink_err_type status;

      if(cfg_ptr->transport == NULL)
      {
        /* get best available transport */
        if_ptr = req_if_ptr = glink_get_best_xport(remote_host);
      }
      else
      {
        if(cfg_ptr->options & GLINK_OPT_INITIAL_XPORT)
        {
          /* xport suggested by client is optional.
           * get best available xport */
          req_if_ptr = glink_get_best_xport(remote_host);
        }
        else
        {
          req_if_ptr = if_ptr;
        }
      }
      /* Xport match found */
      status = glinki_add_ch_to_xport( if_ptr,
                                       req_if_ptr,
                                       ch_ctx,
                                       &allocated_ch_ctx,
                                       TRUE,
                                       TRUE,
                                       if_ptr->glink_priority );

      if (status == GLINK_STATUS_SUCCESS) {
        /* Set the handle and return */
        *handle = allocated_ch_ctx;
      }
      else {
        *handle = NULL;
      }

      glink_os_cs_release(glink_transport_q_cs);

      GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, ch_ctx->name, xport_ctx->xport,
        xport_ctx->remote_ss, status);
      return status;
    }
  } /* end for() */

  glink_os_cs_release(glink_transport_q_cs);

  /* Code gets here if we are not able to find reqeusted transport */
  GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, cfg_ptr->transport,
      cfg_ptr->remote_ss, GLINK_STATUS_NO_TRANSPORT);
  glink_os_free(ch_ctx);
  return GLINK_STATUS_NO_TRANSPORT;
}
예제 #5
0
glink_err_type glinki_add_ch_to_xport
(
  glink_transport_if_type  *if_ptr,
  glink_transport_if_type  *req_if_ptr,
  glink_channel_ctx_type   *ch_ctx,
  glink_channel_ctx_type   **allocated_ch_ctx,
  unsigned int              local_open,
  boolean                      migration_state,
  glink_xport_priority      migrated_ch_prio
)
{
  glink_err_type             status = 0;
  glink_channel_ctx_type     *open_ch_ctx;
  glink_core_xport_ctx_type  *xport_ctx = if_ptr->glink_core_priv;

  /* See if channel already exists in open_list */
  glink_os_cs_acquire(&xport_ctx->channel_q_cs);
  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
  while(open_ch_ctx != NULL)
  {
    if (strcmp(open_ch_ctx->name, ch_ctx->name) == 0)
    {
      /* We've found a channel name is already in the list of open channel */
      /* increase reference open count for channel */
      *allocated_ch_ctx = open_ch_ctx;
      open_ch_ctx->ref_count++;

      /* Case A: Channel was opened before on the same host */
      if((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) && local_open) {

        open_ch_ctx->req_if_ptr = req_if_ptr;

        /* Copy local open ctx params */
        open_ch_ctx->notify_rx = ch_ctx->notify_rx;
        open_ch_ctx->notify_rxv = ch_ctx->notify_rxv;
        open_ch_ctx->notify_tx_done = ch_ctx->notify_tx_done;
        open_ch_ctx->notify_state = ch_ctx->notify_state;
        open_ch_ctx->notify_rx_intent_req = ch_ctx->notify_rx_intent_req;
        open_ch_ctx->notify_rx_intent = ch_ctx->notify_rx_intent;
        open_ch_ctx->notify_rx_sigs = ch_ctx->notify_rx_sigs;
        open_ch_ctx->priv = ch_ctx->priv;
        open_ch_ctx->ch_open_options = ch_ctx->ch_open_options;

        /* release lock before context switch otherwise it is causing
         * deadlock */
        glink_os_cs_release(&xport_ctx->channel_q_cs);

        /* Send open cmd to transport */
        status = if_ptr->tx_cmd_ch_open(if_ptr,
                      open_ch_ctx->lcid, open_ch_ctx->name,
                      open_ch_ctx->req_if_ptr->glink_priority);
      }
      else if ((open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN) &&
               (!local_open))
      {
        /* Case B: Channel was opened on this end and we got a remote open */
        open_ch_ctx->rcid = ch_ctx->rcid;

        status = xport_ctx->channel_init(open_ch_ctx);

        /* release lock before context switch otherwise it is causing deadlock */
        glink_os_cs_release(&xport_ctx->channel_q_cs);

        if (status == GLINK_STATUS_SUCCESS)
        {
          /* Send ACK to transport */
          if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, open_ch_ctx->rcid, migrated_ch_prio);
        }
      } else if ((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE)
                  && (local_open)) {
        /* Allocate new channel context */
        break; /* code would break out of loop and create new ch ctx */
      } else {
        /* Can't handle this state */
        ASSERT(0);
      }

      break;
    } /* end if match found */
    open_ch_ctx = smem_list_next(open_ch_ctx);
  }/* end while */

  if (open_ch_ctx != NULL)
  {
    glink_os_free(ch_ctx);

    /* connect channel here if state is local open and remote open request
     * comes up and channel migration is done; channel will be connected in
     * remote_open_ack if channel state is remote open and local open
     * request comes up */
    if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN &&
       migration_state == FALSE && status == GLINK_STATUS_SUCCESS)
    {
      /* Set the channel state to OPEN */
      open_ch_ctx->state = GLINK_CH_STATE_OPEN;
      /* Inform the client */
      open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
                                GLINK_CONNECTED);
    }
  }
  else
  {
    /* Channel not in the list - it was not previously opened */
    ch_ctx->if_ptr = if_ptr;
    *allocated_ch_ctx = ch_ctx;

    /* Set channel state */
    if (local_open) {
      /* This is a local open */
      ch_ctx->state      = GLINK_CH_STATE_LOCAL_OPEN;
      ch_ctx->req_if_ptr = req_if_ptr;
    }
    else {
      ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN;
    }

    glink_os_cs_init(&ch_ctx->tx_cs);

    /* Append the channel to the transport interface's open_list */
    ch_ctx->ref_count++;
    ch_ctx->lcid = xport_ctx->free_lcid;
    xport_ctx->free_lcid++;
    smem_list_append(&if_ptr->glink_core_priv->open_list, ch_ctx);

    /* release lock before context switch otherwise it is causing deadlock */
    glink_os_cs_release(&xport_ctx->channel_q_cs);

    /* Send the OPEN command to transport */
    if (local_open)
    {
      status = if_ptr->tx_cmd_ch_open(if_ptr, ch_ctx->lcid,
                                      ch_ctx->name,
                                      ch_ctx->req_if_ptr->glink_priority);
    }
    else
    {
      /* initialize channel resources */
      status = xport_ctx->channel_init(ch_ctx);

      /* ACK the transport for remote open */
      if (status == GLINK_STATUS_SUCCESS)
      {
        if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, ch_ctx->rcid,
                                          migrated_ch_prio);
      }
    }

    if (status != GLINK_STATUS_SUCCESS)
    {
      /* Remove the channel from the transport interface's open_list */
      xport_ctx->free_lcid--;

      glink_os_cs_acquire(&xport_ctx->channel_q_cs);
      smem_list_delete(&if_ptr->glink_core_priv->open_list, ch_ctx);
      glink_os_cs_release(&xport_ctx->channel_q_cs);

      /* free the ch_ctx structure and return */
      xport_ctx->channel_cleanup(ch_ctx);
      glink_os_free(ch_ctx);
    }
  }

  return status;
}
예제 #6
0
/*===========================================================================
FUNCTION      glink_core_register_transport

DESCRIPTION   Transport calls this API to register its interface with GLINK
              Core

ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
                      for each edge

            *cfg      Pointer to transport configuration structure.

RETURN VALUE  Standard GLINK error codes.

SIDE EFFECTS  None
===========================================================================*/
glink_err_type glink_core_register_transport
(
  glink_transport_if_type       *if_ptr,
  glink_core_transport_cfg_type *cfg
)
{
  unsigned int remote_host = 0;
  glink_core_xport_ctx_type *xport_ctx;
  /* Param validation */
  if(if_ptr == NULL || cfg == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  if(cfg->name == NULL       ||
     cfg->remote_ss == NULL  ||
     cfg->version == NULL    ||
     cfg->version_count == 0 ||
     cfg->max_cid == 0)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }


  if(if_ptr->tx_cmd_version == NULL             ||
     if_ptr->tx_cmd_version_ack == NULL         ||
     if_ptr->set_version == NULL                ||
     if_ptr->tx_cmd_ch_open == NULL             ||
     if_ptr->tx_cmd_ch_close == NULL            ||
     if_ptr->tx_cmd_ch_remote_open_ack == NULL  ||
     if_ptr->tx_cmd_ch_remote_close_ack == NULL ||
     if_ptr->tx_cmd_set_sigs  == NULL           ||
     if_ptr->ssr  == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
        cfg->remote_ss, GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;;
  }


  /* Allocate/fill out the GLink Core interface structure */
  {
    glink_core_if_type *core_if = glink_os_calloc(sizeof(glink_core_if_type));
    if(core_if == NULL) {
      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
      return GLINK_STATUS_OUT_OF_RESOURCES;
    }
    core_if->link_up = glink_link_up;
    core_if->rx_cmd_version = glink_rx_cmd_version;
    core_if->rx_cmd_version_ack = glink_rx_cmd_version_ack;
    core_if->rx_cmd_ch_remote_open = glink_rx_cmd_ch_remote_open;
    core_if->rx_cmd_ch_open_ack = glink_rx_cmd_ch_open_ack;
    core_if->rx_cmd_ch_close_ack = glink_rx_cmd_ch_close_ack;
    core_if->rx_cmd_ch_remote_close = glink_rx_cmd_ch_remote_close;
    core_if->ch_state_local_trans = glink_ch_state_local_trans;
    core_if->rx_put_pkt_ctx = glink_rx_put_pkt_ctx;
    core_if->rx_cmd_remote_sigs = glink_rx_cmd_remote_sigs;
    core_if->tx_resume = glink_tx_resume;
    core_if->set_core_version = glink_set_core_version;

    /* Set the glink_core_if_ptr to point to the allocated structure */
    if_ptr->glink_core_if_ptr = core_if;
  }

  /* Allocate/fill out the GLink private context data */
  {
     xport_ctx = glink_os_calloc(sizeof(glink_core_xport_ctx_type));
    if(xport_ctx == NULL) {
      /* Free previously allocated memory */
      glink_os_free(if_ptr->glink_core_if_ptr);

      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);

      return GLINK_STATUS_OUT_OF_RESOURCES;
    }

    glink_os_string_copy(xport_ctx->xport, cfg->name,
        sizeof(xport_ctx->xport));
    glink_os_string_copy(xport_ctx->remote_ss, cfg->remote_ss,
        sizeof(xport_ctx->xport));
    xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */
    xport_ctx->version_array = cfg->version;
    xport_ctx->version_indx = cfg->version_count - 1;

    glink_os_cs_init(&xport_ctx->channel_q_cs);
    glink_os_cs_init(&xport_ctx->liid_cs);

    glink_os_cs_acquire(&xport_ctx->channel_q_cs);
    smem_list_init(&xport_ctx->open_list);
    glink_os_cs_release(&xport_ctx->channel_q_cs);

    /* Set the glink_core_if_ptr to point to the allocated structure */
    if_ptr->glink_core_priv = xport_ctx;
    xport_ctx->status = GLINK_XPORT_REGISTERED;
  }

  /* Push the transport interface into appropriate queue */
  remote_host = glinki_find_remote_host(cfg->remote_ss);

  if(remote_host == GLINK_NUM_HOSTS ) {
    /* Unknown transport name trying to register with GLink */
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
           xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);

    return GLINK_STATUS_INVALID_PARAM;
  }
  glink_os_cs_acquire(glink_transport_q_cs);
  smem_list_append(&glink_registered_transports[remote_host], if_ptr);
  glink_os_cs_release(glink_transport_q_cs);

  GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);

  return GLINK_STATUS_SUCCESS;
}
예제 #7
0
/**
 * Client uses this to signal to GLink layer that it is done with the received
 * data buffer. This API should be called to free up the receive buffer, which,
 * in zero-copy mode is actually remote-side's transmit buffer.
 *
 * @param[in]    handle   GLink handle associated with the logical channel
 *
 * @param[in]   *ptr      Pointer to the received buffer
 *
 * @param[in]   reuse    Reuse intent
 *
 * @return       Standard GLink error codes
 *
 * @sideeffects  GLink XAL frees the Rx buffer
 */
glink_err_type glink_rx_done
(
  glink_handle_type handle,
  const void        *ptr,
  boolean           reuse
)
{
  glink_rx_intent_type      *lc_intent;
  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;

  /* Input validation */
  if(handle == NULL || ptr == NULL) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, NULL, "",
        "", GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  /* short circuit for intentless mode */
  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
    return GLINK_STATUS_SUCCESS;
  }

  /* Make sure channel is in OPEN state */
  if(handle->state != GLINK_CH_STATE_OPEN)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
    return GLINK_STATUS_FAILURE;
  }

  /* Free the intent */
  lc_intent = smem_list_first(&handle->pintents->local_intent_client_q);
  while(lc_intent != NULL) {
    size_t tmp;

    if(lc_intent->iovec == ptr || (handle->notify_rxv == NULL &&
       (lc_intent->data == ptr ||
       ptr == lc_intent->vprovider(lc_intent->iovec, 0, &tmp)))) {

      uint32 iid;

      /* Found intent, delete it */
      glink_os_cs_acquire(&handle->pintents->intent_q_cs);
      smem_list_delete(&handle->pintents->local_intent_client_q, lc_intent);
      glink_os_cs_release(&handle->pintents->intent_q_cs);

      iid = lc_intent->iid;

      if (reuse)
      {
        lc_intent->used = 0;

        glink_os_cs_acquire(&handle->pintents->intent_q_cs);
        smem_list_append(&handle->pintents->local_intent_q, lc_intent);
        glink_os_cs_release(&handle->pintents->intent_q_cs);
      }
      else
      {
        /* Free the intent */
        handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
        if(lc_intent->data) {
          /* Free the bounce buffer if we had allocated one */
          glink_os_free(lc_intent->data);
        }
        glink_os_free(lc_intent);
      }

      /* Note that the actual buffer, lc_intent->data, was allocated by the
      * transport and should be freed by the xport. We should not touch it */
      /* Let the xport know we are done with the buffer */
      handle->if_ptr->tx_cmd_local_rx_done(handle->if_ptr, handle->lcid,
                                           iid, reuse);

      GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
          xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
      return GLINK_STATUS_SUCCESS;
    }
    lc_intent = smem_list_next(lc_intent);
  }

  GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
  return GLINK_STATUS_INVALID_PARAM;
}
예제 #8
0
/**
 * Queue one or more Rx intent for the logical GPIC Link channel.
 *
 * @param[in]    handle   GLink handle associated with the logical channel
 *
 * @param[in]   *pkt_priv Per packet private data
 *
 * @param[in]   size      Size of buffer
 *
 * @return       Standard GLink error codes
 *
 * @sideeffects  GLink XAL allocates rx buffers for receiving packets
 */
glink_err_type glink_queue_rx_intent
(
  glink_handle_type handle,
  const void        *pkt_priv,
  size_t            size
)
{
  glink_err_type         status;
  glink_rx_intent_type   *lc_intent;
  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
  size_t tmp;

  /* Input validation */
  if(handle == NULL || size == 0) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, NULL, "",
        "", GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  /* short circuit for intentless mode */
  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
    return GLINK_STATUS_FAILURE;
  }

  /* Make sure channel is in OPEN state */
  if(handle->state != GLINK_CH_STATE_OPEN)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
    return GLINK_STATUS_FAILURE;
  }

  /* Allocate an intent structure */
  lc_intent = glink_os_calloc(sizeof(glink_rx_intent_type));
  if(lc_intent == NULL) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
        xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
    return GLINK_STATUS_OUT_OF_RESOURCES;
  }

  glink_os_cs_acquire(&handle->if_ptr->glink_core_priv->liid_cs);

  /* Call transport API to allocate rx intent buffer */
  status = handle->if_ptr->allocate_rx_intent(handle->if_ptr, size, lc_intent);
  if(status != GLINK_STATUS_SUCCESS) {
    glink_os_free(lc_intent);
    glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
        xport_ctx->remote_ss, status);
    return status;
  }

  if (handle->notify_rxv == NULL &&
     (lc_intent->vprovider(lc_intent->iovec, 0, &tmp) == NULL || tmp < size)) {
    /* Allocate bounce buffer for non-vectored Rx */
    lc_intent->data = glink_os_malloc(size);

    if(lc_intent->data == NULL) {
      handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
      glink_os_free(lc_intent);
      glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
      GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name,
        xport_ctx->xport, xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
      return GLINK_STATUS_OUT_OF_RESOURCES;
    }
  }

  /* push the intent on local queue. Do this before calling tx cmd
     as transport may try to read data into the newly queued rx_buffer */
  lc_intent->iid = handle->if_ptr->glink_core_priv->liid;
  lc_intent->size = size;
  lc_intent->pkt_priv = pkt_priv;
  glink_os_cs_acquire(&handle->pintents->intent_q_cs);
  smem_list_append(&handle->pintents->local_intent_q, lc_intent);
  glink_os_cs_release(&handle->pintents->intent_q_cs);

  /* Call transport API to queue rx intent */
  /* Increment the local intent ID counter associated with this channel */
  handle->if_ptr->glink_core_priv->liid++;

  status = handle->if_ptr->tx_cmd_local_rx_intent(handle->if_ptr,
              handle->lcid, size, lc_intent->iid);
  if(status != GLINK_STATUS_SUCCESS) {
    /* Failure */
    glink_os_cs_acquire(&handle->pintents->intent_q_cs);
    smem_list_delete(&handle->pintents->local_intent_q, lc_intent);
    glink_os_cs_release(&handle->pintents->intent_q_cs);

    handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
    glink_os_free(lc_intent->data);
    glink_os_free(lc_intent);
  }
  glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);

  GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, status);
  return status;
}
예제 #9
0
/**
 * Transmit the provided vector buffer over GLink.
 *
 * @param[in]    handle    GLink handle associated with the logical channel
 *
 * @param[in]   *pkt_priv  Per packet private data
 *
 * @param[in]   *iovec     Pointer to the vector buffer to be transmitted
 *
 * @param[in]   size       Size of buffer
 *
 * @param[in]   vprovider  Buffer provider for virtual space
 *
 * @param[in]   pprovider  Buffer provider for physical space
 *
 * @param[in]   req_intent Whether to block and request for remote rx intent in
 *                         case it is not available for this pkt tx
 *
 * @return       Standard GLink error codes
 *
 * @sideeffects  Causes remote host to wake-up and process rx pkt
 */
glink_err_type glink_txv
(
  glink_handle_type        handle,
  const void               *pkt_priv,
  void                     *iovec,
  size_t                   size,
  glink_buffer_provider_fn vprovider,
  glink_buffer_provider_fn pprovider,
  uint32                   options
)
{
  glink_err_type         status;
  glink_core_tx_pkt_type pctx;
  boolean                req_intent = options & GLINK_TX_REQ_INTENT;
  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;

  /* Input validation */
  if(handle == NULL || iovec == NULL || size == 0 ||
     (vprovider == NULL && pprovider == NULL)) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, NULL, "",
        "", GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  /* Make sure channel is in OPEN state */
  if(handle->state != GLINK_CH_STATE_OPEN )
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
    return GLINK_STATUS_FAILURE;
  }

  /* Protect the entire tx operation under a lock as a client may call
     tx in different thread context */
  glink_os_cs_acquire(&handle->tx_cs);

  pctx.pkt_priv = pkt_priv;
  pctx.size = size;
  pctx.size_remaining = size;
  pctx.vprovider = vprovider;
  pctx.pprovider = pprovider;

  if (vprovider == &glink_dummy_tx_vprovider)
  {
    pctx.data = (void*)iovec;
    pctx.iovec = &pctx;
  }
  else
  {
    pctx.data = (void*)iovec;
    pctx.iovec = iovec;
  }

  status = xport_ctx->use_rm_intent(handle, &pctx, req_intent);

  /* Call transport API to transmit data */
  while (pctx.size_remaining != 0 && status == GLINK_STATUS_SUCCESS)
  {
    status = handle->if_ptr->tx(handle->if_ptr, handle->lcid, &pctx);
  }

  GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, status);

  glink_os_cs_release(&handle->tx_cs);
  return status;
}
예제 #10
0
파일: xport_rpm.c 프로젝트: KortanZ/linux
/*=========================================================================*/
glink_err_type xport_rpm_isr( xport_rpm_ctx_type *ctx_ptr )
{
  uint32 write_ind, read_ind;
  boolean stop_processing = FALSE;

  if (ctx_ptr->reset == TRUE)
  {
    /* reset flag has been set after SSR, notify link up */
    ctx_ptr->reset = FALSE;
    ctx_ptr->xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)ctx_ptr);
  }

  glink_os_cs_acquire(ctx_ptr->rx_link_lock);

  /* Process pending commands and data */
  write_ind = ctx_ptr->rx_desc->write_ind;
  read_ind = ctx_ptr->rx_desc->read_ind;

  XPORT_RPM_LOG("RPM ISR write ind", ctx_ptr->pcfg->remote_ss, write_ind);
  XPORT_RPM_LOG("RPM ISR read ind", ctx_ptr->pcfg->remote_ss, read_ind);

  /* Ensure the index is 64-bit aligned */
  if ((write_ind & 0x7) != 0)
  {
    dprintf(CRITICAL,"%s:%d: Write Index is not aligned: %u\n",__func__, __LINE__, write_ind);
    ASSERT(0);
  }

  while (write_ind != read_ind && !stop_processing)
  {
    uint32 cmd = MSGRAM_READ32(ctx_ptr, read_ind);
    uint32 cid = XPORT_RPM_GET_CHANNEL_ID(cmd); // most commands have channel ID
    uint32 cmd_arg;

    /* it can't wrap aroud here so just inceremt the index */
    read_ind += sizeof(cmd);

    XPORT_RPM_LOG("Cmd Rx", ctx_ptr->pcfg->remote_ss, cmd);

    switch (XPORT_RPM_GET_CMD_ID(cmd))
    {
      case XPORT_RPM_CMD_VERSION_REQ:

        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);

        /* no need to increment read_ind here since it will be rounded up */

        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version(
          (glink_transport_if_type *)ctx_ptr,
          XPORT_RPM_GET_VERSION(cmd), cmd_arg);
        break;

      case XPORT_RPM_CMD_VERSION_ACK:

        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);

        /* no need to increment read_ind here since it will be rounded up */

        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version_ack(
          (glink_transport_if_type *)ctx_ptr,
          XPORT_RPM_GET_VERSION(cmd), cmd_arg);
        break;

      case XPORT_RPM_CMD_OPEN_CHANNEL:
        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
        cmd_arg = ROUNDUP64(cmd_arg);

        read_ind += sizeof(cmd_arg);

        /* channel name should fit into the FIFO */
        if (cmd_arg == 0 || cmd_arg >= ctx_ptr->rx_fifo_size)
        {
          dprintf(CRITICAL, "%s:%d: Invalid name length: %u", __func__, __LINE__, cmd_arg);
          ASSERT(0);
        }
        else
        {
          char  temp_string[ROUNDUP64(GLINK_CH_NAME_LEN)] = {0};
          uint32 num_copied_chars = 0;
          uint32  *string_ptr;

          string_ptr = ( uint32 * )&temp_string[0];
          while( ( num_copied_chars < cmd_arg ) && ( num_copied_chars < sizeof( temp_string ) ) )
          {
            CHECK_INDEX_WRAP_AROUND( read_ind, ctx_ptr->rx_fifo_size );
            *( string_ptr++ ) = MSGRAM_READ32( ctx_ptr, read_ind );

            num_copied_chars += sizeof( uint32 );
            read_ind += sizeof( uint32 );
          }

          /* add all the unread stuff */
          read_ind += cmd_arg - num_copied_chars;

          /* make sure the last character is NULL */
          temp_string[ sizeof( temp_string ) - 1 ] = 0;

          ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
            (glink_transport_if_type *)ctx_ptr, cid, temp_string, GLINK_XPORT_RPM);
        }

        break;

      case XPORT_RPM_CMD_CLOSE_CHANNEL:

        /* no need to increment read_ind here since it will be rounded up */
        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_close(
          (glink_transport_if_type *)ctx_ptr, cid);

        break;

      case XPORT_RPM_CMD_OPEN_CHANNEL_ACK:

        /* no need to increment read_ind here since it will be rounded up */
        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
            (glink_transport_if_type *)ctx_ptr, cid, GLINK_XPORT_RPM);

        break;

      case XPORT_RPM_CMD_CLOSE_CHANNEL_ACK:
        /* no need to increment read_ind here since it will be rounded up */
        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
          (glink_transport_if_type *)ctx_ptr, cid);

        break;

      case XPORT_RPM_CMD_TX_DATA:
      {
        glink_rx_intent_type desc;
        memset( &desc, sizeof( glink_rx_intent_type), 0 );

        read_ind += sizeof(cmd_arg);

        CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);

        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);

        /* packet data should fit into the FIFO */
        if (cmd_arg >= ctx_ptr->rx_fifo_size)
        {
          dprintf(CRITICAL, "%s:%d: Invalid packet length: %u",__func__, __LINE__, cmd_arg);
          ASSERT(0);
        }

        read_ind += 2*sizeof(cmd_arg);

        CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);

        ctx_ptr->pkt_start_ind = read_ind;
        ctx_ptr->pkt_size = cmd_arg;

        desc.size = cmd_arg;
        desc.used = cmd_arg;
        desc.pkt_sz = cmd_arg;
        desc.iovec = ctx_ptr;
        desc.vprovider = xport_rpm_pkt_provider;

        read_ind += cmd_arg;

        ctx_ptr->xport_if.glink_core_if_ptr->rx_put_pkt_ctx(
          (glink_transport_if_type *)ctx_ptr, cid,
          &desc, TRUE);

        /* If interrupt was disabled then stop delivering messages */
        stop_processing = ctx_ptr->irq_mask;

        break;
      }

      case XPORT_RPM_CMD_TX_SIGNALS:

        cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);

        /* no need to increment read_ind here since it will be rounded up */

        ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_remote_sigs(
          (glink_transport_if_type *)ctx_ptr,
          cid, cmd_arg);
        break;

      default:
        dprintf(CRITICAL, "%s:%d: Invalid Command: %u\n",__func__, __LINE__, cmd);
        ASSERT(0);
        break;
    }

    /* Update read index only if transport has not been reset  */
    if( !ctx_ptr->reset )
    {
      read_ind = ROUNDUP64(read_ind);

      if (read_ind >= ctx_ptr->rx_fifo_size)
      {
        read_ind -= ctx_ptr->rx_fifo_size;
      }

      /* Update the shared read index */
      ctx_ptr->rx_desc->read_ind = read_ind;
    }
    else
    {
      stop_processing = TRUE;
    }
  }

  glink_os_cs_release(ctx_ptr->rx_link_lock);

  return GLINK_STATUS_SUCCESS;
}
예제 #11
0
파일: xport_rpm.c 프로젝트: KortanZ/linux
/*=========================================================================*/
static glink_err_type xport_rpm_send_cmd
(
  xport_rpm_ctx_type  *ctx_ptr,
  uint32              *cmd,
  uint32               cmd_size,
  uint32              *data,
  uint32               data_size
)
{
  uint32 total_size = cmd_size + data_size;
  uint32 reserve_size = ROUNDUP64(total_size);
  uint32 write_ind, read_ind, avail_size;

  glink_os_cs_acquire(ctx_ptr->tx_link_lock);

  /* Transport is in reset */
  if( ctx_ptr->reset )
  {
    glink_os_cs_release(ctx_ptr->tx_link_lock);
    return GLINK_STATUS_SUCCESS;
  }

  write_ind = ctx_ptr->tx_desc->write_ind;
  read_ind = ctx_ptr->tx_desc->read_ind;
  avail_size = write_ind < read_ind ? read_ind - write_ind :
               ctx_ptr->tx_fifo_size - write_ind + read_ind;

  if (reserve_size + sizeof(uint64) > avail_size)
  {
    glink_os_cs_release(ctx_ptr->tx_link_lock);
    return GLINK_STATUS_OUT_OF_RESOURCES;
  }

  XPORT_RPM_LOG("send cmd", ctx_ptr->pcfg->remote_ss, cmd[0]);

  write_ind
    = xport_rpm_write_msgram( ctx_ptr, write_ind,
                              cmd, ROUNDUP32( cmd_size ) );

  if (data != NULL)
  {
    write_ind
      = xport_rpm_write_msgram( ctx_ptr, write_ind,
                                data, ROUNDUP32( data_size ) );
  }

  /* add alignment bytes to Tx FIFO */
  write_ind += (reserve_size - total_size) & (~3);

  if (write_ind >= ctx_ptr->tx_fifo_size)
  {
    write_ind -= ctx_ptr->tx_fifo_size;
  }

  ctx_ptr->tx_desc->write_ind = write_ind;

  xport_rpm_send_event(ctx_ptr);

  glink_os_cs_release(ctx_ptr->tx_link_lock);

  return GLINK_STATUS_SUCCESS;
}