diff mbox series

[2/2] mpi3mr: Reduce VD queue depth on detecting the throttling

Message ID 20220708195020.8323-3-sreekanth.reddy@broadcom.com
State New
Headers show
Series mpi3mr: Add support for Resource Based Metering | expand

Commit Message

Sreekanth Reddy July 8, 2022, 7:50 p.m. UTC
Reduce the VD queue depth on detecting the throttling condition.

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
---
 drivers/scsi/mpi3mr/mpi3mr.h    |  10 +++
 drivers/scsi/mpi3mr/mpi3mr_fw.c |   4 ++
 drivers/scsi/mpi3mr/mpi3mr_os.c | 123 ++++++++++++++++++++++++++++++++
 3 files changed, 137 insertions(+)

Comments

Guenter Roeck July 15, 2022, 12:10 a.m. UTC | #1
On Sat, Jul 09, 2022 at 01:20:20AM +0530, Sreekanth Reddy wrote:
> Reduce the VD queue depth on detecting the throttling condition.
> 
> Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>

Building i386:allyesconfig ... failed
--------------
drivers/scsi/mpi3mr/mpi3mr_os.c: In function 'mpi3mr_queue_qd_reduction_event':
drivers/scsi/mpi3mr/mpi3mr_os.c:389:40: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
  389 |         *(__le64 *)fwevt->event_data = (__le64)tg;
      |                                        ^
drivers/scsi/mpi3mr/mpi3mr_os.c: In function 'mpi3mr_fwevt_bh':
drivers/scsi/mpi3mr/mpi3mr_os.c:1655:22: error: cast to pointer from integer of different size
 1655 |                 tg = (struct mpi3mr_throttle_group_info *)
      |                      ^

bisect log attached.

Guenter

---
# bad: [37b355fdaf31ee18bda9a93c2a438dc1cbf57ec9] Add linux-next specific files for 20220714
# good: [32346491ddf24599decca06190ebca03ff9de7f8] Linux 5.19-rc6
git bisect start 'HEAD' 'v5.19-rc6'
# good: [6d30dd0872599b7004e26330fc2e476ad900e7f6] Merge branch 'drm-next' of git://git.freedesktop.org/git/drm/drm.git
git bisect good 6d30dd0872599b7004e26330fc2e476ad900e7f6
# good: [64b90d49f82dcc78b4ecf98bf8cb306713f80c36] Merge branch 'next' of git://git.kernel.org/pub/scm/virt/kvm/kvm.git
git bisect good 64b90d49f82dcc78b4ecf98bf8cb306713f80c36
# good: [9cb02c37af5c63f4e609b370b2b17a9e7f98300d] Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
git bisect good 9cb02c37af5c63f4e609b370b2b17a9e7f98300d
# bad: [c9020490ef7b885984e6cf1d39687794538a4605] Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
git bisect bad c9020490ef7b885984e6cf1d39687794538a4605
# bad: [75c791957c6e636b5c42f63ead2101271cc1bd13] Merge branch 'gpio/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
git bisect bad 75c791957c6e636b5c42f63ead2101271cc1bd13
# good: [297bdc540f0e391568788f8ece3020653748a26f] scsi: smartpqi: Close write read holes
git bisect good 297bdc540f0e391568788f8ece3020653748a26f
# bad: [4dbe57617d045d9579390c160998d2bd6e76a82d] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
git bisect bad 4dbe57617d045d9579390c160998d2bd6e76a82d
# good: [85ebec464953ed20bf43f60b529fa4b568ade219] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
git bisect good 85ebec464953ed20bf43f60b529fa4b568ade219
# bad: [039e231c6573c2384b4cfed16b62f39ccd6be51b] scsi: sd: Support multiple LBA ranges in an UNMAP command
git bisect bad 039e231c6573c2384b4cfed16b62f39ccd6be51b
# good: [6d567dfee0b7b4c66fb1f62d59a2e62e2709b453] scsi: smartpqi: Add ctrl ready timeout module parameter
git bisect good 6d567dfee0b7b4c66fb1f62d59a2e62e2709b453
# bad: [3101bcf7eea56fd76c7cb11b518d6acc9a15a08a] scsi: sg: Allow waiting for commands to complete on removed device
git bisect bad 3101bcf7eea56fd76c7cb11b518d6acc9a15a08a
# good: [f54f85dfd757301791be8ce6fccc6f6604d82b40] scsi: smartpqi: Update version to 2.1.18-045
git bisect good f54f85dfd757301791be8ce6fccc6f6604d82b40
# bad: [c196bc4dce42bdcc2c69ec106d176f427c56003a] scsi: mpi3mr: Reduce VD queue depth on detecting throttling
git bisect bad c196bc4dce42bdcc2c69ec106d176f427c56003a
# good: [fded192f13033676a5ed202cae187d2832fa0093] scsi: mpi3mr: Resource Based Metering
git bisect good fded192f13033676a5ed202cae187d2832fa0093
# first bad commit: [c196bc4dce42bdcc2c69ec106d176f427c56003a] scsi: mpi3mr: Reduce VD queue depth on detecting throttling
diff mbox series

Patch

diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index 6bb3311..0935b2e 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -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;
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index ab79374..6e39f79 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -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);
 		}
 	}
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index e1ccb5f..6e36229 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -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;
+	}
+	*(__le64 *)fwevt->event_data = (__le64)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,21 @@  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 *)
+		    (*(__le64 *)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 +4355,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,