From owner-p4-projects@FreeBSD.ORG Mon Aug 24 19:19:16 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E351A1065691; Mon, 24 Aug 2009 19:19:15 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A7BD4106568B for ; Mon, 24 Aug 2009 19:19:15 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 972CD8FC08 for ; Mon, 24 Aug 2009 19:19:15 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n7OJJF4k010754 for ; Mon, 24 Aug 2009 19:19:15 GMT (envelope-from mav@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n7OJJFH6010752 for perforce@freebsd.org; Mon, 24 Aug 2009 19:19:15 GMT (envelope-from mav@freebsd.org) Date: Mon, 24 Aug 2009 19:19:15 GMT Message-Id: <200908241919.n7OJJFH6010752@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mav@freebsd.org using -f From: Alexander Motin To: Perforce Change Reviews Cc: Subject: PERFORCE change 167744 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Aug 2009 19:19:16 -0000 http://perforce.freebsd.org/chv.cgi?CH=167744 Change 167744 by mav@mav_mavbook on 2009/08/24 19:18:43 Implement PM levels 4 and 5. Alike to 2 and 3, but implemented on driver level. Performance degradation is smaller and not so controller dependent. Affected files ... .. //depot/projects/scottl-camlock/src/share/man/man4/ahci.4#5 edit .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#51 edit .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#18 edit Differences ... ==== //depot/projects/scottl-camlock/src/share/man/man4/ahci.4#5 (text+ko) ==== @@ -25,7 +25,7 @@ .\" .\" $FreeBSD: src/share/man/man4/ahci.4,v 1.2 2009/07/25 18:19:31 mav Exp $ .\" -.Dd June 26, 2009 +.Dd August 24, 2009 .Dt AHCI 4 .Os .Sh NAME @@ -74,7 +74,15 @@ host initiates PARTIAL PM state transition every time port becomes idle; .It 3 host initiates SLUMBER PM state transition every time port becomes idle. +.It 4 +driver initiates PARTIAL PM state transition 1ms after port becomes idle; +.It 5 +driver initiates SLUMBER PM state transition 125ms after port becomes idle. .El +Some controllers, such as ICH8, do not implement modes 2 and 3 with NCQ used. +Because of artificial entering latency, performance degradation in modes +4 and 5 is much smaller then in modes 2 and 3. +.Pp Note that interface Power Management is not compatible with device presence detection. You will have to reset bus manually on device hot-plug. ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#51 (text+ko) ==== @@ -63,6 +63,7 @@ static int ahci_resume(device_t dev); static int ahci_ch_suspend(device_t dev); static int ahci_ch_resume(device_t dev); +static void ahci_ch_pm(void *arg); static void ahci_ch_intr_locked(void *data); static void ahci_ch_intr(void *data); static int ahci_ctlr_reset(device_t dev); @@ -531,8 +532,11 @@ ch->caps = ATA_INL(ctlr->r_mem, AHCI_CAP); ch->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2); ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1, + mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF); resource_int_value(device_get_name(dev), device_get_unit(dev), "pm_level", &ch->pm_level); + if (ch->pm_level > 3) + callout_init_mtx(&ch->pm_timer, &ch->mtx, 0); /* Limit speed for my onboard JMicron external port. * It is not eSATA really. */ if (pci_get_devid(ctlr->dev) == 0x2363197b && @@ -542,7 +546,6 @@ ch->sata_rev = 1; resource_int_value(device_get_name(dev), device_get_unit(dev), "sata_rev", &ch->sata_rev); - mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF); rid = ch->unit; if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE))) @@ -590,6 +593,11 @@ error = ENXIO; goto err3; } + if (ch->pm_level > 3) { + callout_reset(&ch->pm_timer, + (ch->pm_level == 4) ? hz / 1000 : hz / 8, + ahci_ch_pm, dev); + } mtx_unlock(&ch->mtx); return (0); @@ -616,6 +624,8 @@ cam_sim_free(ch->sim, /*free_devq*/TRUE); mtx_unlock(&ch->mtx); + if (ch->pm_level > 3) + callout_drain(&ch->pm_timer); bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); @@ -667,7 +677,7 @@ /* Activate the channel and power/spin up device */ ATA_OUTL(ch->r_mem, AHCI_P_CMD, (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD | - ((ch->pm_level > 1) ? AHCI_P_CMD_ALPE : 0) | + ((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) | ((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 ))); ahci_start_fr(dev); ahci_start(dev); @@ -890,6 +900,23 @@ } static void +ahci_ch_pm(void *arg) +{ + device_t dev = (device_t)arg; + struct ahci_channel *ch = device_get_softc(dev); + uint32_t work; + + if (ch->numrslots != 0) + return; + work = ATA_INL(ch->r_mem, AHCI_P_CMD); + if (ch->pm_level == 4) + work |= AHCI_P_CMD_PARTIAL; + else + work |= AHCI_P_CMD_SLUMBER; + ATA_OUTL(ch->r_mem, AHCI_P_CMD, work); +} + +static void ahci_ch_intr(void *data) { device_t dev = (device_t)data; @@ -1027,6 +1054,9 @@ /* Occupy chosen slot. */ slot = &ch->slot[tag]; slot->ccb = ccb; + /* Stop PM timer. */ + if (ch->numrslots == 0 && ch->pm_level > 3) + callout_stop(&ch->pm_timer); /* Update channel stats. */ ch->numrslots++; if ((ccb->ccb_h.func_code == XPT_ATA_IO) && @@ -1336,6 +1366,11 @@ ahci_begin_transaction(dev, fccb); xpt_release_simq(ch->sim, TRUE); } + /* Start PM timer. */ + if (ch->numrslots == 0 && ch->pm_level > 3) { + callout_schedule(&ch->pm_timer, + (ch->pm_level == 4) ? hz / 1000 : hz / 8); + } } static void ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#18 (text+ko) ==== @@ -359,6 +359,7 @@ int lastslot; /* Last used slot */ int taggedtarget; /* Last tagged target */ union ccb *frozen; /* Frozen command */ + struct callout pm_timer; /* Power management events */ }; /* structure describing a AHCI controller */