aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-07-29 20:17:10 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-23 23:04:42 -0400
commit9b4be528999483d70a1ffc0accd102e477d5a503 (patch)
tree9b868ca20a761b20af3ba79a168b42acb109922f /drivers/scsi/isci
parent39ea2c5b5ffaa344467da53e885cfa4ac0105050 (diff)
[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')
-rw-r--r--drivers/scsi/isci/host.c10
-rw-r--r--drivers/scsi/isci/host.h3
2 files changed, 12 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)
1091 struct isci_request *request; 1091 struct isci_request *request;
1092 struct isci_request *next_request; 1092 struct isci_request *next_request;
1093 struct sas_task *task; 1093 struct sas_task *task;
1094 u16 active;
1094 1095
1095 INIT_LIST_HEAD(&completed_request_list); 1096 INIT_LIST_HEAD(&completed_request_list);
1096 INIT_LIST_HEAD(&errored_request_list); 1097 INIT_LIST_HEAD(&errored_request_list);
@@ -1181,6 +1182,13 @@ static void isci_host_completion_routine(unsigned long data)
1181 } 1182 }
1182 } 1183 }
1183 1184
1185 /* the coalesence timeout doubles at each encoding step, so
1186 * update it based on the ilog2 value of the outstanding requests
1187 */
1188 active = isci_tci_active(ihost);
1189 writel(SMU_ICC_GEN_VAL(NUMBER, active) |
1190 SMU_ICC_GEN_VAL(TIMER, ISCI_COALESCE_BASE + ilog2(active)),
1191 &ihost->smu_registers->interrupt_coalesce_control);
1184} 1192}
1185 1193
1186/** 1194/**
@@ -1471,7 +1479,7 @@ static void sci_controller_ready_state_enter(struct sci_base_state_machine *sm)
1471 struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); 1479 struct isci_host *ihost = container_of(sm, typeof(*ihost), sm);
1472 1480
1473 /* set the default interrupt coalescence number and timeout value. */ 1481 /* set the default interrupt coalescence number and timeout value. */
1474 sci_controller_set_interrupt_coalescence(ihost, 0x10, 250); 1482 sci_controller_set_interrupt_coalescence(ihost, 0, 0);
1475} 1483}
1476 1484
1477static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm) 1485static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm)
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 062101a39f79..9f33831a2f04 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -369,6 +369,9 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
369#define ISCI_TAG_SEQ(tag) (((tag) >> 12) & (SCI_MAX_SEQ-1)) 369#define ISCI_TAG_SEQ(tag) (((tag) >> 12) & (SCI_MAX_SEQ-1))
370#define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1)) 370#define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1))
371 371
372/* interrupt coalescing baseline: 9 == 3 to 5us interrupt delay per command */
373#define ISCI_COALESCE_BASE 9
374
372/* expander attached sata devices require 3 rnc slots */ 375/* expander attached sata devices require 3 rnc slots */
373static inline int sci_remote_device_node_count(struct isci_remote_device *idev) 376static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
374{ 377{