[SCSI] zfcp: add measurement data for average qdio queue utilisation
authorMartin Peschke <mpeschke@linux.vnet.ibm.com>
Mon, 2 Mar 2009 12:08:56 +0000 (13:08 +0100)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Thu, 12 Mar 2009 17:58:18 +0000 (12:58 -0500)
Provide measurement data for the utilisation of the QDIO outbound queue.
The additional value allows to calculate an average queue utilisation
by looking at the deltas per time unit. Needed for capacity planning.
It is up to user space to handle wrap-arounds of the 64 bit value.

The new counter neatly complements the existing counter for queue full
conditions. That is why, both statistics counter have been integrated.

Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_sysfs.c

index 497986f6d643897783078deae9cf16485a561624..969a3f0930377364cb6e1eb5015624bc97eb5e88 100644 (file)
@@ -501,6 +501,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        spin_lock_init(&adapter->scsi_dbf_lock);
        spin_lock_init(&adapter->rec_dbf_lock);
        spin_lock_init(&adapter->req_q_lock);
+       spin_lock_init(&adapter->qdio_stat_lock);
 
        rwlock_init(&adapter->erp_lock);
        rwlock_init(&adapter->abort_lock);
index 56302a1a4b682795b38936e81c496849aace21e5..a0cd4b0801752384977f512ece642ff071812c4f 100644 (file)
@@ -445,6 +445,9 @@ struct zfcp_adapter {
        spinlock_t              req_q_lock;        /* for operations on queue */
        int                     req_q_pci_batch;   /* SBALs since PCI indication
                                                      was last set */
+       ktime_t                 req_q_time; /* time of last fill level change */
+       u64                     req_q_util; /* for accounting */
+       spinlock_t              qdio_stat_lock;
        u32                     fsf_req_seq_no;    /* FSF cmnd seq number */
        wait_queue_head_t       request_wq;        /* can be used to wait for
                                                      more avaliable SBALs */
index 33e0a206a0a44019ffc33a44f7a166960f873741..3d0687090274e5d18d31aeedbb751c25aff9d71a 100644 (file)
@@ -77,6 +77,23 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
        }
 }
 
+/* this needs to be called prior to updating the queue fill level */
+static void zfcp_qdio_account(struct zfcp_adapter *adapter)
+{
+       ktime_t now;
+       s64 span;
+       int free, used;
+
+       spin_lock(&adapter->qdio_stat_lock);
+       now = ktime_get();
+       span = ktime_us_delta(now, adapter->req_q_time);
+       free = max(0, atomic_read(&adapter->req_q.count));
+       used = QDIO_MAX_BUFFERS_PER_Q - free;
+       adapter->req_q_util += used * span;
+       adapter->req_q_time = now;
+       spin_unlock(&adapter->qdio_stat_lock);
+}
+
 static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
                              int queue_no, int first, int count,
                              unsigned long parm)
@@ -93,6 +110,7 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
        /* cleanup all SBALs being program-owned now */
        zfcp_qdio_zero_sbals(queue->sbal, first, count);
 
+       zfcp_qdio_account(adapter);
        atomic_add(count, &queue->count);
        wake_up(&adapter->request_wq);
 }
@@ -359,6 +377,8 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
                sbale->flags |= SBAL_FLAGS0_PCI;
        }
 
+       zfcp_qdio_account(adapter);
+
        retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first,
                         count);
        if (unlikely(retval)) {
index 899af2b45b1e3e862a047e18c8c3740e5c60c288..9e9931af1b5d9c54197b82148564cd927bcce696 100644 (file)
@@ -487,7 +487,8 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
        struct zfcp_adapter *adapter =
                (struct zfcp_adapter *) scsi_host->hostdata[0];
 
-       return sprintf(buf, "%d\n", atomic_read(&adapter->qdio_outb_full));
+       return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full),
+                      (unsigned long long)adapter->req_q_util);
 }
 static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);