diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2011-07-21 00:04:24 (GMT) |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 10:57:31 (GMT) |
commit | 4c5d22bf7bdea68d3d449f6a8e1835da84909346 (patch) | |
tree | fb891101e865e1794c2c4cca71e1f0ecc6485bcb /drivers/scsi/bfa | |
parent | 83763d591b343b07331cebe86715205230c568b1 (diff) | |
download | linux-4c5d22bf7bdea68d3d449f6a8e1835da84909346.tar.xz |
[SCSI] bfa: Added support to configure lunmasking
- Added support to enable / disable lunmasking on Brocade adapter ports.
- Added support to query / clear lunmasking configuration.
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r-- | drivers/scsi/bfa/bfa_defs.h | 4 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.c | 194 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_fcpim.h | 7 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.c | 62 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.h | 21 |
5 files changed, 288 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index 75b9d91..7b3d235 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -175,11 +175,15 @@ enum bfa_status { BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */ BFA_STATUS_PHY_NOT_PRESENT = 183, /* PHY module not present */ BFA_STATUS_FEATURE_NOT_SUPPORTED = 192, /* Feature not supported */ + BFA_STATUS_ENTRY_EXISTS = 193, /* Entry already exists */ + BFA_STATUS_ENTRY_NOT_EXISTS = 194, /* Entry does not exist */ + BFA_STATUS_NO_CHANGE = 195, /* Feature already in that state */ BFA_STATUS_FAA_ENABLED = 197, /* FAA is already enabled */ BFA_STATUS_FAA_DISABLED = 198, /* FAA is already disabled */ BFA_STATUS_FAA_ACQUIRED = 199, /* FAA is already acquired */ BFA_STATUS_FAA_ACQ_ADDR = 200, /* Acquiring addr */ BFA_STATUS_ERROR_TRUNK_ENABLED = 203, /* Trunk enabled on adapter */ + BFA_STATUS_MAX_ENTRY_REACHED = 212, /* MAX entry reached */ BFA_STATUS_MAX_VAL /* Unknown error code */ }; #define bfa_status_t enum bfa_status diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index e601f17..e07bd47 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) { diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index 99fc913..1080bcb 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -416,5 +416,12 @@ void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, void bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn, u16 rp_tag, u8 lp_tag); +bfa_status_t bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 on_off); +bfa_status_t bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf); +bfa_status_t bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, + wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun); +bfa_status_t bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, + wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun); +bfa_status_t bfa_fcpim_lunmask_clear(struct bfa_s *bfa); #endif /* __BFA_FCPIM_H__ */ diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 66349bd..06fc00c 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -2394,6 +2394,56 @@ out: return 0; } +int +bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) +{ + struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; + unsigned long flags; + + spin_lock_irqsave(&bfad->bfad_lock, flags); + if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) + iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE); + else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) + iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE); + else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR) + iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + return 0; +} + +int +bfad_iocmd_fcpim_lunmask_query(struct bfad_s *bfad, void *cmd) +{ + struct bfa_bsg_fcpim_lunmask_query_s *iocmd = + (struct bfa_bsg_fcpim_lunmask_query_s *)cmd; + struct bfa_lunmask_cfg_s *lun_mask = &iocmd->lun_mask; + unsigned long flags; + + spin_lock_irqsave(&bfad->bfad_lock, flags); + iocmd->status = bfa_fcpim_lunmask_query(&bfad->bfa, lun_mask); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + return 0; +} + +int +bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ + struct bfa_bsg_fcpim_lunmask_s *iocmd = + (struct bfa_bsg_fcpim_lunmask_s *)cmd; + unsigned long flags; + + spin_lock_irqsave(&bfad->bfad_lock, flags); + if (v_cmd == IOCMD_FCPIM_LUNMASK_ADD) + iocmd->status = bfa_fcpim_lunmask_add(&bfad->bfa, iocmd->vf_id, + &iocmd->pwwn, iocmd->rpwwn, iocmd->lun); + else if (v_cmd == IOCMD_FCPIM_LUNMASK_DELETE) + iocmd->status = bfa_fcpim_lunmask_delete(&bfad->bfa, + iocmd->vf_id, &iocmd->pwwn, + iocmd->rpwwn, iocmd->lun); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + return 0; +} + static int bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, unsigned int payload_len) @@ -2712,6 +2762,18 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, case IOCMD_VF_RESET_STATS: rc = bfad_iocmd_vf_clr_stats(bfad, iocmd); break; + case IOCMD_FCPIM_LUNMASK_ENABLE: + case IOCMD_FCPIM_LUNMASK_DISABLE: + case IOCMD_FCPIM_LUNMASK_CLEAR: + rc = bfad_iocmd_lunmask(bfad, iocmd, cmd); + break; + case IOCMD_FCPIM_LUNMASK_QUERY: + rc = bfad_iocmd_fcpim_lunmask_query(bfad, iocmd); + break; + case IOCMD_FCPIM_LUNMASK_ADD: + case IOCMD_FCPIM_LUNMASK_DELETE: + rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd); + break; default: rc = -EINVAL; break; diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 1e02652..e859adb 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -137,6 +137,12 @@ enum { IOCMD_QOS_RESET_STATS, IOCMD_VF_GET_STATS, IOCMD_VF_RESET_STATS, + IOCMD_FCPIM_LUNMASK_ENABLE, + IOCMD_FCPIM_LUNMASK_DISABLE, + IOCMD_FCPIM_LUNMASK_CLEAR, + IOCMD_FCPIM_LUNMASK_QUERY, + IOCMD_FCPIM_LUNMASK_ADD, + IOCMD_FCPIM_LUNMASK_DELETE, }; struct bfa_bsg_gen_s { @@ -701,6 +707,21 @@ struct bfa_bsg_vf_reset_stats_s { u16 vf_id; }; +struct bfa_bsg_fcpim_lunmask_query_s { + bfa_status_t status; + u16 bfad_num; + struct bfa_lunmask_cfg_s lun_mask; +}; + +struct bfa_bsg_fcpim_lunmask_s { + bfa_status_t status; + u16 bfad_num; + u16 vf_id; + wwn_t pwwn; + wwn_t rpwwn; + struct scsi_lun lun; +}; + struct bfa_bsg_fcpt_s { bfa_status_t status; u16 vf_id; |