summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2007-03-20 04:38:12 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2007-03-20 04:38:12 +0000
commit87661eb58b8b48426d1646734f3701edb9aa48e7 (patch)
tree7941abe39c60d2f18b136d15238859e09f9de243 /sys
parentf358db4fa96515906a6f924dbeba42e426eae9cc (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.c54
-rw-r--r--sys/dev/ata/atascsi.h9
-rw-r--r--sys/dev/pci/ahci.c102
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);
}