summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2026-01-30 16:47:26 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-04-02 15:49:36 +0200
commit241cb8dee0f83856c728f4fe2c29e331386c92f2 (patch)
tree3ce78c4aea703b632dcd22299ba9bc12ddac4e76 /drivers
parent8f3481028b05e3418b6fe7119428ab44a5b2eb20 (diff)
comedi: add comedi_check_request_region()
There is an existing comedi_request_region(dev, start, len) function used by COMEDI drivers for legacy devices to request an I/O port region starting at a specified base address (which must be non-zero) and with a specified length. It uses request_region(). On success, it sets dev->iobase and dev->iolen and returns 0. There is a alternative function __comedi_request_region(dev, start, len) which does the same thing without setting dev->iobase and dev->iolen. Most hardware devices have restrictions on the allowed I/O port base address and alignment, so add new functions comedi_check_request_region(dev, start, len, minstart, maxend, minalign) and __comedi_check_request_region(dev, start, len, minstart, maxend, minalign) to perform these additional checks. Turn the original functions into static inline wrapper functions that call the new functions. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Link: https://patch.msgid.link/20260130170416.49994-2-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/comedi/drivers.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index db225a3bf012..5b02107bb6bf 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -933,19 +933,24 @@ int comedi_load_firmware(struct comedi_device *dev,
EXPORT_SYMBOL_GPL(comedi_load_firmware);
/**
- * __comedi_request_region() - Request an I/O region for a legacy driver
+ * __comedi_check_request_region() - Request an I/O region for a legacy driver
* @dev: COMEDI device.
* @start: Base address of the I/O region.
* @len: Length of the I/O region.
+ * @minstart: Minimum allowed start address of region.
+ * @maxend: Maximum allowed region end address of region.
+ * @minalign: Required alignment for base address.
*
* Requests the specified I/O port region which must start at a non-zero
- * address.
+ * address, must fall within specified bounds, and must be correctly aligned.
*
* Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
* fails.
*/
-int __comedi_request_region(struct comedi_device *dev,
- unsigned long start, unsigned long len)
+int __comedi_check_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len,
+ unsigned long minstart, unsigned long maxend,
+ unsigned long minalign)
{
if (!start) {
dev_warn(dev->class_dev,
@@ -954,6 +959,19 @@ int __comedi_request_region(struct comedi_device *dev,
return -EINVAL;
}
+ if (start < minstart || start > maxend || maxend - start < len - 1) {
+ dev_warn(dev->class_dev,
+ "%s: I/O base address or length out of range\n",
+ dev->board_name);
+ return -EINVAL;
+ }
+ if (!IS_ALIGNED(start, minalign)) {
+ dev_warn(dev->class_dev,
+ "%s: I/O base address not correctly aligned\n",
+ dev->board_name);
+ return -EINVAL;
+ }
+
if (!request_region(start, len, dev->board_name)) {
dev_warn(dev->class_dev, "%s: I/O port conflict (%#lx,%lu)\n",
dev->board_name, start, len);
@@ -962,16 +980,19 @@ int __comedi_request_region(struct comedi_device *dev,
return 0;
}
-EXPORT_SYMBOL_GPL(__comedi_request_region);
+EXPORT_SYMBOL_GPL(__comedi_check_request_region);
/**
- * comedi_request_region() - Request an I/O region for a legacy driver
+ * comedi_check_request_region() - Request an I/O region for a legacy driver
* @dev: COMEDI device.
* @start: Base address of the I/O region.
* @len: Length of the I/O region.
+ * @minstart: Minimum allowed start address of region.
+ * @maxend: Maximum allowed region end address of region.
+ * @minalign: Required alignment for base address.
*
* Requests the specified I/O port region which must start at a non-zero
- * address.
+ * address, must fall within specified bounds, and must be correctly aligned.
*
* On success, @dev->iobase is set to the base address of the region and
* @dev->iolen is set to its length.
@@ -979,12 +1000,15 @@ EXPORT_SYMBOL_GPL(__comedi_request_region);
* Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
* fails.
*/
-int comedi_request_region(struct comedi_device *dev,
- unsigned long start, unsigned long len)
+int comedi_check_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len,
+ unsigned long minstart, unsigned long maxend,
+ unsigned long minalign)
{
int ret;
- ret = __comedi_request_region(dev, start, len);
+ ret = __comedi_check_request_region(dev, start, len, minstart, maxend,
+ minalign);
if (ret == 0) {
dev->iobase = start;
dev->iolen = len;
@@ -992,7 +1016,7 @@ int comedi_request_region(struct comedi_device *dev,
return ret;
}
-EXPORT_SYMBOL_GPL(comedi_request_region);
+EXPORT_SYMBOL_GPL(comedi_check_request_region);
/**
* comedi_legacy_detach() - A generic (*detach) function for legacy drivers