summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-07-21 02:04:24 +0200
committerJames Bottomley <JBottomley@Parallels.com>2011-07-27 12:57:31 +0200
commit4c5d22bf7bdea68d3d449f6a8e1835da84909346 (patch)
treefb891101e865e1794c2c4cca71e1f0ecc6485bcb /drivers/scsi/bfa
parent[SCSI] bfa: Introduced initiator based lun masking feature. (diff)
downloadlinux-4c5d22bf7bdea68d3d449f6a8e1835da84909346.tar.xz
linux-4c5d22bf7bdea68d3d449f6a8e1835da84909346.zip
[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.h4
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c194
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h7
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c62
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h21
5 files changed, 288 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index 75b9d91d1f94..7b3d235d20b4 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 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)
{
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index 99fc913929b6..1080bcb81cb7 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 66349bde8dca..06fc00caeb41 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 1e02652019b3..e859adb9aa9e 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;