diff options
Diffstat (limited to 'drivers/scsi/bfa/bfa_fcpim.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index e601f178c5a6..e07bd4745d8b 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2553,6 +2553,200 @@ bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn, } } +/* + * set UA for all active luns in LM DB + */ +static void +bfa_ioim_lm_set_ua(struct bfa_s *bfa) +{ + struct bfa_lun_mask_s *lunm_list; + int i; + + lunm_list = bfa_get_lun_mask_list(bfa); + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) + continue; + lunm_list[i].ua = BFA_IOIM_LM_UA_SET; + } +} + +bfa_status_t +bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 update) +{ + struct bfa_lunmask_cfg_s *lun_mask; + + bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) + return BFA_STATUS_FAILED; + + if (bfa_get_lun_mask_status(bfa) == update) + return BFA_STATUS_NO_CHANGE; + + lun_mask = bfa_get_lun_mask(bfa); + lun_mask->status = update; + + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) + bfa_ioim_lm_set_ua(bfa); + + return bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_lunmask_clear(struct bfa_s *bfa) +{ + int i; + struct bfa_lun_mask_s *lunm_list; + + bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) + return BFA_STATUS_FAILED; + + lunm_list = bfa_get_lun_mask_list(bfa); + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if (lunm_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) { + if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) + bfa_rport_unset_lunmask(bfa, + BFA_RPORT_FROM_TAG(bfa, lunm_list[i].rp_tag)); + } + } + + memset(lunm_list, 0, sizeof(struct bfa_lun_mask_s) * MAX_LUN_MASK_CFG); + return bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf) +{ + struct bfa_lunmask_cfg_s *lun_mask; + + bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) + return BFA_STATUS_FAILED; + + lun_mask = bfa_get_lun_mask(bfa); + memcpy(buf, lun_mask, sizeof(struct bfa_lunmask_cfg_s)); + return BFA_STATUS_OK; +} + +bfa_status_t +bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, + wwn_t rpwwn, struct scsi_lun lun) +{ + struct bfa_lun_mask_s *lunm_list; + struct bfa_rport_s *rp = NULL; + int i, free_index = MAX_LUN_MASK_CFG + 1; + struct bfa_fcs_lport_s *port = NULL; + struct bfa_fcs_rport_s *rp_fcs; + + bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) + return BFA_STATUS_FAILED; + + port = bfa_fcs_lookup_port(&((struct bfad_s *)bfa->bfad)->bfa_fcs, + vf_id, *pwwn); + if (port) { + *pwwn = port->port_cfg.pwwn; + rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); + rp = rp_fcs->bfa_rport; + } + + lunm_list = bfa_get_lun_mask_list(bfa); + /* if entry exists */ + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) + free_index = i; + if ((lunm_list[i].lp_wwn == *pwwn) && + (lunm_list[i].rp_wwn == rpwwn) && + (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) == + scsilun_to_int((struct scsi_lun *)&lun))) + return BFA_STATUS_ENTRY_EXISTS; + } + + if (free_index > MAX_LUN_MASK_CFG) + return BFA_STATUS_MAX_ENTRY_REACHED; + + if (rp) { + lunm_list[free_index].lp_tag = bfa_lps_get_tag_from_pid(bfa, + rp->rport_info.local_pid); + lunm_list[free_index].rp_tag = rp->rport_tag; + } else { + lunm_list[free_index].lp_tag = BFA_LP_TAG_INVALID; + lunm_list[free_index].rp_tag = BFA_RPORT_TAG_INVALID; + } + + lunm_list[free_index].lp_wwn = *pwwn; + lunm_list[free_index].rp_wwn = rpwwn; + lunm_list[free_index].lun = lun; + lunm_list[free_index].state = BFA_IOIM_LUN_MASK_ACTIVE; + + /* set for all luns in this rp */ + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if ((lunm_list[i].lp_wwn == *pwwn) && + (lunm_list[i].rp_wwn == rpwwn)) + lunm_list[i].ua = BFA_IOIM_LM_UA_SET; + } + + return bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, + wwn_t rpwwn, struct scsi_lun lun) +{ + struct bfa_lun_mask_s *lunm_list; + struct bfa_rport_s *rp = NULL; + struct bfa_fcs_lport_s *port = NULL; + struct bfa_fcs_rport_s *rp_fcs; + int i; + + /* in min cfg lunm_list could be NULL but no commands should run. */ + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) + return BFA_STATUS_FAILED; + + bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); + bfa_trc(bfa, *pwwn); + bfa_trc(bfa, rpwwn); + bfa_trc(bfa, scsilun_to_int((struct scsi_lun *)&lun)); + + if (*pwwn == 0) { + port = bfa_fcs_lookup_port( + &((struct bfad_s *)bfa->bfad)->bfa_fcs, + vf_id, *pwwn); + if (port) { + *pwwn = port->port_cfg.pwwn; + rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); + rp = rp_fcs->bfa_rport; + } + } + + lunm_list = bfa_get_lun_mask_list(bfa); + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if ((lunm_list[i].lp_wwn == *pwwn) && + (lunm_list[i].rp_wwn == rpwwn) && + (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) == + scsilun_to_int((struct scsi_lun *)&lun))) { + lunm_list[i].lp_wwn = 0; + lunm_list[i].rp_wwn = 0; + int_to_scsilun(0, &lunm_list[i].lun); + lunm_list[i].state = BFA_IOIM_LUN_MASK_INACTIVE; + if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) { + lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID; + lunm_list[i].lp_tag = BFA_LP_TAG_INVALID; + } + return bfa_dconf_update(bfa); + } + } + + /* set for all luns in this rp */ + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if ((lunm_list[i].lp_wwn == *pwwn) && + (lunm_list[i].rp_wwn == rpwwn)) + lunm_list[i].ua = BFA_IOIM_LM_UA_SET; + } + + return BFA_STATUS_ENTRY_NOT_EXISTS; +} + static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete) { |