root/usr/src/uts/common/io/bnxe/577xx/drivers/common/lm/l5/lm_l5sp.c


#include "lm5710.h"
#include "command.h"
#include "everest_l5cm_constants.h"
#include "lm_l5if.h"

static lm_status_t lm_sc_post_init_request(
    IN  struct _lm_device_t *pdev,
    IN  lm_iscsi_state_t *iscsi,
    IN  lm_iscsi_slow_path_request_t *sp_req,
    OUT u8_t *command,
    OUT u64_t *data)
{
    DbgMessage(pdev, VERBOSEl5sp, "##lm__post_initiate_offload_request\n");
    DbgBreakIf(iscsi->hdr.status != STATE_STATUS_INIT_CONTEXT);

    *command = ISCSI_RAMROD_CMD_ID_INIT;
    *data = iscsi->ctx_phys.as_u64;

    return LM_STATUS_PENDING;
}



static lm_status_t lm_sc_post_update_request(
    IN  struct _lm_device_t *pdev,
    IN  lm_iscsi_state_t *iscsi,
    IN  lm_iscsi_slow_path_request_t *sp_req,
    OUT u8_t *command,
    OUT u64_t *data)
{
    struct protocol_common_spe     spe       = {0};

    DbgMessage(pdev, VERBOSEl5sp, "##lm__post_initiate_offload_request\n");
    DbgBreakIf(iscsi->hdr.status != STATE_STATUS_NORMAL);

    *command = ISCSI_RAMROD_CMD_ID_UPDATE_CONN;
    spe.data.phy_address.hi = iscsi->sp_req_data.phys_addr.as_u32.high;
    spe.data.phy_address.lo = iscsi->sp_req_data.phys_addr.as_u32.low;
    *data = *((u64_t*)(&(spe.data.phy_address)));

    return LM_STATUS_PENDING;
}



/* Desciption:
 *  post slow path request of given type for given iscsi state
 * Assumptions:
 *  - caller initialized request->type according to its specific request
 *  - caller allocated space for request->data, according to the specific request type
 *  - all previous slow path requests for given tcp state are already completed
 * Returns:
 *  PENDING, SUCCESS or any failure */
lm_status_t lm_sc_post_slow_path_request(
    IN  struct _lm_device_t *pdev,
    IN  lm_iscsi_state_t *iscsi,
    IN  lm_iscsi_slow_path_request_t *request)
{
    lm_status_t lm_status = LM_STATUS_SUCCESS;
    u64_t       data      = 0;
    u8_t        command   = 0;

    DbgBreakIf(!(pdev && iscsi && request));
    DbgMessage(pdev, VERBOSEl5sp, "### lm_sc_post_slow_path_request cid=%d, type=%d\n", iscsi->cid, request->type);

    switch (request->type)
    {
    /* NirV: called under lock, iscsi_state is being changed */
    case SP_REQUEST_SC_INIT:
        lm_status = lm_sc_post_init_request(pdev, iscsi, request, &command, &data);
        break;

    case SP_REQUEST_SC_UPDATE:
        lm_status = lm_sc_post_update_request(pdev, iscsi, request, &command, &data);
        break;

    default:
        lm_status = LM_STATUS_FAILURE;
        DbgBreakMsg("Illegal slow path request type!\n");
        break;
    }

    if (lm_status == LM_STATUS_PENDING)
    {
        DbgMessage(pdev, VERBOSEl5sp,
                   "calling lm_command_post, cid=%d, command=%d, con_type=%d, data=%lx\n",
                   iscsi->cid, command, ISCSI_CONNECTION_TYPE, data);
        lm_command_post(pdev, iscsi->cid, command, CMD_PRIORITY_NORMAL, ISCSI_CONNECTION_TYPE/*ulp*/, data);
    }

    request->status = lm_status;
    return lm_status;
}



/* Desciption:
 *  initiate a caller allocated lm iscsi state
 * Assumptions:
 *  - caller already zeroed given iscsi state
 * Returns:
 *  SUCCESS or any failure */
lm_status_t lm_sc_init_iscsi_state(
    struct _lm_device_t *pdev,
    lm_state_block_t *state_blk,
    lm_iscsi_state_t *iscsi)
{
    DbgMessage(pdev, VERBOSEl5sp, "###lm_sc_init_iscsi_state, ptr=%p\n", iscsi);
    DbgBreakIf(!(pdev && state_blk && iscsi));

    iscsi->hdr.state_blk     = state_blk;
    iscsi->hdr.state_id      = STATE_ID_UNKNOWN;
    iscsi->hdr.status        = STATE_STATUS_INIT;
    d_list_push_tail(&pdev->iscsi_info.run_time.iscsi_list, &iscsi->hdr.link);

    // NirV: sc: future statistics update

    /* the rest of the iscsi state's fields that require initialization value other than 0,
     * will be initialized later (when lm_sc_init_iscsi_context is called) */

    return LM_STATUS_SUCCESS;
}



/* Desciption:
 *  delete iscsi state from lm _except_ from actual freeing of memory.
 *  the task of freeing of memory is done in lm_sc_free_iscsi_state()
 * Assumptions:
 *  global toe lock is taken by the caller
 */
void lm_sc_del_iscsi_state(
    struct _lm_device_t *pdev,
    lm_iscsi_state_t *iscsi)
{
    u8_t notify_fw = 1;

    DbgMessage(pdev, VERBOSEl5sp, "###lm_sc_del_iscsi_state\n");
    DbgBreakIf(!(pdev && iscsi));
    DbgBreakIf(iscsi->hdr.status >= STATE_STATUS_OFFLOAD_PENDING &&
               iscsi->hdr.status < STATE_STATUS_UPLOAD_DONE);

    /* just a moment before we delete this connection, lets take it's info... */
    /*lm_tcp_collect_stats(pdev, tcp);*/

    d_list_remove_entry(
        &pdev->iscsi_info.run_time.iscsi_list,
        &iscsi->hdr.link);
    /*pdev->iscsi_info.stats.total_upld++;*/


  /* tcp->cid could have not been initialized if delete of state
     is a result of a failed initialization */
    DbgBreakIf(iscsi->hdr.status != STATE_STATUS_UPLOAD_DONE &&
               iscsi->hdr.status != STATE_STATUS_INIT_OFFLOAD_ERR);

    if (iscsi->hdr.status == STATE_STATUS_INIT_OFFLOAD_ERR) {
        notify_fw = 0;
    }

    lm_free_cid_resc(pdev, ISCSI_CONNECTION_TYPE, iscsi->cid, notify_fw);

    iscsi->hdr.state_blk     = NULL;
    iscsi->cid = 0;
    iscsi->ctx_virt = NULL;
    iscsi->ctx_phys.as_u64 = 0;
} /* lm_sc_del_iscsi_state */


/* clean up the lm_fcoe_state */
void
lm_fc_del_fcoe_state(
    struct _lm_device_t             *pdev,
    lm_fcoe_state_t                 *fcoe)
{
    DbgMessage(pdev, VERBOSEl5sp, "###lm_fc_del_fcoe_state\n");
    DbgBreakIf(!(pdev && fcoe));
    /*
    DbgBreakIf(fcoe->hdr.status >= STATE_STATUS_OFFLOAD_PENDING &&
               fcoe->hdr.status < STATE_STATUS_UPLOAD_DONE);
    */

    /* remove the lm_fcoe_state from the state list */
    d_list_remove_entry(&pdev->fcoe_info.run_time.fcoe_list, &fcoe->hdr.link);

  /* tcp->cid could have not been initialized if delete of state
     is a result of a failed initialization */

    /*
    DbgBreakIf(fcoe->hdr.status != STATE_STATUS_UPLOAD_DONE &&
               fcoe->hdr.status != STATE_STATUS_INIT_OFFLOAD_ERR);
    */
} /* lm_fc_del_fcoe_state */



lm_status_t
lm_fc_init_fcoe_state(
    struct _lm_device_t             *pdev,
    lm_state_block_t                *state_blk,
    lm_fcoe_state_t                 *fcoe)
{
    DbgMessage(pdev, VERBOSEl5sp, "###lm_fc_init_fcoe_state, ptr=%p\n", fcoe);
    DbgBreakIf(!(pdev && state_blk && fcoe));

    fcoe->hdr.state_blk     = state_blk;
    fcoe->hdr.state_id      = STATE_ID_UNKNOWN;
    fcoe->hdr.status        = STATE_STATUS_INIT;
    d_list_push_tail(&pdev->fcoe_info.run_time.fcoe_list, &fcoe->hdr.link);

    /* the rest of the fcoe state's fields that require initialization value other than 0,
     * will be initialized later (when lm_fc_init_fcoe_context is called) */

    return LM_STATUS_SUCCESS;
}



void lm_sc_init_sp_req_type(
    struct _lm_device_t          * pdev,
    lm_iscsi_state_t             * iscsi,
    lm_iscsi_slow_path_request_t * lm_req,
    void                         * req_input_data)
{
    void *update_kwqe_virt;
    struct protocol_common_spe spe = {0};

    switch(lm_req->type) {
    case SP_REQUEST_SC_INIT:
        break;
    case SP_REQUEST_SC_UPDATE:

        spe.data.phy_address.hi = iscsi->sp_req_data.phys_addr.as_u32.high;
        spe.data.phy_address.lo = iscsi->sp_req_data.phys_addr.as_u32.low;

        update_kwqe_virt = &iscsi->sp_req_data.virt_addr->update_ctx.kwqe;
        mm_memcpy(update_kwqe_virt, req_input_data, sizeof(struct iscsi_kwqe_conn_update));

        break;
    default:
        DbgBreakMsg("lm_sc_init_sp_req_type: Illegal slow path request type!\n");
    }
} /* lm_init_sp_req_type */