summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2016-09-30 01:13:57 +0000
committerjhb <jhb@FreeBSD.org>2016-09-30 01:13:57 +0000
commit052839dc77fe6edfe29682625c568465791c9f8f (patch)
tree763970cf0e269dc2086a290e054643da6b5f13ae /sys/dev/pci
parent9cd96c281de542b627873b9106cff2dceab6e654 (diff)
downloadFreeBSD-src-052839dc77fe6edfe29682625c568465791c9f8f.zip
FreeBSD-src-052839dc77fe6edfe29682625c568465791c9f8f.tar.gz
MFC 303881: 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. Sponsored by: Chelsio Communications
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci_user.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/sys/dev/pci/pci_user.c b/sys/dev/pci/pci_user.c
index f5a921a..dba76d1 100644
--- a/sys/dev/pci/pci_user.c
+++ b/sys/dev/pci/pci_user.c
@@ -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++;
}
}
OpenPOWER on IntegriCloud