Commit 8cde11b2 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

tty/serdev: add serdev registration interface

Add a new interface for registering a serdev controller and clients, and
a helper function to deregister serdev devices (or a tty device) that
were previously registered using the new interface.

Once every driver currently using the tty_port_register_device() helpers
have been vetted and converted to use the new serdev registration
interface (at least for deregistration), we can move serdev registration
to the current helpers and get rid of the serdev-specific functions.
Reviewed-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6bdc00d0
...@@ -250,16 +250,18 @@ struct device *serdev_tty_port_register(struct tty_port *port, ...@@ -250,16 +250,18 @@ struct device *serdev_tty_port_register(struct tty_port *port,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
void serdev_tty_port_unregister(struct tty_port *port) int serdev_tty_port_unregister(struct tty_port *port)
{ {
struct serdev_controller *ctrl = port->client_data; struct serdev_controller *ctrl = port->client_data;
struct serport *serport = serdev_controller_get_drvdata(ctrl); struct serport *serport = serdev_controller_get_drvdata(ctrl);
if (!serport) if (!serport)
return; return -ENODEV;
serdev_controller_remove(ctrl); serdev_controller_remove(ctrl);
port->client_ops = NULL; port->client_ops = NULL;
port->client_data = NULL; port->client_data = NULL;
serdev_controller_put(ctrl); serdev_controller_put(ctrl);
return 0;
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/serdev.h>
static int tty_port_default_receive_buf(struct tty_port *port, static int tty_port_default_receive_buf(struct tty_port *port,
const unsigned char *p, const unsigned char *p,
...@@ -136,6 +137,80 @@ struct device *tty_port_register_device_attr(struct tty_port *port, ...@@ -136,6 +137,80 @@ struct device *tty_port_register_device_attr(struct tty_port *port,
} }
EXPORT_SYMBOL_GPL(tty_port_register_device_attr); EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
/**
* tty_port_register_device_attr_serdev - register tty or serdev device
* @port: tty_port of the device
* @driver: tty_driver for this device
* @index: index of the tty
* @device: parent if exists, otherwise NULL
* @drvdata: driver data for the device
* @attr_grp: attribute group for the device
*
* Register a serdev or tty device depending on if the parent device has any
* defined serdev clients or not.
*/
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp)
{
struct device *dev;
tty_port_link_device(port, driver, index);
dev = serdev_tty_port_register(port, device, driver, index);
if (PTR_ERR(dev) != -ENODEV) {
/* Skip creating cdev if we registered a serdev device */
return dev;
}
return tty_register_device_attr(driver, index, device, drvdata,
attr_grp);
}
EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
/**
* tty_port_register_device_serdev - register tty or serdev device
* @port: tty_port of the device
* @driver: tty_driver for this device
* @index: index of the tty
* @device: parent if exists, otherwise NULL
*
* Register a serdev or tty device depending on if the parent device has any
* defined serdev clients or not.
*/
struct device *tty_port_register_device_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device)
{
return tty_port_register_device_attr_serdev(port, driver, index,
device, NULL, NULL);
}
EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
/**
* tty_port_unregister_device - deregister a tty or serdev device
* @port: tty_port of the device
* @driver: tty_driver for this device
* @index: index of the tty
*
* If a tty or serdev device is registered with a call to
* tty_port_register_device_serdev() then this function must be called when
* the device is gone.
*/
void tty_port_unregister_device(struct tty_port *port,
struct tty_driver *driver, unsigned index)
{
int ret;
ret = serdev_tty_port_unregister(port);
if (ret == 0)
return;
tty_unregister_device(driver, index);
}
EXPORT_SYMBOL_GPL(tty_port_unregister_device);
int tty_port_alloc_xmit_buf(struct tty_port *port) int tty_port_alloc_xmit_buf(struct tty_port *port)
{ {
/* We may sleep in get_zeroed_page() */ /* We may sleep in get_zeroed_page() */
......
...@@ -308,7 +308,7 @@ struct tty_driver; ...@@ -308,7 +308,7 @@ struct tty_driver;
struct device *serdev_tty_port_register(struct tty_port *port, struct device *serdev_tty_port_register(struct tty_port *port,
struct device *parent, struct device *parent,
struct tty_driver *drv, int idx); struct tty_driver *drv, int idx);
void serdev_tty_port_unregister(struct tty_port *port); int serdev_tty_port_unregister(struct tty_port *port);
#else #else
static inline struct device *serdev_tty_port_register(struct tty_port *port, static inline struct device *serdev_tty_port_register(struct tty_port *port,
struct device *parent, struct device *parent,
...@@ -316,7 +316,10 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port, ...@@ -316,7 +316,10 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port,
{ {
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
static inline void serdev_tty_port_unregister(struct tty_port *port) {} static inline int serdev_tty_port_unregister(struct tty_port *port)
{
return -ENODEV;
}
#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
#endif /*_LINUX_SERDEV_H */ #endif /*_LINUX_SERDEV_H */
...@@ -558,6 +558,15 @@ extern struct device *tty_port_register_device_attr(struct tty_port *port, ...@@ -558,6 +558,15 @@ extern struct device *tty_port_register_device_attr(struct tty_port *port,
struct tty_driver *driver, unsigned index, struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata, struct device *device, void *drvdata,
const struct attribute_group **attr_grp); const struct attribute_group **attr_grp);
extern struct device *tty_port_register_device_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp);
extern void tty_port_unregister_device(struct tty_port *port,
struct tty_driver *driver, unsigned index);
extern int tty_port_alloc_xmit_buf(struct tty_port *port); extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port); extern void tty_port_free_xmit_buf(struct tty_port *port);
extern void tty_port_destroy(struct tty_port *port); extern void tty_port_destroy(struct tty_port *port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment