Reliably return PCI_GETCONF_LAST_DEVICE from PCIOCGETCONF.

Previously the loop in PCIIOCGETCONF would terminate as soon as it
found enough matches.  Now it will continue iterating through the
PCI device list and only terminate if it finds another matching device
for which it has no room to store a conf structure.  This means that
PCI_GETCONF_LAST_DEVICE is reliably returned when the number of
matching devices is equal to the number of slots in the matches
buffer.  For example, if a program requests the conf structure for a
single PCI function with a specified domain/bus/slot/function it will
now get PCI_GETCONF_LAST_DEVICE instead of PCI_GETCONF_MORE_DEVS.

While here, simplify the loop conditional a bit more by explicitly
breaking out of the loop if copyout() fails and removing a redundant
i < pci_numdevs check.

Reviewed by:	vangyzen, imp
MFC after:	1 month
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D7445
This commit is contained in:
jhb 2016-08-09 17:57:11 +00:00
parent bc5282d609
commit 249c1a242e
2 changed files with 11 additions and 12 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 3, 2008
.Dd August 9, 2016
.Dt PCI 4
.Os
.Sh NAME
@ -229,7 +229,8 @@ The status tells the user the disposition of his request for a device list.
The possible status values are:
.Bl -ohang
.It PCI_GETCONF_LAST_DEVICE
This means that there are no more devices in the PCI device list after the
This means that there are no more devices in the PCI device list matching
the specified criteria after the
ones returned in the
.Va matches
buffer.
@ -245,9 +246,7 @@ and
to zero to start over at the beginning of the list.
.It PCI_GETCONF_MORE_DEVS
This tells the user that his buffer was not large enough to hold all of the
remaining devices in the device list that possibly match his criteria.
It is possible for this status to be returned, even when none of the remaining
devices in the list would match the user's criteria.
remaining devices in the device list that match his criteria.
.It PCI_GETCONF_ERROR
This indicates a general error while servicing the user's request.
If the

View File

@ -708,10 +708,9 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
* Go through the list of devices and copy out the devices
* that match the user's criteria.
*/
for (cio->num_matches = 0, error = 0, i = 0,
for (cio->num_matches = 0, i = 0,
dinfo = STAILQ_FIRST(devlist_head);
(dinfo != NULL) && (cio->num_matches < ionum) &&
(error == 0) && (i < pci_numdevs);
dinfo != NULL;
dinfo = STAILQ_NEXT(dinfo, pci_links), i++) {
if (i < cio->offset)
@ -833,11 +832,12 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
} else
#endif /* PRE7_COMPAT */
confdata = &dinfo->conf;
/* Only if we can copy it out do we count it. */
if (!(error = copyout(confdata,
error = copyout(confdata,
(caddr_t)cio->matches +
confsz * cio->num_matches, confsz)))
cio->num_matches++;
confsz * cio->num_matches, confsz);
if (error)
break;
cio->num_matches++;
}
}