static void qla_set_ini_mode()

in qla2xxx/qla_attr.c [1979:2253]


static void qla_set_ini_mode(scsi_qla_host_t *vha, int op)
{
	enum {
		NO_ACTION,
		MODE_CHANGE_ACCEPT,
		MODE_CHANGE_NO_ACTION,
		TARGET_STILL_ACTIVE,
	};
	int action = NO_ACTION;
	int set_mode = 0;
	u8  eo_toggle = 0;	/* exchange offload flipped */

	switch (vha->qlini_mode) {
	case QLA2XXX_INI_MODE_DISABLED:
		switch (op) {
		case QLA2XXX_INI_MODE_DISABLED:
			if (qla_tgt_mode_enabled(vha)) {
				if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
				    vha->hw->flags.exchoffld_enabled)
					eo_toggle = 1;
				if (((vha->ql2xexchoffld !=
				    vha->u_ql2xexchoffld) &&
				    NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
				    eo_toggle) {
					/*
					 * The number of exchange to be offload
					 * was tweaked or offload option was
					 * flipped
					 */
					action = MODE_CHANGE_ACCEPT;
				} else {
					action = MODE_CHANGE_NO_ACTION;
				}
			} else {
				action = MODE_CHANGE_NO_ACTION;
			}
			break;
		case QLA2XXX_INI_MODE_EXCLUSIVE:
			if (qla_tgt_mode_enabled(vha)) {
				if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
				    vha->hw->flags.exchoffld_enabled)
					eo_toggle = 1;
				if (((vha->ql2xexchoffld !=
				    vha->u_ql2xexchoffld) &&
				    NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
				    eo_toggle) {
					/*
					 * The number of exchange to be offload
					 * was tweaked or offload option was
					 * flipped
					 */
					action = MODE_CHANGE_ACCEPT;
				} else {
					action = MODE_CHANGE_NO_ACTION;
				}
			} else {
				action = MODE_CHANGE_ACCEPT;
			}
			break;
		case QLA2XXX_INI_MODE_DUAL:
			action = MODE_CHANGE_ACCEPT;
			/* active_mode is target only, reset it to dual */
			if (qla_tgt_mode_enabled(vha)) {
				set_mode = 1;
				action = MODE_CHANGE_ACCEPT;
			} else {
				action = MODE_CHANGE_NO_ACTION;
			}
			break;

		case QLA2XXX_INI_MODE_ENABLED:
			if (qla_tgt_mode_enabled(vha))
				action = TARGET_STILL_ACTIVE;
			else {
				action = MODE_CHANGE_ACCEPT;
				set_mode = 1;
			}
			break;
		}
		break;

	case QLA2XXX_INI_MODE_EXCLUSIVE:
		switch (op) {
		case QLA2XXX_INI_MODE_EXCLUSIVE:
			if (qla_tgt_mode_enabled(vha)) {
				if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
				    vha->hw->flags.exchoffld_enabled)
					eo_toggle = 1;
				if (((vha->ql2xexchoffld !=
				    vha->u_ql2xexchoffld) &&
				    NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
				    eo_toggle)
					/*
					 * The number of exchange to be offload
					 * was tweaked or offload option was
					 * flipped
					 */
					action = MODE_CHANGE_ACCEPT;
				else
					action = NO_ACTION;
			} else
				action = NO_ACTION;

			break;

		case QLA2XXX_INI_MODE_DISABLED:
			if (qla_tgt_mode_enabled(vha)) {
				if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
				    vha->hw->flags.exchoffld_enabled)
					eo_toggle = 1;
				if (((vha->ql2xexchoffld !=
				      vha->u_ql2xexchoffld) &&
				    NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
				    eo_toggle)
					action = MODE_CHANGE_ACCEPT;
				else
					action = MODE_CHANGE_NO_ACTION;
			} else
				action = MODE_CHANGE_NO_ACTION;
			break;

		case QLA2XXX_INI_MODE_DUAL: /* exclusive -> dual */
			if (qla_tgt_mode_enabled(vha)) {
				action = MODE_CHANGE_ACCEPT;
				set_mode = 1;
			} else
				action = MODE_CHANGE_ACCEPT;
			break;

		case QLA2XXX_INI_MODE_ENABLED:
			if (qla_tgt_mode_enabled(vha))
				action = TARGET_STILL_ACTIVE;
			else {
				if (vha->hw->flags.fw_started)
					action = MODE_CHANGE_NO_ACTION;
				else
					action = MODE_CHANGE_ACCEPT;
			}
			break;
		}
		break;

	case QLA2XXX_INI_MODE_ENABLED:
		switch (op) {
		case QLA2XXX_INI_MODE_ENABLED:
			if (NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg) !=
			    vha->hw->flags.exchoffld_enabled)
				eo_toggle = 1;
			if (((vha->ql2xiniexchg != vha->u_ql2xiniexchg) &&
				NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg)) ||
			    eo_toggle)
				action = MODE_CHANGE_ACCEPT;
			else
				action = NO_ACTION;
			break;
		case QLA2XXX_INI_MODE_DUAL:
		case QLA2XXX_INI_MODE_DISABLED:
			action = MODE_CHANGE_ACCEPT;
			break;
		default:
			action = MODE_CHANGE_NO_ACTION;
			break;
		}
		break;

	case QLA2XXX_INI_MODE_DUAL:
		switch (op) {
		case QLA2XXX_INI_MODE_DUAL:
			if (qla_tgt_mode_enabled(vha) ||
			    qla_dual_mode_enabled(vha)) {
				if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld +
					vha->u_ql2xiniexchg) !=
				    vha->hw->flags.exchoffld_enabled)
					eo_toggle = 1;

				if ((((vha->ql2xexchoffld +
				       vha->ql2xiniexchg) !=
				    (vha->u_ql2xiniexchg +
				     vha->u_ql2xexchoffld)) &&
				    NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg +
					vha->u_ql2xexchoffld)) || eo_toggle)
					action = MODE_CHANGE_ACCEPT;
				else
					action = NO_ACTION;
			} else {
				if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld +
					vha->u_ql2xiniexchg) !=
				    vha->hw->flags.exchoffld_enabled)
					eo_toggle = 1;

				if ((((vha->ql2xexchoffld + vha->ql2xiniexchg)
				    != (vha->u_ql2xiniexchg +
					vha->u_ql2xexchoffld)) &&
				    NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg +
					vha->u_ql2xexchoffld)) || eo_toggle)
					action = MODE_CHANGE_NO_ACTION;
				else
					action = NO_ACTION;
			}
			break;

		case QLA2XXX_INI_MODE_DISABLED:
			if (qla_tgt_mode_enabled(vha) ||
			    qla_dual_mode_enabled(vha)) {
				/* turning off initiator mode */
				set_mode = 1;
				action = MODE_CHANGE_ACCEPT;
			} else {
				action = MODE_CHANGE_NO_ACTION;
			}
			break;

		case QLA2XXX_INI_MODE_EXCLUSIVE:
			if (qla_tgt_mode_enabled(vha) ||
			    qla_dual_mode_enabled(vha)) {
				set_mode = 1;
				action = MODE_CHANGE_ACCEPT;
			} else {
				action = MODE_CHANGE_ACCEPT;
			}
			break;

		case QLA2XXX_INI_MODE_ENABLED:
			if (qla_tgt_mode_enabled(vha) ||
			    qla_dual_mode_enabled(vha)) {
				action = TARGET_STILL_ACTIVE;
			} else {
				action = MODE_CHANGE_ACCEPT;
			}
		}
		break;
	}

	switch (action) {
	case MODE_CHANGE_ACCEPT:
		ql_log(ql_log_warn, vha, 0xffff,
		    "Mode change accepted. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n",
		    mode_to_str[vha->qlini_mode], mode_to_str[op],
		    vha->ql2xexchoffld, vha->u_ql2xexchoffld,
		    vha->ql2xiniexchg, vha->u_ql2xiniexchg);

		vha->qlini_mode = op;
		vha->ql2xexchoffld = vha->u_ql2xexchoffld;
		vha->ql2xiniexchg = vha->u_ql2xiniexchg;
		if (set_mode)
			qlt_set_mode(vha);
		vha->flags.online = 1;
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
		break;

	case MODE_CHANGE_NO_ACTION:
		ql_log(ql_log_warn, vha, 0xffff,
		    "Mode is set. No action taken. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n",
		    mode_to_str[vha->qlini_mode], mode_to_str[op],
		    vha->ql2xexchoffld, vha->u_ql2xexchoffld,
		    vha->ql2xiniexchg, vha->u_ql2xiniexchg);
		vha->qlini_mode = op;
		vha->ql2xexchoffld = vha->u_ql2xexchoffld;
		vha->ql2xiniexchg = vha->u_ql2xiniexchg;
		break;

	case TARGET_STILL_ACTIVE:
		ql_log(ql_log_warn, vha, 0xffff,
		    "Target Mode is active. Unable to change Mode.\n");
		break;

	case NO_ACTION:
	default:
		ql_log(ql_log_warn, vha, 0xffff,
		    "Mode unchange. No action taken. %d|%d pct %d|%d.\n",
		    vha->qlini_mode, op,
		    vha->ql2xexchoffld, vha->u_ql2xexchoffld);
		break;
	}
}