Re: [PATCH 2.6-git] SPI core refresh

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

 



On Thu, Dec 01, 2005 at 07:11:09PM +0300, Vitaly Wool wrote:
> The main changes are:
> 
> - Matching rmk's 2.6.14-git5+ changes for device_driver suspend and
>   resume calls
> - Matching rmk's request to get rid of device_driver's calls to
>   suspend/resume/probe/remove

Thanks.  Please see comments below though.

> +iii. struct spi_driver
> +~~~~~~~~~~~~~~~~~~~~~~
> +
> +struct spi_driver {
> +    	void* (*alloc)( size_t, int );
> +    	void  (*free)( const void* );
> +    	unsigned char* (*get_buffer)( struct spi_device*, void* );
> +    	void (*release_buffer)( struct spi_device*, unsigned char*);
> +    	void (*control)( struct spi_device*, int mode, u32 ctl );
> +        struct device_driver driver;
> +};

This doesn't appear to have been updated.

> +formed spi_driver structure:
> +	extern struct bus_type spi_bus;
> +	static struct spi_driver pnx4008_eeprom_driver = {
> +        	.driver = {
> +                   	.bus = &spi_bus,
> +                   	.name = "pnx4008-eeprom",
> +                   	.probe = pnx4008_spiee_probe,
> +                   	.remove = pnx4008_spiee_remove,
> +                   	.suspend = pnx4008_spiee_suspend,
> +                   	.resume = pnx4008_spiee_resume,
> +               	},
> +};

Ditto.

> +iv. struct spi_bus_driver
> +~~~~~~~~~~~~~~~~~~~~~~~~~
> +To handle transactions over the SPI bus, the spi_bus_driver structure must
> +be prepared and registered with core. Any transactions, either synchronous
> +or asynchronous, go through spi_bus_driver->xfer function.
> +
> +struct spi_bus_driver
> +{
> +        int (*xfer)( struct spi_msg* msgs );
> +        void (*select) ( struct spi_device* arg );
> +        void (*deselect)( struct spi_device* arg );
> +
> +	struct spi_msg *(*retrieve)( struct spi_bus_driver *this, struct spi_bus_data *bd);
> +	void (*reset)( struct spi_bus_driver *this, u32 context);
> +
> +        struct device_driver driver;
> +};

Does this need updating as well?

> +spi_bus_driver structure:
> +	static struct spi_bus_driver spipnx_driver = {
> +        .driver = {
> +                   .bus = &platform_bus_type,
> +                   .name = "spipnx",
> +                   .probe = spipnx_probe,
> +                   .remove = spipnx_remove,
> +                   .suspend = spipnx_suspend,
> +                   .resume = spipnx_resume,
> +                   },
> +        .xfer = spipnx_xfer,
> +};

>From this it looks like it does.

> +/**
> + * spi_bus_suspend - suspend all devices on the spi bus
> + *
> + * @dev: spi device to be suspended
> + * @message: PM message
> + *
> + * This function set device on SPI bus to suspended state, just like platform_bus does
> +**/
> +static int spi_bus_suspend(struct device * dev, pm_message_t message)
> +{
> +	int ret = 0;
> +
> +	if (dev && dev->driver && dev->driver->suspend ) {
> +		ret = TO_SPI_DRIVER(dev->driver)->suspend( TO_SPI_DEV(dev), message);
> +		if (ret == 0 )
> +			dev->power.power_state = message;
> +	}
> +	return ret;
> +}
> +
> +/**
> + * spi_bus_resume - resume functioning of all devices on spi bus
> + *
> + * @dev: device to resume
> + *
> + * This function resumes device on SPI bus, just like platform_bus does
> +**/
> +static int spi_bus_resume(struct device * dev)
> +{
> +	int ret = 0;
> +
> +	if (dev && dev->driver && dev->driver->suspend ) {
> +		ret = TO_SPI_DRIVER(dev->driver)->resume(TO_SPI_DEV(dev));
> +		if (ret == 0)
> +			dev->power.power_state = PMSG_ON;
> +	}
> +	return ret;
> +}

Ok, your bus_type suspend/resume methods call your spi_driver's suspend
and resume methods - good.

> +/*
> + * the functions below are wrappers for corresponding device_driver's methods
> + */
> +int spi_driver_probe (struct device *dev)
> +{
> +	struct spi_driver *sdrv = TO_SPI_DRIVER(dev->driver);
> +	struct spi_device *sdev = TO_SPI_DEV(dev);
> +
> +	return sdrv && sdrv->probe ? sdrv->probe(sdev) : -EFAULT;
> +}
> +
> +int spi_driver_remove (struct device *dev)
> +{
> +	struct spi_driver *sdrv = TO_SPI_DRIVER(dev->driver);
> +	struct spi_device *sdev = TO_SPI_DEV(dev);
> +
> +	return  (sdrv && sdrv->remove)  ? sdrv->remove(sdev) : -EFAULT;
> +}

These are fine, although sdrv will always be non-NULL here.

> +
> +void spi_driver_shutdown (struct device *dev)
> +{
> +	struct spi_driver *sdrv = TO_SPI_DRIVER(dev->driver);
> +	struct spi_device *sdev = TO_SPI_DEV(dev);
> +
> +	if (sdrv && sdrv->shutdown)
> +		sdrv->shutdown(sdev);
> +}

dev->driver may be NULL here.  If it is NULL, sdrv will not be.
Hence you want to do:

	if (dev->driver && sdrv->shutdown)

instead.

> +
> +int spi_driver_suspend (struct device *dev, pm_message_t pm)
> +{
> +	struct spi_driver *sdrv = TO_SPI_DRIVER(dev->driver);
> +	struct spi_device *sdev = TO_SPI_DEV(dev);
> +
> +	return (sdrv && sdrv->suspend) ?  sdrv->suspend(sdev, pm) : -EFAULT;
> +}
> +
> +int spi_driver_resume (struct device *dev)
> +{
> +	struct spi_driver *sdrv = TO_SPI_DRIVER(dev->driver);
> +	struct spi_device *sdev = TO_SPI_DEV(dev);
> +
> +	return (sdrv && sdrv->resume) ? sdrv->resume(sdev) : -EFAULT;
> +}

If the bus_type does not call the device_driver suspend/resume methods,
these are not necessary.

Another oddity I notice is that if there isn't a driver or method, you're
returning -EFAULT - seems odd since if there isn't a driver do you really
want to prevent suspend/resume?

> +static inline int spi_driver_add(struct spi_driver *drv)
> +{
> +	drv->driver.bus = &spi_bus;
> +	drv->driver.probe = spi_driver_probe;
> +	drv->driver.remove = spi_driver_remove;
> +	drv->driver.shutdown = spi_driver_shutdown;

> +	drv->driver.suspend = spi_driver_suspend;
> +	drv->driver.resume = spi_driver_resume;

As a result of the comment above, you don't need these two initialisers.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux