Commit 94506fd1 authored by Martin Peschke's avatar Martin Peschke Committed by James Bottomley

[SCSI] zfcp: add measurement data for average qdio queue utilisation

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: default avatarMartin Peschke <mpeschke@linux.vnet.ibm.com>
Signed-off-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 86f8a1b4
...@@ -501,6 +501,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -501,6 +501,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
spin_lock_init(&adapter->scsi_dbf_lock); spin_lock_init(&adapter->scsi_dbf_lock);
spin_lock_init(&adapter->rec_dbf_lock); spin_lock_init(&adapter->rec_dbf_lock);
spin_lock_init(&adapter->req_q_lock); spin_lock_init(&adapter->req_q_lock);
spin_lock_init(&adapter->qdio_stat_lock);
rwlock_init(&adapter->erp_lock); rwlock_init(&adapter->erp_lock);
rwlock_init(&adapter->abort_lock); rwlock_init(&adapter->abort_lock);
......
...@@ -445,6 +445,9 @@ struct zfcp_adapter { ...@@ -445,6 +445,9 @@ struct zfcp_adapter {
spinlock_t req_q_lock; /* for operations on queue */ spinlock_t req_q_lock; /* for operations on queue */
int req_q_pci_batch; /* SBALs since PCI indication int req_q_pci_batch; /* SBALs since PCI indication
was last set */ 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 */ u32 fsf_req_seq_no; /* FSF cmnd seq number */
wait_queue_head_t request_wq; /* can be used to wait for wait_queue_head_t request_wq; /* can be used to wait for
more avaliable SBALs */ more avaliable SBALs */
......
...@@ -77,6 +77,23 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) ...@@ -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, static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
int queue_no, int first, int count, int queue_no, int first, int count,
unsigned long parm) unsigned long parm)
...@@ -93,6 +110,7 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, ...@@ -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 */ /* cleanup all SBALs being program-owned now */
zfcp_qdio_zero_sbals(queue->sbal, first, count); zfcp_qdio_zero_sbals(queue->sbal, first, count);
zfcp_qdio_account(adapter);
atomic_add(count, &queue->count); atomic_add(count, &queue->count);
wake_up(&adapter->request_wq); wake_up(&adapter->request_wq);
} }
...@@ -359,6 +377,8 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) ...@@ -359,6 +377,8 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
sbale->flags |= SBAL_FLAGS0_PCI; sbale->flags |= SBAL_FLAGS0_PCI;
} }
zfcp_qdio_account(adapter);
retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first, retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first,
count); count);
if (unlikely(retval)) { if (unlikely(retval)) {
......
...@@ -487,7 +487,8 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev, ...@@ -487,7 +487,8 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
struct zfcp_adapter *adapter = struct zfcp_adapter *adapter =
(struct zfcp_adapter *) scsi_host->hostdata[0]; (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); static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment