mirror of https://gitee.com/openkylin/linux.git
staging: comedi: comedi_bond: use bitmap to record opened/closed minors
`do_dev_config()` currently records the comedi minor devices it has opened by setting `devs_opened[minor]` to the pointer returned by `comedi_open()`. This is checked to avoid opening the same minor device twice. The pointer values in `devs_opened[]` aren't needed; we only need to record which minor device numbers are being used. Change `devs_opened` to a bitmap (declared with `DECLARE_BITMAP()`) of length `COMEDI_NUM_BOARD_MINORS` as the minor device numbers are range-checked to fit in a bitmap of this length. Use `test_and_set_bit()` to record the minor device numbers we attempt to open with `comedi_open()`. `bonding_detach()` calls `comedi_close()` to close the comedi minor devices. Since the minor device numbers may be repeated in its list of bonded subdevices, it currently uses a simple `unsigned long devs_closed` variable as a bitmap to keep track of which minor device numbers it has already closed to avoid closing them twice. As a single `unsigned long` consists of less than `COMEDI_NUM_BOARD_MINORS` bits on a 32-bit machine, change `devs_closed to a bitmap of this length using `DECLARE_BITMAP()` and use `test_and_set_bit()` to avoid calling `comedi_close()` more than once for each minor device number in use. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8fe73691f9
commit
f59ebeda20
|
@ -190,10 +190,10 @@ static void *realloc(const void *oldmem, size_t newlen, size_t oldlen)
|
||||||
static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
|
static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct comedi_bond_private *devpriv = dev->private;
|
struct comedi_bond_private *devpriv = dev->private;
|
||||||
|
DECLARE_BITMAP(devs_opened, COMEDI_NUM_BOARD_MINORS);
|
||||||
int i;
|
int i;
|
||||||
struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS];
|
|
||||||
|
|
||||||
memset(devs_opened, 0, sizeof(devs_opened));
|
memset(&devs_opened, 0, sizeof(devs_opened));
|
||||||
devpriv->name[0] = 0;
|
devpriv->name[0] = 0;
|
||||||
/*
|
/*
|
||||||
* Loop through all comedi devices specified on the command-line,
|
* Loop through all comedi devices specified on the command-line,
|
||||||
|
@ -216,7 +216,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
"Cannot bond this driver to itself!\n");
|
"Cannot bond this driver to itself!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (devs_opened[minor]) {
|
if (test_and_set_bit(minor, devs_opened)) {
|
||||||
dev_err(dev->class_dev,
|
dev_err(dev->class_dev,
|
||||||
"Minor %d specified more than once!\n", minor);
|
"Minor %d specified more than once!\n", minor);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -225,7 +225,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
snprintf(file, sizeof(file), "/dev/comedi%u", minor);
|
snprintf(file, sizeof(file), "/dev/comedi%u", minor);
|
||||||
file[sizeof(file) - 1] = 0;
|
file[sizeof(file) - 1] = 0;
|
||||||
|
|
||||||
d = devs_opened[minor] = comedi_open(file);
|
d = comedi_open(file);
|
||||||
|
|
||||||
if (!d) {
|
if (!d) {
|
||||||
dev_err(dev->class_dev,
|
dev_err(dev->class_dev,
|
||||||
|
@ -342,19 +342,19 @@ static int bonding_attach(struct comedi_device *dev,
|
||||||
static void bonding_detach(struct comedi_device *dev)
|
static void bonding_detach(struct comedi_device *dev)
|
||||||
{
|
{
|
||||||
struct comedi_bond_private *devpriv = dev->private;
|
struct comedi_bond_private *devpriv = dev->private;
|
||||||
unsigned long devs_closed = 0;
|
|
||||||
|
|
||||||
if (devpriv) {
|
if (devpriv) {
|
||||||
|
DECLARE_BITMAP(devs_closed, COMEDI_NUM_BOARD_MINORS);
|
||||||
|
|
||||||
|
memset(&devs_closed, 0, sizeof(devs_closed));
|
||||||
while (devpriv->ndevs-- && devpriv->devs) {
|
while (devpriv->ndevs-- && devpriv->devs) {
|
||||||
struct bonded_device *bdev;
|
struct bonded_device *bdev;
|
||||||
|
|
||||||
bdev = devpriv->devs[devpriv->ndevs];
|
bdev = devpriv->devs[devpriv->ndevs];
|
||||||
if (!bdev)
|
if (!bdev)
|
||||||
continue;
|
continue;
|
||||||
if (!(devs_closed & (0x1 << bdev->minor))) {
|
if (!test_and_set_bit(bdev->minor, devs_closed))
|
||||||
comedi_close(bdev->dev);
|
comedi_close(bdev->dev);
|
||||||
devs_closed |= (0x1 << bdev->minor);
|
|
||||||
}
|
|
||||||
kfree(bdev);
|
kfree(bdev);
|
||||||
}
|
}
|
||||||
kfree(devpriv->devs);
|
kfree(devpriv->devs);
|
||||||
|
|
Loading…
Reference in New Issue