Beispiel #1
0
/**
 * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager
 * @lport: Fibre Channel local port to be logged in to the fabric
 *
 * Locking Note: The lport lock is expected to be held before calling
 * this routine.
 */
void fc_lport_enter_flogi(struct fc_lport *lport)
{
	struct fc_frame *fp;

	FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_FLOGI);

	if (lport->point_to_multipoint) {
		if (lport->port_id)
			fc_lport_enter_ready(lport);
		return;
	}

	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
	if (!fp)
		return fc_lport_error(lport, fp);

	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp,
				  lport->vport ? ELS_FDISC : ELS_FLOGI,
				  fc_lport_flogi_resp, lport,
				  lport->vport ? 2 * lport->r_a_tov :
				  lport->e_d_tov))
		fc_lport_error(lport, NULL);
}
Beispiel #2
0
static void fc_lport_enter_rft_id(struct fc_lport *lport)
{
	struct fc_frame *fp;
	struct fc_ns_fts *lps;
	int i;

	FC_LPORT_DBG(lport, "Entered RFT_ID state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_RFT_ID);

	lps = &lport->fcts;
	i = sizeof(lps->ff_type_map) / sizeof(lps->ff_type_map[0]);
	while (--i >= 0)
		if (ntohl(lps->ff_type_map[i]) != 0)
			break;
	if (i < 0) {
		
		fc_lport_enter_scr(lport);
		return;
	}

	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
			    sizeof(struct fc_ns_rft));
	if (!fp) {
		fc_lport_error(lport, fp);
		return;
	}

	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RFT_ID,
				  fc_lport_rft_id_resp,
				  lport, lport->e_d_tov))
		fc_lport_error(lport, fp);
}
Beispiel #3
0
static void fc_lport_enter_disabled(struct fc_lport *lport)
{
	FC_LPORT_DBG(lport, "Entered disabled state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_DISABLED);
	fc_lport_reset_locked(lport);
}
Beispiel #4
0
/**
 * fc_lport_enter_ns() - register some object with the name server
 * @lport: Fibre Channel local port to register
 *
 * Locking Note: The lport lock is expected to be held before calling
 * this routine.
 */
static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state)
{
	struct fc_frame *fp;
	enum fc_ns_req cmd;
	int size = sizeof(struct fc_ct_hdr);
	size_t len;

	FC_LPORT_DBG(lport, "Entered %s state from %s state\n",
		     fc_lport_state_names[state],
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, state);

	switch (state) {
	case LPORT_ST_RNN_ID:
		cmd = FC_NS_RNN_ID;
		size += sizeof(struct fc_ns_rn_id);
		break;
	case LPORT_ST_RSNN_NN:
		len = strnlen(fc_host_symbolic_name(lport->host), 255);
		/* if there is no symbolic name, skip to RFT_ID */
		if (!len)
			return fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);
		cmd = FC_NS_RSNN_NN;
		size += sizeof(struct fc_ns_rsnn) + len;
		break;
	case LPORT_ST_RSPN_ID:
		len = strnlen(fc_host_symbolic_name(lport->host), 255);
		/* if there is no symbolic name, skip to RFT_ID */
		if (!len)
			return fc_lport_enter_ns(lport, LPORT_ST_RFT_ID);
		cmd = FC_NS_RSPN_ID;
		size += sizeof(struct fc_ns_rspn) + len;
		break;
	case LPORT_ST_RFT_ID:
		cmd = FC_NS_RFT_ID;
		size += sizeof(struct fc_ns_rft);
		break;
	case LPORT_ST_RFF_ID:
		cmd = FC_NS_RFF_ID;
		size += sizeof(struct fc_ns_rff_id);
		break;
	default:
		fc_lport_error(lport, NULL);
		return;
	}

	fp = fc_frame_alloc(lport, size);
	if (!fp) {
		fc_lport_error(lport, fp);
		return;
	}

	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, cmd,
				  fc_lport_ns_resp,
				  lport, 3 * lport->r_a_tov))
		fc_lport_error(lport, fp);
}
Beispiel #5
0
static void fc_lport_enter_ready(struct fc_lport *lport)
{
	FC_LPORT_DBG(lport, "Entered READY from state %s\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_READY);

	if (!lport->ptp_rp)
		lport->tt.disc_start(fc_lport_disc_callback, lport);
}
Beispiel #6
0
static void fc_lport_enter_reset(struct fc_lport *lport)
{
	FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_RESET);
	fc_lport_reset_locked(lport);
	if (lport->link_up)
		fc_lport_enter_flogi(lport);
}
Beispiel #7
0
/**
 * fc_lport_config() - Configure a fc_lport
 * @lport: The local port to be configured
 */
int fc_lport_config(struct fc_lport *lport)
{
	INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
	mutex_init(&lport->lp_mutex);

	fc_lport_state_enter(lport, LPORT_ST_DISABLED);

	fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
	fc_lport_add_fc4_type(lport, FC_TYPE_CT);

	return 0;
}
Beispiel #8
0
/**
 * fc_rport_enter_ready() - Enter the ready state and start discovery
 * @lport: The local port that is ready
 *
 * Locking Note: The lport lock is expected to be held before calling
 * this routine.
 */
static void fc_lport_enter_ready(struct fc_lport *lport)
{
	FC_LPORT_DBG(lport, "Entered READY from state %s\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_READY);
	if (lport->vport)
		fc_vport_set_state(lport->vport, FC_VPORT_ACTIVE);
	fc_vports_linkchange(lport);

	if (!lport->ptp_rdata)
		lport->tt.disc_start(fc_lport_disc_callback, lport);
}
Beispiel #9
0
/**
 * fc_fabric_login() - Start the lport state machine
 * @lport: The local port that should log into the fabric
 *
 * Locking Note: This function should not be called
 *		 with the lport lock held.
 */
int fc_fabric_login(struct fc_lport *lport)
{
	int rc = -1;

	mutex_lock(&lport->lp_mutex);
	if (lport->state == LPORT_ST_DISABLED ||
	    lport->state == LPORT_ST_LOGO) {
		fc_lport_state_enter(lport, LPORT_ST_RESET);
		fc_lport_enter_reset(lport);
		rc = 0;
	}
	mutex_unlock(&lport->lp_mutex);

	return rc;
}
Beispiel #10
0
/**
 * fc_lport_enter_reset() - Reset the local port
 * @lport: The local port to be reset
 *
 * Locking Note: The lport lock is expected to be held before calling
 * this routine.
 */
static void fc_lport_enter_reset(struct fc_lport *lport)
{
	FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
		     fc_lport_state(lport));

	if (lport->vport) {
		if (lport->link_up)
			fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING);
		else
			fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);
	}
	fc_lport_state_enter(lport, LPORT_ST_RESET);
	fc_vports_linkchange(lport);
	fc_lport_reset_locked(lport);
	if (lport->link_up)
		fc_lport_enter_flogi(lport);
}
Beispiel #11
0
void fc_lport_enter_flogi(struct fc_lport *lport)
{
	struct fc_frame *fp;

	FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_FLOGI);

	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
	if (!fp)
		return fc_lport_error(lport, fp);

	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI,
				  fc_lport_flogi_resp, lport, lport->e_d_tov))
		fc_lport_error(lport, NULL);
}
Beispiel #12
0
static void fc_lport_enter_scr(struct fc_lport *lport)
{
	struct fc_frame *fp;

	FC_LPORT_DBG(lport, "Entered SCR state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_SCR);

	fp = fc_frame_alloc(lport, sizeof(struct fc_els_scr));
	if (!fp) {
		fc_lport_error(lport, fp);
		return;
	}

	if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR,
				  fc_lport_scr_resp, lport, lport->e_d_tov))
		fc_lport_error(lport, NULL);
}
Beispiel #13
0
static void fc_lport_enter_logo(struct fc_lport *lport)
{
	struct fc_frame *fp;
	struct fc_els_logo *logo;

	FC_LPORT_DBG(lport, "Entered LOGO state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_LOGO);

	fp = fc_frame_alloc(lport, sizeof(*logo));
	if (!fp) {
		fc_lport_error(lport, fp);
		return;
	}

	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO,
				  fc_lport_logo_resp, lport, lport->e_d_tov))
		fc_lport_error(lport, NULL);
}
Beispiel #14
0
static void fc_lport_enter_rpn_id(struct fc_lport *lport)
{
	struct fc_frame *fp;

	FC_LPORT_DBG(lport, "Entered RPN_ID state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_RPN_ID);

	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
			    sizeof(struct fc_ns_rn_id));
	if (!fp) {
		fc_lport_error(lport, fp);
		return;
	}

	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID,
				  fc_lport_rpn_id_resp,
				  lport, lport->e_d_tov))
		fc_lport_error(lport, NULL);
}
Beispiel #15
0
/**
 * fc_rport_enter_dns() - Create a fc_rport for the name server
 * @lport: The local port requesting a remote port for the name server
 *
 * Locking Note: The lport lock is expected to be held before calling
 * this routine.
 */
static void fc_lport_enter_dns(struct fc_lport *lport)
{
	struct fc_rport_priv *rdata;

	FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, LPORT_ST_DNS);

	mutex_lock(&lport->disc.disc_mutex);
	rdata = lport->tt.rport_create(lport, FC_FID_DIR_SERV);
	mutex_unlock(&lport->disc.disc_mutex);
	if (!rdata)
		goto err;

	rdata->ops = &fc_lport_rport_ops;
	lport->tt.rport_login(rdata);
	return;

err:
	fc_lport_error(lport, NULL);
}
static void fc_lport_enter_reset(struct fc_lport *lport)
{
	FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
		     fc_lport_state(lport));

	if (lport->state == LPORT_ST_DISABLED || lport->state == LPORT_ST_LOGO)
		return;

	if (lport->vport) {
		if (lport->link_up)
			fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING);
		else
			fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);
	}
	fc_lport_state_enter(lport, LPORT_ST_RESET);
	fc_host_post_event(lport->host, fc_get_event_number(),
			   FCH_EVT_LIPRESET, 0);
	fc_vports_linkchange(lport);
	fc_lport_reset_locked(lport);
	if (lport->link_up)
		fc_lport_enter_flogi(lport);
}
static void fc_lport_enter_ms(struct fc_lport *lport, enum fc_lport_state state)
{
	struct fc_frame *fp;
	enum fc_fdmi_req cmd;
	int size = sizeof(struct fc_ct_hdr);
	size_t len;
	int numattrs;

	FC_LPORT_DBG(lport, "Entered %s state from %s state\n",
		     fc_lport_state_names[state],
		     fc_lport_state(lport));

	fc_lport_state_enter(lport, state);

	switch (state) {
	case LPORT_ST_RHBA:
		cmd = FC_FDMI_RHBA;
		
		numattrs = 10;
		len = sizeof(struct fc_fdmi_rhba);
		len -= sizeof(struct fc_fdmi_attr_entry);
		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
		len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
		len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
		len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
		len += FC_FDMI_HBA_ATTR_MODEL_LEN;
		len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
		len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
		len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
		len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
		len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
		len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;

		size += len;
		break;
	case LPORT_ST_RPA:
		cmd = FC_FDMI_RPA;
		
		numattrs = 6;
		len = sizeof(struct fc_fdmi_rpa);
		len -= sizeof(struct fc_fdmi_attr_entry);
		len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
		len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
		len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
		len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
		len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
		len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
		len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;

		size += len;
		break;
	case LPORT_ST_DPRT:
		cmd = FC_FDMI_DPRT;
		len = sizeof(struct fc_fdmi_dprt);
		size += len;
		break;
	case LPORT_ST_DHBA:
		cmd = FC_FDMI_DHBA;
		len = sizeof(struct fc_fdmi_dhba);
		size += len;
		break;
	default:
		fc_lport_error(lport, NULL);
		return;
	}

	FC_LPORT_DBG(lport, "Cmd=0x%x Len %d size %d\n",
			     cmd, (int)len, size);
	fp = fc_frame_alloc(lport, size);
	if (!fp) {
		fc_lport_error(lport, fp);
		return;
	}

	if (!lport->tt.elsct_send(lport, FC_FID_MGMT_SERV, fp, cmd,
				  fc_lport_ms_resp,
				  lport, 3 * lport->r_a_tov))
		fc_lport_error(lport, fp);
}