Add two latest advisories:

Fix an integer overflow in computing the size of a temporary buffer
can result in a buffer which is too small for the requested
operation. [13:09]

Fix a bug that could lead to kernel memory disclosure with
SCTP state cookie. [13:10]

Add latest errata notices:

Fix a data corruption problem with mfi(4) operating on > 2TB
disks in a JBOD. [EN-13:03]
This commit is contained in:
Xin LI 2013-08-22 01:12:09 +00:00
parent 09753ffb21
commit b735a9d213
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=42568
11 changed files with 1451 additions and 0 deletions

View file

@ -0,0 +1,109 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
=============================================================================
FreeBSD-EN-13:03.mfi Errata Notice
The FreeBSD Project
Topic: data corruption with mfi(4) JBOD disks > 2TB
Category: contrib
Module: mfi
Announced: 2013-08-22
Credits: Steven Hartland, Doug Ambrisko
Affects: FreeBSD 9.1
Corrected: 2012-12-03 18:37:02 UTC (stable/9, 9.1-STABLE)
2013-08-22 00:51:48 UTC (releng/9.1, 9.1-RELEASE-p6)
For general information regarding FreeBSD Errata Notices and Security
Advisories, including descriptions of the fields above, security
branches, and the following sections, please visit
<URL:http://security.freebsd.org/>.
I. Background
The mfi(4) driver supports LSI's next generation PCI Express SAS RAID
controllers. The driver supports JBOD attachment through /dev/mfisyspd?
device nodes.
Logical block addressing (LBA) is a common scheme used for specifying the
location of sectors on hard drives.
II. Problem Description
The way mfi(4) implements access of "syspd" or also known as JBOD always
uses READ10/WRITE10 commands for underlying disk. When writing over 2^32
sectors, the LBA would wrap and starts writing at the beginning of the
disk.
III. Impact
Writing beyond 2TB to mfi(4) connected JBODs would result in data corruption.
IV. Workaround
No workaround is available, but systems that do not use mfi(4) as a JBOD
HBA or do not have disks with 2^32 or more sectors (2^41 or more bytes with
512-byte logical sector size) are not affected.
V. Solution
Perform one of the following:
1) Upgrade your system to a supported FreeBSD stable or release / security
branch (releng) dated after the correction date.
2) To update your present system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
# fetch http://security.FreeBSD.org/patches/EN-13:03/mfi.patch
# fetch http://security.FreeBSD.org/patches/EN-13:03/mfi.patch.asc
# gpg --verify mfi.patch.asc
b) Apply the patch.
# cd /usr/src
# patch < /path/to/patch
c) Recompile your kernel as described in
<URL:http://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the
system.
3) To update your system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
VI. Correction details
The following list contains the revision numbers of each file that was
corrected in FreeBSD.
Branch/path Revision
- -------------------------------------------------------------------------
stable/9/ r243824
releng/9.1/ r254631
- -------------------------------------------------------------------------
VII. References
http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/173291
The latest revision of this Errata Notice is available at
http://security.FreeBSD.org/advisories/FreeBSD-EN-13:03.mfi.asc
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.21 (FreeBSD)
iEYEARECAAYFAlIVY1YACgkQFdaIBMps37IHmwCfZH+1Gi0u7eYMXYevu0KHaG3a
rCwAn2ecdXnLOsaC6D6i2mo4dmI4HLDk
=AwdQ
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,121 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
FreeBSD-SA-13:09.ip_multicast Security Advisory
The FreeBSD Project
Topic: integer overflow in IP_MSFILTER
Category: core
Module: kernel
Announced: 2013-08-22
Credits: Clement Lecigne (Google Security Team)
Affects: All supported versions of FreeBSD.
Corrected: 2013-08-22 00:51:37 UTC (stable/9, 9.2-PRERELEASE)
2013-08-22 00:51:43 UTC (releng/9.2, 9.2-RC2-p1)
2013-08-22 00:51:48 UTC (releng/9.1, 9.1-RELEASE-p6)
2013-08-22 00:51:37 UTC (stable/8, 8.4-STABLE)
2013-08-22 00:51:56 UTC (releng/8.4, 8.4-RELEASE-p3)
2013-08-22 00:51:56 UTC (releng/8.3, 8.3-RELEASE-p10)
CVE Name: CVE-2013-3077
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:http://security.FreeBSD.org/>.
I. Background
IP multicast is a method of sending Internet Protocol (IP) datagrams to a
group of interested receivers in a single transmission.
II. Problem Description
An integer overflow in computing the size of a temporary buffer can
result in a buffer which is too small for the requested operation.
III. Impact
An unprivileged process can read or write pages of memory which belong to
the kernel. These may lead to exposure of sensitive information or allow
privilege escalation.
IV. Workaround
No workaround is available.
V. Solution
Perform one of the following:
1) Upgrade your vulnerable system to a supported FreeBSD stable or
release / security branch (releng) dated after the correction date.
2) To update your vulnerable system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
# fetch http://security.FreeBSD.org/patches/SA-13:09/ip_multicast.patch
# fetch http://security.FreeBSD.org/patches/SA-13:09/ip_multicast.patch.asc
# gpg --verify ip_multicast.patch.asc
b) Apply the patch.
# cd /usr/src
# patch < /path/to/patch
c) Recompile your kernel as described in
<URL:http://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the
system.
3) To update your vulnerable system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/8/ r254629
releng/8.3/ r254632
releng/8.4/ r254632
stable/9/ r254629
releng/9.1/ r254631
releng/9.2/ r254630
- -------------------------------------------------------------------------
To see which files were modified by a particular revision, run the
following command, replacing XXXXXX with the revision number, on a
machine with Subversion installed:
# svn diff -cXXXXXX --summarize svn://svn.freebsd.org/base
Or visit the following URL, replacing XXXXXX with the revision number:
<URL:http://svnweb.freebsd.org/base?view=revision&revision=XXXXXX>
VII. References
<other info on vulnerability>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-3077>
The latest revision of this advisory is available at
<URL:http://security.FreeBSD.org/advisories/FreeBSD-SA-13:09.ip_multicast.asc>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.21 (FreeBSD)
iEYEARECAAYFAlIVY1YACgkQFdaIBMps37K1cwCeOwXryun/C0EceD7v1se+z8w1
EUYAoJ7Hh/bOjyuD6oR6ZOEqtDVIL5LP
=6Ehk
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,133 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
=============================================================================
FreeBSD-SA-13:10.sctp Security Advisory
The FreeBSD Project
Topic: Kernel memory disclosure in sctp(4)
Category: core
Module: sctp
Announced: 2013-08-22
Credits: Julian Seward, Michael Tuexen
Affects: All supported versions of FreeBSD.
Corrected: 2013-08-15 04:25:16 UTC (stable/9, 9.2-PRERELEASE)
2013-08-15 05:14:20 UTC (releng/9.2, 9.2-RC2)
2013-08-22 00:51:48 UTC (releng/9.1, 9.1-RELEASE-p6)
2013-08-15 04:35:25 UTC (stable/8, 8.4-STABLE)
2013-08-22 00:51:56 UTC (releng/8.4, 8.4-RELEASE-p3)
2013-08-22 00:51:56 UTC (releng/8.3, 8.3-RELEASE-p10)
CVE Name: CVE-2013-5209
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:http://security.FreeBSD.org/>.
I. Background
The SCTP protocol provides reliable, flow-controlled, two-way transmission
of data. It is a message oriented protocol and can support the SOCK_STREAM
and SOCK_SEQPACKET abstractions.
The SCTP protocol checks the integrity of messages by validating the state
cookie information that is returned from the peer.
II. Problem Description
When initializing the SCTP state cookie being sent in INIT-ACK chunks,
a buffer allocated from the kernel stack is not completely initialized.
III. Impact
Fragments of kernel memory may be included in SCTP packets and
transmitted over the network. For each SCTP session, there are two
separate instances in which a 4-byte fragment may be transmitted.
This memory might contain sensitive information, such as portions of the
file cache or terminal buffers. This information might be directly
useful, or it might be leveraged to obtain elevated privileges in
some way. For example, a terminal buffer might include an user-entered
password.
IV. Workaround
No workaround is available, but systems not using the SCTP protocol
are not vulnerable.
V. Solution
Perform one of the following:
1) Upgrade your vulnerable system to a supported FreeBSD stable or
release / security branch (releng) dated after the correction date.
2) To update your vulnerable system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
# fetch http://security.FreeBSD.org/patches/SA-13:10/sctp.patch
# fetch http://security.FreeBSD.org/patches/SA-13:10/sctp.patch.asc
# gpg --verify sctp.patch.asc
b) Apply the patch.
# cd /usr/src
# patch < /path/to/patch
c) Recompile your kernel as described in
<URL:http://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the
system.
3) To update your vulnerable system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/8/ r254354
releng/8.3/ r254632
releng/8.4/ r254632
stable/9/ r254352
releng/9.1/ r254631
releng/9.2/ r254355
- -------------------------------------------------------------------------
To see which files were modified by a particular revision, run the
following command, replacing XXXXXX with the revision number, on a
machine with Subversion installed:
# svn diff -cXXXXXX --summarize svn://svn.freebsd.org/base
Or visit the following URL, replacing XXXXXX with the revision number:
<URL:http://svnweb.freebsd.org/base?view=revision&revision=XXXXXX>
VII. References
<other info on vulnerability>
<URL:http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-5209>
The latest revision of this advisory is available at
<URL:http://security.FreeBSD.org/advisories/FreeBSD-SA-13:10.sctp.asc>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.21 (FreeBSD)
iEYEARECAAYFAlIVY1YACgkQFdaIBMps37L0AQCgh30FZd+f+rmzMabRFkTPVEmX
tZgAnRuZptKgvlHkqnEhUj30tH6xLDCO
=KJ8k
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,994 @@
Index: sys/dev/mfi/mfi.c
===================================================================
--- sys/dev/mfi/mfi.c (revision 254079)
+++ sys/dev/mfi/mfi.c (working copy)
@@ -107,7 +107,7 @@ static void mfi_bio_complete(struct mfi_command *)
static struct mfi_command *mfi_build_ldio(struct mfi_softc *,struct bio*);
static struct mfi_command *mfi_build_syspdio(struct mfi_softc *,struct bio*);
static int mfi_send_frame(struct mfi_softc *, struct mfi_command *);
-static int mfi_abort(struct mfi_softc *, struct mfi_command *);
+static int mfi_abort(struct mfi_softc *, struct mfi_command **);
static int mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, struct thread *);
static void mfi_timeout(void *);
static int mfi_user_command(struct mfi_softc *,
@@ -373,6 +373,8 @@ mfi_attach(struct mfi_softc *sc)
sx_init(&sc->mfi_config_lock, "MFI config");
TAILQ_INIT(&sc->mfi_ld_tqh);
TAILQ_INIT(&sc->mfi_syspd_tqh);
+ TAILQ_INIT(&sc->mfi_ld_pend_tqh);
+ TAILQ_INIT(&sc->mfi_syspd_pend_tqh);
TAILQ_INIT(&sc->mfi_evt_queue);
TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc);
TASK_INIT(&sc->mfi_map_sync_task, 0, mfi_handle_map_sync, sc);
@@ -694,6 +696,7 @@ mfi_attach(struct mfi_softc *sc)
device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
return (EINVAL);
}
+ sc->mfi_intr_ptr = mfi_intr_tbolt;
sc->mfi_enable_intr(sc);
} else {
if ((error = mfi_comms_init(sc)) != 0)
@@ -704,6 +707,7 @@ mfi_attach(struct mfi_softc *sc)
device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
return (EINVAL);
}
+ sc->mfi_intr_ptr = mfi_intr;
sc->mfi_enable_intr(sc);
}
if ((error = mfi_get_controller_info(sc)) != 0)
@@ -1278,6 +1282,17 @@ mfi_shutdown(struct mfi_softc *sc)
struct mfi_command *cm;
int error;
+
+ if (sc->mfi_aen_cm)
+ sc->cm_aen_abort = 1;
+ if (sc->mfi_aen_cm != NULL)
+ mfi_abort(sc, &sc->mfi_aen_cm);
+
+ if (sc->mfi_map_sync_cm)
+ sc->cm_map_abort = 1;
+ if (sc->mfi_map_sync_cm != NULL)
+ mfi_abort(sc, &sc->mfi_map_sync_cm);
+
mtx_lock(&sc->mfi_io_lock);
error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_SHUTDOWN, NULL, 0);
if (error) {
@@ -1285,12 +1300,6 @@ mfi_shutdown(struct mfi_softc *sc)
return (error);
}
- if (sc->mfi_aen_cm != NULL)
- mfi_abort(sc, sc->mfi_aen_cm);
-
- if (sc->mfi_map_sync_cm != NULL)
- mfi_abort(sc, sc->mfi_map_sync_cm);
-
dcmd = &cm->cm_frame->dcmd;
dcmd->header.flags = MFI_FRAME_DIR_NONE;
cm->cm_flags = MFI_CMD_POLLED;
@@ -1312,6 +1321,7 @@ mfi_syspdprobe(struct mfi_softc *sc)
struct mfi_command *cm = NULL;
struct mfi_pd_list *pdlist = NULL;
struct mfi_system_pd *syspd, *tmp;
+ struct mfi_system_pending *syspd_pend;
int error, i, found;
sx_assert(&sc->mfi_config_lock, SA_XLOCKED);
@@ -1352,6 +1362,10 @@ mfi_syspdprobe(struct mfi_softc *sc)
if (syspd->pd_id == pdlist->addr[i].device_id)
found = 1;
}
+ TAILQ_FOREACH(syspd_pend, &sc->mfi_syspd_pend_tqh, pd_link) {
+ if (syspd_pend->pd_id == pdlist->addr[i].device_id)
+ found = 1;
+ }
if (found == 0)
mfi_add_sys_pd(sc, pdlist->addr[i].device_id);
}
@@ -1387,6 +1401,7 @@ mfi_ldprobe(struct mfi_softc *sc)
struct mfi_command *cm = NULL;
struct mfi_ld_list *list = NULL;
struct mfi_disk *ld;
+ struct mfi_disk_pending *ld_pend;
int error, i;
sx_assert(&sc->mfi_config_lock, SA_XLOCKED);
@@ -1415,6 +1430,10 @@ mfi_ldprobe(struct mfi_softc *sc)
if (ld->ld_id == list->ld_list[i].ld.v.target_id)
goto skip_add;
}
+ TAILQ_FOREACH(ld_pend, &sc->mfi_ld_pend_tqh, ld_link) {
+ if (ld_pend->ld_id == list->ld_list[i].ld.v.target_id)
+ goto skip_add;
+ }
mfi_add_ld(sc, list->ld_list[i].ld.v.target_id);
skip_add:;
}
@@ -1617,9 +1636,7 @@ mfi_aen_register(struct mfi_softc *sc, int seq, in
< current_aen.members.evt_class)
current_aen.members.evt_class =
prior_aen.members.evt_class;
- mtx_lock(&sc->mfi_io_lock);
- mfi_abort(sc, sc->mfi_aen_cm);
- mtx_unlock(&sc->mfi_io_lock);
+ mfi_abort(sc, &sc->mfi_aen_cm);
}
}
@@ -1811,10 +1828,17 @@ mfi_add_ld(struct mfi_softc *sc, int id)
struct mfi_command *cm;
struct mfi_dcmd_frame *dcmd = NULL;
struct mfi_ld_info *ld_info = NULL;
+ struct mfi_disk_pending *ld_pend;
int error;
mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+ ld_pend = malloc(sizeof(*ld_pend), M_MFIBUF, M_NOWAIT | M_ZERO);
+ if (ld_pend != NULL) {
+ ld_pend->ld_id = id;
+ TAILQ_INSERT_TAIL(&sc->mfi_ld_pend_tqh, ld_pend, ld_link);
+ }
+
error = mfi_dcmd_command(sc, &cm, MFI_DCMD_LD_GET_INFO,
(void **)&ld_info, sizeof(*ld_info));
if (error) {
@@ -1855,11 +1879,13 @@ mfi_add_ld_complete(struct mfi_command *cm)
hdr = &cm->cm_frame->header;
ld_info = cm->cm_private;
- if (hdr->cmd_status != MFI_STAT_OK) {
+ if (sc->cm_map_abort || hdr->cmd_status != MFI_STAT_OK) {
free(ld_info, M_MFIBUF);
+ wakeup(&sc->mfi_map_sync_cm);
mfi_release_command(cm);
return;
}
+ wakeup(&sc->mfi_map_sync_cm);
mfi_release_command(cm);
mtx_unlock(&sc->mfi_io_lock);
@@ -1884,10 +1910,17 @@ static int mfi_add_sys_pd(struct mfi_softc *sc, in
struct mfi_command *cm;
struct mfi_dcmd_frame *dcmd = NULL;
struct mfi_pd_info *pd_info = NULL;
+ struct mfi_system_pending *syspd_pend;
int error;
mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+ syspd_pend = malloc(sizeof(*syspd_pend), M_MFIBUF, M_NOWAIT | M_ZERO);
+ if (syspd_pend != NULL) {
+ syspd_pend->pd_id = id;
+ TAILQ_INSERT_TAIL(&sc->mfi_syspd_pend_tqh, syspd_pend, pd_link);
+ }
+
error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_GET_INFO,
(void **)&pd_info, sizeof(*pd_info));
if (error) {
@@ -1981,19 +2014,87 @@ mfi_bio_command(struct mfi_softc *sc)
mfi_enqueue_bio(sc, bio);
return cm;
}
+
+/*
+ * mostly copied from cam/scsi/scsi_all.c:scsi_read_write
+ */
+
+int
+mfi_build_cdb(int readop, uint8_t byte2, u_int64_t lba, u_int32_t block_count, uint8_t *cdb)
+{
+ int cdb_len;
+
+ if (((lba & 0x1fffff) == lba)
+ && ((block_count & 0xff) == block_count)
+ && (byte2 == 0)) {
+ /* We can fit in a 6 byte cdb */
+ struct scsi_rw_6 *scsi_cmd;
+
+ scsi_cmd = (struct scsi_rw_6 *)cdb;
+ scsi_cmd->opcode = readop ? READ_6 : WRITE_6;
+ scsi_ulto3b(lba, scsi_cmd->addr);
+ scsi_cmd->length = block_count & 0xff;
+ scsi_cmd->control = 0;
+ cdb_len = sizeof(*scsi_cmd);
+ } else if (((block_count & 0xffff) == block_count) && ((lba & 0xffffffff) == lba)) {
+ /* Need a 10 byte CDB */
+ struct scsi_rw_10 *scsi_cmd;
+
+ scsi_cmd = (struct scsi_rw_10 *)cdb;
+ scsi_cmd->opcode = readop ? READ_10 : WRITE_10;
+ scsi_cmd->byte2 = byte2;
+ scsi_ulto4b(lba, scsi_cmd->addr);
+ scsi_cmd->reserved = 0;
+ scsi_ulto2b(block_count, scsi_cmd->length);
+ scsi_cmd->control = 0;
+ cdb_len = sizeof(*scsi_cmd);
+ } else if (((block_count & 0xffffffff) == block_count) &&
+ ((lba & 0xffffffff) == lba)) {
+ /* Block count is too big for 10 byte CDB use a 12 byte CDB */
+ struct scsi_rw_12 *scsi_cmd;
+
+ scsi_cmd = (struct scsi_rw_12 *)cdb;
+ scsi_cmd->opcode = readop ? READ_12 : WRITE_12;
+ scsi_cmd->byte2 = byte2;
+ scsi_ulto4b(lba, scsi_cmd->addr);
+ scsi_cmd->reserved = 0;
+ scsi_ulto4b(block_count, scsi_cmd->length);
+ scsi_cmd->control = 0;
+ cdb_len = sizeof(*scsi_cmd);
+ } else {
+ /*
+ * 16 byte CDB. We'll only get here if the LBA is larger
+ * than 2^32
+ */
+ struct scsi_rw_16 *scsi_cmd;
+
+ scsi_cmd = (struct scsi_rw_16 *)cdb;
+ scsi_cmd->opcode = readop ? READ_16 : WRITE_16;
+ scsi_cmd->byte2 = byte2;
+ scsi_u64to8b(lba, scsi_cmd->addr);
+ scsi_cmd->reserved = 0;
+ scsi_ulto4b(block_count, scsi_cmd->length);
+ scsi_cmd->control = 0;
+ cdb_len = sizeof(*scsi_cmd);
+ }
+
+ return cdb_len;
+}
+
static struct mfi_command *
mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
{
struct mfi_command *cm;
struct mfi_pass_frame *pass;
- int flags = 0, blkcount = 0;
uint32_t context = 0;
+ int flags = 0, blkcount = 0, readop;
+ uint8_t cdb_len;
if ((cm = mfi_dequeue_free(sc)) == NULL)
return (NULL);
/* Zero out the MFI frame */
- context = cm->cm_frame->header.context;
+ context = cm->cm_frame->header.context;
bzero(cm->cm_frame, sizeof(union mfi_frame));
cm->cm_frame->header.context = context;
pass = &cm->cm_frame->pass;
@@ -2001,35 +2102,31 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio
pass->header.cmd = MFI_CMD_PD_SCSI_IO;
switch (bio->bio_cmd & 0x03) {
case BIO_READ:
-#define SCSI_READ 0x28
- pass->cdb[0] = SCSI_READ;
flags = MFI_CMD_DATAIN;
+ readop = 1;
break;
case BIO_WRITE:
-#define SCSI_WRITE 0x2a
- pass->cdb[0] = SCSI_WRITE;
flags = MFI_CMD_DATAOUT;
+ readop = 0;
break;
default:
- panic("Invalid bio command");
+ /* TODO: what about BIO_DELETE??? */
+ panic("Unsupported bio command %x\n", bio->bio_cmd);
}
/* Cheat with the sector length to avoid a non-constant division */
blkcount = (bio->bio_bcount + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN;
/* Fill the LBA and Transfer length in CDB */
- pass->cdb[2] = (bio->bio_pblkno & 0xff000000) >> 24;
- pass->cdb[3] = (bio->bio_pblkno & 0x00ff0000) >> 16;
- pass->cdb[4] = (bio->bio_pblkno & 0x0000ff00) >> 8;
- pass->cdb[5] = bio->bio_pblkno & 0x000000ff;
- pass->cdb[7] = (blkcount & 0xff00) >> 8;
- pass->cdb[8] = (blkcount & 0x00ff);
+ cdb_len = mfi_build_cdb(readop, 0, bio->bio_pblkno, blkcount,
+ pass->cdb);
pass->header.target_id = (uintptr_t)bio->bio_driver1;
+ pass->header.lun_id = 0;
pass->header.timeout = 0;
pass->header.flags = 0;
pass->header.scsi_status = 0;
pass->header.sense_len = MFI_SENSE_LEN;
pass->header.data_len = bio->bio_bcount;
- pass->header.cdb_len = 10;
+ pass->header.cdb_len = cdb_len;
pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
cm->cm_complete = mfi_bio_complete;
@@ -2047,7 +2144,8 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *b
{
struct mfi_io_frame *io;
struct mfi_command *cm;
- int flags, blkcount;
+ int flags;
+ uint32_t blkcount;
uint32_t context = 0;
if ((cm = mfi_dequeue_free(sc)) == NULL)
@@ -2068,7 +2166,8 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *b
flags = MFI_CMD_DATAOUT;
break;
default:
- panic("Invalid bio command");
+ /* TODO: what about BIO_DELETE??? */
+ panic("Unsupported bio command %x\n", bio->bio_cmd);
}
/* Cheat with the sector length to avoid a non-constant division */
@@ -2358,7 +2457,7 @@ mfi_complete(struct mfi_softc *sc, struct mfi_comm
}
static int
-mfi_abort(struct mfi_softc *sc, struct mfi_command *cm_abort)
+mfi_abort(struct mfi_softc *sc, struct mfi_command **cm_abort)
{
struct mfi_command *cm;
struct mfi_abort_frame *abort;
@@ -2365,8 +2464,7 @@ static int
int i = 0;
uint32_t context = 0;
- mtx_assert(&sc->mfi_io_lock, MA_OWNED);
-
+ mtx_lock(&sc->mfi_io_lock);
if ((cm = mfi_dequeue_free(sc)) == NULL) {
return (EBUSY);
}
@@ -2380,29 +2478,27 @@ static int
abort->header.cmd = MFI_CMD_ABORT;
abort->header.flags = 0;
abort->header.scsi_status = 0;
- abort->abort_context = cm_abort->cm_frame->header.context;
- abort->abort_mfi_addr_lo = (uint32_t)cm_abort->cm_frame_busaddr;
+ abort->abort_context = (*cm_abort)->cm_frame->header.context;
+ abort->abort_mfi_addr_lo = (uint32_t)(*cm_abort)->cm_frame_busaddr;
abort->abort_mfi_addr_hi =
- (uint32_t)((uint64_t)cm_abort->cm_frame_busaddr >> 32);
+ (uint32_t)((uint64_t)(*cm_abort)->cm_frame_busaddr >> 32);
cm->cm_data = NULL;
cm->cm_flags = MFI_CMD_POLLED;
- if (sc->mfi_aen_cm)
- sc->cm_aen_abort = 1;
- if (sc->mfi_map_sync_cm)
- sc->cm_map_abort = 1;
mfi_mapcmd(sc, cm);
mfi_release_command(cm);
- while (i < 5 && sc->mfi_aen_cm != NULL) {
- msleep(&sc->mfi_aen_cm, &sc->mfi_io_lock, 0, "mfiabort",
+ mtx_unlock(&sc->mfi_io_lock);
+ while (i < 5 && *cm_abort != NULL) {
+ tsleep(cm_abort, 0, "mfiabort",
5 * hz);
i++;
}
- while (i < 5 && sc->mfi_map_sync_cm != NULL) {
- msleep(&sc->mfi_map_sync_cm, &sc->mfi_io_lock, 0, "mfiabort",
- 5 * hz);
- i++;
+ if (*cm_abort != NULL) {
+ /* Force a complete if command didn't abort */
+ mtx_lock(&sc->mfi_io_lock);
+ (*cm_abort)->cm_complete(*cm_abort);
+ mtx_unlock(&sc->mfi_io_lock);
}
return (0);
@@ -2458,8 +2554,8 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id
{
struct mfi_command *cm;
struct mfi_pass_frame *pass;
- int error;
- int blkcount = 0;
+ int error, readop, cdb_len;
+ uint32_t blkcount;
if ((cm = mfi_dequeue_free(sc)) == NULL)
return (EBUSY);
@@ -2467,14 +2563,10 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id
pass = &cm->cm_frame->pass;
bzero(pass->cdb, 16);
pass->header.cmd = MFI_CMD_PD_SCSI_IO;
- pass->cdb[0] = SCSI_WRITE;
- pass->cdb[2] = (lba & 0xff000000) >> 24;
- pass->cdb[3] = (lba & 0x00ff0000) >> 16;
- pass->cdb[4] = (lba & 0x0000ff00) >> 8;
- pass->cdb[5] = (lba & 0x000000ff);
+
+ readop = 0;
blkcount = (len + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN;
- pass->cdb[7] = (blkcount & 0xff00) >> 8;
- pass->cdb[8] = (blkcount & 0x00ff);
+ cdb_len = mfi_build_cdb(readop, 0, lba, blkcount, pass->cdb);
pass->header.target_id = id;
pass->header.timeout = 0;
pass->header.flags = 0;
@@ -2481,7 +2573,7 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id
pass->header.scsi_status = 0;
pass->header.sense_len = MFI_SENSE_LEN;
pass->header.data_len = len;
- pass->header.cdb_len = 10;
+ pass->header.cdb_len = cdb_len;
pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
cm->cm_data = virt;
@@ -2488,7 +2580,7 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id
cm->cm_len = len;
cm->cm_sg = &pass->sgl;
cm->cm_total_frame_size = MFI_PASS_FRAME_SIZE;
- cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT;
+ cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT | MFI_CMD_SCSI;
error = mfi_mapcmd(sc, cm);
bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
@@ -2687,16 +2779,24 @@ mfi_check_command_post(struct mfi_softc *sc, struc
}
}
-static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm)
+static int
+mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm)
{
- struct mfi_config_data *conf_data=(struct mfi_config_data *)cm->cm_data;
+ struct mfi_config_data *conf_data;
struct mfi_command *ld_cm = NULL;
struct mfi_ld_info *ld_info = NULL;
+ struct mfi_ld_config *ld;
+ char *p;
int error = 0;
- if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) &&
- (conf_data->ld[0].params.isSSCD == 1)) {
- error = 1;
+ conf_data = (struct mfi_config_data *)cm->cm_data;
+
+ if (cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) {
+ p = (char *)conf_data->array;
+ p += conf_data->array_size * conf_data->array_count;
+ ld = (struct mfi_ld_config *)p;
+ if (ld->params.isSSCD == 1)
+ error = 1;
} else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) {
error = mfi_dcmd_command (sc, &ld_cm, MFI_DCMD_LD_GET_INFO,
(void **)&ld_info, sizeof(*ld_info));
Index: sys/dev/mfi/mfi_cam.c
===================================================================
--- sys/dev/mfi/mfi_cam.c (revision 254079)
+++ sys/dev/mfi/mfi_cam.c (working copy)
@@ -79,6 +79,11 @@ static void mfip_cam_poll(struct cam_sim *);
static struct mfi_command * mfip_start(void *);
static void mfip_done(struct mfi_command *cm);
+static int mfi_allow_disks = 0;
+TUNABLE_INT("hw.mfi.allow_cam_disk_passthrough", &mfi_allow_disks);
+SYSCTL_INT(_hw_mfi, OID_AUTO, allow_cam_disk_passthrough, CTLFLAG_RD,
+ &mfi_allow_disks, 0, "event message locale");
+
static devclass_t mfip_devclass;
static device_method_t mfip_methods[] = {
DEVMETHOD(device_probe, mfip_probe),
@@ -349,7 +354,8 @@ mfip_done(struct mfi_command *cm)
command = csio->cdb_io.cdb_bytes[0];
if (command == INQUIRY) {
device = csio->data_ptr[0] & 0x1f;
- if ((device == T_DIRECT) || (device == T_PROCESSOR))
+ if ((!mfi_allow_disks && device == T_DIRECT) ||
+ (device == T_PROCESSOR))
csio->data_ptr[0] =
(csio->data_ptr[0] & 0xe0) | T_NODEVICE;
}
@@ -392,6 +398,9 @@ mfip_done(struct mfi_command *cm)
static void
mfip_cam_poll(struct cam_sim *sim)
{
- return;
+ struct mfip_softc *sc = cam_sim_softc(sim);
+ struct mfi_softc *mfisc = sc->mfi_sc;
+
+ mfisc->mfi_intr_ptr(mfisc);
}
Index: sys/dev/mfi/mfi_disk.c
===================================================================
--- sys/dev/mfi/mfi_disk.c (revision 254079)
+++ sys/dev/mfi/mfi_disk.c (working copy)
@@ -93,6 +93,7 @@ mfi_disk_attach(device_t dev)
{
struct mfi_disk *sc;
struct mfi_ld_info *ld_info;
+ struct mfi_disk_pending *ld_pend;
uint64_t sectors;
uint32_t secsize;
char *state;
@@ -111,6 +112,13 @@ mfi_disk_attach(device_t dev)
secsize = MFI_SECTOR_LEN;
mtx_lock(&sc->ld_controller->mfi_io_lock);
TAILQ_INSERT_TAIL(&sc->ld_controller->mfi_ld_tqh, sc, ld_link);
+ TAILQ_FOREACH(ld_pend, &sc->ld_controller->mfi_ld_pend_tqh,
+ ld_link) {
+ TAILQ_REMOVE(&sc->ld_controller->mfi_ld_pend_tqh,
+ ld_pend, ld_link);
+ free(ld_pend, M_MFIBUF);
+ break;
+ }
mtx_unlock(&sc->ld_controller->mfi_io_lock);
switch (ld_info->ld_config.params.state) {
@@ -131,16 +139,16 @@ mfi_disk_attach(device_t dev)
break;
}
- if ( strlen(ld_info->ld_config.properties.name) == 0 ) {
- device_printf(dev,
- "%juMB (%ju sectors) RAID volume (no label) is %s\n",
- sectors / (1024 * 1024 / secsize), sectors, state);
- } else {
- device_printf(dev,
- "%juMB (%ju sectors) RAID volume '%s' is %s\n",
- sectors / (1024 * 1024 / secsize), sectors,
- ld_info->ld_config.properties.name, state);
- }
+ if ( strlen(ld_info->ld_config.properties.name) == 0 ) {
+ device_printf(dev,
+ "%juMB (%ju sectors) RAID volume (no label) is %s\n",
+ sectors / (1024 * 1024 / secsize), sectors, state);
+ } else {
+ device_printf(dev,
+ "%juMB (%ju sectors) RAID volume '%s' is %s\n",
+ sectors / (1024 * 1024 / secsize), sectors,
+ ld_info->ld_config.properties.name, state);
+ }
sc->ld_disk = disk_alloc();
sc->ld_disk->d_drv1 = sc;
Index: sys/dev/mfi/mfi_syspd.c
===================================================================
--- sys/dev/mfi/mfi_syspd.c (revision 254079)
+++ sys/dev/mfi/mfi_syspd.c (working copy)
@@ -89,7 +89,6 @@ DRIVER_MODULE(mfisyspd, mfi, mfi_syspd_driver, mfi
static int
mfi_syspd_probe(device_t dev)
{
-
return (0);
}
@@ -98,12 +97,12 @@ mfi_syspd_attach(device_t dev)
{
struct mfi_system_pd *sc;
struct mfi_pd_info *pd_info;
+ struct mfi_system_pending *syspd_pend;
uint64_t sectors;
uint32_t secsize;
sc = device_get_softc(dev);
pd_info = device_get_ivars(dev);
-
sc->pd_dev = dev;
sc->pd_id = pd_info->ref.v.device_id;
sc->pd_unit = device_get_unit(dev);
@@ -115,6 +114,13 @@ mfi_syspd_attach(device_t dev)
secsize = MFI_SECTOR_LEN;
mtx_lock(&sc->pd_controller->mfi_io_lock);
TAILQ_INSERT_TAIL(&sc->pd_controller->mfi_syspd_tqh, sc, pd_link);
+ TAILQ_FOREACH(syspd_pend, &sc->pd_controller->mfi_syspd_pend_tqh,
+ pd_link) {
+ TAILQ_REMOVE(&sc->pd_controller->mfi_syspd_pend_tqh,
+ syspd_pend, pd_link);
+ free(syspd_pend, M_MFIBUF);
+ break;
+ }
mtx_unlock(&sc->pd_controller->mfi_io_lock);
device_printf(dev, "%juMB (%ju sectors) SYSPD volume\n",
sectors / (1024 * 1024 / secsize), sectors);
@@ -139,6 +145,7 @@ mfi_syspd_attach(device_t dev)
disk_create(sc->pd_disk, DISK_VERSION);
device_printf(dev, " SYSPD volume attached\n");
+
return (0);
}
Index: sys/dev/mfi/mfi_tbolt.c
===================================================================
--- sys/dev/mfi/mfi_tbolt.c (revision 254079)
+++ sys/dev/mfi/mfi_tbolt.c (working copy)
@@ -69,13 +69,10 @@ uint8_t
mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd);
union mfi_mpi2_request_descriptor *mfi_build_and_issue_cmd(struct mfi_softc
*sc, struct mfi_command *mfi_cmd);
-int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd);
void mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
struct mfi_cmd_tbolt *cmd);
static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command
*mfi_cmd, pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd);
-static int mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command
- *mfi_cmd, uint8_t *cdb);
void
map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
uint8_t ext_status);
@@ -502,6 +499,7 @@ mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
+ i * MEGASAS_MAX_SZ_CHAIN_FRAME);
cmd->sg_frame_phys_addr = sc->sg_frame_busaddr + i
* MEGASAS_MAX_SZ_CHAIN_FRAME;
+ cmd->sync_cmd_idx = sc->mfi_max_fw_cmds;
TAILQ_INSERT_TAIL(&(sc->mfi_cmd_tbolt_tqh), cmd, next);
}
@@ -574,11 +572,11 @@ void
map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
uint8_t ext_status)
{
-
switch (status) {
case MFI_STAT_OK:
- mfi_cmd->cm_frame->header.cmd_status = 0;
- mfi_cmd->cm_frame->dcmd.header.cmd_status = 0;
+ mfi_cmd->cm_frame->header.cmd_status = MFI_STAT_OK;
+ mfi_cmd->cm_frame->dcmd.header.cmd_status = MFI_STAT_OK;
+ mfi_cmd->cm_error = MFI_STAT_OK;
break;
case MFI_STAT_SCSI_IO_FAILED:
@@ -618,6 +616,7 @@ mfi_tbolt_return_cmd(struct mfi_softc *sc, struct
{
mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+ cmd->sync_cmd_idx = sc->mfi_max_fw_cmds;
TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next);
}
@@ -667,16 +666,26 @@ mfi_tbolt_complete_cmd(struct mfi_softc *sc)
extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status;
map_tbolt_cmd_status(cmd_mfi, status, extStatus);
- /* remove command from busy queue if not polled */
- TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) {
- if (cmd_mfi_check == cmd_mfi) {
- mfi_remove_busy(cmd_mfi);
- break;
+ if (cmd_mfi->cm_flags & MFI_CMD_SCSI &&
+ (cmd_mfi->cm_flags & MFI_CMD_POLLED) != 0) {
+ /* polled LD/SYSPD IO command */
+ mfi_tbolt_return_cmd(sc, cmd_tbolt);
+ /* XXX mark okay for now DJA */
+ cmd_mfi->cm_frame->header.cmd_status = MFI_STAT_OK;
+ } else {
+
+ /* remove command from busy queue if not polled */
+ TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) {
+ if (cmd_mfi_check == cmd_mfi) {
+ mfi_remove_busy(cmd_mfi);
+ break;
+ }
}
+
+ /* complete the command */
+ mfi_complete(sc, cmd_mfi);
+ mfi_tbolt_return_cmd(sc, cmd_tbolt);
}
- cmd_mfi->cm_error = 0;
- mfi_complete(sc, cmd_mfi);
- mfi_tbolt_return_cmd(sc, cmd_tbolt);
sc->last_reply_idx++;
if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) {
@@ -811,13 +820,13 @@ mfi_tbolt_build_ldio(struct mfi_softc *sc, struct
MFI_FRAME_DIR_READ)
io_info.isRead = 1;
- io_request->RaidContext.timeoutValue
- = MFI_FUSION_FP_DEFAULT_TIMEOUT;
- io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST;
- io_request->DevHandle = device_id;
- cmd->request_desc->header.RequestFlags
- = (MFI_REQ_DESCRIPT_FLAGS_LD_IO
- << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.timeoutValue
+ = MFI_FUSION_FP_DEFAULT_TIMEOUT;
+ io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
+ cmd->request_desc->header.RequestFlags
+ = (MFI_REQ_DESCRIPT_FLAGS_LD_IO
+ << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
if ((io_request->IoFlags == 6) && (io_info.numBlocks == 0))
io_request->RaidContext.RegLockLength = 0x100;
io_request->DataLength = mfi_cmd->cm_frame->io.header.data_len
@@ -825,41 +834,37 @@ mfi_tbolt_build_ldio(struct mfi_softc *sc, struct
}
int
-mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd)
-{
- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ
- || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
- return 1;
- else
- return 0;
-}
-
-int
mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
struct mfi_cmd_tbolt *cmd)
{
- uint32_t device_id;
+ struct mfi_mpi2_request_raid_scsi_io *io_request;
uint32_t sge_count;
- uint8_t cdb[32], cdb_len;
+ uint8_t cdb_len;
+ int readop;
+ u_int64_t lba;
- memset(cdb, 0, 32);
- struct mfi_mpi2_request_raid_scsi_io *io_request = cmd->io_request;
+ io_request = cmd->io_request;
+ if (!(mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ
+ || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE))
+ return 1;
- device_id = mfi_cmd->cm_frame->header.target_id;
+ mfi_tbolt_build_ldio(sc, mfi_cmd, cmd);
- /* Have to build CDB here for TB as BSD don't have a scsi layer */
- if ((cdb_len = mfi_tbolt_build_cdb(sc, mfi_cmd, cdb)) == 1)
- return 1;
+ /* Convert to SCSI command CDB */
+ bzero(io_request->CDB.CDB32, sizeof(io_request->CDB.CDB32));
+ if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+ readop = 0;
+ else
+ readop = 1;
- /* Just the CDB length,rest of the Flags are zero */
+ lba = mfi_cmd->cm_frame->io.lba_hi;
+ lba = (lba << 32) + mfi_cmd->cm_frame->io.lba_lo;
+ cdb_len = mfi_build_cdb(readop, 0, lba,
+ mfi_cmd->cm_frame->io.header.data_len, io_request->CDB.CDB32);
+
+ /* Just the CDB length, rest of the Flags are zero */
io_request->IoFlags = cdb_len;
- memcpy(io_request->CDB.CDB32, cdb, 32);
- if (mfi_tbolt_is_ldio(mfi_cmd))
- mfi_tbolt_build_ldio(sc, mfi_cmd , cmd);
- else
- return 1;
-
/*
* Construct SGL
*/
@@ -883,85 +888,13 @@ mfi_tbolt_build_io(struct mfi_softc *sc, struct mf
io_request->SenseBufferLowAddress = mfi_cmd->cm_sense_busaddr;
io_request->SenseBufferLength = MFI_SENSE_LEN;
+ io_request->RaidContext.Status = MFI_STAT_INVALID_STATUS;
+ io_request->RaidContext.exStatus = MFI_STAT_INVALID_STATUS;
+
return 0;
}
-static int
-mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
- uint8_t *cdb)
-{
- uint32_t lba_lo, lba_hi, num_lba;
- uint8_t cdb_len;
- if (mfi_cmd == NULL || cdb == NULL)
- return 1;
- num_lba = mfi_cmd->cm_frame->io.header.data_len;
- lba_lo = mfi_cmd->cm_frame->io.lba_lo;
- lba_hi = mfi_cmd->cm_frame->io.lba_hi;
-
- if (lba_hi == 0 && (num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) {
- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
- /* Read 6 or Write 6 */
- cdb[0] = (uint8_t) (0x0A);
- else
- cdb[0] = (uint8_t) (0x08);
-
- cdb[4] = (uint8_t) num_lba;
- cdb[3] = (uint8_t) (lba_lo & 0xFF);
- cdb[2] = (uint8_t) (lba_lo >> 8);
- cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F);
- cdb_len = 6;
- }
- else if (lba_hi == 0 && (num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) {
- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
- /* Read 10 or Write 10 */
- cdb[0] = (uint8_t) (0x2A);
- else
- cdb[0] = (uint8_t) (0x28);
- cdb[8] = (uint8_t) (num_lba & 0xFF);
- cdb[7] = (uint8_t) (num_lba >> 8);
- cdb[5] = (uint8_t) (lba_lo & 0xFF);
- cdb[4] = (uint8_t) (lba_lo >> 8);
- cdb[3] = (uint8_t) (lba_lo >> 16);
- cdb[2] = (uint8_t) (lba_lo >> 24);
- cdb_len = 10;
- } else if ((num_lba > 0xFFFF) && (lba_hi == 0)) {
- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
- /* Read 12 or Write 12 */
- cdb[0] = (uint8_t) (0xAA);
- else
- cdb[0] = (uint8_t) (0xA8);
- cdb[9] = (uint8_t) (num_lba & 0xFF);
- cdb[8] = (uint8_t) (num_lba >> 8);
- cdb[7] = (uint8_t) (num_lba >> 16);
- cdb[6] = (uint8_t) (num_lba >> 24);
- cdb[5] = (uint8_t) (lba_lo & 0xFF);
- cdb[4] = (uint8_t) (lba_lo >> 8);
- cdb[3] = (uint8_t) (lba_lo >> 16);
- cdb[2] = (uint8_t) (lba_lo >> 24);
- cdb_len = 12;
- } else {
- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
- cdb[0] = (uint8_t) (0x8A);
- else
- cdb[0] = (uint8_t) (0x88);
- cdb[13] = (uint8_t) (num_lba & 0xFF);
- cdb[12] = (uint8_t) (num_lba >> 8);
- cdb[11] = (uint8_t) (num_lba >> 16);
- cdb[10] = (uint8_t) (num_lba >> 24);
- cdb[9] = (uint8_t) (lba_lo & 0xFF);
- cdb[8] = (uint8_t) (lba_lo >> 8);
- cdb[7] = (uint8_t) (lba_lo >> 16);
- cdb[6] = (uint8_t) (lba_lo >> 24);
- cdb[5] = (uint8_t) (lba_hi & 0xFF);
- cdb[4] = (uint8_t) (lba_hi >> 8);
- cdb[3] = (uint8_t) (lba_hi >> 16);
- cdb[2] = (uint8_t) (lba_hi >> 24);
- cdb_len = 16;
- }
- return cdb_len;
-}
-
static int
mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd)
@@ -1100,8 +1033,7 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct
if ((cm->cm_flags & MFI_CMD_POLLED) == 0) {
cm->cm_timestamp = time_uptime;
mfi_enqueue_busy(cm);
- }
- else { /* still get interrupts for it */
+ } else { /* still get interrupts for it */
hdr->cmd_status = MFI_STAT_INVALID_STATUS;
hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
}
@@ -1118,19 +1050,28 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct
}
else
device_printf(sc->mfi_dev, "DJA NA XXX SYSPDIO\n");
- }
- else if (hdr->cmd == MFI_CMD_LD_SCSI_IO ||
+ } else if (hdr->cmd == MFI_CMD_LD_SCSI_IO ||
hdr->cmd == MFI_CMD_LD_READ || hdr->cmd == MFI_CMD_LD_WRITE) {
+ cm->cm_flags |= MFI_CMD_SCSI;
if ((req_desc = mfi_build_and_issue_cmd(sc, cm)) == NULL) {
device_printf(sc->mfi_dev, "LDIO Failed \n");
return 1;
}
- } else
- if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) {
+ } else if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) {
device_printf(sc->mfi_dev, "Mapping from MFI to MPT "
"Failed\n");
return 1;
- }
+ }
+
+ if (cm->cm_flags & MFI_CMD_SCSI) {
+ /*
+ * LD IO needs to be posted since it doesn't get
+ * acknowledged via a status update so have the
+ * controller reply via mfi_tbolt_complete_cmd.
+ */
+ hdr->flags &= ~MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+ }
+
MFI_WRITE4(sc, MFI_ILQP, (req_desc->words & 0xFFFFFFFF));
MFI_WRITE4(sc, MFI_IHQP, (req_desc->words >>0x20));
@@ -1137,12 +1078,21 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct
if ((cm->cm_flags & MFI_CMD_POLLED) == 0)
return 0;
+ if (cm->cm_flags & MFI_CMD_SCSI) {
+ /* check reply queue */
+ mfi_tbolt_complete_cmd(sc);
+ }
+
/* This is a polled command, so busy-wait for it to complete. */
while (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
DELAY(1000);
tm -= 1;
if (tm <= 0)
- break;
+ break;
+ if (cm->cm_flags & MFI_CMD_SCSI) {
+ /* check reply queue */
+ mfi_tbolt_complete_cmd(sc);
+ }
}
if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
@@ -1375,7 +1325,7 @@ mfi_tbolt_sync_map_info(struct mfi_softc *sc)
free(ld_sync, M_MFIBUF);
goto out;
}
-
+
context = cmd->cm_frame->header.context;
bzero(cmd->cm_frame, sizeof(union mfi_frame));
cmd->cm_frame->header.context = context;
Index: sys/dev/mfi/mfivar.h
===================================================================
--- sys/dev/mfi/mfivar.h (revision 254079)
+++ sys/dev/mfi/mfivar.h (working copy)
@@ -105,6 +105,7 @@ struct mfi_command {
#define MFI_ON_MFIQ_READY (1<<6)
#define MFI_ON_MFIQ_BUSY (1<<7)
#define MFI_ON_MFIQ_MASK ((1<<5)|(1<<6)|(1<<7))
+#define MFI_CMD_SCSI (1<<8)
uint8_t retry_for_fw_reset;
void (* cm_complete)(struct mfi_command *cm);
void *cm_private;
@@ -125,6 +126,11 @@ struct mfi_disk {
#define MFI_DISK_FLAGS_DISABLED 0x02
};
+struct mfi_disk_pending {
+ TAILQ_ENTRY(mfi_disk_pending) ld_link;
+ int ld_id;
+};
+
struct mfi_system_pd {
TAILQ_ENTRY(mfi_system_pd) pd_link;
device_t pd_dev;
@@ -136,6 +142,11 @@ struct mfi_system_pd {
int pd_flags;
};
+struct mfi_system_pending {
+ TAILQ_ENTRY(mfi_system_pending) pd_link;
+ int pd_id;
+};
+
struct mfi_evt_queue_elm {
TAILQ_ENTRY(mfi_evt_queue_elm) link;
struct mfi_evt_detail detail;
@@ -284,6 +295,8 @@ struct mfi_softc {
TAILQ_HEAD(,mfi_disk) mfi_ld_tqh;
TAILQ_HEAD(,mfi_system_pd) mfi_syspd_tqh;
+ TAILQ_HEAD(,mfi_disk_pending) mfi_ld_pend_tqh;
+ TAILQ_HEAD(,mfi_system_pending) mfi_syspd_pend_tqh;
eventhandler_tag mfi_eh;
struct cdev *mfi_cdev;
@@ -302,6 +315,7 @@ struct mfi_softc {
uint32_t frame_cnt);
int (*mfi_adp_reset)(struct mfi_softc *sc);
int (*mfi_adp_check_reset)(struct mfi_softc *sc);
+ void (*mfi_intr_ptr)(void *sc);
/* ThunderBolt */
uint32_t mfi_tbolt;
@@ -420,7 +434,8 @@ extern int mfi_tbolt_reset(struct mfi_softc *sc);
extern void mfi_tbolt_sync_map_info(struct mfi_softc *sc);
extern void mfi_handle_map_sync(void *context, int pending);
extern int mfi_dcmd_command(struct mfi_softc *, struct mfi_command **,
- uint32_t, void **, size_t);
+ uint32_t, void **, size_t);
+extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *);
#define MFIQ_ADD(sc, qname) \
do { \

View file

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.21 (FreeBSD)
iEYEABECAAYFAlIVY24ACgkQFdaIBMps37JCXwCfZhVM1OjOQdzZpIxjNN80C1u1
JskAoJxlytTc77jV6csrcPfYIFv/oTJD
=MxiW
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,26 @@
Index: sys/netinet/in_mcast.c
===================================================================
--- sys/netinet/in_mcast.c (revision 254252)
+++ sys/netinet/in_mcast.c (working copy)
@@ -1648,6 +1648,8 @@
* has asked for, but we always tell userland how big the
* buffer really needs to be.
*/
+ if (msfr.msfr_nsrcs > in_mcast_maxsocksrc)
+ msfr.msfr_nsrcs = in_mcast_maxsocksrc;
tss = NULL;
if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) {
tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,
Index: sys/netinet6/in6_mcast.c
===================================================================
--- sys/netinet6/in6_mcast.c (revision 254252)
+++ sys/netinet6/in6_mcast.c (working copy)
@@ -1625,6 +1625,8 @@
* has asked for, but we always tell userland how big the
* buffer really needs to be.
*/
+ if (msfr.msfr_nsrcs > in6_mcast_maxsocksrc)
+ msfr.msfr_nsrcs = in6_mcast_maxsocksrc;
tss = NULL;
if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) {
tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,

View file

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.21 (FreeBSD)
iEYEABECAAYFAlIVY24ACgkQFdaIBMps37KUkgCfU1WO0UwQEQeRo+DcgCFIf6j7
R9YAn3m43TNCB0hft+Fmlt7ikftEOCoQ
=m93m
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,19 @@
Index: sys/netinet/sctp_output.c
===================================================================
--- sys/netinet/sctp_output.c (revision 254337)
+++ sys/netinet/sctp_output.c (revision 254338)
@@ -5406,6 +5406,14 @@
}
SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
+ /*
+ * We might not overwrite the identification[] completely and on
+ * some platforms time_entered will contain some padding. Therefore
+ * zero out the cookie to avoid putting uninitialized memory on the
+ * wire.
+ */
+ memset(&stc, 0, sizeof(struct sctp_state_cookie));
+
/* the time I built cookie */
(void)SCTP_GETTIME_TIMEVAL(&stc.time_entered);

View file

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.21 (FreeBSD)
iEYEABECAAYFAlIVY24ACgkQFdaIBMps37JspQCdHJl2JvDn4fmmqM8xLRJsHghE
onAAn1F8HgApNEcBndp/DlnyiSnPyBCw
=Qaow
-----END PGP SIGNATURE-----

View file

@ -7,6 +7,22 @@
<year>
<name>2013</name>
<month>
<name>8</name>
<day>
<name>22</name>
<advisory>
<name>FreeBSD-SA-13:10.sctp</name>
</advisory>
<advisory>
<name>FreeBSD-SA-13:09.ip_multicast</name>
</advisory>
</day>
</month>
<month>
<name>7</name>

View file

@ -7,6 +7,18 @@
<year>
<name>2013</name>
<month>
<name>8</name>
<day>
<name>22</name>
<notice>
<name>FreeBSD-EN-13:03.mfi</name>
</notice>
</day>
</month>
<month>
<name>6</name>