^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Intel Wireless WiMAX Connection 2400m over USB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Notification handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * * Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * * Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * notice, this list of conditions and the following disclaimer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * * Neither the name of Intel Corporation nor the names of its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * contributors may be used to endorse or promote products derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Intel Corporation <linux-wimax@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Yanir Lubetkin <yanirx.lubetkin@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - Initial implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * The notification endpoint is active when the device is not in boot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * mode; in here we just read and get notifications; based on those,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * we act to either reinitialize the device after a reboot or to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * submit a RX request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * ROADMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * i2400mu_usb_notification_setup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * i2400mu_usb_notification_release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * i2400mu_usb_notification_cb() Called when a URB is ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * i2400mu_notif_grok()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * i2400m_is_boot_barker()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * i2400m_dev_reset_handle()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * i2400mu_rx_kick()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include "i2400m-usb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define D_SUBMODULE notif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include "usb-debug-levels.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) __le32 i2400m_ZERO_BARKER[4] = { 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Process a received notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * In normal operation mode, we can only receive two types of payloads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * on the notification endpoint:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * - a reboot barker, we do a bootstrap (the device has reseted).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * - a block of zeroes: there is pending data in the IN endpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) size_t buf_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct i2400m *i2400m = &i2400mu->i2400m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) d_fnstart(4, dev, "(i2400m %p buf %p buf_len %zu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) i2400mu, buf, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (buf_len < sizeof(i2400m_ZERO_BARKER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* Not a bug, just ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) goto error_bad_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!memcmp(i2400m_ZERO_BARKER, buf, sizeof(i2400m_ZERO_BARKER))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) i2400mu_rx_kick(i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ret = i2400m_is_boot_barker(i2400m, buf, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (unlikely(ret >= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ret = i2400m_dev_reset_handle(i2400m, "device rebooted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) else /* Unknown or unexpected data in the notif message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) i2400m_unknown_barker(i2400m, buf, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) error_bad_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) d_fnend(4, dev, "(i2400m %p buf %p buf_len %zu) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) i2400mu, buf, buf_len, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * URB callback for the notification endpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @urb: the urb received from the notification endpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * This function will just process the USB side of the transaction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * checking everything is fine, pass the processing to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * i2400m_notification_grok() and resubmit the URB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) void i2400mu_notification_cb(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct i2400mu *i2400mu = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) d_fnstart(4, dev, "(urb %p status %d actual_length %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) urb, urb->status, urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ret = urb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = i2400mu_notification_grok(i2400mu, urb->transfer_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (ret == -EIO && edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EDC_ERROR_TIMEFRAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto error_exceeded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret == -ENOMEM) /* uff...power cycle? shutdown? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto error_exceeded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case -EINVAL: /* while removing driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case -ENODEV: /* dev disconnect ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case -ENOENT: /* ditto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case -ESHUTDOWN: /* URB killed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case -ECONNRESET: /* disconnection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) goto out; /* Notify around */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) default: /* Some error? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (edc_inc(&i2400mu->urb_edc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) goto error_exceeded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dev_err(dev, "notification: URB error %d, retrying\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) usb_mark_last_busy(i2400mu->usb_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ret = usb_submit_urb(i2400mu->notif_urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case -EINVAL: /* while removing driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case -ENODEV: /* dev disconnect ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case -ENOENT: /* ditto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case -ESHUTDOWN: /* URB killed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case -ECONNRESET: /* disconnection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break; /* just ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) default: /* Some error? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dev_err(dev, "notification: cannot submit URB: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto error_submit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) urb, urb->status, urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) error_exceeded:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dev_err(dev, "maximum errors in notification URB exceeded; "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) "resetting device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) error_submit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) usb_queue_reset_device(i2400mu->usb_iface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) urb, urb->status, urb->actual_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * setup the notification endpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * This procedure prepares the notification urb and handler for receiving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * unsolicited barkers from the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int i2400mu_notification_setup(struct i2400mu *i2400mu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int usb_pipe, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct usb_endpoint_descriptor *epd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) d_fnstart(4, dev, "(i2400m %p)\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) buf = kmalloc(I2400MU_MAX_NOTIFICATION_LEN, GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto error_buf_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) i2400mu->notif_urb = usb_alloc_urb(0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!i2400mu->notif_urb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto error_alloc_urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) epd = usb_get_epd(i2400mu->usb_iface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) i2400mu->endpoint_cfg.notification);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) usb_pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) usb_fill_int_urb(i2400mu->notif_urb, i2400mu->usb_dev, usb_pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) buf, I2400MU_MAX_NOTIFICATION_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) i2400mu_notification_cb, i2400mu, epd->bInterval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ret = usb_submit_urb(i2400mu->notif_urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) dev_err(dev, "notification: cannot submit URB: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto error_submit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) error_submit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) usb_free_urb(i2400mu->notif_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) error_alloc_urb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) error_buf_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Tear down of the notification mechanism
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Kill the interrupt endpoint urb, free any allocated resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * We need to check if we have done it before as for example,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * _suspend() call this; if after a suspend() we get a _disconnect()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * (as the case is when hibernating), nothing bad happens.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) void i2400mu_notification_release(struct i2400mu *i2400mu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (i2400mu->notif_urb != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) usb_kill_urb(i2400mu->notif_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) kfree(i2400mu->notif_urb->transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) usb_free_urb(i2400mu->notif_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) i2400mu->notif_urb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) d_fnend(4, dev, "(i2400mu %p)\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }