[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>
This commit is contained in:
Krishna Gudipati 2011-07-20 17:04:24 -07:00 committed by James Bottomley
parent 83763d591b
commit 4c5d22bf7b
5 changed files with 288 additions and 0 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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__ */

View File

@ -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;

View File

@ -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;