diff options
Diffstat (limited to 'drivers/tty/tty_port.c')
-rw-r--r-- | drivers/tty/tty_port.c | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 1d21a9c1d33e..4fb3165384c4 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
@@ -34,7 +34,9 @@ static int tty_port_default_receive_buf(struct tty_port *port, | |||
34 | if (!disc) | 34 | if (!disc) |
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | mutex_lock(&tty->atomic_write_lock); | ||
37 | ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); | 38 | ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); |
39 | mutex_unlock(&tty->atomic_write_lock); | ||
38 | 40 | ||
39 | tty_ldisc_deref(disc); | 41 | tty_ldisc_deref(disc); |
40 | 42 | ||
@@ -129,19 +131,85 @@ struct device *tty_port_register_device_attr(struct tty_port *port, | |||
129 | struct device *device, void *drvdata, | 131 | struct device *device, void *drvdata, |
130 | const struct attribute_group **attr_grp) | 132 | const struct attribute_group **attr_grp) |
131 | { | 133 | { |
134 | tty_port_link_device(port, driver, index); | ||
135 | return tty_register_device_attr(driver, index, device, drvdata, | ||
136 | attr_grp); | ||
137 | } | ||
138 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr); | ||
139 | |||
140 | /** | ||
141 | * tty_port_register_device_attr_serdev - register tty or serdev device | ||
142 | * @port: tty_port of the device | ||
143 | * @driver: tty_driver for this device | ||
144 | * @index: index of the tty | ||
145 | * @device: parent if exists, otherwise NULL | ||
146 | * @drvdata: driver data for the device | ||
147 | * @attr_grp: attribute group for the device | ||
148 | * | ||
149 | * Register a serdev or tty device depending on if the parent device has any | ||
150 | * defined serdev clients or not. | ||
151 | */ | ||
152 | struct device *tty_port_register_device_attr_serdev(struct tty_port *port, | ||
153 | struct tty_driver *driver, unsigned index, | ||
154 | struct device *device, void *drvdata, | ||
155 | const struct attribute_group **attr_grp) | ||
156 | { | ||
132 | struct device *dev; | 157 | struct device *dev; |
133 | 158 | ||
134 | tty_port_link_device(port, driver, index); | 159 | tty_port_link_device(port, driver, index); |
135 | 160 | ||
136 | dev = serdev_tty_port_register(port, device, driver, index); | 161 | dev = serdev_tty_port_register(port, device, driver, index); |
137 | if (PTR_ERR(dev) != -ENODEV) | 162 | if (PTR_ERR(dev) != -ENODEV) { |
138 | /* Skip creating cdev if we registered a serdev device */ | 163 | /* Skip creating cdev if we registered a serdev device */ |
139 | return dev; | 164 | return dev; |
165 | } | ||
140 | 166 | ||
141 | return tty_register_device_attr(driver, index, device, drvdata, | 167 | return tty_register_device_attr(driver, index, device, drvdata, |
142 | attr_grp); | 168 | attr_grp); |
143 | } | 169 | } |
144 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr); | 170 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev); |
171 | |||
172 | /** | ||
173 | * tty_port_register_device_serdev - register tty or serdev device | ||
174 | * @port: tty_port of the device | ||
175 | * @driver: tty_driver for this device | ||
176 | * @index: index of the tty | ||
177 | * @device: parent if exists, otherwise NULL | ||
178 | * | ||
179 | * Register a serdev or tty device depending on if the parent device has any | ||
180 | * defined serdev clients or not. | ||
181 | */ | ||
182 | struct device *tty_port_register_device_serdev(struct tty_port *port, | ||
183 | struct tty_driver *driver, unsigned index, | ||
184 | struct device *device) | ||
185 | { | ||
186 | return tty_port_register_device_attr_serdev(port, driver, index, | ||
187 | device, NULL, NULL); | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(tty_port_register_device_serdev); | ||
190 | |||
191 | /** | ||
192 | * tty_port_unregister_device - deregister a tty or serdev device | ||
193 | * @port: tty_port of the device | ||
194 | * @driver: tty_driver for this device | ||
195 | * @index: index of the tty | ||
196 | * | ||
197 | * If a tty or serdev device is registered with a call to | ||
198 | * tty_port_register_device_serdev() then this function must be called when | ||
199 | * the device is gone. | ||
200 | */ | ||
201 | void tty_port_unregister_device(struct tty_port *port, | ||
202 | struct tty_driver *driver, unsigned index) | ||
203 | { | ||
204 | int ret; | ||
205 | |||
206 | ret = serdev_tty_port_unregister(port); | ||
207 | if (ret == 0) | ||
208 | return; | ||
209 | |||
210 | tty_unregister_device(driver, index); | ||
211 | } | ||
212 | EXPORT_SYMBOL_GPL(tty_port_unregister_device); | ||
145 | 213 | ||
146 | int tty_port_alloc_xmit_buf(struct tty_port *port) | 214 | int tty_port_alloc_xmit_buf(struct tty_port *port) |
147 | { | 215 | { |
@@ -189,9 +257,6 @@ static void tty_port_destructor(struct kref *kref) | |||
189 | /* check if last port ref was dropped before tty release */ | 257 | /* check if last port ref was dropped before tty release */ |
190 | if (WARN_ON(port->itty)) | 258 | if (WARN_ON(port->itty)) |
191 | return; | 259 | return; |
192 | |||
193 | serdev_tty_port_unregister(port); | ||
194 | |||
195 | if (port->xmit_buf) | 260 | if (port->xmit_buf) |
196 | free_page((unsigned long)port->xmit_buf); | 261 | free_page((unsigned long)port->xmit_buf); |
197 | tty_port_destroy(port); | 262 | tty_port_destroy(port); |