fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortedisc_action_t fct_handle_local_port_event(fct_i_local_port_t *iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortedisc_action_t fct_walk_discovery_queue(fct_i_local_port_t *iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortedisc_action_t fct_process_els(fct_i_local_port_t *iport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_status_t fct_send_accrjt(fct_cmd_t *cmd, uint8_t accrjt,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortedisc_action_t fct_link_init_complete(fct_i_local_port_t *iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_status_t fct_complete_previous_li_cmd(fct_i_local_port_t *iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_status_t fct_sol_plogi(fct_i_local_port_t *iport, uint32_t id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_status_t fct_sol_ct(fct_i_local_port_t *iport, uint32_t id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_status_t fct_ns_scr(fct_i_local_port_t *iport, uint32_t id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic disc_action_t fct_check_cmdlist(fct_i_local_port_t *iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic disc_action_t fct_check_solcmd_queue(fct_i_local_port_t *iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void fct_rscn_verify(fct_i_local_port_t *iport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *rscn_req_payload, uint32_t rscn_req_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortechar *fct_els_names[] = { 0, "LS_RJT", "ACC", "PLOGI", "FLOGI", "LOGO",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x10 */ "ECHO", "TEST", "RRQ", "REC", "SRR", 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "TPRLO", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x50 */ "PDISC", "FDISC", "ADISC", "RNC", "FARP",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x60 */ "FAN", "RSCN", "SCR", 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x70 */ "LINIT", "LPC", "LSTS", 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * NOTE: if anybody drops the iport_worker_lock then they should not return
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * DISC_ACTION_NO_WORK. Which also means, dont drop the lock if you have
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * nothing to do. Or else return DISC_ACTION_RESCAN or DISC_ACTION_DELAY_RESCAN.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * But you cannot be infinitly returning those so have some logic to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * determine that there is nothing to do without dropping the lock.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_local_port_t *port = (fct_local_port_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_local_port_t *iport = (fct_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte drv_usectohz(FCT_CMDLIST_CHECK_SECONDS * 1000000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "iport is %p", iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Discovery loop */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&iport->iport_flags, IPORT_WORKER_RUNNING);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((iport->iport_flags & IPORT_TERMINATE_WORKER) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Local port events are of the highest prioriy
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte suggested_action |= fct_handle_local_port_event(iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We could post solicited ELSes to discovery queue.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * solicited CT will be processed inside fct_check_solcmd_queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte suggested_action |= fct_check_solcmd_queue(iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * All solicited and unsolicited ELS will be handled here
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte suggested_action |= fct_walk_discovery_queue(iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We only process it when there's no outstanding link init CMD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iport->iport_link_state == PORT_STATE_LINK_INIT_START) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte !(iport->iport_li_state & (LI_STATE_FLAG_CMD_WAITING |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte suggested_action |= fct_process_link_init(iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We process cmd aborting in the end
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_cmdcheck_clock <= ddi_get_lbolt()) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte drv_usectohz(FCT_CMDLIST_CHECK_SECONDS * 1000000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_offline_prstate != FCT_OPR_DONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte suggested_action |= fct_handle_port_offline(iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (suggested_action & DISC_ACTION_DELAY_RESCAN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is not very optimum as whoever returned
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * DISC_ACTION_DELAY_RESCAN must have dropped the lock
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and more things might have queued up. But since
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we are only doing small delays, it only delays
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * things by a few ms, which is okey.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (suggested_action & DISC_ACTION_USE_SHORT_DELAY) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&iport->iport_worker_cv,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &iport->iport_worker_lock, dl, TR_CLOCK_TICK);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tmp_delay = (int64_t)(iport->iport_cmdcheck_clock -
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&iport->iport_worker_cv,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &iport->iport_worker_lock, (clock_t)tmp_delay,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&iport->iport_flags, ~IPORT_WORKER_RUNNING);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char *topologies[] = { "Unknown", "Direct Pt-to-Pt", "Private Loop",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Public Loop" };
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_li_to_txt(fct_link_info_t *li, char *topology, char *speed)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (li->port_topology > PORT_TOPOLOGY_PUBLIC_LOOP) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) sprintf(topology, "Invalid %02x", li->port_topology);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strcpy(topology, topologies[li->port_topology]);
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek if ((s == 0) || ((s & 0xf00) != 0) || !ISP2(s)) {
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang } else if (s == PORT_SPEED_10G) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * discovery lock held.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * XXX: Implement command cleanup upon Link down.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * XXX: Implement a clean start and FC-GS registrations upon Link up.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ================ Local Port State Machine ============
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * <hba fatal> <Link up>---|
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | <Start>--->[LINK_DOWN]--->[LINK_INIT_START]--->[LINK_INIT_DONE]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | ^ ^ ^ | |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | |---| | |--<Link down> |-| |---><Link Reset><--|
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | | | v | v
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * |->[FATAL_CLEANING] [LINK_DOWN_CLEANING]--->[LINK_UP_CLEANING]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * |--<Link up>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * =======================================================
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * An explicit port_online() is only allowed in LINK_DOWN state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * An explicit port_offline() is only allowed in LINKDOWN and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * LINK_INIT_DONE state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_handle_local_port_event(fct_i_local_port_t *iport)
d8c54e3d070f57cc1b4d6c8262f0868219c8ce7cSam Cramer DTRACE_FC_1(link__up, fct_i_local_port_t, iport);
d8c54e3d070f57cc1b4d6c8262f0868219c8ce7cSam Cramer } else if (in->event_type == FCT_EVENT_LINK_DOWN) {
d8c54e3d070f57cc1b4d6c8262f0868219c8ce7cSam Cramer DTRACE_FC_1(link__down, fct_i_local_port_t, iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Calculate new state */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (in->event_type == FCT_EVENT_LINK_UP) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_link_state == PORT_STATE_LINK_DOWN_CLEANING)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else if (iport->iport_link_state == PORT_STATE_LINK_DOWN)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else { /* This should not happen */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Link up received when link state was"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (in->event_type == FCT_I_EVENT_CLEANUP_POLL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else { /* This should not have happened */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (in->event_type == FCT_EVENT_LINK_RESET) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Link reset is only allowed when we are Online */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (in->event_type == FCT_I_EVENT_LINK_INIT_DONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_link_state == PORT_STATE_LINK_INIT_START) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "port state change from %x to %x",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state |= LI_STATE_FLAG_NO_LI_YET;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((li_ret = iport->iport_port->port_get_link_info(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "port_get_link_info failed, ret %llx, forcing "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This will reset LI_STATE_FLAG_NO_LI_YET */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_lport_has_bigger_wwn(fct_i_local_port_t *iport)
d8c54e3d070f57cc1b4d6c8262f0868219c8ce7cSam Cramer DTRACE_FC_1(fabric__login__start, fct_i_local_port_t, iport);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_link_info.port_topology & PORT_TOPOLOGY_PRIVATE_LOOP) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fx.fx_sid = iport->iport_link_info.portid & 0xFF;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(iport->iport_port->port_nwwn, fx.fx_nwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(iport->iport_port->port_pwwn, fx.fx_pwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = iport->iport_port->port_flogi_xchg(iport->iport_port, &fx);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The unsolicited path finished it. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This is a private loop. There is no switch. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is really an error. This means we cannot init the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * link. Lets force the link to go down.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((ret == FCT_SUCCESS) && (fx.fx_op == ELS_OP_LSRJT)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((fx.fx_rjt_reason == 5) || (fx.fx_rjt_reason == 0xe) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((fx.fx_rjt_reason == 9) && (fx.fx_rjt_expl == 0x29))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "iport-%p: flogi xchg failed. "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Forcing link down, ret=%llx login_retry=%d ret_op=%d "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "reason=%d expl=%d", iport, ret, iport->iport_login_retry,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_handle_event(iport->iport_port, FCT_EVENT_LINK_DOWN, 0, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FLOGI succeeded. Update local port state */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(fx.fx_nwwn, iport->iport_link_info.port_rnwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(fx.fx_pwwn, iport->iport_link_info.port_rpwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Called by FCAs to handle unsolicited FLOGIs.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_handle_rcvd_flogi(fct_local_port_t *port, fct_flogi_xchg_t *fx)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport = (fct_i_local_port_t *)port->port_fct_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iport->iport_flags & IPORT_ALLOW_UNSOL_FLOGI) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((iport->iport_flags & IPORT_ALLOW_UNSOL_FLOGI) == 0) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iport->iport_link_state != PORT_STATE_LINK_INIT_START) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((iport->iport_li_state & LI_STATE_MASK) > LI_STATE_N2N_PLOGI)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_link_info.port_fct_flogi_done == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(fx->fx_pwwn, iport->iport_link_info.port_rpwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(fx->fx_nwwn, iport->iport_link_info.port_rnwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(iport->iport_port->port_pwwn, fx->fx_pwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(iport->iport_port->port_nwwn, fx->fx_nwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iport_li_state can only be changed here and local_event
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Is FLOGI even needed or already done ? */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iport->iport_link_info.port_no_fct_flogi) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_NOTE, "%s LINK UP, portid %x, topology %s,"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * rehash it if change from fabric to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * none fabric, vice versa
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_link_old_topology = li->port_topology;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Skip next level if topo is not N2N */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (li->port_topology != PORT_TOPOLOGY_PT_TO_PT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_li_state & LI_STATE_FLAG_CMD_RETCHECK) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state &= ~LI_STATE_FLAG_CMD_RETCHECK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_li_comp_status != FCT_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " to PLOGI to remote port in N2N "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " ret=%llx, forcing link down",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Find out if we need to do PLOGI at all */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ddi_get_lbolt() >= iport->iport_li_cmd_timeout) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Cant wait forever */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "N2N: Remote port is "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "not logging in, forcing from our side");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (force_login || fct_lport_has_bigger_wwn(iport)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state |= LI_STATE_FLAG_CMD_RETCHECK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_li_state & LI_STATE_FLAG_CMD_RETCHECK) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state &= ~LI_STATE_FLAG_CMD_RETCHECK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_li_comp_status != FCT_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Fabric controller login failed. Just skip all
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the fabric controller related cmds.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Good. Now lets go to next state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We want to come back in the same state and check its ret
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We can't modify the state here
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state |= LI_STATE_FLAG_CMD_RETCHECK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We dont care about success of this state. Just go to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * next state upon completion.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_li_state & LI_STATE_FLAG_CMD_RETCHECK) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state &= ~LI_STATE_FLAG_CMD_RETCHECK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iport->iport_li_comp_status != FCT_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state |= LI_STATE_FLAG_CMD_RETCHECK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check if we need skip the state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte NULL ? iport->iport_port->port_sym_port_name : NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte NULL ? iport->iport_port->port_default_alias : NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd = fct_create_solels(iport->iport_port, NULL, implicit,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (ctop != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd = fct_create_solct(iport->iport_port, NULL, ctop,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state |= LI_STATE_FLAG_CMD_WAITING;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_post_to_solcmd_queue(iport->iport_port, cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Handles both solicited and unsolicited elses. Can be called inside
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * interrupt context.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Posting %ssol ELS %x (%s) rp_id=%x"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " lp_id=%x", (cmd->cmd_type == FCT_CMD_RCVD_ELS) ? "un" : "",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Make sure local port is sane */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iport->iport_link_state & S_LINK_ONLINE) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "ELS %x not posted becasue"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(cmd, FCT_LOCAL_PORT_OFFLINE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Weed out any bad initiators in case of N2N topology */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iport->iport_link_state == PORT_STATE_LINK_INIT_START) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iport->iport_link_info.port_topology == PORT_TOPOLOGY_PT_TO_PT)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We dont allow remote port to plogi in N2N if we have not yet
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * resolved the topology.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "port %x is trying to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "PLOGI in N2N topology, While we have not resolved"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "trying to PLOGI in N2N topology, even "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "though it has smaller PWWN",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Remote port is assigning us a PORTID as
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a part of PLOGI.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For all unsolicited ELSes that are not FLOGIs, our portid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * has been established by now. Sometimes port IDs change due to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * link resets but remote ports may still send ELSes using the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * old IDs. Kill those right here.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cmd->cmd_lportid != iport->iport_link_info.portid) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "wrong lportid %x, expecting %x. Killing ELS.",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We always lookup by portid. port handles are too
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * unreliable at this stage.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte irp = fct_portid_to_portptr(iport, cmd->cmd_rportid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* drop the lock while we do allocations */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Grab port lock as writer since we are going
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to modify the local port struct.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Make sure nobody created the struct except us */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_portid_to_portptr(iport, cmd->cmd_rportid)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Oh well, free it */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Start over becasue we dropped the lock */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* A PLOGI is by default a logout of previous session */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* A PLOGI also invalidates any RSCNs related to this rp */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For everything else, we have (or be able to lookup) a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * valid port pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX Throw a logout to the initiator */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received from %x without a session",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "to %x without a session",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(cmd, FCT_NOT_LOGGED_IN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Lets get a slot for this els
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This should not have happened */
590ebdb02417ee80bf5da3a617dadf2469fa3b7eallan "ran out of xchg resources");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Tell the framework that fct_cmd_free() can decrement the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * irp_nonfcp_xchg_count variable.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_IMPLICIT_CMD_HAS_RESOURCE);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_16(&irp->irp_nonfcp_xchg_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Grab the remote port lock while we modify the port state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we should not drop the fca port lock (as a reader) until we
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * modify the remote port state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((op == ELS_OP_PLOGI) || (op == ELS_OP_PRLI) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((op == ELS_OP_PLOGI) || (op == ELS_OP_LOGO)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_SESSION_AFFECTING);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_16(&irp->irp_nsa_elses_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Cleanup I/Os for a rport. ttc is a bit Mask of cmd types to clean.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * No locks held.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_trigger_rport_cleanup(fct_i_remote_port_t *irp, int ttc)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total = port->port_max_xchges - iport->iport_nslots_free;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((cleaned + skipped) == total) && (unhandled == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * XXX: handle this situation.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Clean up trouble for irp"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " %p, c/s/u/t = %d/%d/%d/%d", irp, cleaned, skipped,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&icmd->icmd_flags, ~ICMD_IN_IRP_QUEUE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_register_remote_port(fct_local_port_t *port, fct_remote_port_t *rp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport = (fct_i_local_port_t *)port->port_fct_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret = port->port_register_remote_port(port, rp, cmd)) !=
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_register_remote_port: FCA "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "returned a handle (%d) for portid %x which is "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iport->iport_rp_slots[rp->rp_handle] != NULL) &&
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan "fct_register_remote_port: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "FCA returned a handle %d for portid %x "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "which was already in use for a different "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Pick a handle for this port */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This is really pushing it. */
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan "fct_register_remote_port "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Cannot register portid %x because all the "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* By this time rport_handle is valid */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&irp->irp_flags, IRP_HANDLE_OPENED);
640c1670a105457bb0040e8e11037b53ab6ebcfaJosef 'Jeff' Sipek atomic_inc_64(&iport->iport_last_change);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_log_remote_port_event(port, ESC_SUNFC_TARGET_ADD,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * XXX Throw HBA fatal error event
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(irp->irp_snn, strlen(irp->irp_snn) + 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(irp->irp_spn, strlen(irp->irp_spn) + 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret = port->port_deregister_remote_port(port, rp)) !=
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_HANDLE_OPENED);
640c1670a105457bb0040e8e11037b53ab6ebcfaJosef 'Jeff' Sipek atomic_inc_64(&iport->iport_last_change);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_log_remote_port_event(port, ESC_SUNFC_TARGET_REMOVE,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_send_accrjt(fct_cmd_t *cmd, uint8_t accrjt, uint8_t reason, uint8_t expl)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_local_port_t *port = (fct_local_port_t *)cmd->cmd_port;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els->els_resp_size = els->els_resp_alloc_size = 8;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els->els_resp_payload = (uint8_t *)kmem_zalloc(8, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_walk_discovery_queue(fct_i_local_port_t *iport)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disc_action_t suggested_action = DISC_ACTION_NO_WORK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (pirp = &iport->iport_rpwe_head; *pirp != NULL; ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* dequeue irp from discovery queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* queue irp for deregister */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * wait for another scan until
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * deregister timeout
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When we dropped the lock,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * something went in.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* do deregister */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* drop the lock */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (irp_cur_item = irp_dereg_list; irp_cur_item != NULL; ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_deregister_remote_port(iport->iport_port,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (++irp_cur_item->irp_dereg_count >= 5) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * It looks like we can't deregister it in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * normal way, so we have to use extrem way
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_walk_discovery_queue: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "iport-%p, can't deregister irp-%p after "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* grab the iport_lock */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* recover */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_local_port_t *iport = (fct_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_remote_port_t *irp = (fct_i_remote_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Drain I/Os */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((irp->irp_nonfcp_xchg_count + irp->irp_fcp_xchg_count) > 1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Trigger cleanup if necessary */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((irp->irp_flags & IRP_SESSION_CLEANUP) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "handling PLOGI rp_id"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Cleanup everything except elses */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_trigger_rport_cleanup(irp, ~(cmd->cmd_type))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: handle this */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_process_plogi: unable to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "clean up I/O. iport-%p, icmd-%p", (void *)iport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
590ebdb02417ee80bf5da3a617dadf2469fa3b7eallan " PLOGI rp_id %x, waiting for cmds to"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SESSION_CLEANUP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Session can only be terminated after all the I/Os have drained */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_deregister_scsi_session(iport->iport_port->port_lport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SCSI_SESSION_STARTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p = els->els_resp_payload = (uint8_t *)kmem_zalloc(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(els->els_req_payload, p, els->els_resp_size);
d8c54e3d070f57cc1b4d6c8262f0868219c8ce7cSam Cramer fct_wwn_to_str(port->port_pwwn_str, port->port_pwwn);
d8c54e3d070f57cc1b4d6c8262f0868219c8ce7cSam Cramer fct_wwn_to_str(port->port_nwwn_str, port->port_nwwn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_wwn_to_devid_desc((scsi_devid_desc_t *)irp->irp_id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret == FCT_SUCCESS) && !(icmd->icmd_flags & ICMD_IMPLICIT)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret == FCT_SUCCESS) && IPORT_IN_NS_TOPO(iport) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The reason we set this flag is to prevent
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * killing a PRLI while we have not yet processed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a response to PLOGI. Because the initiator
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will send a PRLI as soon as it responds to PLOGI.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check fct_process_els() for more info.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_KNOWN_TO_FCA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Do not touch cmd here as it may have been freed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteuint8_t fct_prli_temp[] = { 0x20, 0x10, 0, 0x14, 8, 0, 0x20, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, 0, 0, 0 };
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_local_port_t *iport = (fct_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_remote_port_t *irp = (fct_i_remote_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We dont support solicited PRLIs yet */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (irp->irp_flags & IRP_SOL_PLOGI_IN_PROGRESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Dont process the PRLI yet. Let the framework process the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * PLOGI completion 1st. This should be very quick because
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the reason we got the PRLI is because the initiator
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * has responded to PLOGI already.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: Probably need a timeout here */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The caller has made sure that login is done */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Make sure the process is fcp in this case */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((els->els_req_size != 20) || (bcmp(els->els_req_payload,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "PRLI received from"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " %x for unknown FC-4 type %x", cmd->cmd_rportid,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Rejecting PRLI from %x "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = fct_send_accrjt(cmd, ELS_OP_LSRJT, 3, 0x2c);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Trigger cleanup if necessary */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "handling PRLI from"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_trigger_rport_cleanup(irp, FCT_CMD_FCP_XCHG)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: handle this */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_process_prli: unable to clean "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
590ebdb02417ee80bf5da3a617dadf2469fa3b7eallan " PRLI from %x, waiting for cmds to"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_FCP_CLEANUP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Session can only be terminated after all the I/Os have drained */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_deregister_scsi_session(iport->iport_port->port_lport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SCSI_SESSION_STARTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* All good, lets start a session */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ses = (stmf_scsi_session_t *)stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ses->ss_rport_id = (scsi_devid_desc_t *)irp->irp_id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_register_scsi_session(port->port_lport, ses) !=
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The reason IRP_SCSI_SESSION_STARTED is different
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * from IRP_PRLI_DONE is that we clear IRP_PRLI_DONE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * inside interrupt context. We dont want to deregister
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the session from an interrupt.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&irp->irp_flags, IRP_SCSI_SESSION_STARTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* fail PRLI */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* accept PRLI */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els->els_resp_payload = (uint8_t *)kmem_zalloc(20, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX the two bytes below need to set as per capabilities */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els->els_resp_size = els->els_resp_alloc_size = 20;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret = port->port_send_cmd_response(cmd, 0)) !=
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_deregister_scsi_session(port->port_lport, ses);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Mark that PRLI is done */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_local_port_t *iport = (fct_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_remote_port_t *irp = (fct_i_remote_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Drain I/Os */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((irp->irp_nonfcp_xchg_count + irp->irp_fcp_xchg_count) > 1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Trigger cleanup if necessary */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((irp->irp_flags & IRP_SESSION_CLEANUP) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "handling LOGO rp_id"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Cleanup everything except elses */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_trigger_rport_cleanup(irp, ~(cmd->cmd_type))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: need more handling */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_process_logo: unable to clean "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
590ebdb02417ee80bf5da3a617dadf2469fa3b7eallan " LOGO rp_id %x, waiting for cmds to"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SESSION_CLEANUP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Session can only be terminated after all the I/Os have drained */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_deregister_scsi_session(iport->iport_port->port_lport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SCSI_SESSION_STARTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* don't send response if this is an implicit logout cmd */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_KNOWN_TO_FCA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Do not touch cmd here as it may have been freed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_local_port_t *iport = (fct_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_remote_port_t *irp = (fct_i_remote_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We do not support solicited PRLOs yet */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Drain I/Os */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Trigger cleanup if necessary */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "handling LOGO from"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Cleanup everything except elses */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_trigger_rport_cleanup(irp, FCT_CMD_FCP_XCHG)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: need more handling */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_process_prlo: unable to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "clean up I/O. iport-%p, icmd-%p", (void *)iport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
590ebdb02417ee80bf5da3a617dadf2469fa3b7eallan " PRLO from %x, waiting for cmds to"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_FCP_CLEANUP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Session can only be terminated after all the I/Os have drained */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_deregister_scsi_session(iport->iport_port->port_lport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SCSI_SESSION_STARTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_local_port_t *iport = (fct_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_i_remote_port_t *irp = (fct_i_remote_port_t *)
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_16(&irp->irp_nsa_elses_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Validate the adisc request */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((els->els_req_size != 28) || (bcmp(rp->rp_pwwn, p + 8, 8)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els->els_resp_size = els->els_resp_alloc_size = 28;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els->els_resp_payload = (uint8_t *)kmem_zalloc(28, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmd->icmd_cmd->cmd_type == FCT_CMD_RCVD_ELS);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_16(&ICMD_TO_IRP(icmd)->irp_nsa_elses_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Rejecting unknown unsol els %x (%s)",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = fct_send_accrjt(icmd->icmd_cmd, ELS_OP_LSRJT, 1, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(icmd->icmd_cmd, ret);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_16(&ICMD_TO_IRP(icmd)->irp_nsa_elses_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmd->icmd_cmd->cmd_type == FCT_CMD_RCVD_ELS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Accepting RSCN %x (%s)",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rscn_req_payload = kmem_alloc(rscn_req_size, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ICMD_TO_ELS(icmd)->els_req_payload, rscn_req_payload,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = fct_send_accrjt(icmd->icmd_cmd, ELS_OP_ACC, 1, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(icmd->icmd_cmd, ret);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_process_els(fct_i_local_port_t *iport, fct_i_remote_port_t *irp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Do some cleanup based on the following.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - We can only have one session affecting els pending.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - If any session affecting els is pending no other els is allowed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - If PLOGI is not done, nothing except PLOGI or LOGO is allowed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * NOTE: If port is down the cleanup is done outside of this
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * NOTE: There is a side effect, if a sa ELS (non PLOGI) is received
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * while a PLOGI is pending, it will kill itself and the PLOGI.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which is probably ok.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte els = (fct_els_t *)((*ppcmd)->icmd_cmd)->cmd_specific;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((*ppcmd)->icmd_cmd->cmd_type == FCT_CMD_RCVD_ELS) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The initiator sent a PRLI right after responding
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to PLOGI and we have not yet finished processing
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the PLOGI completion. We should not kill the PRLI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * as the initiator may not retry it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This els might have set the CLEANUP flag */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SESSION_CLEANUP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Killing ELS %x cond 1",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (((*ppcmd)->icmd_flags & ICMD_SESSION_AFFECTING) == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Killing ELS %x cond 2",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (((irp->irp_flags & IRP_PLOGI_DONE) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Killing ELS %x cond 3",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((*ppcmd)->icmd_flags & ICMD_SESSION_AFFECTING)
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_16(&irp->irp_nsa_elses_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&cmd_to_abort->icmd_flags, ~ICMD_IN_IRP_QUEUE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(cmd_to_abort->icmd_cmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * pick from the top of the queue
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The cleanup took care of everything.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((icmd->icmd_flags & ICMD_ELS_PROCESSING_STARTED) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Processing %ssol ELS %x (%s) "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "rp_id=%x", (cmd->cmd_type == FCT_CMD_RCVD_ELS) ? "un" : "",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_ELS_PROCESSING_STARTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if ((op == ELS_OP_PRLO) || (op == ELS_OP_TPRLO)) {
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_16(&irp->irp_nsa_elses_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_KNOWN_TO_FCA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((s = port->port_send_cmd(cmd)) != FCT_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&icmd->icmd_flags, ~ICMD_KNOWN_TO_FCA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "transport failed, ret = %llx", s);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This if condition will be false if a sa ELS trigged a cleanup
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and set the ret = DISC_ACTION_DELAY_RESCAN. In that case we should
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * keep it that way.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Since we dropped the lock, we will force a rescan. The
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * only exception is if someone returned
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * DISC_ACTION_DELAY_RESCAN, in which case that should be the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return value.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_handle_sol_els_completion(fct_i_local_port_t *iport, fct_i_cmd_t *icmd)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (icmd->icmd_cmd->cmd_comp_status == FCT_SUCCESS) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(els->els_resp_payload + 20, irp->irp_rp->rp_pwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(els->els_resp_payload + 28, irp->irp_rp->rp_nwwn, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_wwn_to_devid_desc((scsi_devid_desc_t *)irp->irp_id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (irp && (els->els_req_payload[0] == ELS_OP_PLOGI)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&irp->irp_flags, ~IRP_SOL_PLOGI_IN_PROGRESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_CMD_COMPLETE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "Sol ELS %x (%s) completed with "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd->icmd_cmd->cmd_comp_status, icmd->icmd_cmd->cmd_rportid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Everytime, we release half of the difference
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&iport->iport_total_alloced_ncmds);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The efficiency of handling solicited commands is very low here. But
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fortunately, we seldom send solicited commands. So it will not hurt
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the system performance much.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (icmd = iport->iport_solcmd_queue; icmd; icmd = next_icmd) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This solicited cmd is new.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Dispatch ELSes to discovery queue to make use of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * existent framework.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmd->icmd_cmd->cmd_type == FCT_CMD_SOL_ELS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (icmd->icmd_flags & ICMD_CMD_COMPLETE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * To make fct_check_solcmd simple and flexible,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We need only call callback to finish post-handling.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Release resources for this solicited cmd
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This solicited cmd is still ongoing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We need check if it's time to abort this cmd
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Let's make sure local port is sane
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iport->iport_link_state & S_LINK_ONLINE) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "fct_transport_solct: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "solcmd-%p transport failed, becasue port state was %x",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(cmd, FCT_LOCAL_PORT_OFFLINE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Let's make sure we have plogi-ed to name server
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "fct_transport_solct: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Must login to name server first - cmd-%p", cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(cmd, FCT_NOT_LOGGED_IN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Let's get a slot for this solcmd
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_alloc_cmd_slot(iport, cmd) == FCT_SLOT_EOL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "fct_transport_solcmd: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_queue_cmd_for_termination(cmd, FCT_NO_XCHG_RESOURCE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fct_netbuf_to_value(ICMD_TO_CT(icmd)->ct_req_payload + 8, 2) ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&query_irp->irp_flags, ~IRP_RSCN_QUEUED);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_16(&irp->irp_nonfcp_xchg_count);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&icmd->icmd_flags, ICMD_KNOWN_TO_FCA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&icmd->icmd_flags, ~ICMD_KNOWN_TO_FCA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_logo_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "solicited LOGO is not accepted - icmd/%p", icmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gsnn_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&ICMD_TO_IPORT(icmd)->iport_worker_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_enter(&ICMD_TO_IPORT(icmd)->iport_lock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&ICMD_TO_IPORT(icmd)->iport_worker_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp = fct_lookup_irp_by_nodewwn(ICMD_TO_IPORT(icmd),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gsnn_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Release previous resource, then allocate needed resource
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Update symbolic node name
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((query_irp->irp_flags & IRP_SCSI_SESSION_STARTED) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gsnn_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_state &= ~LI_STATE_FLAG_CMD_WAITING;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmd->icmd_cmd->cmd_comp_status != FCT_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(iport->iport_alias, "fct_link_init_cb: ELS-%x failed"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "comp_status- %llx", ICMD_TO_ELS(icmd)->els_req_payload[0],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iport->iport_li_comp_status = icmd->icmd_cmd->cmd_comp_status;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (icmd->icmd_cmd->cmd_type == FCT_CMD_SOL_ELS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_link_init_cb: ELS-%x is rejected",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmd->icmd_cmd->cmd_type == FCT_CMD_SOL_CT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "fct_link_init_cb: CT-%02x%02x is rejected",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gcs_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_portid = (req[17] << 16) | (req[18] << 8) | req[19];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp = fct_portid_to_portptr(iport, query_portid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp->irp_cos = (resp[16] << 27) | (resp[17] << 18) |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gft_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_portid = (req[17] << 16) | (req[18] << 8) | req[19];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp = fct_portid_to_portptr(iport, query_portid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) memcpy(query_irp->irp_fc4types, resp + 16, 32);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&ICMD_TO_IPORT(icmd)->iport_worker_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_enter(&ICMD_TO_IPORT(icmd)->iport_lock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&ICMD_TO_IPORT(icmd)->iport_worker_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp = fct_lookup_irp_by_portwwn(ICMD_TO_IPORT(icmd),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gid_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "new RSCN arrived - query_irp/%p, private-%x", query_irp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gid_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "not proper irp_flags - query_irp/%p", query_irp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check if it has disappeared
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gid_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check if its portid has changed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp->irp_rp, 1, ELS_OP_LOGO, 0, fct_logo_cb);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&ICMD_TO_IPORT(icmd)->iport_worker_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&ICMD_TO_IPORT(icmd)->iport_worker_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gspn_cb: "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "GSPN_ID is not accepted by NS - icmd/%p", icmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_portid = (req[17] << 16) | (req[18] << 8) | req[19];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp = fct_portid_to_portptr(iport, query_portid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte query_irp->irp_spn = kmem_zalloc(spnlen + 1, KM_SLEEP);
c946faca5d4627284fb79c6b04e652b471034495allan stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_rls_cb: "
c946faca5d4627284fb79c6b04e652b471034495allan /* Get the response and store it somewhere */
c946faca5d4627284fb79c6b04e652b471034495allan rls_resp = (fct_port_link_status_t *)rls_cb_data->fct_link_status;
c946faca5d4627284fb79c6b04e652b471034495allan rls_resp->LinkFailureCount = BE_32(*((uint32_t *)(resp + 4)));
c946faca5d4627284fb79c6b04e652b471034495allan rls_resp->LossOfSyncCount = BE_32(*((uint32_t *)(resp + 8)));
c946faca5d4627284fb79c6b04e652b471034495allan rls_resp->LossOfSignalsCount = BE_32(*((uint32_t *)(resp + 12)));
c946faca5d4627284fb79c6b04e652b471034495allan rls_resp->InvalidCRCCount = BE_32(*((uint32_t *)(resp + 24)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For lookup functions, we move locking up one level
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_lookup_irp_by_nodewwn(fct_i_local_port_t *iport, uint8_t *nodewwn)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (idx = 0; idx < FCT_HASH_TABLE_SIZE; idx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bcmp(irp->irp_rp->rp_nwwn, nodewwn, FC_WWN_LEN)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_lookup_irp_by_portwwn(fct_i_local_port_t *iport, uint8_t *portwwn)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (idx = 0; idx < FCT_HASH_TABLE_SIZE; idx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bcmp(irp->irp_rp->rp_pwwn, portwwn, FC_WWN_LEN)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ct_cmd = fct_create_solct(port, irp->irp_rp, NS_GID_PN, \
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek cnt = atomic_inc_32_nv(&irp->irp_rscn_counter); \
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortefct_rscn_verify(fct_i_local_port_t *iport, uint8_t *rscn_req_payload,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fct_netbuf_to_value(rscn_req_payload + 2, 2) - 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (; page_buf <= last_page_buf; page_buf += 4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page_portid = fct_netbuf_to_value(page_buf + 1, 3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(irp && !(irp->irp_flags & IRP_RSCN_QUEUED))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; /* try next page */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; /* try next page */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (idx = 0; idx < FCT_HASH_TABLE_SIZE; idx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; /* try next irp */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; /* try next irp */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; /* try next irp */