| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /****************************************************************************** |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Driver for Option High Speed Mobile Devices. |
|---|
| .. | .. |
|---|
| 10 | 11 | * <ajb@spheresystems.co.uk> |
|---|
| 11 | 12 | * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> |
|---|
| 12 | 13 | * Copyright (C) 2008 Novell, Inc. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 15 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 16 | | - * published by the Free Software Foundation. |
|---|
| 17 | | - * |
|---|
| 18 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 19 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 21 | | - * GNU General Public License for more details. |
|---|
| 22 | | - * |
|---|
| 23 | | - * You should have received a copy of the GNU General Public License |
|---|
| 24 | | - * along with this program; if not, write to the Free Software |
|---|
| 25 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
|---|
| 26 | | - * USA |
|---|
| 27 | | - * |
|---|
| 28 | 14 | * |
|---|
| 29 | 15 | *****************************************************************************/ |
|---|
| 30 | 16 | |
|---|
| .. | .. |
|---|
| 200 | 186 | int intr_completed; |
|---|
| 201 | 187 | struct usb_endpoint_descriptor *endp; |
|---|
| 202 | 188 | struct urb *urb; |
|---|
| 203 | | - struct hso_serial_state_notification serial_state_notification; |
|---|
| 189 | + struct hso_serial_state_notification *serial_state_notification; |
|---|
| 204 | 190 | u16 prev_UART_state_bitmap; |
|---|
| 205 | 191 | struct uart_icount icount; |
|---|
| 206 | 192 | }; |
|---|
| .. | .. |
|---|
| 833 | 819 | }; |
|---|
| 834 | 820 | |
|---|
| 835 | 821 | /* called when a packet did not ack after watchdogtimeout */ |
|---|
| 836 | | -static void hso_net_tx_timeout(struct net_device *net) |
|---|
| 822 | +static void hso_net_tx_timeout(struct net_device *net, unsigned int txqueue) |
|---|
| 837 | 823 | { |
|---|
| 838 | 824 | struct hso_net *odev = netdev_priv(net); |
|---|
| 839 | 825 | |
|---|
| .. | .. |
|---|
| 844 | 830 | dev_warn(&net->dev, "Tx timed out.\n"); |
|---|
| 845 | 831 | |
|---|
| 846 | 832 | /* Tear the waiting frame off the list */ |
|---|
| 847 | | - if (odev->mux_bulk_tx_urb && |
|---|
| 848 | | - (odev->mux_bulk_tx_urb->status == -EINPROGRESS)) |
|---|
| 833 | + if (odev->mux_bulk_tx_urb) |
|---|
| 849 | 834 | usb_unlink_urb(odev->mux_bulk_tx_urb); |
|---|
| 850 | 835 | |
|---|
| 851 | 836 | /* Update statistics */ |
|---|
| .. | .. |
|---|
| 1227 | 1212 | * This needs to be a tasklet otherwise we will |
|---|
| 1228 | 1213 | * end up recursively calling this function. |
|---|
| 1229 | 1214 | */ |
|---|
| 1230 | | -static void hso_unthrottle_tasklet(struct hso_serial *serial) |
|---|
| 1215 | +static void hso_unthrottle_tasklet(unsigned long data) |
|---|
| 1231 | 1216 | { |
|---|
| 1217 | + struct hso_serial *serial = (struct hso_serial *)data; |
|---|
| 1232 | 1218 | unsigned long flags; |
|---|
| 1233 | 1219 | |
|---|
| 1234 | 1220 | spin_lock_irqsave(&serial->serial_lock, flags); |
|---|
| .. | .. |
|---|
| 1278 | 1264 | /* Force default termio settings */ |
|---|
| 1279 | 1265 | _hso_serial_set_termios(tty, NULL); |
|---|
| 1280 | 1266 | tasklet_init(&serial->unthrottle_tasklet, |
|---|
| 1281 | | - (void (*)(unsigned long))hso_unthrottle_tasklet, |
|---|
| 1267 | + hso_unthrottle_tasklet, |
|---|
| 1282 | 1268 | (unsigned long)serial); |
|---|
| 1283 | 1269 | result = hso_start_serial_device(serial->parent, GFP_KERNEL); |
|---|
| 1284 | 1270 | if (result) { |
|---|
| .. | .. |
|---|
| 1446 | 1432 | usb_rcvintpipe(usb, |
|---|
| 1447 | 1433 | tiocmget->endp-> |
|---|
| 1448 | 1434 | bEndpointAddress & 0x7F), |
|---|
| 1449 | | - &tiocmget->serial_state_notification, |
|---|
| 1435 | + tiocmget->serial_state_notification, |
|---|
| 1450 | 1436 | sizeof(struct hso_serial_state_notification), |
|---|
| 1451 | 1437 | tiocmget_intr_callback, serial, |
|---|
| 1452 | 1438 | tiocmget->endp->bInterval); |
|---|
| .. | .. |
|---|
| 1493 | 1479 | /* wIndex should be the USB interface number of the port to which the |
|---|
| 1494 | 1480 | * notification applies, which should always be the Modem port. |
|---|
| 1495 | 1481 | */ |
|---|
| 1496 | | - serial_state_notification = &tiocmget->serial_state_notification; |
|---|
| 1482 | + serial_state_notification = tiocmget->serial_state_notification; |
|---|
| 1497 | 1483 | if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE || |
|---|
| 1498 | 1484 | serial_state_notification->bNotification != B_NOTIFICATION || |
|---|
| 1499 | 1485 | le16_to_cpu(serial_state_notification->wValue) != W_VALUE || |
|---|
| .. | .. |
|---|
| 2476 | 2462 | &interface_to_usbdev(interface)->dev, |
|---|
| 2477 | 2463 | RFKILL_TYPE_WWAN, |
|---|
| 2478 | 2464 | &hso_rfkill_ops, hso_dev); |
|---|
| 2479 | | - if (!hso_net->rfkill) { |
|---|
| 2480 | | - dev_err(dev, "%s - Out of memory\n", __func__); |
|---|
| 2465 | + if (!hso_net->rfkill) |
|---|
| 2481 | 2466 | return; |
|---|
| 2482 | | - } |
|---|
| 2467 | + |
|---|
| 2483 | 2468 | if (rfkill_register(hso_net->rfkill) < 0) { |
|---|
| 2484 | 2469 | rfkill_destroy(hso_net->rfkill); |
|---|
| 2485 | 2470 | hso_net->rfkill = NULL; |
|---|
| .. | .. |
|---|
| 2552 | 2537 | if (!hso_net->mux_bulk_tx_buf) |
|---|
| 2553 | 2538 | goto err_free_tx_urb; |
|---|
| 2554 | 2539 | |
|---|
| 2555 | | - add_net_device(hso_dev); |
|---|
| 2540 | + result = add_net_device(hso_dev); |
|---|
| 2541 | + if (result) { |
|---|
| 2542 | + dev_err(&interface->dev, "Failed to add net device\n"); |
|---|
| 2543 | + goto err_free_tx_buf; |
|---|
| 2544 | + } |
|---|
| 2556 | 2545 | |
|---|
| 2557 | 2546 | /* registering our net device */ |
|---|
| 2558 | 2547 | result = register_netdev(net); |
|---|
| 2559 | 2548 | if (result) { |
|---|
| 2560 | 2549 | dev_err(&interface->dev, "Failed to register device\n"); |
|---|
| 2561 | | - goto err_free_tx_buf; |
|---|
| 2550 | + goto err_rmv_ndev; |
|---|
| 2562 | 2551 | } |
|---|
| 2563 | 2552 | |
|---|
| 2564 | 2553 | hso_log_port(hso_dev); |
|---|
| .. | .. |
|---|
| 2567 | 2556 | |
|---|
| 2568 | 2557 | return hso_dev; |
|---|
| 2569 | 2558 | |
|---|
| 2570 | | -err_free_tx_buf: |
|---|
| 2559 | +err_rmv_ndev: |
|---|
| 2571 | 2560 | remove_net_device(hso_dev); |
|---|
| 2561 | +err_free_tx_buf: |
|---|
| 2572 | 2562 | kfree(hso_net->mux_bulk_tx_buf); |
|---|
| 2573 | 2563 | err_free_tx_urb: |
|---|
| 2574 | 2564 | usb_free_urb(hso_net->mux_bulk_tx_urb); |
|---|
| .. | .. |
|---|
| 2594 | 2584 | usb_free_urb(tiocmget->urb); |
|---|
| 2595 | 2585 | tiocmget->urb = NULL; |
|---|
| 2596 | 2586 | serial->tiocmget = NULL; |
|---|
| 2587 | + kfree(tiocmget->serial_state_notification); |
|---|
| 2588 | + tiocmget->serial_state_notification = NULL; |
|---|
| 2597 | 2589 | kfree(tiocmget); |
|---|
| 2598 | 2590 | } |
|---|
| 2599 | 2591 | } |
|---|
| .. | .. |
|---|
| 2644 | 2636 | num_urbs = 2; |
|---|
| 2645 | 2637 | serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget), |
|---|
| 2646 | 2638 | GFP_KERNEL); |
|---|
| 2647 | | - /* it isn't going to break our heart if serial->tiocmget |
|---|
| 2648 | | - * allocation fails don't bother checking this. |
|---|
| 2649 | | - */ |
|---|
| 2650 | | - if (serial->tiocmget) { |
|---|
| 2651 | | - tiocmget = serial->tiocmget; |
|---|
| 2652 | | - tiocmget->endp = hso_get_ep(interface, |
|---|
| 2653 | | - USB_ENDPOINT_XFER_INT, |
|---|
| 2654 | | - USB_DIR_IN); |
|---|
| 2655 | | - if (!tiocmget->endp) { |
|---|
| 2656 | | - dev_err(&interface->dev, "Failed to find INT IN ep\n"); |
|---|
| 2657 | | - goto exit; |
|---|
| 2658 | | - } |
|---|
| 2659 | | - |
|---|
| 2660 | | - tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL); |
|---|
| 2661 | | - if (tiocmget->urb) { |
|---|
| 2662 | | - mutex_init(&tiocmget->mutex); |
|---|
| 2663 | | - init_waitqueue_head(&tiocmget->waitq); |
|---|
| 2664 | | - } else |
|---|
| 2665 | | - hso_free_tiomget(serial); |
|---|
| 2639 | + if (!serial->tiocmget) |
|---|
| 2640 | + goto exit; |
|---|
| 2641 | + serial->tiocmget->serial_state_notification |
|---|
| 2642 | + = kzalloc(sizeof(struct hso_serial_state_notification), |
|---|
| 2643 | + GFP_KERNEL); |
|---|
| 2644 | + if (!serial->tiocmget->serial_state_notification) |
|---|
| 2645 | + goto exit; |
|---|
| 2646 | + tiocmget = serial->tiocmget; |
|---|
| 2647 | + tiocmget->endp = hso_get_ep(interface, |
|---|
| 2648 | + USB_ENDPOINT_XFER_INT, |
|---|
| 2649 | + USB_DIR_IN); |
|---|
| 2650 | + if (!tiocmget->endp) { |
|---|
| 2651 | + dev_err(&interface->dev, "Failed to find INT IN ep\n"); |
|---|
| 2652 | + goto exit; |
|---|
| 2666 | 2653 | } |
|---|
| 2667 | | - } |
|---|
| 2668 | | - else |
|---|
| 2654 | + |
|---|
| 2655 | + tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL); |
|---|
| 2656 | + if (!tiocmget->urb) |
|---|
| 2657 | + goto exit; |
|---|
| 2658 | + |
|---|
| 2659 | + mutex_init(&tiocmget->mutex); |
|---|
| 2660 | + init_waitqueue_head(&tiocmget->waitq); |
|---|
| 2661 | + } else { |
|---|
| 2669 | 2662 | num_urbs = 1; |
|---|
| 2663 | + } |
|---|
| 2670 | 2664 | |
|---|
| 2671 | 2665 | if (hso_serial_common_create(serial, num_urbs, BULK_URB_RX_SIZE, |
|---|
| 2672 | 2666 | BULK_URB_TX_SIZE)) |
|---|
| .. | .. |
|---|
| 2682 | 2676 | if (! |
|---|
| 2683 | 2677 | (serial->out_endp = |
|---|
| 2684 | 2678 | hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT))) { |
|---|
| 2685 | | - dev_err(&interface->dev, "Failed to find BULK IN ep\n"); |
|---|
| 2679 | + dev_err(&interface->dev, "Failed to find BULK OUT ep\n"); |
|---|
| 2686 | 2680 | goto exit2; |
|---|
| 2687 | 2681 | } |
|---|
| 2688 | 2682 | |
|---|