PERFORCE change 167760 for review
Alexander Motin
mav at FreeBSD.org
Mon Aug 24 23:04:24 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167760
Change 167760 by mav at mav_mavbook on 2009/08/24 23:03:57
Implement AHCI Command Completion Coalescing (CCC) feature support.
CCC reduces number of context switches on systems with many parallel
requests, but it can decrease disk performance on some workloads
due to additional command latency.
Affected files ...
.. //depot/projects/scottl-camlock/src/share/man/man4/ahci.4#6 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#52 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#19 edit
Differences ...
==== //depot/projects/scottl-camlock/src/share/man/man4/ahci.4#6 (text+ko) ====
@@ -60,6 +60,13 @@
.It 2
multiple MSI vectors used, if supported;
.El
+.It Va hint.ahci.X.ccc
+controls Command Completion Coalescing (CCC) usage by the specified controller.
+Non-zero value enables CCC and defines maximum time (in ms), request can wait
+for interrupt, if there are some more requests present on controller queue.
+CCC reduces number of context switches on systems with many parallel requests,
+but it can decrease disk performance on some workloads due to additional
+command latency.
.It Va hint.ahcich.X.pm_level
controls SATA interface Power Management for specified channel,
allowing some power to be saved at the cost of additional command
==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#52 (text+ko) ====
@@ -125,6 +125,8 @@
u_int32_t version, caps, caps2;
ctlr->dev = dev;
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "ccc", &ctlr->ccc);
/* if we have a memory BAR(5) we are likely on an AHCI part */
ctlr->r_rid = PCIR_BAR(5);
if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -272,6 +274,21 @@
ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
/* Clear interrupts */
ATA_OUTL(ctlr->r_mem, AHCI_IS, ATA_INL(ctlr->r_mem, AHCI_IS));
+ /* Configure CCC */
+ if (ctlr->ccc) {
+ ATA_OUTL(ctlr->r_mem, AHCI_CCCP, ATA_INL(ctlr->r_mem, AHCI_PI));
+ ATA_OUTL(ctlr->r_mem, AHCI_CCCC,
+ (ctlr->ccc << AHCI_CCCC_TV_SHIFT) |
+ (4 << AHCI_CCCC_CC_SHIFT) |
+ AHCI_CCCC_EN);
+ ctlr->cccv = (ATA_INL(ctlr->r_mem, AHCI_CCCC) &
+ AHCI_CCCC_INT_MASK) >> AHCI_CCCC_INT_SHIFT;
+ if (bootverbose) {
+ device_printf(dev,
+ "CCC with %dms/4cmd enabled on vector %d\n",
+ ctlr->ccc, ctlr->cccv);
+ }
+ }
/* Enable AHCI interrupts */
ATA_OUTL(ctlr->r_mem, AHCI_GHC,
ATA_INL(ctlr->r_mem, AHCI_GHC) | AHCI_GHC_IE);
@@ -332,7 +349,8 @@
for (i = 0; i < ctlr->numirqs; i++) {
ctlr->irqs[i].ctlr = ctlr;
ctlr->irqs[i].r_irq_rid = i + (msi ? 1 : 0);
- if (ctlr->numirqs == 1 || i >= ctlr->channels)
+ if (ctlr->numirqs == 1 || i >= ctlr->channels ||
+ (ctlr->ccc && i == ctlr->cccv))
ctlr->irqs[i].mode = AHCI_IRQ_MODE_ALL;
else if (i == ctlr->numirqs - 1)
ctlr->irqs[i].mode = AHCI_IRQ_MODE_AFTER;
@@ -367,9 +385,11 @@
int unit;
is = ATA_INL(ctlr->r_mem, AHCI_IS);
- if (irq->mode == AHCI_IRQ_MODE_ALL)
+ if (irq->mode == AHCI_IRQ_MODE_ALL) {
+ if (ctlr->ccc)
+ is = ctlr->ichannels;
unit = 0;
- else /* AHCI_IRQ_MODE_AFTER */
+ } else /* AHCI_IRQ_MODE_AFTER */
unit = irq->r_irq_rid - 1;
for (; unit < ctlr->channels; unit++) {
if ((is & (1 << unit)) != 0 &&
@@ -1585,6 +1605,7 @@
ahci_reset(device_t dev)
{
struct ahci_channel *ch = device_get_softc(dev);
+ struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
int i;
if (bootverbose)
@@ -1631,8 +1652,8 @@
(AHCI_P_IX_CPD | AHCI_P_IX_TFE | AHCI_P_IX_HBF |
AHCI_P_IX_HBD | AHCI_P_IX_IF | AHCI_P_IX_OF |
((ch->pm_level == 0) ? AHCI_P_IX_PRC | AHCI_P_IX_PC : 0) |
- AHCI_P_IX_DP | AHCI_P_IX_UF | AHCI_P_IX_SDB |
- AHCI_P_IX_DS | AHCI_P_IX_PS | AHCI_P_IX_DHR));
+ AHCI_P_IX_DP | AHCI_P_IX_UF | (ctlr->ccc ? 0 : AHCI_P_IX_SDB) |
+ AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR)));
if (bootverbose)
device_printf(dev, "AHCI reset done: device found\n");
/* Tell the XPT about the event */
==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#19 (text+ko) ====
@@ -176,6 +176,16 @@
#define AHCI_PI 0x0c
#define AHCI_VS 0x10
+#define AHCI_CCCC 0x14
+#define AHCI_CCCC_TV_MASK 0xffff0000
+#define AHCI_CCCC_TV_SHIFT 16
+#define AHCI_CCCC_CC_MASK 0x0000ff00
+#define AHCI_CCCC_CC_SHIFT 8
+#define AHCI_CCCC_INT_MASK 0x000000f8
+#define AHCI_CCCC_INT_SHIFT 3
+#define AHCI_CCCC_EN 0x00000001
+#define AHCI_CCCP 0x18
+
#define AHCI_CAP2 0x24
#define AHCI_CAP2_BOH 0x00000001
#define AHCI_CAP2_NVMP 0x00000002
@@ -381,6 +391,8 @@
int numirqs;
int channels;
int ichannels;
+ int ccc; /* CCC timeout */
+ int cccv; /* CCC vector */
struct {
void (*function)(void *);
void *argument;
More information about the p4-projects
mailing list