summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2008-07-17 13:16:30 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2008-07-17 13:16:30 +0000
commit2adbce083b5957abfe218a36a4ce448dfe0ebbb9 (patch)
tree1c6524c215eb936310791e9d2da766c525c8dd04 /sys/dev/pci
parent2a617ec98b1bb0e73dd63cafaab4d04c84c5c6e6 (diff)
Increase the size of the diskinfo struct, which has grown
4 bytes in the new firmware. To allow this to work on older firmwares add a "short read allowed" flag to arc_msgbuf(), which will allow short reads by getting the read length from the header of the response the firmware sends. Only set the flag on the arc_msgbuf() call that deals with the diskinfo struct for now. Discussed with and ok dlg@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/arc.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/sys/dev/pci/arc.c b/sys/dev/pci/arc.c
index eb6bb0fe971..4ab3d708ec7 100644
--- a/sys/dev/pci/arc.c
+++ b/sys/dev/pci/arc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arc.c,v 1.76 2008/06/27 12:04:29 jsg Exp $ */
+/* $OpenBSD: arc.c,v 1.77 2008/07/17 13:16:29 jsg Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -301,7 +301,7 @@ struct arc_fw_diskinfo {
u_int8_t drive_select;
u_int8_t raid_number; // 0xff unowned
struct arc_fw_scsiattr scsi_attr;
- u_int8_t reserved[40];
+ u_int8_t reserved[44];
} __packed;
struct arc_fw_sysinfo {
@@ -483,7 +483,7 @@ void arc_unlock(struct arc_softc *);
void arc_wait(struct arc_softc *);
u_int8_t arc_msg_cksum(void *, u_int16_t);
int arc_msgbuf(struct arc_softc *, void *, size_t,
- void *, size_t);
+ void *, size_t, int);
/* bioctl */
int arc_bioctl(struct device *, u_long, caddr_t);
@@ -1120,7 +1120,7 @@ arc_bio_alarm(struct arc_softc *sc, struct bioc_alarm *ba)
}
arc_lock(sc);
- error = arc_msgbuf(sc, request, len, reply, sizeof(reply));
+ error = arc_msgbuf(sc, request, len, reply, sizeof(reply), 0);
arc_unlock(sc);
if (error != 0)
@@ -1149,7 +1149,7 @@ arc_bio_alarm_state(struct arc_softc *sc, struct bioc_alarm *ba)
arc_lock(sc);
error = arc_msgbuf(sc, &request, sizeof(request),
- sysinfo, sizeof(struct arc_fw_sysinfo));
+ sysinfo, sizeof(struct arc_fw_sysinfo), 0);
arc_unlock(sc);
if (error != 0)
@@ -1179,7 +1179,7 @@ arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
request[0] = ARC_FW_SYSINFO;
error = arc_msgbuf(sc, request, 1, sysinfo,
- sizeof(struct arc_fw_sysinfo));
+ sizeof(struct arc_fw_sysinfo), 0);
if (error != 0)
goto out;
@@ -1189,7 +1189,7 @@ arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
for (i = 0; i < maxvols; i++) {
request[1] = i;
error = arc_msgbuf(sc, request, sizeof(request), volinfo,
- sizeof(struct arc_fw_volinfo));
+ sizeof(struct arc_fw_volinfo), 0);
if (error != 0)
goto out;
@@ -1236,7 +1236,7 @@ arc_bio_blink(struct arc_softc *sc, struct bioc_blink *blink)
mask = htole32(sc->sc_ledmask);
bcopy(&mask, &request[2], 3);
- error = arc_msgbuf(sc, request, sizeof(request), NULL, 0);
+ error = arc_msgbuf(sc, request, sizeof(request), NULL, 0, 0);
if (error)
return (EIO);
@@ -1255,7 +1255,7 @@ arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
request[0] = ARC_FW_SYSINFO;
error = arc_msgbuf(sc, request, 1, sysinfo,
- sizeof(struct arc_fw_sysinfo));
+ sizeof(struct arc_fw_sysinfo), 0);
if (error != 0)
goto out;
@@ -1265,7 +1265,7 @@ arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
for (i = 0; i < maxvols; i++) {
request[1] = i;
error = arc_msgbuf(sc, request, sizeof(request), volinfo,
- sizeof(struct arc_fw_volinfo));
+ sizeof(struct arc_fw_volinfo), 0);
if (error != 0)
goto out;
@@ -1396,7 +1396,7 @@ arc_bio_disk(struct arc_softc *sc, struct bioc_disk *bd)
request[0] = ARC_FW_RAIDINFO;
request[1] = volinfo->raid_set_number;
error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
- sizeof(struct arc_fw_raidinfo));
+ sizeof(struct arc_fw_raidinfo), 0);
if (error != 0)
goto out;
@@ -1421,7 +1421,7 @@ arc_bio_disk(struct arc_softc *sc, struct bioc_disk *bd)
request[0] = ARC_FW_DISKINFO;
request[1] = raidinfo->device_array[bd->bd_diskid];
error = arc_msgbuf(sc, request, sizeof(request), diskinfo,
- sizeof(struct arc_fw_diskinfo));
+ sizeof(struct arc_fw_diskinfo), 1);
if (error != 0)
goto out;
@@ -1477,11 +1477,12 @@ arc_msg_cksum(void *cmd, u_int16_t len)
int
arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
- size_t rbuflen)
+ size_t rbuflen, int sreadok)
{
u_int8_t rwbuf[ARC_RA_IOC_RWBUF_MAXLEN];
u_int8_t *wbuf, *rbuf;
int wlen, wdone = 0, rlen, rdone = 0;
+ u_int16_t rlenhdr = 0;
struct arc_fw_bufhdr *bufhdr;
u_int32_t reg, rwlen;
int error = 0;
@@ -1583,6 +1584,24 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
bcopy(rwbuf, &rbuf[rdone], rwlen);
rdone += rwlen;
+
+ /*
+ * Allow for short reads, by reading the length
+ * value from the response header and shrinking our
+ * idea of size, if required.
+ * This deals with the growth of diskinfo struct from
+ * 128 to 132 bytes.
+ */
+ if (sreadok && rdone >= sizeof(struct arc_fw_bufhdr) &&
+ rlenhdr == 0) {
+ bufhdr = (struct arc_fw_bufhdr *)rbuf;
+ rlenhdr = letoh16(bufhdr->len);
+ if (rlenhdr < rbuflen) {
+ rbuflen = rlenhdr;
+ rlen = sizeof(struct arc_fw_bufhdr) +
+ rbuflen + 1; /* 1 for cksum */
+ }
+ }
}
} while (rdone != rlen);