Skip to content

Commit

Permalink
[SCSI] bfa: Added support to configure lunmasking
Browse files Browse the repository at this point in the history
- 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>
  • Loading branch information
Krishna Gudipati authored and James Bottomley committed Jul 27, 2011
1 parent 83763d5 commit 4c5d22b
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 0 deletions.
4 changes: 4 additions & 0 deletions drivers/scsi/bfa/bfa_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
194 changes: 194 additions & 0 deletions drivers/scsi/bfa/bfa_fcpim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
7 changes: 7 additions & 0 deletions drivers/scsi/bfa/bfa_fcpim.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
62 changes: 62 additions & 0 deletions drivers/scsi/bfa/bfad_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2394,6 +2394,56 @@ bfad_iocmd_vf_clr_stats(struct bfad_s *bfad, void *cmd)
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)
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 21 additions & 0 deletions drivers/scsi/bfa/bfad_bsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 4c5d22b

Please sign in to comment.