Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c5d22bf authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[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: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 83763d59
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+194 −0
Original line number Diff line number Diff line
@@ -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)
{
+7 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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;
+21 −0
Original line number Diff line number Diff line
@@ -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;