RE: [Q]staging/comedi: Considation of *_find_boardinfo possible?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday, January 30, 2013 4:04 AM, Ian Abbott wrote:
> One way is to enumerate the possible indices of the custom board array 
> as a set of enum constants, initialize the custom board array using 
> designated element initializers (indexed by the enum constants) and 
> include the same enum constant in the 'driver_data' member of the struct 
> pci_device_id elements of the module's PCI device table.  Then the 
> module's PCI driver's probe function can index directly into the custom 
> board array without searching.

Ian,

The method you describe is what I was also considering. The only
problem is it will introduce a lot of churn in the drivers.

I'm hoping to eliminate all the unnecessary boardinfo's from the
drivers before going down this path.

> The missing link in the above is passing the index from the 
> 'driver_data' through to the modules' comedi_driver's 'auto_attach' 
> function. The 'comedi_pci_auto_config()' function does not currently 
> have a parameter for passing this information, but the underlying 
> 'comedi_auto_config()' function does.  Either the existing 
> 'comedi_pci_auto_config()' function could be extended, or a separate 
> extended version of the function could be added (maybe as an inline 
> function in comedidev.h), or the modules could call 
> 'comedi_auto_config()' directly.
>
> We have posted patches to add extra context to 
> 'comedi_pci_auto_config()' before, but they weren't applied because we 
> didn't have a clear use case for them.  Now we have, but I wouldn't mind 
> leaving the existing function alone and adding a new one.

Yah, that was the intention of my patches. They just weren't clear. Also,
my patches changed the type on the 'context' which appears to not be
needed.

> The nice thing is that it's all under the control of the individual drivers.
>
> Here's some code to illustrate what I'm on about in the above description:
>
> struct foobar_board {
>	const char *name;
>	unsigned int ai_chans;
>	unsigned int ai_bits;
> };

I would also like to make a common "boardinfo" struct that the comedi
core can then use in the comedi_recognize() and comedi_report_boards()
functions to remove the need for the pointer math. Something like:

struct comedi_board {
	const char *name;
	const void *private;
};

The comedi_driver then could be changed to:

+	const struct comedi_board *boards;
-	/* number of elements in board_name and board_id arrays */
-	unsigned int num_names;
-	const char *const *board_name;
-	/* offset in bytes from one board name pointer to the next */
-	int offset;
};

The board_ptr in comedi_device would then change to:

+	const struct comedi_board *board_ptr;
-	const void *board_ptr;

The comedi_board() helper would also need changed:

static inline const void *comedi_board(const struct comedi_device *dev)
{
+	return (dev->board_ptr) ? dev->board_ptr->private : NULL;
-	return dev->board_ptr;
}

It still returns the driver specific boardinfo as a const void *.

The common comedi_board would also allow removing the board_name
from the comedi_device. A helper function could just fetch it:

static const char *comedi_board_name(struct comedi_device *dev)
{
	return (dev->board_ptr) ? dev->board_ptr->name : dev->driver->driver_name;
}

> enum foobar_board_nums {
>	bn_foo,
>	bn_bar,
>	bn_baz
> };
>
> static const struct foobar_board foobar_boards[] = {
>	[bn_foo] = {
>		.name = "foo",
>		.ai_chans = 4,
>		.ai_bits = 12,
>	},
>	[bn_bar] = {
>		.name = "bar",
>		.ai_chans = 4,
>		.ai_bits = 16,
>	},
>	[bn_baz] = {
>		.name = "baz",
>		.ai_chans = 8,
>		.ai_bits = 16,
>	},
> };

Using the common comedi_board would change this a bit:

static const struct foobar_board[] = {
	[bn_foo] = {
		.ai_chans = 4,
		.ai_bits = 12,
	},
	[bn_bar] = {
		.ai_chans = 4,
		.ai_bits = 16,
	},
	[bn_baz] = {
		.ai_chans = 8,
		.ai_bits = 16,
	},
};

static const struct comedi_board foobar_boards[] = {
	[bn_foo] = {
		.name = "foo",
		.private = &foorbar_info[bn_foo],
	},
	[bn_bar] = {
		.name = "bar",
		.private = &foorbar_info[bn_bar],
	},
	[bn_baz] = {
		.name = "baz",
		.private = &foorbar_info[bn_baz],
	},
};

Any other "common" information that the comedi core needs to
access could be added to comedi_board. All the driver specific
information stays in the private struct.

> static int foobar_auto_attach(struct comedi_device *dev,
> 			      unsigned long context_bn)
> {
>	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
>	struct foobar_board *thisboard = &foobar_boards[bn_foo];
>
>	dev->board_ptr = thisboard;	/* no searching! */

The dev->board_ptr should just be set in the comedi core before
calling the drivers auto_attach. Something like:

		comedi_set_hw_dev(comedi_dev, hardware_device);
		comedi_dev->driver = driver;
+		if (driver->boards)
+			comedi_dev->board_ptr = &driver->boards[context];
		ret = driver->auto_attach(comedi_dev, context);

Actually, if we go this route, the context should not be required in the
auto_attach since the core has already taken care of it.

Basically, once the auto_attach is called the comedi_device already has
the following fields initialized correctly:

driver		points to the comedi_driver
hw_dev	points to the underlying device (pci/usb/pcmcia/etc.)
board_name	no longer needed
board_ptr	points to the correct comedi_board 'context'

Other than that, the rest of your code follows what I'm thinking.

Opinion?

Regards,
Hartley

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux