From owner-freebsd-acpi@FreeBSD.ORG Mon Apr 7 15:52:59 2008 Return-Path: Delivered-To: freebsd-acpi@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 87A821065727; Mon, 7 Apr 2008 15:52:59 +0000 (UTC) (envelope-from takawata@init-main.com) Received: from sana.init-main.com (unknown [IPv6:2001:240:28::1]) by mx1.freebsd.org (Postfix) with ESMTP id 327B68FC16; Mon, 7 Apr 2008 15:52:59 +0000 (UTC) (envelope-from takawata@init-main.com) Received: from ns.init-main.com (localhost [127.0.0.1]) by sana.init-main.com (8.14.1/8.13.8) with ESMTP id m37FdLcT026089; Tue, 8 Apr 2008 00:39:21 +0900 (JST) (envelope-from takawata@ns.init-main.com) Message-Id: <200804071539.m37FdLcT026089@sana.init-main.com> To: sos@freebsd.org, freebsd-acpi@freebsd.org Date: Tue, 08 Apr 2008 00:39:21 +0900 From: Takanori Watanabe Cc: Subject: some problems in suspend/resume on ThinkPad X61 X-BeenThere: freebsd-acpi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: ACPI and power management development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Apr 2008 15:52:59 -0000 I bought a new laptop;ThinkPad X61 and I'm trying to hack suspend/resume. As the first step, I'm trying to make sure to suspend/resume work in uniprocessor kernel. Finally I did succeeded to suspend and resume with 1) fwohci disabled 2) if_em down 3) hw.acpi.reset_video=1 4) modify ata driver with following crude patch. (Not generic solution.) So I want ata_pci_controller->chipinit and ata_pci_controller->allocate should split into two parts:Hardware initialization and data structure initialization. --- ata-chipset.c.~1.212.~ 2008-03-07 09:29:19.000000000 +0000 +++ ata-chipset.c 2008-04-08 00:23:34.000000000 +0000 @@ -540,7 +540,37 @@ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1); return 0; } +void ata_ahci_tell_dma(device_t dev); +void ata_ahci_tell_dma(device_t dev) +{ + struct ata_pci_controller *ctlr; + struct ata_channel *ch = device_get_softc(dev); + u_int64_t work; + int offset = ch->unit << 7; + + ctlr = device_get_softc(device_get_parent(dev)); + /* setup work areas */ + work = ch->dma->work_bus + ATA_AHCI_CL_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); + + work = ch->dma->work_bus + ATA_AHCI_FB_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); + /* enable wanted port interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, + (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | + ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | + ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP | + ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS | + ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); + + /* start operations on this channel */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE | + ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST)); +} static int ata_ahci_allocate(device_t dev) { --- ata-pci.c.~1.123.~ 2007-11-18 14:44:52.000000000 +0000 +++ ata-pci.c 2008-04-07 23:25:04.000000000 +0000 @@ -48,6 +48,7 @@ #include #include #include +extern void ata_ahci_tell_dma(device_t dev); /* local vars */ static MALLOC_DEFINE(M_ATAPCI, "ata_pci", "ATA driver PCI"); @@ -186,6 +187,18 @@ return ENXIO; } +static int ata_pci_resume(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int chans = ctlr->channels; + ctlr->chipinit(dev); + + if(chans != ctlr->channels){ + device_printf(dev, "WARNING: channel number changed\n"); + } + + return bus_generic_resume(dev); +} int ata_pci_attach(device_t dev) { @@ -546,7 +559,7 @@ DEVMETHOD(device_detach, ata_pci_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_resume, ata_pci_resume), /* bus methods */ DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), @@ -678,6 +691,15 @@ ctlr->setmode(dev, mode); } +static int ata_pcichannel_resume(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + if(ch->dma&&ctlr->r_res2) + ata_ahci_tell_dma(dev); + + return ata_resume(dev); +} static device_method_t ata_pcichannel_methods[] = { /* device interface */ DEVMETHOD(device_probe, ata_pcichannel_probe), @@ -685,7 +707,7 @@ DEVMETHOD(device_detach, ata_pcichannel_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, ata_suspend), - DEVMETHOD(device_resume, ata_resume), + DEVMETHOD(device_resume, ata_pcichannel_resume), /* ATA methods */ DEVMETHOD(ata_setmode, ata_pcichannel_setmode),