From owner-freebsd-hackers@FreeBSD.ORG Sun Nov 2 16:35:20 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 10D7B16A4CE for ; Sun, 2 Nov 2003 16:35:20 -0800 (PST) Received: from webmail.tiscali.de (relay1.tiscali.de [62.26.116.129]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4A44643FB1 for ; Sun, 2 Nov 2003 16:35:14 -0800 (PST) (envelope-from walter@pelissero.de) Received: from daemon.home.loc (62.246.53.170) by webmail.tiscali.de (6.7.019) id 3F9D28A800311079 for hackers@freebsd.org; Mon, 3 Nov 2003 01:35:13 +0100 Received: from hyde.home.loc (hyde.home.loc [10.0.0.2]) by daemon.home.loc (8.12.9/8.12.8) with ESMTP id hA30X13V000387 for ; Mon, 3 Nov 2003 01:33:01 +0100 (CET) (envelope-from wcp@hyde.home.loc) Received: from hyde.home.loc (localhost [127.0.0.1]) by hyde.home.loc (8.12.9/8.12.8) with ESMTP id hA30XKKv064393 for ; Mon, 3 Nov 2003 01:33:20 +0100 (CET) (envelope-from wcp@hyde.home.loc) Received: (from wcp@localhost) by hyde.home.loc (8.12.9/8.12.6/Submit) id hA30XJpj064390; Mon, 3 Nov 2003 01:33:19 +0100 (CET) (envelope-from wcp) From: "Walter C. Pelissero" MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <16293.41551.103901.897025@hyde.home.loc> Date: Mon, 3 Nov 2003 01:33:19 +0100 To: hackers@freebsd.org X-Mailer: VM 7.16 under Emacs 21.3.50.1 X-Attribution: WP Subject: SCSI spin down on suspend (patch) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: walter@pelissero.de List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Nov 2003 00:35:20 -0000 I eventually got around to hack scsi_da.c to implement spin down/up on suspend/resume events of APM or ACPI. Actually the ACPI stuff is untested and the APM once didn't work properly on my system: one of the disks, after resume, was misbehaving (hardware errors). A power toggle fixed the problem, though. I suspect this code could be improved introducing a delay after the spin up of each HD (I've got 6 HD hooked to a 350W power supply, this might explain the hardware error), but not being a kernel hacker myself, I don't know how to proceed. Suggestions are welcome. Please note you need to define CAM_APM_COOP or CAM_ACPI_COOP. --- scsi_da.c.orig Mon Nov 3 00:15:55 2003 +++ scsi_da.c Mon Nov 3 00:18:04 2003 @@ -72,6 +72,15 @@ #include #endif /* !_KERNEL */ +#ifdef CAM_ACPI_COOP +# include +# include +# include +#endif /* CAM_ACPI_COOP */ +#ifdef CAM_APM_COOP +# include +#endif + #ifdef _KERNEL typedef enum { DA_STATE_PROBE, @@ -142,6 +151,40 @@ da_quirks quirks; }; +#ifdef CAM_APM_COOP +static void da_start_stop_all(int start); + +static int +da_apm_suspend (void *junk) +{ + da_start_stop_all (0); + return 0; +} + +static int +da_apm_resume (void *junk) +{ + da_start_stop_all (1); + return 0; +} + +struct apmhook da_suspend_hook = { + 0, /* next */ + da_apm_suspend, /* fun */ + 0, /* arg */ + "da_suspend", /* name */ + 0 /* order */ +}; + +struct apmhook da_resume_hook = { + 0, /* next */ + da_apm_resume, /* fun */ + 0, /* arg */ + "da_resume", /* name */ + 0 /* order */ +}; +#endif /* CAM_APM_COOP */ + static const char quantum[] = "QUANTUM"; static const char microp[] = "MICROP"; @@ -213,6 +256,12 @@ {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE }, + { {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS540S", "*"}, + DA_Q_NO_SYNC_CACHE }, + { {T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CP3500*", "*"}, + DA_Q_NO_SYNC_CACHE }, + { {T_DIRECT, SIP_MEDIA_REMOVABLE, "DataFab*", "*", "*"}, + DA_Q_NO_6_BYTE | DA_Q_NO_SYNC_CACHE }, { /* * Doesn't work correctly with 6 byte reads/writes. @@ -935,6 +984,71 @@ return (0); } +/* + * Step through all DA peripheral drivers and spin them up/down. + */ +static void +da_start_stop_all(int start) +{ + struct cam_periph *periph; + struct da_softc *softc; + + for (periph = TAILQ_FIRST(&dadriver.units); periph != NULL; + periph = TAILQ_NEXT(periph, unit_links)) { + union ccb ccb; + softc = (struct da_softc *)periph->softc; + + xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); + + ccb.ccb_h.ccb_state = DA_CCB_DUMP; + scsi_start_stop(&ccb.csio, + /*retries*/1, + /*cbfcnp*/dadone, + MSG_SIMPLE_Q_TAG, + start, + /*load_eject*/ 0, + /*immediate*/ FALSE, + /*sense_len*/ SSD_FULL_SIZE, + /*timeout*/ 50000); + + xpt_polled_action(&ccb); + + if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (((ccb.ccb_h.status & CAM_STATUS_MASK) == + CAM_SCSI_STATUS_ERROR) + && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){ + int error_code, sense_key, asc, ascq; + + scsi_extract_sense(&ccb.csio.sense_data, + &error_code, &sense_key, + &asc, &ascq); + + if (sense_key != SSD_KEY_ILLEGAL_REQUEST) + scsi_sense_print(&ccb.csio); + } else { + xpt_print_path(periph->path); + printf("Suspend disk failed, status " + "== 0x%x, scsi status == 0x%x\n", + ccb.ccb_h.status, ccb.csio.scsi_status); + } + } + } +} + +#ifdef CAM_ACPI_COOP +static void +da_start_all(void *arg, int state) +{ + da_start_stop_all(1); +} + +static void +da_stop_all(void *arg, int state) +{ + da_start_stop_all(0); +} +#endif /* CAM_ACPI_COOP */ + static void dainit(void) { @@ -987,6 +1101,14 @@ if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown, NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) printf("dainit: shutdown event registration failed!\n"); +#ifdef CAM_ACPI_COOP + EVENTHANDLER_REGISTER(acpi_sleep_event, da_stop_all, NULL, ACPI_EVENT_PRI_DEFAULT); + EVENTHANDLER_REGISTER(acpi_wakeup_event, da_start_all, NULL, ACPI_EVENT_PRI_DEFAULT); +#endif +#ifdef CAM_APM_COOP + apm_hook_establish (APM_HOOK_SUSPEND, &da_suspend_hook); + apm_hook_establish (APM_HOOK_RESUME, &da_resume_hook); +#endif } } -- walter pelissero http://www.pelissero.de