summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMagnus Damm <damm+renesas@opensource.se>2021-12-12 22:21:28 +0900
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-12-30 13:29:56 +0100
commitd8e9a406a931f687945703a4bac45042eb81ce92 (patch)
treee93562187f9adb69b1d7002ae1e1c303ec525482 /include
parentad234e2bac274a43c9fa540bde8cd9f0c627b71f (diff)
downloadlinux-d8e9a406a931f687945703a4bac45042eb81ce92.tar.bz2
serdev: BREAK/FRAME/PARITY/OVERRUN notification prototype V2
Allow serdev device drivers get notified by hardware errors such as BREAK, FRAME, PARITY and OVERRUN. With this patch, in the event of an error detected in the UART device driver the serdev_device_driver will get the newly introduced ->error() callback invoked if serdev_device_set_error_mask() has previously been used to enable the type of error. The errors are taken straight from the TTY layer and fed into the serdev_device_driver after filtering out only enabled errors. Without this patch the hardware errors never reach the serdev_device_driver. Signed-off-by: Magnus Damm <damm+renesas@opensource.se> Link: https://lore.kernel.org/r/163931528842.27756.3665040315954968747.sendpatchset@octo Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/serdev.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 3368c261ab62..0d0b22fc7e37 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -19,12 +19,15 @@ struct serdev_device;
/**
* struct serdev_device_ops - Callback operations for a serdev device
+ * @error: Function called with errors received from device;
+ * may sleep.
* @receive_buf: Function called with data received from device;
* returns number of bytes accepted; may sleep.
* @write_wakeup: Function called when ready to transmit more data; must
* not sleep.
*/
struct serdev_device_ops {
+ void (*error)(struct serdev_device *, unsigned long);
int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t);
void (*write_wakeup)(struct serdev_device *);
};
@@ -76,6 +79,11 @@ enum serdev_parity {
SERDEV_PARITY_ODD,
};
+#define SERDEV_ERROR_BREAK 0
+#define SERDEV_ERROR_FRAME 1
+#define SERDEV_ERROR_PARITY 2
+#define SERDEV_ERROR_OVERRUN 3
+
/*
* serdev controller structures
*/
@@ -85,6 +93,7 @@ struct serdev_controller_ops {
int (*write_room)(struct serdev_controller *);
int (*open)(struct serdev_controller *);
void (*close)(struct serdev_controller *);
+ void (*set_error_mask)(struct serdev_controller *, unsigned long);
void (*set_flow_control)(struct serdev_controller *, bool);
int (*set_parity)(struct serdev_controller *, enum serdev_parity);
unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
@@ -190,12 +199,24 @@ static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
return serdev->ops->receive_buf(serdev, data, count);
}
+static inline void serdev_controller_error(struct serdev_controller *ctrl,
+ unsigned long errors)
+{
+ struct serdev_device *serdev = ctrl->serdev;
+
+ if (!serdev || !serdev->ops->error)
+ return;
+
+ serdev->ops->error(serdev, errors);
+}
+
#if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
int serdev_device_open(struct serdev_device *);
void serdev_device_close(struct serdev_device *);
int devm_serdev_device_open(struct device *, struct serdev_device *);
unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
+void serdev_device_set_error_mask(struct serdev_device *, unsigned long);
void serdev_device_set_flow_control(struct serdev_device *, bool);
int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
void serdev_device_wait_until_sent(struct serdev_device *, long);
@@ -238,6 +259,7 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev
{
return 0;
}
+static inline void serdev_device_set_error_mask(struct serdev_device *sdev, unsigned long mask) {}
static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
static inline int serdev_device_write_buf(struct serdev_device *serdev,
const unsigned char *buf,