summaryrefslogtreecommitdiff
path: root/drivers/scsi/bfa/bfa_svc.c
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2012-09-22 04:23:59 +0400
committerJames Bottomley <JBottomley@Parallels.com>2012-10-07 14:03:50 +0400
commitbc0e2c2a97c1747ac0ade9b8620b14079e69fe3d (patch)
tree41fa46fba9a056b22f3b1212e076ec33529cab15 /drivers/scsi/bfa/bfa_svc.c
parent56d92aa5cf7c96c70f81d0350c94faf46a9fb76d (diff)
downloadlinux-bc0e2c2a97c1747ac0ade9b8620b14079e69fe3d.tar.xz
[SCSI] bfa: Add support for FC Arbitrated Loop topology.
- Add private loop topology support at 2G/4G/8G speeds with following limitations 1. No support for multiple initiators in the loop 2. No public loop support. If attached to a loop with an FL_Port, device continues to work as a private NL_Port in the loop 3. No auto topology detection. User has to manually set the configured topology to loop if attaching to loop. - When loop topology is configured, enabling FC port features QoS/Trunk/TRL are not allowed and vice versa. Signed-off-by: Vijaya Mohan Guvva <vmohan@brocade.com> Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa/bfa_svc.c')
-rw-r--r--drivers/scsi/bfa/bfa_svc.c93
1 files changed, 83 insertions, 10 deletions
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index b2538d60db34..fcad11629f10 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -1244,6 +1244,12 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
* Just ignore
*/
break;
+ case BFA_LPS_SM_SET_N2N_PID:
+ /*
+ * When topology is set to loop, bfa_lps_set_n2n_pid() sends
+ * this event. Ignore this event.
+ */
+ break;
default:
bfa_sm_fault(lps->bfa, event);
@@ -1261,6 +1267,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
switch (event) {
case BFA_LPS_SM_FWRSP:
+ case BFA_LPS_SM_OFFLINE:
if (lps->status == BFA_STATUS_OK) {
bfa_sm_set_state(lps, bfa_lps_sm_online);
if (lps->fdisc)
@@ -1289,7 +1296,6 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
bfa_lps_login_comp(lps);
break;
- case BFA_LPS_SM_OFFLINE:
case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
@@ -2250,11 +2256,11 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
bfa_trc(fcport->bfa,
- pevent->link_state.vc_fcf.fcf.fipenabled);
+ pevent->link_state.attr.vc_fcf.fcf.fipenabled);
bfa_trc(fcport->bfa,
- pevent->link_state.vc_fcf.fcf.fipfailed);
+ pevent->link_state.attr.vc_fcf.fcf.fipfailed);
- if (pevent->link_state.vc_fcf.fcf.fipfailed)
+ if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
BFA_PL_EID_FIP_FCF_DISC, 0,
"FIP FCF Discovery Failed");
@@ -2996,6 +3002,21 @@ bfa_fcport_iocdisable(struct bfa_s *bfa)
bfa_trunk_iocdisable(bfa);
}
+/*
+ * Update loop info in fcport for SCN online
+ */
+static void
+bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
+ struct bfa_fcport_loop_info_s *loop_info)
+{
+ fcport->myalpa = loop_info->myalpa;
+ fcport->alpabm_valid =
+ loop_info->alpabm_val;
+ memcpy(fcport->alpabm.alpa_bm,
+ loop_info->alpabm.alpa_bm,
+ sizeof(struct fc_alpabm_s));
+}
+
static void
bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
{
@@ -3005,12 +3026,15 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
fcport->speed = pevent->link_state.speed;
fcport->topology = pevent->link_state.topology;
- if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
- fcport->myalpa = 0;
+ if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
+ bfa_fcport_update_loop_info(fcport,
+ &pevent->link_state.attr.loop_info);
+ return;
+ }
/* QoS Details */
fcport->qos_attr = pevent->link_state.qos_attr;
- fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr;
+ fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
/*
* update trunk state if applicable
@@ -3019,7 +3043,8 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
trunk->attr.state = BFA_TRUNK_DISABLED;
/* update FCoE specific */
- fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan);
+ fcport->fcoe_vlan =
+ be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
bfa_trc(fcport->bfa, fcport->speed);
bfa_trc(fcport->bfa, fcport->topology);
@@ -3609,6 +3634,9 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
if (fcport->cfg.trunked == BFA_TRUE)
return BFA_STATUS_TRUNK_ENABLED;
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (speed == BFA_PORT_SPEED_16GBPS))
+ return BFA_STATUS_UNSUPP_SPEED;
if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
bfa_trc(bfa, fcport->speed_sup);
return BFA_STATUS_UNSUPP_SPEED;
@@ -3663,7 +3691,24 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
switch (topology) {
case BFA_PORT_TOPOLOGY_P2P:
+ break;
+
case BFA_PORT_TOPOLOGY_LOOP:
+ if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
+ (fcport->qos_attr.state != BFA_QOS_DISABLED))
+ return BFA_STATUS_ERROR_QOS_ENABLED;
+ if (fcport->cfg.ratelimit != BFA_FALSE)
+ return BFA_STATUS_ERROR_TRL_ENABLED;
+ if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
+ (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
+ return BFA_STATUS_ERROR_TRUNK_ENABLED;
+ if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
+ (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
+ return BFA_STATUS_UNSUPP_SPEED;
+ if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
+ return BFA_STATUS_LOOP_UNSUPP_MEZZ;
+ break;
+
case BFA_PORT_TOPOLOGY_AUTO:
break;
@@ -3686,6 +3731,17 @@ bfa_fcport_get_topology(struct bfa_s *bfa)
return fcport->topology;
}
+/**
+ * Get config topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.topology;
+}
+
bfa_status_t
bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
{
@@ -3761,9 +3817,11 @@ bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
u8
bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
+ return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
- return fcport->cfg.rx_bbcredit;
+ else
+ return 0;
}
void
@@ -4707,6 +4765,21 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
break;
+ case BFI_RPORT_I2H_LIP_SCN_ONLINE:
+ bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
+ &msg.lip_scn->loop_info);
+ bfa_cb_rport_scn_online(bfa);
+ break;
+
+ case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
+ bfa_cb_rport_scn_offline(bfa);
+ break;
+
+ case BFI_RPORT_I2H_NO_DEV:
+ rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
+ bfa_cb_rport_scn_no_dev(rp->rport_drv);
+ break;
+
default:
bfa_trc(bfa, m->mhdr.msg_id);
WARN_ON(1);