Exemple #1
0
static int
fcoet_process_sol_abts_rjt(fcoe_frame_t *frm)
{
	fcoet_exchange_t	*xch	   = NULL;
	uint16_t		 sol_oxid;

	sol_oxid = FRM_OXID(frm);
	if (mod_hash_remove(FRM2SS(frm)->ss_sol_oxid_hash,
	    (mod_hash_key_t)(intptr_t)sol_oxid,
	    (mod_hash_val_t *)&xch) != 0) {
		/*
		 * So far ABTS for FLOGI might be removed from ss_sol_oxid_hash
		 * in fcoet_watch_handle_sol_flogi, Will improve it later
		 */
		return (FCOE_SUCCESS);
	}

	xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE;

	if (!FRM_IS_LAST_FRAME(frm)) {
		FCOET_LOG("fcoet_process_sol_abts_rjt",
		    "not supported this kind frame");
		return (FCOE_FAILURE);
	}

	FCOET_LOG("fcoet_process_sol_abts_rjt",
	    "ABTS_RJT received rjt reason %x but there is nothing to do",
	    frm->frm_payload[1]);
	return (FCOE_SUCCESS);
}
Exemple #2
0
/*
 * Solicited frames callback area
 */
static int
fcoet_send_unsol_els_rsp_done(fcoe_frame_t *frm)
{
	fcoet_exchange_t	*xch = FRM2TFM(frm)->tfm_xch;
	fct_status_t		 fc_st;
	uint32_t		 iof;

	FCOET_EXT_LOG("fcoet_send_unsol_els_rsp_done",
	    "frm/oxid/els: %p/%x/%x",
	    frm, FRM_OXID(frm), XCH2ELS(xch)->els_req_payload[0]);
	if (xch->xch_flags & XCH_FLAG_FCT_CALLED_ABORT) {
		FCOET_RELE_XCHG(xch);
		return (FCOE_SUCCESS);
	}

	if (fcoet_clear_unsol_exchange(xch) == FCOE_FAILURE) {
		FCOET_RELE_XCHG(xch);
		return (FCOE_SUCCESS);
	}

	FCOET_RELE_XCHG(xch);
	if (XCH2ELS(xch)->els_req_payload[0] != ELS_OP_FLOGI) {
		fc_st = FCT_SUCCESS;
		iof = FCT_IOF_FCA_DONE;
		fct_send_response_done(xch->xch_cmd, fc_st, iof);
	} else {
		/*
		 * We need update ss_link_info and flags.
		 */
		mutex_enter(&xch->xch_ss->ss_watch_mutex);
		xch->xch_ss->ss_link_info.portid =
		    xch->xch_cmd->cmd_lportid;
		xch->xch_ss->ss_link_info.port_topology =
		    PORT_TOPOLOGY_PT_TO_PT;
		if (frm->frm_eport->eport_link_speed == FCOE_PORT_SPEED_1G) {
			xch->xch_ss->ss_link_info.port_speed = PORT_SPEED_1G;
		} else if (frm->frm_eport->eport_link_speed ==
		    FCOE_PORT_SPEED_10G) {
			xch->xch_ss->ss_link_info.port_speed = PORT_SPEED_10G;
		}
		xch->xch_ss->ss_link_info.port_no_fct_flogi = 1;
		xch->xch_ss->ss_link_info.port_fca_flogi_done = 1;
		xch->xch_ss->ss_link_info.port_fct_flogi_done = 0;
		bcopy(XCH2ELS(xch)->els_req_payload + 20,
		    xch->xch_ss->ss_link_info.port_rpwwn, 8);
		bcopy(XCH2ELS(xch)->els_req_payload + 28,
		    xch->xch_ss->ss_link_info.port_rnwwn, 8);
		atomic_or_32(&xch->xch_ss->ss_flags,
		    SS_FLAG_UNSOL_FLOGI_DONE);
		atomic_or_32(&xch->xch_ss->ss_flags,
		    SS_FLAG_REPORT_TO_FCT);

		xch->xch_ss->ss_sol_flogi_state = SFS_FLOGI_ACC;
		mutex_exit(&xch->xch_ss->ss_watch_mutex);

		fct_free(xch->xch_cmd);
	}
	return (FCOE_SUCCESS);
}
Exemple #3
0
/*
 * It's still in the context of being aborted exchange, but FCT can't support
 * this scheme, so there are two fct_cmd_t that are bound with one exchange.
 */
static int
fcoet_process_unsol_abts_req(fcoe_frame_t *frm)
{
	fct_cmd_t		*cmd;
	fcoet_exchange_t	*xch = NULL;
	uint16_t		 unsol_rxid;

	FCOET_LOG("fcoet_process_unsol_abts_req", "ABTS: %x/%x",
	    FRM_OXID(frm), FRM_RXID(frm));
	unsol_rxid = FRM_RXID(frm);
	if (mod_hash_find_cb(FRM2SS(frm)->ss_unsol_rxid_hash,
	    (mod_hash_key_t)(intptr_t)unsol_rxid,
	    (mod_hash_val_t *)&xch, fcoet_modhash_find_cb) != 0) {
		FCOET_LOG("fcoet_process_unsol_abts_req",
		    "can't find aborted exchange");
		return (FCOE_SUCCESS);
	}

	fcoet_init_tfm(frm, xch);
	if (!FRM_IS_LAST_FRAME(frm)) {
		FCOET_LOG("fcoet_process_unsol_abts_req",
		    "not supported this kind frame");
		FCOET_RELE_XCHG(xch);
		return (FCOE_FAILURE);
	}

	cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS, 0, 0);
	if (cmd == NULL) {
		FCOET_LOG("fcoet_process_unsol_abts_req",
		    "can't alloc fct_cmd_t");
		FCOET_RELE_XCHG(xch);
		return (FCOE_FAILURE);
	}

	xch->xch_flags |= XCH_FLAG_INI_ASKED_ABORT;
	cmd->cmd_fca_private = xch;
	cmd->cmd_port = xch->xch_cmd->cmd_port;
	cmd->cmd_rp_handle = xch->xch_cmd->cmd_rp_handle;
	cmd->cmd_rportid = xch->xch_cmd->cmd_rportid;
	cmd->cmd_lportid = xch->xch_cmd->cmd_lportid;
	cmd->cmd_oxid = xch->xch_cmd->cmd_oxid;
	cmd->cmd_rxid = xch->xch_cmd->cmd_rxid;
	fct_post_rcvd_cmd(cmd, NULL);
	FCOET_LOG("fcoet_process_unsol_abts_req",
	    "abts now: xch/%p, frm/%p - time/%p",
	    xch, frm, ddi_get_lbolt());

	FCOET_RELE_XCHG(xch);
	return (FCOE_SUCCESS);
}
void
fcoe_post_frame(fcoe_frame_t *frm)
{
	fcoe_worker_t *w;
	uint16_t	oxid = FRM_OXID(frm);

	w = &fcoe_workers[oxid % fcoe_nworkers_running];
	mutex_enter(&w->worker_lock);
	list_insert_tail(&w->worker_frm_list, frm->frm_fcoe_private);
	w->worker_ntasks++;
	if ((w->worker_flags & FCOE_WORKER_ACTIVE) == 0) {
		cv_signal(&w->worker_cv);
	}
	mutex_exit(&w->worker_lock);
}
Exemple #5
0
/*
 * It must be from link, but could be incomplete because of network problems
 */
static int
fcoet_process_sol_els_rsp(fcoe_frame_t *frm)
{
	uint32_t		 actual_size;
	fct_status_t		 fc_st;
	uint32_t		 iof;
	uint16_t		 sol_oxid;
	fcoet_exchange_t	*xch = NULL;
	fct_els_t		*els = NULL;
	int			 ret = FCOE_SUCCESS;

	sol_oxid = FRM_OXID(frm);
	if (mod_hash_find_cb(FRM2SS(frm)->ss_sol_oxid_hash,
	    (mod_hash_key_t)(intptr_t)sol_oxid,
	    (mod_hash_val_t *)&xch, fcoet_modhash_find_cb) != 0) {
		return (FCOE_FAILURE);
	}
	if (xch != FRM2SS(frm)->ss_sol_flogi) {
		fcoet_clear_sol_exchange(xch);
	}

	fcoet_init_tfm(frm, xch);
	els = CMD2ELS(xch->xch_cmd);
	ASSERT(FRM_IS_LAST_FRAME(frm));
	actual_size = els->els_resp_size;
	if (actual_size > frm->frm_payload_size) {
		actual_size = frm->frm_payload_size;
	}

	els->els_resp_size = (uint16_t)actual_size;
	bcopy(frm->frm_payload, els->els_resp_payload, actual_size);

	if (xch->xch_ss->ss_sol_flogi == xch) {
		/*
		 * We handle FLOGI internally
		 */
		ret = fcoet_process_sol_flogi_rsp(frm);
		FCOET_RELE_XCHG(xch);
	} else {
		fc_st = FCT_SUCCESS;
		iof = FCT_IOF_FCA_DONE;
		FCOET_RELE_XCHG(xch);
		fct_send_cmd_done(xch->xch_cmd, fc_st, iof);
	}
	return (ret);
}
Exemple #6
0
static int
fcoet_process_sol_ct_rsp(fcoe_frame_t *frm)
{
	uint32_t		 actual_size;
	fct_status_t		 fc_st;
	uint32_t		 iof;
	fct_sol_ct_t		*ct  = NULL;
	fcoet_exchange_t	*xch = NULL;
	uint16_t		 sol_oxid;

	sol_oxid = FRM_OXID(frm);

	if (mod_hash_remove(FRM2SS(frm)->ss_sol_oxid_hash,
	    (mod_hash_key_t)(intptr_t)sol_oxid,
	    (mod_hash_val_t *)&xch) != 0) {
		return (FCOE_SUCCESS);
	}

	xch->xch_flags &= ~XCH_FLAG_IN_HASH_TABLE;
	fcoet_init_tfm(frm, xch);

	ASSERT(FRM_IS_LAST_FRAME(frm));
	actual_size = CMD2ELS(xch->xch_cmd)->els_resp_size;
	if (actual_size > frm->frm_payload_size) {
		actual_size = frm->frm_payload_size;
	}
	ct = CMD2CT(xch->xch_cmd);
	ct->ct_resp_size = (uint16_t)actual_size;

	bcopy(frm->frm_payload,
	    CMD2CT(xch->xch_cmd)->ct_resp_payload, actual_size);

	fc_st = FCT_SUCCESS;
	iof = FCT_IOF_FCA_DONE;
	fct_send_cmd_done(xch->xch_cmd, fc_st, iof);

	return (FCOE_SUCCESS);
}
Exemple #7
0
/*
 * For unsolicited exchanges, FCoET is only responsible for allocation of
 * req_payload. FCT will allocate resp_payload after the exchange is
 * passed on.
 */
static fcoet_exchange_t *
fcoet_create_unsol_exchange(fcoe_frame_t *frm)
{
	uint8_t			 r_ctl;
	int			 cdb_size;
	fcoet_exchange_t	*xch, *xch_tmp;
	fct_cmd_t		*cmd;
	fcoe_fcp_cmnd_t		*ffc;
	uint32_t		task_expected_len = 0;

	r_ctl = FRM_R_CTL(frm);
	switch (r_ctl) {
	case 0x22:
		/*
		 * FCoET's unsolicited ELS
		 */
		cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS,
		    GET_STRUCT_SIZE(fcoet_exchange_t) +
		    frm->frm_payload_size, 0);
		if (cmd == NULL) {
			FCOET_EXT_LOG(0, "can't get cmd");
			return (NULL);
		}
		break;

	case 0x06:
		/*
		 * FCoET's unsolicited SCSI cmd
		 */
		cdb_size = 16;	/* need improve later */
		cmd = fct_scsi_task_alloc(FRM2SS(frm)->ss_port, FCT_HANDLE_NONE,
		    FRM_S_ID(frm), frm->frm_payload, cdb_size,
		    STMF_TASK_EXT_NONE);
		if (cmd == NULL) {
			FCOET_EXT_LOG(0, "can't get fcp cmd");
			return (NULL);
		}
		ffc = (fcoe_fcp_cmnd_t *)frm->frm_payload;
		task_expected_len = FCOE_B2V_4(ffc->ffc_fcp_dl);
		break;

	default:
		FCOET_EXT_LOG(0, "unsupported R_CTL: %x", r_ctl);
		return (NULL);
	}

	/*
	 * xch initialization
	 */
	xch = CMD2XCH(cmd);
	xch->xch_oxid = FRM_OXID(frm);
	xch->xch_flags = 0;
	xch->xch_ss = FRM2SS(frm);
	xch->xch_cmd = cmd;
	xch->xch_current_seq = NULL;
	xch->xch_left_data_size = 0;
	if (task_expected_len) {
		xch->xch_dbuf_num =
		    (task_expected_len + FCOET_MAX_DBUF_LEN - 1) /
		    FCOET_MAX_DBUF_LEN;
		xch->xch_dbufs =
		    kmem_zalloc(xch->xch_dbuf_num * sizeof (stmf_data_buf_t *),
		    KM_SLEEP);
	}
	xch->xch_start_time = ddi_get_lbolt();
	do {
		xch->xch_rxid = atomic_add_16_nv(
		    &xch->xch_ss->ss_next_unsol_rxid, 1);
		if (xch->xch_rxid == 0xFFFF) {
			xch->xch_rxid = atomic_add_16_nv(
			    &xch->xch_ss->ss_next_unsol_rxid, 1);
		}
	} while (mod_hash_find(FRM2SS(frm)->ss_unsol_rxid_hash,
	    (mod_hash_key_t)(intptr_t)xch->xch_rxid,
	    (mod_hash_val_t)&xch_tmp) == 0);

	xch->xch_sequence_no = 0;
	xch->xch_ref = 0;
	(void) mod_hash_insert(xch->xch_ss->ss_unsol_rxid_hash,
	    (mod_hash_key_t)(intptr_t)xch->xch_rxid, (mod_hash_val_t)xch);
	xch->xch_flags |= XCH_FLAG_IN_HASH_TABLE;

	/*
	 * cmd initialization
	 */
	cmd->cmd_port = FRM2SS(frm)->ss_port;
	cmd->cmd_rp_handle = FCT_HANDLE_NONE;
	cmd->cmd_rportid = FRM_S_ID(frm);
	cmd->cmd_lportid = FRM_D_ID(frm);
	cmd->cmd_oxid = xch->xch_oxid;
	cmd->cmd_rxid = xch->xch_rxid;

	fcoet_init_tfm(frm, xch);
	return (xch);
}