diff options
Diffstat (limited to 'drivers/scsi/bfa/bfa_fcs_rport.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_fcs_rport.c | 121 |
1 files changed, 82 insertions, 39 deletions
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index caaee6f..2c51445 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -262,6 +262,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_PLOGI_RCVD: + case RPSM_EVENT_PLOGI_COMP: case RPSM_EVENT_SCN: /* * Ignore, SCN is possibly online notification. @@ -470,6 +471,7 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_PRLO_RCVD: + case RPSM_EVENT_PLOGI_COMP: break; case RPSM_EVENT_LOGO_RCVD: @@ -484,9 +486,9 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_PLOGI_RCVD: - bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); + rport->plogi_pending = BFA_TRUE; + bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); - bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_DELETE: @@ -891,6 +893,18 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, switch (event) { case RPSM_EVENT_HCB_OFFLINE: + if (bfa_fcs_lport_is_online(rport->port) && + (rport->plogi_pending)) { + rport->plogi_pending = BFA_FALSE; + bfa_sm_set_state(rport, + bfa_fcs_rport_sm_plogiacc_sending); + bfa_fcs_rport_send_plogiacc(rport, NULL); + break; + } + /* + * !! fall through !! + */ + case RPSM_EVENT_ADDRESS_CHANGE: if (bfa_fcs_lport_is_online(rport->port)) { if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { @@ -921,6 +935,8 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_RCVD: case RPSM_EVENT_PRLO_RCVD: + case RPSM_EVENT_PLOGI_RCVD: + case RPSM_EVENT_LOGO_IMP: /* * Ignore, already offline. */ @@ -957,10 +973,18 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, */ if (bfa_fcs_lport_is_online(rport->port) && (!BFA_FCS_PID_IS_WKA(rport->pid))) { - bfa_sm_set_state(rport, - bfa_fcs_rport_sm_nsdisc_sending); - rport->ns_retries = 0; - bfa_fcs_rport_send_nsdisc(rport, NULL); + if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { + bfa_sm_set_state(rport, + bfa_fcs_rport_sm_nsdisc_sending); + rport->ns_retries = 0; + bfa_fcs_rport_send_nsdisc(rport, NULL); + } else { + /* For N2N Direct Attach, try to re-login */ + bfa_sm_set_state(rport, + bfa_fcs_rport_sm_plogi_sending); + rport->plogi_retries = 0; + bfa_fcs_rport_send_plogi(rport, NULL); + } } else { /* * if it is not a well known address, reset the @@ -1356,7 +1380,8 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.pwwn, port->port_cfg.nwwn, - bfa_fcport_get_maxfrsize(port->fcs->bfa)); + bfa_fcport_get_maxfrsize(port->fcs->bfa), + bfa_fcport_get_rx_bbcredit(port->fcs->bfa)); bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, @@ -1476,7 +1501,8 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) rport->pid, bfa_fcs_lport_get_fcid(port), rport->reply_oxid, port->port_cfg.pwwn, port->port_cfg.nwwn, - bfa_fcport_get_maxfrsize(port->fcs->bfa)); + bfa_fcport_get_maxfrsize(port->fcs->bfa), + bfa_fcport_get_rx_bbcredit(port->fcs->bfa)); bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); @@ -2024,6 +2050,11 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport) rport->stats.onlines++; + if ((!rport->pid) || (!rport->pwwn)) { + bfa_trc(rport->fcs, rport->pid); + bfa_sm_fault(rport->fcs, rport->pid); + } + if (bfa_fcs_lport_is_initiator(port)) { bfa_fcs_itnim_rport_online(rport->itnim); if (!BFA_FCS_PID_IS_WKA(rport->pid)) @@ -2047,6 +2078,7 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport) char rpwwn_buf[BFA_STRING_32]; rport->stats.offlines++; + rport->plogi_pending = BFA_FALSE; wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); wwn2str(rpwwn_buf, rport->pwwn); @@ -2120,7 +2152,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi) port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred); bfa_fcport_set_tx_bbcredit(port->fcs->bfa, - port->fabric->bb_credit); + port->fabric->bb_credit, 0); } } @@ -2233,22 +2265,6 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs, bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); } -static int -wwn_compare(wwn_t wwn1, wwn_t wwn2) -{ - u8 *b1 = (u8 *) &wwn1; - u8 *b2 = (u8 *) &wwn2; - int i; - - for (i = 0; i < sizeof(wwn_t); i++) { - if (b1[i] < b2[i]) - return -1; - if (b1[i] > b2[i]) - return 1; - } - return 0; -} - /* * Called by bport/vport to handle PLOGI received from an existing * remote port. @@ -2266,19 +2282,8 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, rport->reply_oxid = rx_fchs->ox_id; bfa_trc(rport->fcs, rport->reply_oxid); - /* - * In Switched fabric topology, - * PLOGI to each other. If our pwwn is smaller, ignore it, - * if it is not a well known address. - * If the link topology is N2N, - * this Plogi should be accepted. - */ - if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) && - (bfa_fcs_fabric_is_switched(rport->port->fabric)) && - (!BFA_FCS_PID_IS_WKA(rport->pid))) { - bfa_trc(rport->fcs, rport->pid); - return; - } + rport->pid = rx_fchs->s_id; + bfa_trc(rport->fcs, rport->pid); rport->stats.plogi_rcvd++; bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); @@ -2531,7 +2536,45 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id) bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD); } - +void +bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, + struct bfa_rport_attr_s *rport_attr) +{ + struct bfa_rport_qos_attr_s qos_attr; + struct bfa_fcs_lport_s *port = rport->port; + bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed; + + memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s)); + memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s)); + + rport_attr->pid = rport->pid; + rport_attr->pwwn = rport->pwwn; + rport_attr->nwwn = rport->nwwn; + rport_attr->cos_supported = rport->fc_cos; + rport_attr->df_sz = rport->maxfrsize; + rport_attr->state = bfa_fcs_rport_get_state(rport); + rport_attr->fc_cos = rport->fc_cos; + rport_attr->cisc = rport->cisc; + rport_attr->scsi_function = rport->scsi_function; + rport_attr->curr_speed = rport->rpf.rpsc_speed; + rport_attr->assigned_speed = rport->rpf.assigned_speed; + + qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority; + qos_attr.qos_flow_id = + cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id); + rport_attr->qos_attr = qos_attr; + + rport_attr->trl_enforced = BFA_FALSE; + if (bfa_fcport_is_ratelim(port->fcs->bfa) && + (rport->scsi_function == BFA_RPORT_TARGET)) { + if (rport_speed == BFA_PORT_SPEED_UNKNOWN) + rport_speed = + bfa_fcport_get_ratelim_speed(rport->fcs->bfa); + + if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port)) + rport_attr->trl_enforced = BFA_TRUE; + } +} /* * Remote port implementation. |