scsi: mpi3mr: Reduce VD queue depth on detecting throttling
Reduce the VD queue depth on detecting the throttling condition. [mkp: incorporate fix for pointer cast issue reported by the test robot and Guenter Roeck] Link: https://lore.kernel.org/r/20220708195020.8323-3-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
f10af05732
Коммит
cf1ce8b715
|
@ -436,6 +436,10 @@ struct mpi3mr_intr_info {
|
|||
* struct mpi3mr_throttle_group_info - Throttle group info
|
||||
*
|
||||
* @io_divert: Flag indicates io divert is on or off for the TG
|
||||
* @need_qd_reduction: Flag to indicate QD reduction is needed
|
||||
* @qd_reduction: Queue Depth reduction in units of 10%
|
||||
* @fw_qd: QueueDepth value reported by the firmware
|
||||
* @modified_qd: Modified QueueDepth value due to throttling
|
||||
* @id: Throttle Group ID.
|
||||
* @high: High limit to turn on throttling in 512 byte blocks
|
||||
* @low: Low limit to turn off throttling in 512 byte blocks
|
||||
|
@ -443,6 +447,10 @@ struct mpi3mr_intr_info {
|
|||
*/
|
||||
struct mpi3mr_throttle_group_info {
|
||||
u8 io_divert;
|
||||
u8 need_qd_reduction;
|
||||
u8 qd_reduction;
|
||||
u16 fw_qd;
|
||||
u16 modified_qd;
|
||||
u16 id;
|
||||
u32 high;
|
||||
u32 low;
|
||||
|
@ -486,6 +494,7 @@ struct tgt_dev_pcie {
|
|||
* cached from firmware given data
|
||||
*
|
||||
* @state: State of the VD
|
||||
* @tg_qd_reduction: Queue Depth reduction in units of 10%
|
||||
* @tg_id: VDs throttle group ID
|
||||
* @high: High limit to turn on throttling in 512 byte blocks
|
||||
* @low: Low limit to turn off throttling in 512 byte blocks
|
||||
|
@ -493,6 +502,7 @@ struct tgt_dev_pcie {
|
|||
*/
|
||||
struct tgt_dev_vd {
|
||||
u8 state;
|
||||
u8 tg_qd_reduction;
|
||||
u16 tg_id;
|
||||
u32 tg_high;
|
||||
u32 tg_low;
|
||||
|
|
|
@ -4077,9 +4077,13 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
|
|||
tg = mrioc->throttle_groups;
|
||||
for (i = 0; i < mrioc->num_io_throttle_group; i++, tg++) {
|
||||
tg->id = 0;
|
||||
tg->fw_qd = 0;
|
||||
tg->modified_qd = 0;
|
||||
tg->io_divert = 0;
|
||||
tg->need_qd_reduction = 0;
|
||||
tg->high = 0;
|
||||
tg->low = 0;
|
||||
tg->qd_reduction = 0;
|
||||
atomic_set(&tg->pend_large_data_sz, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ MODULE_PARM_DESC(logging_level,
|
|||
static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
|
||||
struct mpi3mr_drv_cmd *cmdparam, u32 event_ctx);
|
||||
|
||||
#define MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION (0xFFFF)
|
||||
|
||||
/**
|
||||
* mpi3mr_host_tag_for_scmd - Get host tag for a scmd
|
||||
* @mrioc: Adapter instance reference
|
||||
|
@ -354,6 +356,50 @@ void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_queue_qd_reduction_event - Queue TG QD reduction event
|
||||
* @mrioc: Adapter instance reference
|
||||
* @tg: Throttle group information pointer
|
||||
*
|
||||
* Accessor to queue on synthetically generated driver event to
|
||||
* the event worker thread, the driver event will be used to
|
||||
* reduce the QD of all VDs in the TG from the worker thread.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void mpi3mr_queue_qd_reduction_event(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_throttle_group_info *tg)
|
||||
{
|
||||
struct mpi3mr_fwevt *fwevt;
|
||||
u16 sz = sizeof(struct mpi3mr_throttle_group_info *);
|
||||
|
||||
/*
|
||||
* If the QD reduction event is already queued due to throttle and if
|
||||
* the QD is not restored through device info change event
|
||||
* then dont queue further reduction events
|
||||
*/
|
||||
if (tg->fw_qd != tg->modified_qd)
|
||||
return;
|
||||
|
||||
fwevt = mpi3mr_alloc_fwevt(sz);
|
||||
if (!fwevt) {
|
||||
ioc_warn(mrioc, "failed to queue TG QD reduction event\n");
|
||||
return;
|
||||
}
|
||||
*(struct mpi3mr_throttle_group_info **)fwevt->event_data = tg;
|
||||
fwevt->mrioc = mrioc;
|
||||
fwevt->event_id = MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION;
|
||||
fwevt->send_ack = 0;
|
||||
fwevt->process_evt = 1;
|
||||
fwevt->evt_ctx = 0;
|
||||
fwevt->event_data_size = sz;
|
||||
tg->modified_qd = max_t(u16, (tg->fw_qd * tg->qd_reduction) / 10, 8);
|
||||
|
||||
dprint_event_bh(mrioc, "qd reduction event queued for tg_id(%d)\n",
|
||||
tg->id);
|
||||
mpi3mr_fwevt_add_to_list(mrioc, fwevt);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_invalidate_devhandles -Invalidate device handles
|
||||
* @mrioc: Adapter instance reference
|
||||
|
@ -880,6 +926,7 @@ static int mpi3mr_change_queue_depth(struct scsi_device *sdev,
|
|||
else if (!q_depth)
|
||||
q_depth = MPI3MR_DEFAULT_SDEV_QD;
|
||||
retval = scsi_change_queue_depth(sdev, q_depth);
|
||||
sdev->max_queue_depth = sdev->queue_depth;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1100,6 +1147,11 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||
tg->id = vdinf_io_throttle_group;
|
||||
tg->high = tgtdev->dev_spec.vd_inf.tg_high;
|
||||
tg->low = tgtdev->dev_spec.vd_inf.tg_low;
|
||||
tg->qd_reduction =
|
||||
tgtdev->dev_spec.vd_inf.tg_qd_reduction;
|
||||
if (is_added == true)
|
||||
tg->fw_qd = tgtdev->q_depth;
|
||||
tg->modified_qd = tgtdev->q_depth;
|
||||
}
|
||||
tgtdev->dev_spec.vd_inf.tg = tg;
|
||||
if (scsi_tgt_priv_data)
|
||||
|
@ -1493,6 +1545,60 @@ static void mpi3mr_logdata_evt_bh(struct mpi3mr_ioc *mrioc,
|
|||
fwevt->event_data_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_update_sdev_qd - Update SCSI device queue depath
|
||||
* @sdev: SCSI device reference
|
||||
* @data: Queue depth reference
|
||||
*
|
||||
* This is an iterator function called for each SCSI device in a
|
||||
* target to update the QD of each SCSI device.
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
static void mpi3mr_update_sdev_qd(struct scsi_device *sdev, void *data)
|
||||
{
|
||||
u16 *q_depth = (u16 *)data;
|
||||
|
||||
scsi_change_queue_depth(sdev, (int)*q_depth);
|
||||
sdev->max_queue_depth = sdev->queue_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_set_qd_for_all_vd_in_tg -set QD for TG VDs
|
||||
* @mrioc: Adapter instance reference
|
||||
* @tg: Throttle group information pointer
|
||||
*
|
||||
* Accessor to reduce QD for each device associated with the
|
||||
* given throttle group.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void mpi3mr_set_qd_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_throttle_group_info *tg)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mpi3mr_tgt_dev *tgtdev;
|
||||
struct mpi3mr_stgt_priv_data *tgt_priv;
|
||||
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) {
|
||||
if (tgtdev->starget && tgtdev->starget->hostdata) {
|
||||
tgt_priv = tgtdev->starget->hostdata;
|
||||
if (tgt_priv->throttle_group == tg) {
|
||||
dprint_event_bh(mrioc,
|
||||
"updating qd due to throttling for persist_id(%d) original_qd(%d), reduced_qd (%d)\n",
|
||||
tgt_priv->perst_id, tgtdev->q_depth,
|
||||
tg->modified_qd);
|
||||
starget_for_each_device(tgtdev->starget,
|
||||
(void *)&tg->modified_qd,
|
||||
mpi3mr_update_sdev_qd);
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_fwevt_bh - Firmware event bottomhalf handler
|
||||
* @mrioc: Adapter instance reference
|
||||
|
@ -1550,6 +1656,20 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
|||
mpi3mr_logdata_evt_bh(mrioc, fwevt);
|
||||
break;
|
||||
}
|
||||
case MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION:
|
||||
{
|
||||
struct mpi3mr_throttle_group_info *tg;
|
||||
|
||||
tg = *(struct mpi3mr_throttle_group_info **)fwevt->event_data;
|
||||
dprint_event_bh(mrioc,
|
||||
"qd reduction event processed for tg_id(%d) reduction_needed(%d)\n",
|
||||
tg->id, tg->need_qd_reduction);
|
||||
if (tg->need_qd_reduction) {
|
||||
mpi3mr_set_qd_for_all_vd_in_tg(mrioc, tg);
|
||||
tg->need_qd_reduction = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4234,8 +4354,10 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
|
|||
mrioc->io_throttle_high) ||
|
||||
(tg_pend_data_len >= tg->high))) {
|
||||
tg->io_divert = 1;
|
||||
tg->need_qd_reduction = 1;
|
||||
mpi3mr_set_io_divert_for_all_vd_in_tg(mrioc,
|
||||
tg, 1);
|
||||
mpi3mr_queue_qd_reduction_event(mrioc, tg);
|
||||
}
|
||||
} else {
|
||||
ioc_pend_data_len = atomic_add_return(data_len_blks,
|
||||
|
|
Загрузка…
Ссылка в новой задаче