diff options
author | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2007-03-20 04:38:12 +0000 |
---|---|---|
committer | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2007-03-20 04:38:12 +0000 |
commit | 87661eb58b8b48426d1646734f3701edb9aa48e7 (patch) | |
tree | 7941abe39c60d2f18b136d15238859e09f9de243 /sys | |
parent | f358db4fa96515906a6f924dbeba42e426eae9cc (diff) |
Change API for struct ata_xfer allocation to move it into the device that
atascsi will be driving, and add it to the AHCI CCB.
This effectively gives us all the resources we need for a transfer in one
hit, meaning that we don't need to worry about whether we will have a pool
shortage or not enough CCBs. The SCSI mid layer should take care to never
exceed the number of CCBs we have available, based on our sc_link.openings.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ata/atascsi.c | 54 | ||||
-rw-r--r-- | sys/dev/ata/atascsi.h | 9 | ||||
-rw-r--r-- | sys/dev/pci/ahci.c | 102 |
3 files changed, 86 insertions, 79 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c index a3e3e3b7185..0bc0d856652 100644 --- a/sys/dev/ata/atascsi.c +++ b/sys/dev/ata/atascsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atascsi.c,v 1.15 2007/03/13 11:20:57 dlg Exp $ */ +/* $OpenBSD: atascsi.c,v 1.16 2007/03/20 04:38:11 pascoe Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -23,7 +23,6 @@ #include <sys/malloc.h> #include <sys/device.h> #include <sys/proc.h> -#include <sys/pool.h> #include <sys/queue.h> #include <scsi/scsi_all.h> @@ -171,10 +170,6 @@ int atascsi_stuffup(struct scsi_xfer *); int ata_running = 0; -struct pool ata_xfer_pool; - -void ata_init(void); -void ata_destroy(void); int ata_exec(struct atascsi *, struct ata_xfer *); @@ -188,8 +183,6 @@ atascsi_attach(struct device *self, struct atascsi_attach_args *aaa) struct atascsi *as; int i; - ata_init(); - as = malloc(sizeof(struct atascsi), M_DEVBUF, M_WAITOK); bzero(as, sizeof(struct atascsi)); @@ -231,8 +224,6 @@ atascsi_attach(struct device *self, struct atascsi_attach_args *aaa) int atascsi_detach(struct atascsi *as) { - ata_destroy(); - return (0); } @@ -391,7 +382,7 @@ atascsi_disk_inq(struct scsi_xfer *xs) xa = ata_setup_identify(ap, xs->flags & SCSI_NOSLEEP); if (xa == NULL) - return (atascsi_stuffup(xs)); + return (NO_CCB); xa->complete = atascsi_disk_inq_done; xa->timeout = xs->timeout; @@ -457,7 +448,7 @@ atascsi_disk_capacity(struct scsi_xfer *xs) xa = ata_setup_identify(ap, xs->flags & SCSI_NOSLEEP); if (xa == NULL) - return (atascsi_stuffup(xs)); + return (NO_CCB); xa->complete = atascsi_disk_capacity_done; xa->timeout = xs->timeout; @@ -554,49 +545,22 @@ atascsi_stuffup(struct scsi_xfer *xs) return (COMPLETE); } -void -ata_init(void) -{ - if (ata_running++) - return; - - pool_init(&ata_xfer_pool, sizeof(struct ata_xfer), 0, 0, 0, "xapl", - NULL); -} - -void -ata_destroy(void) -{ - if (--ata_running) - return; - - pool_destroy(&ata_xfer_pool); -} - int ata_exec(struct atascsi *as, struct ata_xfer *xa) { - xa->state = ATA_S_PENDING; - return (as->as_methods->ata_cmd(as->as_cookie, xa)); + return (as->as_methods->ata_cmd(xa)); } + struct ata_xfer * -ata_get_xfer(struct ata_port *ap, int nosleep) +ata_get_xfer(struct ata_port *ap, int nosleep /* XXX unused */) { - struct ata_xfer *xa; - - xa = pool_get(&ata_xfer_pool, nosleep ? PR_NOWAIT : PR_WAITOK); - if (xa != NULL) { - bzero(&xa->cmd, sizeof(xa->cmd)); - xa->port = ap; - xa->state = ATA_S_SETUP; - } - - return (xa); + return (ap->ap_as->as_methods->ata_get_xfer(ap->ap_as->as_cookie, + ap->ap_port)); } void ata_put_xfer(struct ata_xfer *xa) { - pool_put(&ata_xfer_pool, xa); + xa->ata_put_xfer(xa); } diff --git a/sys/dev/ata/atascsi.h b/sys/dev/ata/atascsi.h index db745284b00..91ee6e2dfae 100644 --- a/sys/dev/ata/atascsi.h +++ b/sys/dev/ata/atascsi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atascsi.h,v 1.8 2007/03/13 11:22:36 dlg Exp $ */ +/* $OpenBSD: atascsi.h,v 1.9 2007/03/20 04:38:11 pascoe Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -21,7 +21,8 @@ struct ata_xfer; struct atascsi_methods { int (*probe)(void *, int); - int (*ata_cmd)(void *, struct ata_xfer *); + struct ata_xfer * (*ata_get_xfer)(void *, int ); + int (*ata_cmd)(struct ata_xfer *); }; struct atascsi_attach_args { @@ -64,7 +65,6 @@ struct ata_xfer { struct timeout stimeout; u_int timeout; - struct ata_port *port; int flags; #define ATA_F_READ (1<<0) #define ATA_F_WRITE (1<<1) @@ -75,8 +75,11 @@ struct ata_xfer { #define ATA_S_PENDING 1 #define ATA_S_COMPLETE 2 #define ATA_S_ERROR 3 +#define ATA_S_PUT 6 void *atascsi_private; + + void (*ata_put_xfer)(struct ata_xfer *); }; #define ATA_QUEUED 0 diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c index 552f4769bbf..ce3f28f8992 100644 --- a/sys/dev/pci/ahci.c +++ b/sys/dev/pci/ahci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ahci.c,v 1.77 2007/03/07 03:25:24 pascoe Exp $ */ +/* $OpenBSD: ahci.c,v 1.78 2007/03/20 04:38:11 pascoe Exp $ */ /* * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> @@ -39,6 +39,7 @@ #define DPRINTF(m, f...) do { if (ahcidebug & (m)) printf(f); } while (0) #define AHCI_D_VERBOSE 0x01 #define AHCI_D_INTR 0x02 +#define AHCI_D_XFER 0x08 int ahcidebug = AHCI_D_VERBOSE | AHCI_D_INTR; #else #define DPRINTF(m, f...) @@ -308,6 +309,9 @@ struct ahci_softc; struct ahci_port; struct ahci_ccb { + /* ATA xfer associated with this CCB. Must be 1st struct member. */ + struct ata_xfer ccb_xa; + int ccb_slot; struct ahci_port *ccb_port; @@ -315,7 +319,6 @@ struct ahci_ccb { struct ahci_cmd_hdr *ccb_cmd_hdr; struct ahci_cmd_table *ccb_cmd_table; - struct ata_xfer *ccb_xa; void (*ccb_done)(struct ahci_ccb *); TAILQ_ENTRY(ahci_ccb) ccb_entry; @@ -419,7 +422,7 @@ int ahci_intr(void *); int ahci_port_intr(struct ahci_port *, u_int32_t); struct ahci_ccb *ahci_get_ccb(struct ahci_port *); -void ahci_put_ccb(struct ahci_port *, struct ahci_ccb *); +void ahci_put_ccb(struct ahci_ccb *); struct ahci_dmamem *ahci_dmamem_alloc(struct ahci_softc *, size_t); void ahci_dmamem_free(struct ahci_softc *, @@ -447,10 +450,14 @@ int ahci_pwait_ne(struct ahci_port *, bus_size_t, /* provide methods for atascsi to call */ int ahci_ata_probe(void *, int); -int ahci_ata_cmd(void *, struct ata_xfer *); +struct ata_xfer * ahci_ata_get_xfer(void *, int); +void ahci_ata_put_xfer(struct ata_xfer *); +int ahci_ata_cmd(struct ata_xfer *); + struct atascsi_methods ahci_atascsi_methods = { ahci_ata_probe, + ahci_ata_get_xfer, ahci_ata_cmd }; @@ -852,7 +859,9 @@ nomem: ccb->ccb_cmd_hdr->ctba_hi = htole32((u_int32_t)(dva >> 32)); ccb->ccb_cmd_hdr->ctba_lo = htole32((u_int32_t)dva); - ahci_put_ccb(ap, ccb); + ccb->ccb_xa.ata_put_xfer = ahci_ata_put_xfer; + + ahci_put_ccb(ccb); } /* Wait for ICC change to complete */ @@ -1122,7 +1131,7 @@ ahci_port_softreset(struct ahci_port *ap) err: if (ccb != NULL) { s = splbio(); - ahci_put_ccb(ap, ccb); + ahci_put_ccb(ccb); splx(s); } @@ -1189,7 +1198,7 @@ ahci_load_prdt(struct ahci_ccb *ccb) { struct ahci_port *ap = ccb->ccb_port; struct ahci_softc *sc = ap->ap_sc; - struct ata_xfer *xa = ccb->ccb_xa; + struct ata_xfer *xa = &ccb->ccb_xa; struct ahci_prdt *prdt = ccb->ccb_cmd_table->prdt, *prd; bus_dmamap_t dmap = ccb->ccb_dmamap; struct ahci_cmd_hdr *cmd_slot = ccb->ccb_cmd_hdr; @@ -1404,15 +1413,20 @@ ahci_get_ccb(struct ahci_port *ap) struct ahci_ccb *ccb; ccb = TAILQ_FIRST(&ap->ap_ccb_free); - if (ccb != NULL) + if (ccb != NULL) { TAILQ_REMOVE(&ap->ap_ccb_free, ccb, ccb_entry); + ccb->ccb_xa.state = ATA_S_SETUP; + } return (ccb); } void -ahci_put_ccb(struct ahci_port *ap, struct ahci_ccb *ccb) +ahci_put_ccb(struct ahci_ccb *ccb) { + struct ahci_port *ap = ccb->ccb_port; + + ccb->ccb_xa.state = ATA_S_PUT; TAILQ_INSERT_TAIL(&ap->ap_ccb_free, ccb, ccb_entry); } @@ -1580,26 +1594,48 @@ ahci_ata_probe(void *xsc, int port) return ATA_PORT_T_DISK; } -int -ahci_ata_cmd(void *xsc, struct ata_xfer *xa) +struct ata_xfer * +ahci_ata_get_xfer(void *aaa_cookie, int port) { - struct ahci_softc *sc = xsc; - struct ahci_port *ap = sc->sc_ports[xa->port->ap_port]; + struct ahci_softc *sc = aaa_cookie; + struct ahci_port *ap = sc->sc_ports[port]; struct ahci_ccb *ccb; - struct ahci_cmd_hdr *cmd_slot; - u_int8_t *fis; - int s; - if (ap == NULL) - return (ATA_ERROR); + splassert(IPL_BIO); - s = splbio(); ccb = ahci_get_ccb(ap); - splx(s); - if (ccb == NULL) - return (ATA_ERROR); + if (ccb == NULL) { + DPRINTF(AHCI_D_XFER, "%s: ahci_ata_get_xfer: NULL ccb\n", + PORTNAME(ap)); + return (NULL); + } + + DPRINTF(AHCI_D_XFER, "%s: ahci_ata_get_xfer got slot %d\n", + PORTNAME(ap), ccb->ccb_slot); + + return ((struct ata_xfer *)ccb); +} + +void +ahci_ata_put_xfer(struct ata_xfer *xa) +{ + struct ahci_ccb *ccb = (struct ahci_ccb *)xa; + + splassert(IPL_BIO); + + DPRINTF(AHCI_D_XFER, "ahci_ata_put_xfer slot %d\n", ccb->ccb_slot); + + ahci_put_ccb(ccb); +} + +int +ahci_ata_cmd(struct ata_xfer *xa) +{ + struct ahci_ccb *ccb = (struct ahci_ccb *)xa; + struct ahci_cmd_hdr *cmd_slot; + u_int8_t *fis; + int s; - ccb->ccb_xa = xa; ccb->ccb_done = ahci_ata_cmd_done; cmd_slot = ccb->ccb_cmd_hdr; bzero(ccb->ccb_cmd_table, sizeof(struct ahci_cmd_table)); @@ -1626,17 +1662,15 @@ ahci_ata_cmd(void *xsc, struct ata_xfer *xa) fis[18] = 0; fis[19] = 0; - if (ahci_load_prdt(ccb) != 0) { - s = splbio(); - ahci_put_ccb(ap, ccb); - splx(s); - return (ATA_ERROR); - } + if (ahci_load_prdt(ccb) != 0) + goto failcmd; cmd_slot->flags = htole16(5); /* FIS length (in DWORDs) */ if (xa->flags & ATA_F_WRITE) cmd_slot->flags |= htole16(AHCI_CMD_LIST_FLAG_W); + xa->state = ATA_S_PENDING; + if (xa->flags & ATA_F_POLL) { if (ahci_poll(ccb, 1000) != 0) return (ATA_ERROR); @@ -1647,6 +1681,13 @@ ahci_ata_cmd(void *xsc, struct ata_xfer *xa) ahci_start(ccb); splx(s); return (ATA_QUEUED); + +failcmd: + s = splbio(); + xa->state = ATA_S_ERROR; + xa->complete(xa); + splx(s); + return (ATA_ERROR); } void @@ -1654,7 +1695,7 @@ ahci_ata_cmd_done(struct ahci_ccb *ccb) { struct ahci_port *ap = ccb->ccb_port; struct ahci_softc *sc = ap->ap_sc; - struct ata_xfer *xa = ccb->ccb_xa; + struct ata_xfer *xa = &ccb->ccb_xa; bus_dmamap_t dmap = ccb->ccb_dmamap; if (xa->datalen != 0) { @@ -1665,7 +1706,6 @@ ahci_ata_cmd_done(struct ahci_ccb *ccb) bus_dmamap_unload(sc->sc_dmat, dmap); } - ahci_put_ccb(ap, ccb); xa->state = ATA_S_COMPLETE; xa->complete(xa); } |