PERFORCE change 177249 for review
Alexander Motin
mav at FreeBSD.org
Fri Apr 23 05:12:21 UTC 2010
http://p4web.freebsd.org/@@177249?ac=10
Change 177249 by mav at mav_mavtest on 2010/04/23 05:12:15
Implement Command Completion Coalescing support.
Affected files ...
.. //depot/projects/scottl-camlock/src/sys/conf/files#73 edit
.. //depot/projects/scottl-camlock/src/sys/conf/kmod.mk#22 edit
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.c#10 edit
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.h#7 edit
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs_if.m#1 add
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs_pci.c#2 edit
.. //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs_soc.c#2 edit
Differences ...
==== //depot/projects/scottl-camlock/src/sys/conf/files#73 (text+ko) ====
@@ -1292,6 +1292,7 @@
dev/mpt/mpt_user.c optional mpt
dev/msk/if_msk.c optional msk inet
dev/mvs/mvs.c optional mvs
+dev/mvs/mvs_if.m standard
dev/mvs/mvs_pci.c optional mvs pci
dev/mwl/if_mwl.c optional mwl
dev/mwl/if_mwl_pci.c optional mwl pci
==== //depot/projects/scottl-camlock/src/sys/conf/kmod.mk#22 (text+ko) ====
@@ -337,7 +337,7 @@
dev/agp/agp_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \
dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \
dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
- dev/mii/miibus_if.m dev/ofw/ofw_bus_if.m \
+ dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \
dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \
dev/pci/pcib_if.m dev/ppbus/ppbus_if.m dev/smbus/smbus_if.m \
dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \
==== //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.c#10 (text+ko) ====
@@ -440,6 +440,7 @@
ch->curr_mode = mode;
ch->fbs_enabled = 0;
ch->fake_busy = 0;
+ MVS_EDMA(device_get_parent(dev), dev, mode);
device_printf(dev, "EDMA mode: %d\n", mode);
if (mode == MVS_EDMA_OFF)
return;
@@ -631,7 +632,7 @@
device_printf(dev, "FISIC %08x\n", fisic);
}
if (selfdis)
- ch->curr_mode = MVS_EDMA_OFF;
+ ch->curr_mode = MVS_EDMA_UNKNOWN;
ATA_OUTL(ch->r_mem, EDMA_IEC, ~iec);
/* Interface errors or Device error. */
if (iec & (0xfc1e9000 | EDMA_IE_EDEVERR)) {
@@ -1117,7 +1118,6 @@
void *buf;
bus_size_t size;
- slot->dma.nsegs = 0;
slot->state = MVS_SLOT_LOADING;
if (ccb->ccb_h.func_code == XPT_ATA_IO) {
buf = ccb->ataio.data_ptr;
@@ -1247,7 +1247,11 @@
eprd[i].prdbah = htole32((segs[i].ds_addr >> 16) >> 16);
}
eprd[i - 1].bytecount |= htole32(MVS_EPRD_EOF);
- slot->dma.nsegs = nsegs;
+ if (nsegs == 1) {
+ slot->dma.addr = segs[0].ds_addr;
+ slot->dma.len = segs[0].ds_len;
+ } else
+ slot->dma.addr = 0;
bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
((slot->ccb->ccb_h.flags & CAM_DIR_IN) ?
BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
@@ -1275,14 +1279,19 @@
if (ch->quirks & MVS_Q_GENIIE) {
crqb2e = (struct mvs_crqb_gen2e *)
(ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx));
- crqb2e->cprdbl = htole32(eprd);
- crqb2e->cprdbh = htole32((eprd >> 16) >> 16);
crqb2e->ctrlflg = htole32(
((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB2E_READ : 0) |
(slot->tag << MVS_CRQB2E_DTAG_SHIFT) |
(port << MVS_CRQB2E_PMP_SHIFT) |
(slot->slot << MVS_CRQB2E_HTAG_SHIFT));
- crqb2e->drbc = 0;
+ /* If there is only one segment - no need to use S/G table. */
+ if (slot->dma.addr != 0) {
+ eprd = slot->dma.addr;
+ crqb2e->ctrlflg |= htole32(MVS_CRQB2E_CPRD);
+ crqb2e->drbc = slot->dma.len;
+ }
+ crqb2e->cprdbl = htole32(eprd);
+ crqb2e->cprdbh = htole32((eprd >> 16) >> 16);
crqb2e->cmd[0] = 0;
crqb2e->cmd[1] = 0;
crqb2e->cmd[2] = ccb->ataio.cmd.command;
==== //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs.h#7 (text+ko) ====
@@ -26,6 +26,8 @@
* $FreeBSD: src/sys/dev/mvs/mvs.h,v 1.11 2010/02/14 12:30:35 mav Exp $
*/
+#include "mvs_if.h"
+
/* Chip registers */
#define CHIP_PCIEIC 0x1900 /* PCIe Interrupt Cause */
#define CHIP_PCIEIM 0x1910 /* PCIe Interrupt Mask */
@@ -40,7 +42,9 @@
#define IC_HC0 0x000001ff /* bits 0-8 = HC0 */
#define IC_HC_SHIFT 9 /* HC1 shift */
#define IC_HC1 (IC_HC0 << IC_HC_SHIFT) /* 9-17 = HC1 */
+#define IC_ERR_HC0 0x00000055 /* HC0 ERR_IRQ */
#define IC_DONE_HC0 0x000000aa /* HC0 DONE_IRQ */
+#define IC_ERR_HC1 (IC_ERR_HC0 << IC_HC_SHIFT) /* HC1 ERR_IRQ */
#define IC_DONE_HC1 (IC_DONE_HC0 << IC_HC_SHIFT) /* HC1 DONE_IRQ */
#define IC_HC0_COAL_DONE (1 << 8) /* HC0 IRQ coalescing */
#define IC_HC1_COAL_DONE (1 << 17) /* HC1 IRQ coalescing */
@@ -57,6 +61,13 @@
#define CHIP_SOC_LED 0x2C /* SoC LED Configuration */
+#define CHIP_ICC 0x18008
+#define CHIP_ICC_ALL_PORTS (1 << 4) /* all ports irq event */
+#define CHIP_ICT 0x180cc
+#define CHIP_ITT 0x180d0
+#define CHIP_TRAN_COAL_CAUSE_LO 0x18088
+#define CHIP_TRAN_COAL_CAUSE_HI 0x1808c
+
/* Host Controller registers */
#define HC_SIZE 0x10000
#define HC_OFFSET 0x20000
@@ -448,7 +459,8 @@
struct ata_dmaslot {
bus_dmamap_t data_map; /* Data DMA map */
- int nsegs; /* Number of segs loaded */
+ bus_addr_t addr; /* Data address */
+ uint16_t len; /* Data size */
};
/* structure holding DMA related information */
@@ -561,10 +573,13 @@
void *handle;
int r_irq_rid;
} irq;
+ struct mtx mtx; /* MIM access lock */
int quirks;
int channels;
int ccc; /* CCC timeout */
int cccc; /* CCC commands */
+ int gmim;
+ int pmim;
struct {
void (*function)(void *);
void *argument;
==== //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs_pci.c#2 (text+ko) ====
@@ -120,8 +120,19 @@
ctlr->ccc = 0;
ctlr->cccc = 0;
}
- if (ctlr->ccc > 100)
- ctlr->ccc = 100;
+ if (ctlr->ccc > 100000)
+ ctlr->ccc = 100000;
+ device_printf(dev,
+ "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
+ ((ctlr->quirks & MVS_Q_GENI) ? "I" :
+ ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
+ ctlr->channels,
+ ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
+ ((ctlr->quirks & MVS_Q_GENI) ?
+ "not supported" : "supported"),
+ ((ctlr->quirks & MVS_Q_GENIIE) ?
+ " with FBS" : ""));
+ mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF);
/* We should have a memory BAR(0). */
ctlr->r_rid = PCIR_BAR(0);
if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -147,16 +158,6 @@
rman_fini(&ctlr->sc_iomem);
return ENXIO;
}
- device_printf(dev,
- "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
- ((ctlr->quirks & MVS_Q_GENI) ? "I" :
- ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
- ctlr->channels,
- ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
- ((ctlr->quirks & MVS_Q_GENI) ?
- "not supported" : "supported"),
- ((ctlr->quirks & MVS_Q_GENIIE) ?
- " with FBS" : ""));
/* Attach all channels on this controller */
for (unit = 0; unit < ctlr->channels; unit++) {
child = device_add_child(dev, "mvsch", -1);
@@ -194,6 +195,7 @@
rman_fini(&ctlr->sc_iomem);
if (ctlr->r_mem)
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ mtx_destroy(&ctlr->mtx);
return (0);
}
@@ -201,7 +203,7 @@
mvs_ctlr_setup(device_t dev)
{
struct mvs_controller *ctlr = device_get_softc(dev);
- int i;
+ int i, ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0;
/* Mask chip interrupts */
ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000);
@@ -209,28 +211,58 @@
ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000);
/* Clear PCI interrupts */
ATA_OUTL(ctlr->r_mem, CHIP_PCIIC, 0x00000000);
- /* Clear HC interrupts */
- for (i = 0; i < ctlr->channels / 4; i++)
+ if (ccc && bootverbose) {
+ device_printf(dev,
+ "CCC with %dus/%dcmd enabled\n",
+ ctlr->ccc, ctlr->cccc);
+ }
+ ccc *= 150;
+ /* Configure chip-global CCC */
+ if (ctlr->channels > 4 && (ctlr->quirks & MVS_Q_GENI) == 0) {
+ ATA_OUTL(ctlr->r_mem, CHIP_ICT, cccc);
+ ATA_OUTL(ctlr->r_mem, CHIP_ITT, ccc);
+ ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS);
+ if (ccc)
+ ccim |= IC_ALL_PORTS_COAL_DONE;
+ ccc = 0;
+ cccc = 0;
+ }
+ for (i = 0; i < ctlr->channels / 4; i++) {
+ /* Configure per-HC CCC */
+ ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ICT, cccc);
+ ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ITT, ccc);
+ if (ccc)
+ ccim |= (IC_HC0_COAL_DONE << (i * IC_HC_SHIFT));
+ /* Clear HC interrupts */
ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_IC, 0x00000000);
- /* Configure CCC */
-#if 0
- if (ctlr->ccc) {
- ATA_OUTL(ctlr->r_mem, HC_ICT, ctlr->cccc & HC_ICT_SAICOALT_MASK);
- ATA_OUTL(ctlr->r_mem, HC_ITT, (ctlr->ccc * 150000) & HC_ITT_SAITMTH_MASK);
- if (bootverbose) {
- device_printf(dev,
- "CCC with %dms/%dcmd enabled\n",
- ctlr->ccc, ctlr->cccc);
- }
}
-#endif
/* Enable chip interrupts */
- ATA_OUTL(ctlr->r_mem, CHIP_MIM, IC_HC0 | IC_HC1 /*| IC_ALL_PORTS_COAL_DONE*/);
+ ctlr->gmim = (ccim ? ccim : (IC_DONE_HC0 | IC_DONE_HC1)) |
+ IC_ERR_HC0 | IC_ERR_HC1;
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->gmim | ctlr->pmim);
/* Enable PCI interrupts */
ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x007fffff);
return (0);
}
+static void
+mvs_edma(device_t dev, device_t child, int mode)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
+ int bit = IC_DONE_IRQ << (unit * 2 + unit / 4) ;
+
+ if (ctlr->ccc == 0)
+ return;
+ mtx_lock(&ctlr->mtx);
+ if (mode == MVS_EDMA_OFF)
+ ctlr->pmim |= bit;
+ else
+ ctlr->pmim &= ~bit;
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->gmim | ctlr->pmim);
+ mtx_unlock(&ctlr->mtx);
+}
+
static int
mvs_suspend(device_t dev)
{
@@ -301,10 +333,10 @@
ic = ATA_INL(ctlr->r_mem, CHIP_MIC);
//device_printf(ctlr->dev, "irq MIC:%08x\n", ic);
if (ic & IC_ALL_PORTS_COAL_DONE)
- ATA_OUTL(ctlr->r_mem, CHIP_MIC, ~IC_ALL_PORTS_COAL_DONE);
+ ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS);
for (p = 0; p < ctlr->channels; p++) {
if ((p & 3) == 0) {
- if (p == 4)
+ if (p != 0)
ic >>= 1;
if ((ic & IC_HC0) == 0) {
p += 3;
@@ -438,6 +470,7 @@
DEVMETHOD(bus_release_resource, mvs_release_resource),
DEVMETHOD(bus_setup_intr, mvs_setup_intr),
DEVMETHOD(bus_teardown_intr,mvs_teardown_intr),
+ DEVMETHOD(mvs_edma, mvs_edma),
{ 0, 0 }
};
static driver_t mvs_driver = {
==== //depot/projects/scottl-camlock/src/sys/dev/mvs/mvs_soc.c#2 (text+ko) ====
@@ -112,8 +112,19 @@
ctlr->ccc = 0;
ctlr->cccc = 0;
}
- if (ctlr->ccc > 100)
- ctlr->ccc = 100;
+ if (ctlr->ccc > 100000)
+ ctlr->ccc = 100000;
+ device_printf(dev,
+ "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
+ ((ctlr->quirks & MVS_Q_GENI) ? "I" :
+ ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
+ ctlr->channels,
+ ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
+ ((ctlr->quirks & MVS_Q_GENI) ?
+ "not supported" : "supported"),
+ ((ctlr->quirks & MVS_Q_GENIIE) ?
+ " with FBS" : ""));
+ mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF);
/* We should have a memory BAR(0). */
ctlr->r_rid = 0;
if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -139,16 +150,6 @@
rman_fini(&ctlr->sc_iomem);
return ENXIO;
}
- device_printf(dev,
- "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
- ((ctlr->quirks & MVS_Q_GENI) ? "I" :
- ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
- ctlr->channels,
- ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
- ((ctlr->quirks & MVS_Q_GENI) ?
- "not supported" : "supported"),
- ((ctlr->quirks & MVS_Q_GENIIE) ?
- " with FBS" : ""));
/* Attach all channels on this controller */
for (unit = 0; unit < ctlr->channels; unit++) {
child = device_add_child(dev, "mvsch", -1);
@@ -185,6 +186,7 @@
rman_fini(&ctlr->sc_iomem);
if (ctlr->r_mem)
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ mtx_destroy(&ctlr->mtx);
return (0);
}
@@ -192,6 +194,7 @@
mvs_ctlr_setup(device_t dev)
{
struct mvs_controller *ctlr = device_get_softc(dev);
+ int ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0;
/* Mask chip interrupts */
ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, 0x00000000);
@@ -199,23 +202,41 @@
ATA_OUTL(ctlr->r_mem, HC_IC, 0x00000000);
/* Clear chip interrupts */
ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIC, 0);
- /* Configure CCC */
-#if 0
- if (ctlr->ccc) {
- ATA_OUTL(ctlr->r_mem, HC_ICT, ctlr->cccc & HC_ICT_SAICOALT_MASK);
- ATA_OUTL(ctlr->r_mem, HC_ITT, (ctlr->ccc * 150000) & HC_ITT_SAITMTH_MASK);
- if (bootverbose) {
- device_printf(dev,
- "CCC with %dms/%dcmd enabled\n",
- ctlr->ccc, ctlr->cccc);
- }
+ /* Configure per-HC CCC */
+ if (ccc && bootverbose) {
+ device_printf(dev,
+ "CCC with %dus/%dcmd enabled\n",
+ ctlr->ccc, ctlr->cccc);
}
-#endif
+ ccc *= 150;
+ ATA_OUTL(ctlr->r_mem, HC_ICT, cccc);
+ ATA_OUTL(ctlr->r_mem, HC_ITT, ccc);
+ if (ccc)
+ ccim |= IC_HC0_COAL_DONE;
/* Enable chip interrupts */
- ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, IC_HC0 | IC_HC1 /*| IC_ALL_PORTS_COAL_DONE*/);
+ ctlr->gmim = (ccc ? IC_HC0_COAL_DONE : IC_DONE_HC0) | IC_ERR_HC0;
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim);
return (0);
}
+static void
+mvs_edma(device_t dev, device_t child, int mode)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
+ int bit = IC_DONE_IRQ << (unit * 2);
+
+ if (ctlr->ccc == 0)
+ return;
+ mtx_lock(&ctlr->mtx);
+ if (mode == MVS_EDMA_OFF)
+ ctlr->pmim |= bit;
+ else
+ ctlr->pmim &= ~bit;
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim);
+ mtx_unlock(&ctlr->mtx);
+}
+
static int
mvs_suspend(device_t dev)
{
@@ -272,30 +293,21 @@
ic = ATA_INL(ctlr->r_mem, CHIP_SOC_MIC);
//device_printf(ctlr->dev, "irq MIC:%08x\n", ic);
- if (ic & IC_ALL_PORTS_COAL_DONE)
- ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIC, ~IC_ALL_PORTS_COAL_DONE);
+ if ((ic & IC_HC0) == 0)
+ return;
+ aic = 0;
+ if (ic & (IC_DONE_IRQ << 0))
+ aic |= HC_IC_DONE(0) | HC_IC_DEV(0);
+ if (ic & (IC_DONE_IRQ << 2))
+ aic |= HC_IC_DONE(1) | HC_IC_DEV(1);
+ if (ic & (IC_DONE_IRQ << 4))
+ aic |= HC_IC_DONE(2) | HC_IC_DEV(2);
+ if (ic & (IC_DONE_IRQ << 6))
+ aic |= HC_IC_DONE(3) | HC_IC_DEV(3);
+ if (ic & IC_HC0_COAL_DONE)
+ aic |= HC_IC_COAL;
+ ATA_OUTL(ctlr->r_mem, HC_IC, ~aic);
for (p = 0; p < ctlr->channels; p++) {
- if ((p & 3) == 0) {
- if (p == 4)
- ic >>= 1;
- if ((ic & IC_HC0) == 0) {
- p += 3;
- ic >>= 8;
- continue;
- }
- aic = 0;
- if (ic & (IC_DONE_IRQ << 0))
- aic |= HC_IC_DONE(0) | HC_IC_DEV(0);
- if (ic & (IC_DONE_IRQ << 2))
- aic |= HC_IC_DONE(1) | HC_IC_DEV(1);
- if (ic & (IC_DONE_IRQ << 4))
- aic |= HC_IC_DONE(2) | HC_IC_DEV(2);
- if (ic & (IC_DONE_IRQ << 6))
- aic |= HC_IC_DONE(3) | HC_IC_DEV(3);
- if (ic & IC_HC0_COAL_DONE)
- aic |= HC_IC_COAL;
- ATA_OUTL(ctlr->r_mem, HC_IC, ~aic);
- }
arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ);
if ((arg.cause != 0) &&
(function = ctlr->interrupt[p].function)) {
@@ -410,6 +422,7 @@
DEVMETHOD(bus_release_resource, mvs_release_resource),
DEVMETHOD(bus_setup_intr, mvs_setup_intr),
DEVMETHOD(bus_teardown_intr,mvs_teardown_intr),
+ DEVMETHOD(mvs_edma, mvs_edma),
{ 0, 0 }
};
static driver_t mvs_driver = {
More information about the p4-projects
mailing list