scsi: qla2xxx: edif: Reduce memory usage during low I/O
authorQuinn Tran <qutran@marvell.com>
Thu, 22 Dec 2022 04:39:30 +0000 (20:39 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 12 Jan 2023 04:48:26 +0000 (23:48 -0500)
For edif, each I/O requires a secondary buffer to carry the FCP
cmnd. During high traffic time, these buffers are cached in the qpair. As
traffic dies down, these buffers will be trimmed as needed. If traffic is
reduced to none over 2 consecutive intervals, then these buffers will be
further trimmed.

Free FCP cmnd buffers to reduce memory usage during slow I/O time.

Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c

index 6f6190404939d11aaee4adcf4d1aff424fb6a2e6..972f1144b9d323befaee1ca3d536280bbce3fa9b 100644 (file)
@@ -3735,7 +3735,10 @@ struct  qla_buf_pool {
        u16 num_bufs;
        u16 num_active;
        u16 max_used;
-       u16 reserved;
+       u16 num_alloc;
+       u16 prev_max;
+       u16 pad;
+       uint32_t take_snapshot:1;
        unsigned long *buf_map;
        void **buf_array;
        dma_addr_t *dma_array;
@@ -4874,6 +4877,7 @@ typedef struct scsi_qla_host {
 #define LOOP_READY     5
 #define LOOP_DEAD      6
 
+       unsigned long   buf_expired;
        unsigned long   relogin_jif;
        unsigned long   dpc_flags;
 #define RESET_MARKER_NEEDED    0       /* Send marker to ISP. */
index d802d37fe739eae9bef6f8552e2b579ec8c63de4..9142df876c733451dd62a2d06723f4b8ffc8705a 100644 (file)
@@ -293,6 +293,7 @@ extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *);
 extern void qla2x00_async_event(scsi_qla_host_t *, struct rsp_que *,
        uint16_t *);
 extern int  qla2x00_vp_abort_isp(scsi_qla_host_t *);
+void qla_adjust_buf(struct scsi_qla_host *);
 
 /*
  * Global Function Prototypes in qla_iocb.c source file.
index 5976a2f036e67a09623e8b53412f38d4ec29f7ad..c6ca39b8e23d38f3f40cc6b623d83b2770ac87c0 100644 (file)
@@ -1170,6 +1170,7 @@ again:
 
                dsc->buf = qp->buf_pool.buf_array[tag] = buf;
                dsc->buf_dma = qp->buf_pool.dma_array[tag] = buf_dma;
+               qp->buf_pool.num_alloc++;
        } else {
                dsc->buf = qp->buf_pool.buf_array[tag];
                dsc->buf_dma = qp->buf_pool.dma_array[tag];
@@ -1185,14 +1186,107 @@ again:
        return 0;
 }
 
+void qla_trim_buf(struct qla_qpair *qp, u16 trim)
+{
+       int i, j;
+       struct qla_hw_data *ha = qp->vha->hw;
+
+       if (!trim)
+               return;
+
+       for (i = 0; i < trim; i++) {
+               j = qp->buf_pool.num_alloc - 1;
+               if (test_bit(j, qp->buf_pool.buf_map)) {
+                       ql_dbg(ql_dbg_io + ql_dbg_verbose, qp->vha, 0x300b,
+                              "QP id(%d): trim active buf[%d]. Remain %d bufs\n",
+                              qp->id, j, qp->buf_pool.num_alloc);
+                       return;
+               }
+
+               if (qp->buf_pool.buf_array[j]) {
+                       dma_pool_free(ha->fcp_cmnd_dma_pool, qp->buf_pool.buf_array[j],
+                                     qp->buf_pool.dma_array[j]);
+                       qp->buf_pool.buf_array[j] = NULL;
+                       qp->buf_pool.dma_array[j] = 0;
+               }
+               qp->buf_pool.num_alloc--;
+               if (!qp->buf_pool.num_alloc)
+                       break;
+       }
+       ql_dbg(ql_dbg_io + ql_dbg_verbose, qp->vha, 0x3010,
+              "QP id(%d): trimmed %d bufs. Remain %d bufs\n",
+              qp->id, trim, qp->buf_pool.num_alloc);
+}
+
+void __qla_adjust_buf(struct qla_qpair *qp)
+{
+       u32 trim;
+
+       qp->buf_pool.take_snapshot = 0;
+       qp->buf_pool.prev_max = qp->buf_pool.max_used;
+       qp->buf_pool.max_used = qp->buf_pool.num_active;
+
+       if (qp->buf_pool.prev_max > qp->buf_pool.max_used &&
+           qp->buf_pool.num_alloc > qp->buf_pool.max_used) {
+               /* down trend */
+               trim = qp->buf_pool.num_alloc - qp->buf_pool.max_used;
+               trim  = (trim * 10) / 100;
+               trim = trim ? trim : 1;
+               qla_trim_buf(qp, trim);
+       } else if (!qp->buf_pool.prev_max  && !qp->buf_pool.max_used) {
+               /* 2 periods of no io */
+               qla_trim_buf(qp, qp->buf_pool.num_alloc);
+       }
+}
 
 /* it is assume qp->qp_lock is held at this point */
 void qla_put_buf(struct qla_qpair *qp, struct qla_buf_dsc *dsc)
 {
        if (dsc->tag == TAG_FREED)
                return;
+       lockdep_assert_held(qp->qp_lock_ptr);
 
        clear_bit(dsc->tag, qp->buf_pool.buf_map);
        qp->buf_pool.num_active--;
        dsc->tag = TAG_FREED;
+
+       if (qp->buf_pool.take_snapshot)
+               __qla_adjust_buf(qp);
+}
+
+#define EXPIRE (60 * HZ)
+void qla_adjust_buf(struct scsi_qla_host *vha)
+{
+       unsigned long flags;
+       int i;
+       struct qla_qpair *qp;
+
+       if (vha->vp_idx)
+               return;
+
+       if (!vha->buf_expired) {
+               vha->buf_expired = jiffies + EXPIRE;
+               return;
+       }
+       if (time_before(jiffies, vha->buf_expired))
+               return;
+
+       vha->buf_expired = jiffies + EXPIRE;
+
+       for (i = 0; i < vha->hw->num_qpairs; i++) {
+               qp = vha->hw->queue_pair_map[i];
+               if (!qp)
+                       continue;
+               if (!qp->buf_pool.num_alloc)
+                       continue;
+
+               if (qp->buf_pool.take_snapshot) {
+                       /* no io has gone through in the last EXPIRE period */
+                       spin_lock_irqsave(qp->qp_lock_ptr, flags);
+                       __qla_adjust_buf(qp);
+                       spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
+               } else {
+                       qp->buf_pool.take_snapshot = 1;
+               }
+       }
 }
index f8758cea11d68e84a702a793e89ec9767d41f996..d07a914559d34a57d9c0e99fb4d561286662523a 100644 (file)
@@ -7522,6 +7522,7 @@ qla2x00_timer(struct timer_list *t)
                set_bit(SET_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags);
                start_dpc++;
        }
+       qla_adjust_buf(vha);
 
        /* borrowing w to signify dpc will run */
        w = 0;