[SCSI] bfa: Add support for IO throttling at port level

Add capability to limit the number of exchanges on a port to
avoid queue-full conditions from the target side.

Signed-off-by: Sudarsana Reddy Kalluru <skalluru@brocade.com>
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
Krishna Gudipati 2012-09-21 17:26:41 -07:00 committed by James Bottomley
parent 6894f013a7
commit 7ace27ae28
8 changed files with 182 additions and 8 deletions

View File

@ -983,7 +983,8 @@ bfa_iocfc_send_cfg(void *bfa_arg)
cfg_info->single_msix_vec = 1; cfg_info->single_msix_vec = 1;
cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG; cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
cfg_info->num_cqs = cfg->fwcfg.num_cqs; cfg_info->num_cqs = cfg->fwcfg.num_cqs;
cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs); cfg_info->num_ioim_reqs = cpu_to_be16(bfa_fcpim_get_throttle_cfg(bfa,
cfg->fwcfg.num_ioim_reqs));
cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs); cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa); bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
@ -1245,10 +1246,14 @@ bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
static void static void
bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg) bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
{ {
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs); bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs); bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
bfa_rport_res_recfg(bfa, fwcfg->num_rports); bfa_rport_res_recfg(bfa, fwcfg->num_rports);
bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs); bfa_fcp_res_recfg(bfa, cpu_to_be16(cfg_info->num_ioim_reqs),
fwcfg->num_ioim_reqs);
bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs); bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
} }

View File

@ -875,6 +875,19 @@ struct bfa_lunmask_cfg_s {
struct bfa_lun_mask_s lun_list[MAX_LUN_MASK_CFG]; struct bfa_lun_mask_s lun_list[MAX_LUN_MASK_CFG];
}; };
struct bfa_throttle_cfg_s {
u16 is_valid;
u16 value;
u32 rsvd;
};
struct bfa_defs_fcpim_throttle_s {
u16 max_value;
u16 cur_value;
u16 cfg_value;
u16 rsvd;
};
/* /*
* Physical port configuration * Physical port configuration
*/ */

View File

@ -3703,6 +3703,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_mem_dma_s *seg_ptr; struct bfa_mem_dma_s *seg_ptr;
u16 idx, nsegs, num_io_req; u16 idx, nsegs, num_io_req;
fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs; fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
fcp->num_fwtio_reqs = cfg->fwcfg.num_fwtio_reqs; fcp->num_fwtio_reqs = cfg->fwcfg.num_fwtio_reqs;
fcp->num_itns = cfg->fwcfg.num_rports; fcp->num_itns = cfg->fwcfg.num_rports;
@ -3725,6 +3726,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa); bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
} }
fcp->throttle_update_required = 1;
bfa_fcpim_attach(fcp, bfad, cfg, pcidev); bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
bfa_iotag_attach(fcp); bfa_iotag_attach(fcp);
@ -3763,23 +3765,33 @@ bfa_fcp_iocdisable(struct bfa_s *bfa)
{ {
struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
/* Enqueue unused ioim resources to free_q */
list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
bfa_fcpim_iocdisable(fcp); bfa_fcpim_iocdisable(fcp);
} }
void void
bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw) bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw)
{ {
struct bfa_fcp_mod_s *mod = BFA_FCP_MOD(bfa); struct bfa_fcp_mod_s *mod = BFA_FCP_MOD(bfa);
struct list_head *qe; struct list_head *qe;
int i; int i;
/* Update io throttle value only once during driver load time */
if (!mod->throttle_update_required)
return;
for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) { for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe); bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
list_add_tail(qe, &mod->iotag_unused_q); list_add_tail(qe, &mod->iotag_unused_q);
} }
if (mod->num_ioim_reqs != num_ioim_fw) {
bfa_trc(bfa, mod->num_ioim_reqs);
bfa_trc(bfa, num_ioim_fw);
}
mod->max_ioim_reqs = max_ioim_fw;
mod->num_ioim_reqs = num_ioim_fw;
mod->throttle_update_required = 0;
} }
void void
@ -3837,3 +3849,88 @@ bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
bfa_mem_kva_curp(fcp) = (u8 *) iotag; bfa_mem_kva_curp(fcp) = (u8 *) iotag;
} }
/**
* To send config req, first try to use throttle value from flash
* If 0, then use driver parameter
* We need to use min(flash_val, drv_val) because
* memory allocation was done based on this cfg'd value
*/
u16
bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param)
{
u16 tmp;
struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
/*
* If throttle value from flash is already in effect after driver is
* loaded then until next load, always return current value instead
* of actual flash value
*/
if (!fcp->throttle_update_required)
return (u16)fcp->num_ioim_reqs;
tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0;
if (!tmp || (tmp > drv_cfg_param))
tmp = drv_cfg_param;
return tmp;
}
bfa_status_t
bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value)
{
if (!bfa_dconf_get_min_cfg(bfa)) {
BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value;
BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1;
return BFA_STATUS_OK;
}
return BFA_STATUS_FAILED;
}
u16
bfa_fcpim_read_throttle(struct bfa_s *bfa)
{
struct bfa_throttle_cfg_s *throttle_cfg =
&(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg);
return ((!bfa_dconf_get_min_cfg(bfa)) ?
((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0);
}
bfa_status_t
bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value)
{
/* in min cfg no commands should run. */
if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
(!bfa_dconf_read_data_valid(bfa)))
return BFA_STATUS_FAILED;
bfa_fcpim_write_throttle(bfa, value);
return bfa_dconf_update(bfa);
}
bfa_status_t
bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf)
{
struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
struct bfa_defs_fcpim_throttle_s throttle;
if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
(!bfa_dconf_read_data_valid(bfa)))
return BFA_STATUS_FAILED;
memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s));
throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs);
throttle.cfg_value = bfa_fcpim_read_throttle(bfa);
if (!throttle.cfg_value)
throttle.cfg_value = throttle.cur_value;
throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs);
memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s));
return BFA_STATUS_OK;
}

View File

@ -42,7 +42,7 @@ void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m)); void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m));
void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m); void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m);
void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp); void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp);
void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw); void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw);
#define BFA_FCP_MOD(_hal) (&(_hal)->modules.fcp_mod) #define BFA_FCP_MOD(_hal) (&(_hal)->modules.fcp_mod)
#define BFA_MEM_FCP_KVA(__bfa) (&(BFA_FCP_MOD(__bfa)->kva_seg)) #define BFA_MEM_FCP_KVA(__bfa) (&(BFA_FCP_MOD(__bfa)->kva_seg))
@ -150,6 +150,7 @@ struct bfa_fcp_mod_s {
struct list_head iotag_unused_q; /* unused IO resources*/ struct list_head iotag_unused_q; /* unused IO resources*/
struct bfa_iotag_s *iotag_arr; struct bfa_iotag_s *iotag_arr;
struct bfa_itn_s *itn_arr; struct bfa_itn_s *itn_arr;
int max_ioim_reqs;
int num_ioim_reqs; int num_ioim_reqs;
int num_fwtio_reqs; int num_fwtio_reqs;
int num_itns; int num_itns;
@ -157,6 +158,7 @@ struct bfa_fcp_mod_s {
struct bfa_fcpim_s fcpim; struct bfa_fcpim_s fcpim;
struct bfa_mem_dma_s dma_seg[BFA_FCP_DMA_SEGS]; struct bfa_mem_dma_s dma_seg[BFA_FCP_DMA_SEGS];
struct bfa_mem_kva_s kva_seg; struct bfa_mem_kva_s kva_seg;
int throttle_update_required;
}; };
/* /*
@ -418,5 +420,10 @@ bfa_status_t bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id,
bfa_status_t bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, bfa_status_t bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id,
wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun); wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun);
bfa_status_t bfa_fcpim_lunmask_clear(struct bfa_s *bfa); bfa_status_t bfa_fcpim_lunmask_clear(struct bfa_s *bfa);
u16 bfa_fcpim_read_throttle(struct bfa_s *bfa);
bfa_status_t bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value);
bfa_status_t bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value);
bfa_status_t bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf);
u16 bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param);
#endif /* __BFA_FCPIM_H__ */ #endif /* __BFA_FCPIM_H__ */

View File

@ -3026,6 +3026,9 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
struct bfa_rport_qos_attr_s qos_attr; struct bfa_rport_qos_attr_s qos_attr;
struct bfa_fcs_lport_s *port = rport->port; struct bfa_fcs_lport_s *port = rport->port;
bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed; bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
struct bfa_port_attr_s port_attr;
bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s)); memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s)); memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
@ -3056,7 +3059,8 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
rport_speed = rport_speed =
bfa_fcport_get_ratelim_speed(rport->fcs->bfa); bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port)) if ((bfa_fcs_lport_get_rport_max_speed(port) !=
BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
rport_attr->trl_enforced = BFA_TRUE; rport_attr->trl_enforced = BFA_TRUE;
} }
} }

View File

@ -716,6 +716,7 @@ struct bfa_dconf_hdr_s {
struct bfa_dconf_s { struct bfa_dconf_s {
struct bfa_dconf_hdr_s hdr; struct bfa_dconf_hdr_s hdr;
struct bfa_lunmask_cfg_s lun_mask; struct bfa_lunmask_cfg_s lun_mask;
struct bfa_throttle_cfg_s throttle_cfg;
}; };
#pragma pack() #pragma pack()
@ -738,6 +739,8 @@ struct bfa_dconf_mod_s {
#define bfa_dconf_read_data_valid(__bfa) \ #define bfa_dconf_read_data_valid(__bfa) \
(BFA_DCONF_MOD(__bfa)->read_data_valid) (BFA_DCONF_MOD(__bfa)->read_data_valid)
#define BFA_DCONF_UPDATE_TOV 5000 /* memtest timeout in msec */ #define BFA_DCONF_UPDATE_TOV 5000 /* memtest timeout in msec */
#define bfa_dconf_get_min_cfg(__bfa) \
(BFA_DCONF_MOD(__bfa)->min_cfg)
void bfa_dconf_modinit(struct bfa_s *bfa); void bfa_dconf_modinit(struct bfa_s *bfa);
void bfa_dconf_modexit(struct bfa_s *bfa); void bfa_dconf_modexit(struct bfa_s *bfa);

View File

@ -2547,6 +2547,36 @@ bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
return 0; return 0;
} }
int
bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_throttle_s *iocmd =
(struct bfa_bsg_fcpim_throttle_s *)cmd;
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_fcpim_throttle_get(&bfad->bfa,
(void *)&iocmd->throttle);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return 0;
}
int
bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_throttle_s *iocmd =
(struct bfa_bsg_fcpim_throttle_s *)cmd;
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_fcpim_throttle_set(&bfad->bfa,
iocmd->throttle.cfg_value);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return 0;
}
static int static int
bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
unsigned int payload_len) unsigned int payload_len)
@ -2881,6 +2911,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_FCPIM_LUNMASK_DELETE: case IOCMD_FCPIM_LUNMASK_DELETE:
rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd); rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd);
break; break;
case IOCMD_FCPIM_THROTTLE_QUERY:
rc = bfad_iocmd_fcpim_throttle_query(bfad, iocmd);
break;
case IOCMD_FCPIM_THROTTLE_SET:
rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd);
break;
default: default:
rc = -EINVAL; rc = -EINVAL;
break; break;

View File

@ -145,6 +145,8 @@ enum {
IOCMD_DIAG_DPORT_DISABLE, IOCMD_DIAG_DPORT_DISABLE,
IOCMD_DIAG_DPORT_GET_STATE, IOCMD_DIAG_DPORT_GET_STATE,
IOCMD_QOS_SET_BW, IOCMD_QOS_SET_BW,
IOCMD_FCPIM_THROTTLE_QUERY,
IOCMD_FCPIM_THROTTLE_SET
}; };
struct bfa_bsg_gen_s { struct bfa_bsg_gen_s {
@ -740,6 +742,13 @@ struct bfa_bsg_fcpim_lunmask_s {
struct scsi_lun lun; struct scsi_lun lun;
}; };
struct bfa_bsg_fcpim_throttle_s {
bfa_status_t status;
u16 bfad_num;
u16 vf_id;
struct bfa_defs_fcpim_throttle_s throttle;
};
struct bfa_bsg_fcpt_s { struct bfa_bsg_fcpt_s {
bfa_status_t status; bfa_status_t status;
u16 vf_id; u16 vf_id;