diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-07-29 17:17:10 -0700 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-08-23 20:04:42 -0700 |
commit | 9b4be528999483d70a1ffc0accd102e477d5a503 (patch) | |
tree | 9b868ca20a761b20af3ba79a168b42acb109922f /drivers/scsi/isci/host.c | |
parent | 39ea2c5b5ffaa344467da53e885cfa4ac0105050 (diff) | |
download | lwn-9b4be528999483d70a1ffc0accd102e477d5a503.tar.gz lwn-9b4be528999483d70a1ffc0accd102e477d5a503.zip |
[SCSI] isci: dynamic interrupt coalescing
Hardware allows both an outstanding number commands and a timeout value
(whichever occurs first) as a gate to the next interrupt generation. This
scheme at completion time looks at the remaining number of outstanding tasks
and sets the timeout to maximize small transaction operation. If transactions
are large (take more than a few 10s of microseconds to complete) then
performance is not interrupt processing bound, so the small timeouts this
scheme generates are overridden by the time it takes for a completion to
arrive.
Tested-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/isci/host.c')
-rw-r--r-- | drivers/scsi/isci/host.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 26072f1e9852..2328f98c7f1e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1091,6 +1091,7 @@ static void isci_host_completion_routine(unsigned long data) struct isci_request *request; struct isci_request *next_request; struct sas_task *task; + u16 active; INIT_LIST_HEAD(&completed_request_list); INIT_LIST_HEAD(&errored_request_list); @@ -1181,6 +1182,13 @@ static void isci_host_completion_routine(unsigned long data) } } + /* the coalesence timeout doubles at each encoding step, so + * update it based on the ilog2 value of the outstanding requests + */ + active = isci_tci_active(ihost); + writel(SMU_ICC_GEN_VAL(NUMBER, active) | + SMU_ICC_GEN_VAL(TIMER, ISCI_COALESCE_BASE + ilog2(active)), + &ihost->smu_registers->interrupt_coalesce_control); } /** @@ -1471,7 +1479,7 @@ static void sci_controller_ready_state_enter(struct sci_base_state_machine *sm) struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* set the default interrupt coalescence number and timeout value. */ - sci_controller_set_interrupt_coalescence(ihost, 0x10, 250); + sci_controller_set_interrupt_coalescence(ihost, 0, 0); } static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm) |