From 654326fabc767267ba9c829da615e8b55d818f34 Mon Sep 17 00:00:00 2001 From: jdolecek Date: Wed, 24 Oct 2018 19:38:00 +0000 Subject: [PATCH] detach the controller itself on shutdown; adjust to not detach already detached atabus/channel --- sys/dev/ata/TODO.ncq | 3 --- sys/dev/ata/ata.c | 6 ++++-- sys/dev/ata/atavar.h | 11 ++++++----- sys/dev/ic/ahcisata_core.c | 35 ++++++++++++++++++++++++++++------- sys/dev/ic/ahcisatavar.h | 3 ++- sys/dev/ic/siisata.c | 36 ++++++++++++++++++++++++++---------- sys/dev/ic/siisatavar.h | 3 ++- sys/dev/pci/ahcisata_pci.c | 19 +++++++++++++++---- sys/dev/pci/siisata_pci.c | 19 +++++++++++++++---- 9 files changed, 98 insertions(+), 37 deletions(-) diff --git a/sys/dev/ata/TODO.ncq b/sys/dev/ata/TODO.ncq index 10069eaacec5..0ff54aa282dd 100644 --- a/sys/dev/ata/TODO.ncq +++ b/sys/dev/ata/TODO.ncq @@ -14,6 +14,3 @@ set - old bug - kern/16789 add support for the NCQ TRIM if supported by device? - -ahcisata(4)/siisata(4) - enable detach on shutdown, and fix the issue -with atabus being detached several times diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c index 654c5787d2a6..887df8c2b24e 100644 --- a/sys/dev/ata/ata.c +++ b/sys/dev/ata/ata.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.142 2018/10/22 20:13:47 jdolecek Exp $ */ +/* $NetBSD: ata.c,v 1.143 2018/10/24 19:38:00 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -25,7 +25,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.142 2018/10/22 20:13:47 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.143 2018/10/24 19:38:00 jdolecek Exp $"); #include "opt_ata.h" @@ -216,6 +216,8 @@ ata_channel_detach(struct ata_channel *chp) return; ata_channel_destroy(chp); + + chp->ch_flags |= ATACH_DETACHED; } static void diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h index 7db6fb22b01d..990f96f0cbc3 100644 --- a/sys/dev/ata/atavar.h +++ b/sys/dev/ata/atavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: atavar.h,v 1.100 2018/10/22 20:13:47 jdolecek Exp $ */ +/* $NetBSD: atavar.h,v 1.101 2018/10/24 19:38:00 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -410,10 +410,11 @@ struct ata_channel { #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */ #define ATACH_TH_RESCAN 0x400 /* rescan requested */ #define ATACH_NCQ 0x800 /* channel executing NCQ commands */ -#define ATACH_DMA_BEFORE_CMD 0x1000 /* start DMA first */ -#define ATACH_TH_DRIVE_RESET 0x2000 /* asked thread to drive(s) reset */ -#define ATACH_RECOVERING 0x4000 /* channel is recovering */ -#define ATACH_TH_RECOVERY 0x8000 /* asked thread to run recovery */ +#define ATACH_DMA_BEFORE_CMD 0x01000 /* start DMA first */ +#define ATACH_TH_DRIVE_RESET 0x02000 /* asked thread to drive(s) reset */ +#define ATACH_RECOVERING 0x04000 /* channel is recovering */ +#define ATACH_TH_RECOVERY 0x08000 /* asked thread to run recovery */ +#define ATACH_DETACHED 0x10000 /* channel was destroyed */ #define ATACH_NODRIVE 0xff /* no drive selected for reset */ diff --git a/sys/dev/ic/ahcisata_core.c b/sys/dev/ic/ahcisata_core.c index 43775e59d85f..81a1f97a409d 100644 --- a/sys/dev/ic/ahcisata_core.c +++ b/sys/dev/ic/ahcisata_core.c @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_core.c,v 1.64 2018/10/22 20:13:47 jdolecek Exp $ */ +/* $NetBSD: ahcisata_core.c,v 1.65 2018/10/24 19:38:00 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -26,7 +26,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.64 2018/10/22 20:13:47 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.65 2018/10/24 19:38:00 jdolecek Exp $"); #include #include @@ -477,6 +477,24 @@ end: } } +void +ahci_childdetached(struct ahci_softc *sc, device_t child) +{ + struct ahci_channel *achp; + struct ata_channel *chp; + + for (int i = 0; i < AHCI_MAX_PORTS; i++) { + achp = &sc->sc_channels[i]; + chp = &achp->ata_channel; + + if ((sc->sc_ahci_ports & (1U << i)) == 0) + continue; + + if (child == chp->atabus) + chp->atabus = NULL; + } +} + int ahci_detach(struct ahci_softc *sc, int flags) { @@ -502,10 +520,15 @@ ahci_detach(struct ahci_softc *sc, int flags) break; } - if (chp->atabus == NULL) + if (chp->atabus != NULL) { + if ((error = config_detach(chp->atabus, flags)) != 0) + return error; + + KASSERT(chp->atabus == NULL); + } + + if (chp->ch_flags & ATACH_DETACHED) continue; - if ((error = config_detach(chp->atabus, flags)) != 0) - return error; for (j = 0; j < sc->sc_ncmds; j++) bus_dmamap_destroy(sc->sc_dmat, achp->ahcic_datad[j]); @@ -517,8 +540,6 @@ ahci_detach(struct ahci_softc *sc, int flags) bus_dmamem_free(sc->sc_dmat, &achp->ahcic_cmd_tbl_seg, achp->ahcic_cmd_tbl_nseg); - chp->atabus = NULL; - ata_channel_detach(chp); } diff --git a/sys/dev/ic/ahcisatavar.h b/sys/dev/ic/ahcisatavar.h index cde537408f85..fb780506f85c 100644 --- a/sys/dev/ic/ahcisatavar.h +++ b/sys/dev/ic/ahcisatavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisatavar.h,v 1.19 2018/10/22 20:13:47 jdolecek Exp $ */ +/* $NetBSD: ahcisatavar.h,v 1.20 2018/10/24 19:38:00 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -117,6 +117,7 @@ struct ahci_softc { void ahci_attach(struct ahci_softc *); int ahci_detach(struct ahci_softc *, int); +void ahci_childdetached(struct ahci_softc *, device_t); void ahci_resume(struct ahci_softc *); int ahci_intr(void *); diff --git a/sys/dev/ic/siisata.c b/sys/dev/ic/siisata.c index 45ab1cbb56a3..b06cc35069b3 100644 --- a/sys/dev/ic/siisata.c +++ b/sys/dev/ic/siisata.c @@ -1,4 +1,4 @@ -/* $NetBSD: siisata.c,v 1.36 2018/10/22 20:13:47 jdolecek Exp $ */ +/* $NetBSD: siisata.c,v 1.37 2018/10/24 19:38:00 jdolecek Exp $ */ /* from ahcisata_core.c */ @@ -79,7 +79,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.36 2018/10/22 20:13:47 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.37 2018/10/24 19:38:00 jdolecek Exp $"); #include #include @@ -408,6 +408,19 @@ siisata_attach_port(struct siisata_softc *sc, int port) return; } +void +siisata_childdetached(struct siisata_softc *sc, device_t child) +{ + struct ata_channel *chp; + + for (int i = 0; i < sc->sc_atac.atac_nchannels; i++) { + chp = sc->sc_chanarray[i]; + + if (child == chp->atabus) + chp->atabus = NULL; + } +} + int siisata_detach(struct siisata_softc *sc, int flags) { @@ -417,14 +430,22 @@ siisata_detach(struct siisata_softc *sc, int flags) struct ata_channel *chp; int i, j, error; + if (adapt->adapt_refcnt != 0) + return EBUSY; + for (i = 0; i < sc->sc_atac.atac_nchannels; i++) { schp = &sc->sc_channels[i]; chp = sc->sc_chanarray[i]; - if (chp->atabus == NULL) + if (chp->atabus != NULL) { + if ((error = config_detach(chp->atabus, flags)) != 0) + return error; + + KASSERT(chp->atabus == NULL); + } + + if (chp->ch_flags & ATACH_DETACHED) continue; - if ((error = config_detach(chp->atabus, flags)) != 0) - return error; for (j = 0; j < SIISATA_MAX_SLOTS; j++) bus_dmamap_destroy(sc->sc_dmat, schp->sch_datad[j]); @@ -436,14 +457,9 @@ siisata_detach(struct siisata_softc *sc, int flags) bus_dmamem_free(sc->sc_dmat, &schp->sch_prb_seg, schp->sch_prb_nseg); - chp->atabus = NULL; - ata_channel_detach(chp); } - if (adapt->adapt_refcnt != 0) - return EBUSY; - /* leave the chip in reset */ GRWRITE(sc, GR_GC, GR_GC_GLBLRST); diff --git a/sys/dev/ic/siisatavar.h b/sys/dev/ic/siisatavar.h index d801caecc458..52b824ca98d7 100644 --- a/sys/dev/ic/siisatavar.h +++ b/sys/dev/ic/siisatavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: siisatavar.h,v 1.8 2018/10/22 20:13:47 jdolecek Exp $ */ +/* $NetBSD: siisatavar.h,v 1.9 2018/10/24 19:38:00 jdolecek Exp $ */ /* from ahcisatavar.h */ @@ -114,6 +114,7 @@ struct siisata_softc { void siisata_attach(struct siisata_softc *); int siisata_detach(struct siisata_softc *, int); +void siisata_childdetached(struct siisata_softc *, device_t); void siisata_resume(struct siisata_softc *); int siisata_intr(void *); diff --git a/sys/dev/pci/ahcisata_pci.c b/sys/dev/pci/ahcisata_pci.c index 3bb0935b08d6..8332f4e1407a 100644 --- a/sys/dev/pci/ahcisata_pci.c +++ b/sys/dev/pci/ahcisata_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_pci.c,v 1.40 2018/10/22 21:40:45 jdolecek Exp $ */ +/* $NetBSD: ahcisata_pci.c,v 1.41 2018/10/24 19:38:00 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -26,7 +26,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.40 2018/10/22 21:40:45 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.41 2018/10/24 19:38:00 jdolecek Exp $"); #include #include @@ -208,11 +208,13 @@ static int ahci_pci_has_quirk(pci_vendor_id_t, pci_product_id_t); static int ahci_pci_match(device_t, cfdata_t, void *); static void ahci_pci_attach(device_t, device_t, void *); static int ahci_pci_detach(device_t, int); +static void ahci_pci_childdetached(device_t, device_t); static bool ahci_pci_resume(device_t, const pmf_qual_t *); -CFATTACH_DECL_NEW(ahcisata_pci, sizeof(struct ahci_pci_softc), - ahci_pci_match, ahci_pci_attach, ahci_pci_detach, NULL); +CFATTACH_DECL3_NEW(ahcisata_pci, sizeof(struct ahci_pci_softc), + ahci_pci_match, ahci_pci_attach, ahci_pci_detach, NULL, + NULL, ahci_pci_childdetached, DVF_DETACH_SHUTDOWN); static int ahci_pci_has_quirk(pci_vendor_id_t vendor, pci_product_id_t product) @@ -328,6 +330,15 @@ ahci_pci_attach(device_t parent, device_t self, void *aux) aprint_error_dev(self, "couldn't establish power handler\n"); } +static void +ahci_pci_childdetached(device_t dv, device_t child) +{ + struct ahci_pci_softc *psc = device_private(dv); + struct ahci_softc *sc = &psc->ah_sc; + + ahci_childdetached(sc, child); +} + static int ahci_pci_detach(device_t dv, int flags) { diff --git a/sys/dev/pci/siisata_pci.c b/sys/dev/pci/siisata_pci.c index 08f472e992d9..eec63dfd6ee3 100644 --- a/sys/dev/pci/siisata_pci.c +++ b/sys/dev/pci/siisata_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: siisata_pci.c,v 1.18 2018/10/22 21:40:45 jdolecek Exp $ */ +/* $NetBSD: siisata_pci.c,v 1.19 2018/10/24 19:38:00 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -51,7 +51,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: siisata_pci.c,v 1.18 2018/10/22 21:40:45 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: siisata_pci.c,v 1.19 2018/10/24 19:38:00 jdolecek Exp $"); #include #include @@ -74,6 +74,7 @@ struct siisata_pci_softc { static int siisata_pci_match(device_t, cfdata_t, void *); static void siisata_pci_attach(device_t, device_t, void *); static int siisata_pci_detach(device_t, int); +static void siisata_pci_childdetached(device_t, device_t); static bool siisata_pci_resume(device_t, const pmf_qual_t *); struct siisata_pci_board { @@ -110,8 +111,9 @@ static const struct siisata_pci_board siisata_pci_boards[] = { }, }; -CFATTACH_DECL_NEW(siisata_pci, sizeof(struct siisata_pci_softc), - siisata_pci_match, siisata_pci_attach, siisata_pci_detach, NULL); +CFATTACH_DECL3_NEW(siisata_pci, sizeof(struct siisata_pci_softc), + siisata_pci_match, siisata_pci_attach, siisata_pci_detach, NULL, + NULL, siisata_pci_childdetached, DVF_DETACH_SHUTDOWN); static const struct siisata_pci_board * siisata_pci_lookup(const struct pci_attach_args * pa) @@ -306,6 +308,15 @@ siisata_pci_detach(device_t dv, int flags) return 0; } +static void +siisata_pci_childdetached(device_t dv, device_t child) +{ + struct siisata_pci_softc *psc = device_private(dv); + struct siisata_softc *sc = &psc->si_sc; + + siisata_childdetached(sc, child); +} + static bool siisata_pci_resume(device_t dv, const pmf_qual_t *qual) {