diff options
Diffstat (limited to 'drivers/tty/serdev/core.c')
-rw-r--r-- | drivers/tty/serdev/core.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index f4c6c90add78..6701d1011fce 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c | |||
@@ -116,17 +116,41 @@ void serdev_device_close(struct serdev_device *serdev) | |||
116 | } | 116 | } |
117 | EXPORT_SYMBOL_GPL(serdev_device_close); | 117 | EXPORT_SYMBOL_GPL(serdev_device_close); |
118 | 118 | ||
119 | int serdev_device_write_buf(struct serdev_device *serdev, | 119 | void serdev_device_write_wakeup(struct serdev_device *serdev) |
120 | const unsigned char *buf, size_t count) | 120 | { |
121 | complete(&serdev->write_comp); | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(serdev_device_write_wakeup); | ||
124 | |||
125 | int serdev_device_write(struct serdev_device *serdev, | ||
126 | const unsigned char *buf, size_t count, | ||
127 | unsigned long timeout) | ||
121 | { | 128 | { |
122 | struct serdev_controller *ctrl = serdev->ctrl; | 129 | struct serdev_controller *ctrl = serdev->ctrl; |
130 | int ret; | ||
123 | 131 | ||
124 | if (!ctrl || !ctrl->ops->write_buf) | 132 | if (!ctrl || !ctrl->ops->write_buf || |
133 | (timeout && !serdev->ops->write_wakeup)) | ||
125 | return -EINVAL; | 134 | return -EINVAL; |
126 | 135 | ||
127 | return ctrl->ops->write_buf(ctrl, buf, count); | 136 | mutex_lock(&serdev->write_lock); |
137 | do { | ||
138 | reinit_completion(&serdev->write_comp); | ||
139 | |||
140 | ret = ctrl->ops->write_buf(ctrl, buf, count); | ||
141 | if (ret < 0) | ||
142 | break; | ||
143 | |||
144 | buf += ret; | ||
145 | count -= ret; | ||
146 | |||
147 | } while (count && | ||
148 | (timeout = wait_for_completion_timeout(&serdev->write_comp, | ||
149 | timeout))); | ||
150 | mutex_unlock(&serdev->write_lock); | ||
151 | return ret < 0 ? ret : (count ? -ETIMEDOUT : 0); | ||
128 | } | 152 | } |
129 | EXPORT_SYMBOL_GPL(serdev_device_write_buf); | 153 | EXPORT_SYMBOL_GPL(serdev_device_write); |
130 | 154 | ||
131 | void serdev_device_write_flush(struct serdev_device *serdev) | 155 | void serdev_device_write_flush(struct serdev_device *serdev) |
132 | { | 156 | { |
@@ -232,6 +256,8 @@ struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl) | |||
232 | serdev->dev.parent = &ctrl->dev; | 256 | serdev->dev.parent = &ctrl->dev; |
233 | serdev->dev.bus = &serdev_bus_type; | 257 | serdev->dev.bus = &serdev_bus_type; |
234 | serdev->dev.type = &serdev_device_type; | 258 | serdev->dev.type = &serdev_device_type; |
259 | init_completion(&serdev->write_comp); | ||
260 | mutex_init(&serdev->write_lock); | ||
235 | return serdev; | 261 | return serdev; |
236 | } | 262 | } |
237 | EXPORT_SYMBOL_GPL(serdev_device_alloc); | 263 | EXPORT_SYMBOL_GPL(serdev_device_alloc); |