diff options
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 111 |
1 files changed, 47 insertions, 64 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 87802ea8bbc8..7d207d91a6a8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -187,100 +187,92 @@ void usb_serial_put(struct usb_serial *serial) | |||
187 | * Create the termios objects for this tty. We use the default | 187 | * Create the termios objects for this tty. We use the default |
188 | * USB serial settings but permit them to be overridden by | 188 | * USB serial settings but permit them to be overridden by |
189 | * serial->type->init_termios. | 189 | * serial->type->init_termios. |
190 | * | ||
191 | * This is the first place a new tty gets used. Hence this is where we | ||
192 | * acquire references to the usb_serial structure and the driver module, | ||
193 | * where we store a pointer to the port, and where we do an autoresume. | ||
194 | * All these actions are reversed in serial_do_free(). | ||
190 | */ | 195 | */ |
191 | static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | 196 | static int serial_install(struct tty_driver *driver, struct tty_struct *tty) |
192 | { | 197 | { |
193 | int idx = tty->index; | 198 | int idx = tty->index; |
194 | struct usb_serial *serial; | 199 | struct usb_serial *serial; |
195 | int retval; | 200 | struct usb_serial_port *port; |
201 | int retval = -ENODEV; | ||
202 | |||
203 | serial = usb_serial_get_by_index(idx); | ||
204 | if (!serial) | ||
205 | return retval; | ||
206 | |||
207 | port = serial->port[idx - serial->minor]; | ||
208 | if (!port) | ||
209 | goto error_no_port; | ||
210 | if (!try_module_get(serial->type->driver.owner)) | ||
211 | goto error_module_get; | ||
212 | |||
213 | retval = usb_autopm_get_interface(serial->interface); | ||
214 | if (retval) | ||
215 | goto error_get_interface; | ||
196 | 216 | ||
197 | /* If the termios setup has yet to be done */ | 217 | /* If the termios setup has yet to be done */ |
198 | if (tty->driver->termios[idx] == NULL) { | 218 | if (tty->driver->termios[idx] == NULL) { |
199 | /* perform the standard setup */ | 219 | /* perform the standard setup */ |
200 | retval = tty_init_termios(tty); | 220 | retval = tty_init_termios(tty); |
201 | if (retval) | 221 | if (retval) |
202 | return retval; | 222 | goto error_init_termios; |
203 | /* allow the driver to update it */ | 223 | /* allow the driver to update it */ |
204 | serial = usb_serial_get_by_index(tty->index); | 224 | if (serial->type->init_termios) |
205 | if (serial) { | 225 | serial->type->init_termios(tty); |
206 | if (serial->type->init_termios) | ||
207 | serial->type->init_termios(tty); | ||
208 | usb_serial_put(serial); | ||
209 | mutex_unlock(&serial->disc_mutex); | ||
210 | } | ||
211 | } | 226 | } |
227 | mutex_unlock(&serial->disc_mutex); | ||
228 | |||
229 | tty->driver_data = port; | ||
230 | |||
212 | /* Final install (we use the default method) */ | 231 | /* Final install (we use the default method) */ |
213 | tty_driver_kref_get(driver); | 232 | tty_driver_kref_get(driver); |
214 | tty->count++; | 233 | tty->count++; |
215 | driver->ttys[idx] = tty; | 234 | driver->ttys[idx] = tty; |
216 | return 0; | 235 | return retval; |
236 | |||
237 | error_init_termios: | ||
238 | usb_autopm_put_interface(serial->interface); | ||
239 | error_get_interface: | ||
240 | module_put(serial->type->driver.owner); | ||
241 | error_module_get: | ||
242 | error_no_port: | ||
243 | usb_serial_put(serial); | ||
244 | mutex_unlock(&serial->disc_mutex); | ||
245 | return retval; | ||
217 | } | 246 | } |
218 | 247 | ||
219 | static int serial_open (struct tty_struct *tty, struct file *filp) | 248 | static int serial_open (struct tty_struct *tty, struct file *filp) |
220 | { | 249 | { |
221 | struct usb_serial *serial; | 250 | struct usb_serial *serial; |
222 | struct usb_serial_port *port; | 251 | struct usb_serial_port *port; |
223 | unsigned int portNumber; | ||
224 | int retval = 0; | 252 | int retval = 0; |
225 | int first = 0; | 253 | int first = 0; |
226 | 254 | ||
227 | dbg("%s", __func__); | 255 | dbg("%s", __func__); |
228 | 256 | ||
229 | /* get the serial object associated with this tty pointer */ | 257 | port = tty->driver_data; |
230 | serial = usb_serial_get_by_index(tty->index); | 258 | serial = port->serial; |
231 | if (!serial) { | ||
232 | tty->driver_data = NULL; | ||
233 | return -ENODEV; | ||
234 | } | ||
235 | |||
236 | portNumber = tty->index - serial->minor; | ||
237 | port = serial->port[portNumber]; | ||
238 | if (!port || serial->disconnected) | ||
239 | retval = -ENODEV; | ||
240 | /* | ||
241 | * Note: Our locking order requirement does not allow port->mutex | ||
242 | * to be acquired while serial->disc_mutex is held. | ||
243 | */ | ||
244 | mutex_unlock(&serial->disc_mutex); | ||
245 | if (retval) | ||
246 | goto bailout_serial_put; | ||
247 | 259 | ||
248 | if (mutex_lock_interruptible(&port->mutex)) { | 260 | if (mutex_lock_interruptible(&port->mutex)) |
249 | retval = -ERESTARTSYS; | 261 | return -ERESTARTSYS; |
250 | goto bailout_serial_put; | ||
251 | } | ||
252 | 262 | ||
253 | ++port->port.count; | 263 | ++port->port.count; |
254 | |||
255 | /* set up our port structure making the tty driver | ||
256 | * remember our port object, and us it */ | ||
257 | tty->driver_data = port; | ||
258 | tty_port_tty_set(&port->port, tty); | 264 | tty_port_tty_set(&port->port, tty); |
259 | 265 | ||
260 | /* If the console is attached, the device is already open */ | 266 | /* If the console is attached, the device is already open */ |
261 | if (port->port.count == 1 && !port->console) { | 267 | if (port->port.count == 1 && !port->console) { |
262 | first = 1; | 268 | first = 1; |
263 | /* lock this module before we call it | ||
264 | * this may fail, which means we must bail out, | ||
265 | * safe because we are called with BKL held */ | ||
266 | if (!try_module_get(serial->type->driver.owner)) { | ||
267 | retval = -ENODEV; | ||
268 | goto bailout_mutex_unlock; | ||
269 | } | ||
270 | |||
271 | mutex_lock(&serial->disc_mutex); | 269 | mutex_lock(&serial->disc_mutex); |
272 | if (serial->disconnected) | ||
273 | retval = -ENODEV; | ||
274 | else | ||
275 | retval = usb_autopm_get_interface(serial->interface); | ||
276 | if (retval) | ||
277 | goto bailout_module_put; | ||
278 | 270 | ||
279 | /* only call the device specific open if this | 271 | /* only call the device specific open if this |
280 | * is the first time the port is opened */ | 272 | * is the first time the port is opened */ |
281 | retval = serial->type->open(tty, port); | 273 | retval = serial->type->open(tty, port); |
282 | if (retval) | 274 | if (retval) |
283 | goto bailout_interface_put; | 275 | goto bailout_module_put; |
284 | mutex_unlock(&serial->disc_mutex); | 276 | mutex_unlock(&serial->disc_mutex); |
285 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | 277 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); |
286 | } | 278 | } |
@@ -297,18 +289,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
297 | goto bailout_mutex_unlock; | 289 | goto bailout_mutex_unlock; |
298 | /* Undo the initial port actions */ | 290 | /* Undo the initial port actions */ |
299 | mutex_lock(&serial->disc_mutex); | 291 | mutex_lock(&serial->disc_mutex); |
300 | bailout_interface_put: | ||
301 | usb_autopm_put_interface(serial->interface); | ||
302 | bailout_module_put: | 292 | bailout_module_put: |
303 | mutex_unlock(&serial->disc_mutex); | 293 | mutex_unlock(&serial->disc_mutex); |
304 | module_put(serial->type->driver.owner); | ||
305 | bailout_mutex_unlock: | 294 | bailout_mutex_unlock: |
306 | port->port.count = 0; | 295 | port->port.count = 0; |
307 | tty->driver_data = NULL; | ||
308 | tty_port_tty_set(&port->port, NULL); | ||
309 | mutex_unlock(&port->mutex); | 296 | mutex_unlock(&port->mutex); |
310 | bailout_serial_put: | ||
311 | usb_serial_put(serial); | ||
312 | return retval; | 297 | return retval; |
313 | } | 298 | } |
314 | 299 | ||
@@ -355,9 +340,6 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
355 | { | 340 | { |
356 | struct usb_serial_port *port = tty->driver_data; | 341 | struct usb_serial_port *port = tty->driver_data; |
357 | 342 | ||
358 | if (!port) | ||
359 | return; | ||
360 | |||
361 | dbg("%s - port %d", __func__, port->number); | 343 | dbg("%s - port %d", __func__, port->number); |
362 | 344 | ||
363 | if (tty_port_close_start(&port->port, tty, filp) == 0) | 345 | if (tty_port_close_start(&port->port, tty, filp) == 0) |
@@ -365,7 +347,6 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
365 | serial_do_down(port); | 347 | serial_do_down(port); |
366 | tty_port_close_end(&port->port, tty); | 348 | tty_port_close_end(&port->port, tty); |
367 | tty_port_tty_set(&port->port, NULL); | 349 | tty_port_tty_set(&port->port, NULL); |
368 | |||
369 | } | 350 | } |
370 | 351 | ||
371 | /** | 352 | /** |
@@ -386,9 +367,11 @@ static void serial_do_free(struct tty_struct *tty) | |||
386 | /* The console is magical. Do not hang up the console hardware | 367 | /* The console is magical. Do not hang up the console hardware |
387 | * or there will be tears. | 368 | * or there will be tears. |
388 | */ | 369 | */ |
389 | if (port == NULL || port->console) | 370 | if (port->console) |
390 | return; | 371 | return; |
391 | 372 | ||
373 | tty->driver_data = NULL; | ||
374 | |||
392 | serial = port->serial; | 375 | serial = port->serial; |
393 | owner = serial->type->driver.owner; | 376 | owner = serial->type->driver.owner; |
394 | 377 | ||