^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Intel Wireless WiMAX Connection 2400m
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Generic probe/disconnect, reset and message passing
^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 <linux-wimax@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * See i2400m.h for driver documentation. This contains helpers for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * the driver model glue [_setup()/_release()], handling device resets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * [_dev_reset_handle()], and the backends for the WiMAX stack ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * reset [_op_reset()] and message from user [_op_msg_from_user()].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * ROADMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * i2400m_op_msg_from_user()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * i2400m_msg_to_dev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * wimax_msg_to_user_send()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * i2400m_op_reset()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * i240m->bus_reset()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * i2400m_dev_reset_handle()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * __i2400m_dev_reset_handle()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * __i2400m_dev_stop()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * __i2400m_dev_start()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * i2400m_setup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * i2400m->bus_setup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * i2400m_bootrom_init()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * register_netdev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * wimax_dev_add()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * i2400m_dev_start()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * __i2400m_dev_start()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * i2400m_dev_bootstrap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * i2400m_tx_setup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * i2400m->bus_dev_start()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * i2400m_firmware_check()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * i2400m_check_mac_addr()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * i2400m_release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * i2400m_dev_stop()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * __i2400m_dev_stop()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * i2400m_dev_shutdown()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * i2400m->bus_dev_stop()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * i2400m_tx_release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * i2400m->bus_release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * wimax_dev_rm()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * unregister_netdev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include "i2400m.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/wimax/i2400m.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define D_SUBMODULE driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include "debug-levels.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) static char i2400m_debug_params[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) module_param_string(debug, i2400m_debug_params, sizeof(i2400m_debug_params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) MODULE_PARM_DESC(debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "String of space-separated NAME:VALUE pairs, where NAMEs "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "are the different debug submodules and VALUE are the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) "initial debug value to set.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static char i2400m_barkers_params[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) module_param_string(barkers, i2400m_barkers_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) sizeof(i2400m_barkers_params), 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MODULE_PARM_DESC(barkers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) "String of comma-separated 32-bit values; each is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) "recognized as the value the device sends as a reboot "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) "signal; values are appended to a list--setting one value "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "as zero cleans the existing list and starts a new one.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * WiMAX stack operation: relay a message from user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @wimax_dev: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @pipe_name: named pipe the message is for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @msg_buf: pointer to the message bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @msg_len: length of the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @genl_info: passed by the generic netlink layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * The WiMAX stack will call this function when a message was received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * from user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * For the i2400m, this is an L3L4 message, as specified in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * include/linux/wimax/i2400m.h, and thus prefixed with a 'struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * i2400m_l3l4_hdr'. Driver (and device) expect the messages to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * coded in Little Endian.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * This function just verifies that the header declaration and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * payload are consistent and then deals with it, either forwarding it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * to the device or procesing it locally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * In the i2400m, messages are basically commands that will carry an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * ack, so we use i2400m_msg_to_dev() and then deliver the ack back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * user space. The rx.c code might intercept the response and use it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * to update the driver's state, but then it will pass it on so it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * be relayed back to user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * Note that asynchronous events from the device are processed and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * sent to user space in rx.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const char *pipe_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) const void *msg_buf, size_t msg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) const struct genl_info *genl_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct sk_buff *ack_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) d_fnstart(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "msg_len %zu genl_info %p)\n", wimax_dev, i2400m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) msg_buf, msg_len, genl_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ack_skb = i2400m_msg_to_dev(i2400m, msg_buf, msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) result = PTR_ERR(ack_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (IS_ERR(ack_skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto error_msg_to_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) result = wimax_msg_send(&i2400m->wimax_dev, ack_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) error_msg_to_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) "genl_info %p) = %d\n", wimax_dev, i2400m, msg_buf, msg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) genl_info, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * Context to wait for a reset to finalize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct i2400m_reset_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct completion completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * WiMAX stack operation: reset a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @wimax_dev: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * See the documentation for wimax_reset() and wimax_dev->op_reset for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * the requirements of this function. The WiMAX stack guarantees
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * serialization on calls to this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Do a warm reset on the device; if it fails, resort to a cold reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * and return -ENODEV. On successful warm reset, we need to block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * until it is complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * The bus-driver implementation of reset takes care of falling back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * to cold reset if warm fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int i2400m_op_reset(struct wimax_dev *wimax_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct i2400m_reset_ctx ctx = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .completion = COMPLETION_INITIALIZER_ONSTACK(ctx.completion),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .result = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) d_fnstart(4, dev, "(wimax_dev %p)\n", wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) mutex_lock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) i2400m->reset_ctx = &ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) result = i2400m_reset(i2400m, I2400M_RT_WARM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) result = wait_for_completion_timeout(&ctx.completion, 4*HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (result == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) result = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) else if (result > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) result = ctx.result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* if result < 0, pass it on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mutex_lock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) i2400m->reset_ctx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) d_fnend(4, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * Check the MAC address we got from boot mode is ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Returns: 0 if ok, < 0 errno code on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int i2400m_check_mac_addr(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) const struct i2400m_tlv_detailed_device_info *ddi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct net_device *net_dev = i2400m->wimax_dev.net_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) skb = i2400m_get_device_info(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (IS_ERR(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) result = PTR_ERR(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dev_err(dev, "Cannot verify MAC address, error reading: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Extract MAC address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ddi = (void *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ddi->mac_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (!memcmp(net_dev->perm_addr, ddi->mac_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) sizeof(ddi->mac_address)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) goto ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dev_warn(dev, "warning: device reports a different MAC address "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) "to that of boot mode's\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dev_warn(dev, "device reports %pM\n", ddi->mac_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_warn(dev, "boot mode reported %pM\n", net_dev->perm_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (is_zero_ether_addr(ddi->mac_address))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dev_err(dev, "device reports an invalid MAC address, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) "not updating\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) dev_warn(dev, "updating MAC address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) net_dev->addr_len = ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) memcpy(net_dev->perm_addr, ddi->mac_address, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) memcpy(net_dev->dev_addr, ddi->mac_address, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ok:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * __i2400m_dev_start - Bring up driver communication with the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @flags: boot mode flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Returns: 0 if ok, < 0 errno code on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Uploads firmware and brings up all the resources needed to be able
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * to communicate with the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * The workqueue has to be setup early, at least before RX handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * (it's only real user for now) so it can process reports as they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * arrive. We also want to destroy it if we retry, to make sure it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * flushed...easier like this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * TX needs to be setup before the bus-specific code (otherwise on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * shutdown, the bus-tx code could try to access it).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct net_device *net_dev = wimax_dev->net_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int times = i2400m->bus_bm_retries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) result = i2400m_dev_bootstrap(i2400m, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dev_err(dev, "cannot bootstrap device: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) goto error_bootstrap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) result = i2400m_tx_setup(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) goto error_tx_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) result = i2400m_rx_setup(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto error_rx_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (i2400m->work_queue == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dev_err(dev, "cannot create workqueue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto error_create_workqueue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (i2400m->bus_dev_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) result = i2400m->bus_dev_start(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) goto error_bus_dev_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) i2400m->ready = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) wmb(); /* see i2400m->ready's documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* process pending reports from the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) queue_work(i2400m->work_queue, &i2400m->rx_report_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) result = i2400m_firmware_check(i2400m); /* fw versions ok? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) goto error_fw_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* At this point is ok to send commands to the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) result = i2400m_check_mac_addr(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto error_check_mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) result = i2400m_dev_initialize(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) goto error_dev_initialize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* We don't want any additional unwanted error recovery triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * from any other context so if anything went wrong before we come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * here, let's keep i2400m->error_recovery untouched and leave it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * dev_reset_handle(). See dev_reset_handle(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) atomic_dec(&i2400m->error_recovery);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Every thing works so far, ok, now we are ready to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * take error recovery if it's required. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* At this point, reports will come for the device and set it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * to the right state if it is different than UNINITIALIZED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) net_dev, i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) error_dev_initialize:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) error_check_mac_addr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) error_fw_check:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) i2400m->ready = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) wmb(); /* see i2400m->ready's documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) flush_workqueue(i2400m->work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (i2400m->bus_dev_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) i2400m->bus_dev_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) error_bus_dev_start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) destroy_workqueue(i2400m->work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) error_create_workqueue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) i2400m_rx_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) error_rx_setup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) i2400m_tx_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) error_tx_setup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) error_bootstrap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (result == -EL3RST && times-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) flags = I2400M_BRI_SOFT|I2400M_BRI_MAC_REINIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) net_dev, i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mutex_lock(&i2400m->init_mutex); /* Well, start the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (i2400m->updown == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) result = __i2400m_dev_start(i2400m, bm_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (result >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) i2400m->updown = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) i2400m->alive = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) wmb();/* see i2400m->updown and i2400m->alive's doc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * i2400m_dev_stop - Tear down driver communication with the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Returns: 0 if ok, < 0 errno code on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * Releases all the resources allocated to communicate with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * device. Note we cannot destroy the workqueue earlier as until RX is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * fully destroyed, it could still try to schedule jobs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) void __i2400m_dev_stop(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) complete(&i2400m->msg_completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) i2400m_net_wake_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) i2400m_dev_shutdown(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * Make sure no report hooks are running *before* we stop the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * communication infrastructure with the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) i2400m->ready = 0; /* nobody can queue work anymore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) wmb(); /* see i2400m->ready's documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) flush_workqueue(i2400m->work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (i2400m->bus_dev_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) i2400m->bus_dev_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) destroy_workqueue(i2400m->work_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) i2400m_rx_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) i2400m_tx_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * Watch out -- we only need to stop if there is a need for it. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * device could have reset itself and failed to come up again (see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * _i2400m_dev_reset_handle()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) void i2400m_dev_stop(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mutex_lock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (i2400m->updown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) __i2400m_dev_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) i2400m->updown = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) i2400m->alive = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) wmb(); /* see i2400m->updown and i2400m->alive's doc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * Listen to PM events to cache the firmware before suspend/hibernation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * When the device comes out of suspend, it might go into reset and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * firmware has to be uploaded again. At resume, most of the times, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * can't load firmware images from disk, so we need to cache it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * i2400m_fw_cache() will allocate a kobject and attach the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * to it; that way we don't have to worry too much about the fw loader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * hitting a race condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Note: modus operandi stolen from the Orinoco driver; thx.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int i2400m_pm_notifier(struct notifier_block *notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) unsigned long pm_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct i2400m *i2400m =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) container_of(notifier, struct i2400m, pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) d_fnstart(3, dev, "(i2400m %p pm_event %lx)\n", i2400m, pm_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) switch (pm_event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case PM_HIBERNATION_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) case PM_SUSPEND_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) i2400m_fw_cache(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case PM_POST_RESTORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* Restore from hibernation failed. We need to clean
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * up in exactly the same way, so fall through. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) case PM_POST_HIBERNATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) case PM_POST_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) i2400m_fw_uncache(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) case PM_RESTORE_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) d_fnend(3, dev, "(i2400m %p pm_event %lx) = void\n", i2400m, pm_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * pre-reset is called before a device is going on reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * This has to be followed by a call to i2400m_post_reset(), otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * bad things might happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int i2400m_pre_reset(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) d_printf(1, dev, "pre-reset shut down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mutex_lock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (i2400m->updown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) netif_tx_disable(i2400m->wimax_dev.net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) __i2400m_dev_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* down't set updown to zero -- this way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * post_reset can restore properly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (i2400m->bus_release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) i2400m->bus_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) EXPORT_SYMBOL_GPL(i2400m_pre_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * Restore device state after a reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * Do the work needed after a device reset to bring it up to the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * state as it was before the reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * NOTE: this requires i2400m->init_mutex taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int i2400m_post_reset(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) d_printf(1, dev, "post-reset start\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (i2400m->bus_setup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) result = i2400m->bus_setup(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_err(dev, "bus-specific setup failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) goto error_bus_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mutex_lock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (i2400m->updown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) result = __i2400m_dev_start(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) i2400m, I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto error_dev_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) error_dev_start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (i2400m->bus_release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) i2400m->bus_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* even if the device was up, it could not be recovered, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * mark it as down. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) i2400m->updown = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) wmb(); /* see i2400m->updown's documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) error_bus_setup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) EXPORT_SYMBOL_GPL(i2400m_post_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * The device has rebooted; fix up the device and the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * Tear down the driver communication with the device, reload the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * firmware and reinitialize the communication with the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * If someone calls a reset when the device's firmware is down, in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * theory we won't see it because we are not listening. However, just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * in case, leave the code to handle it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * If there is a reset context, use it; this means someone is waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * for us to tell him when the reset operation is complete and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * device is ready to rock again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * NOTE: if we are in the process of bringing up or down the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * communication with the device [running i2400m_dev_start() or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * _stop()], don't do anything, let it fail and handle it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * This function is ran always in a thread context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * This function gets passed, as payload to i2400m_work() a 'const
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * char *' ptr with a "reason" why the reset happened (for messages).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) void __i2400m_dev_reset_handle(struct work_struct *ws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct i2400m *i2400m = container_of(ws, struct i2400m, reset_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) const char *reason = i2400m->reset_reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct i2400m_reset_ctx *ctx = i2400m->reset_ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) i2400m->boot_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) wmb(); /* Make sure i2400m_msg_to_dev() sees boot_mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (mutex_trylock(&i2400m->init_mutex) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* We are still in i2400m_dev_start() [let it fail] or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * i2400m_dev_stop() [we are shutting down anyway, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * ignore it] or we are resetting somewhere else. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) dev_err(dev, "device rebooted somewhere else?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) complete(&i2400m->msg_completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) dev_err(dev, "%s: reinitializing driver\n", reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (i2400m->updown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) __i2400m_dev_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) i2400m->updown = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) wmb(); /* see i2400m->updown's documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (i2400m->alive) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) result = __i2400m_dev_start(i2400m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) dev_err(dev, "%s: cannot start the device: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) reason, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) result = -EUCLEAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (atomic_read(&i2400m->bus_reset_retries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) >= I2400M_BUS_RESET_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) dev_err(dev, "tried too many times to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) "reset the device, giving up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (i2400m->reset_ctx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) ctx->result = result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) complete(&ctx->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) mutex_unlock(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (result == -EUCLEAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * We come here because the reset during operational mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * wasn't successfully done and need to proceed to a bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * reset. For the dev_reset_handle() to be able to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * the reset event later properly, we restore boot_mode back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * to the state before previous reset. ie: just like we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * issuing the bus reset for the first time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) i2400m->boot_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) atomic_inc(&i2400m->bus_reset_retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* ops, need to clean up [w/ init_mutex not held] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) result = i2400m_reset(i2400m, I2400M_RT_BUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (result >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (i2400m->alive) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* great, we expect the device state up and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * dev_start() actually brings the device state up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) i2400m->updown = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) atomic_set(&i2400m->bus_reset_retries, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ws, i2400m, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * i2400m_dev_reset_handle - Handle a device's reset in a thread context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * Schedule a device reset handling out on a thread context, so it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * is safe to call from atomic context. We can't use the i2400m's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * queue as we are going to destroy it and reinitialize it as part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * the driver bringup/bringup process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * See __i2400m_dev_reset_handle() for details; that takes care of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * reinitializing the driver to handle the reset, calling into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * bus-specific functions ops as needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) i2400m->reset_reason = reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return schedule_work(&i2400m->reset_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * The actual work of error recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * The current implementation of error recovery is to trigger a bus reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) void __i2400m_error_recovery(struct work_struct *ws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct i2400m *i2400m = container_of(ws, struct i2400m, recovery_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) i2400m_reset(i2400m, I2400M_RT_BUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * Schedule a work struct for error recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * The intention of error recovery is to bring back the device to some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * known state whenever TX sees -110 (-ETIMEOUT) on copying the data to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * the device. The TX failure could mean a device bus stuck, so the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * error recovery implementation is to trigger a bus reset to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * and hopefully it can bring back the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * The actual work of error recovery has to be in a thread context because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * it is kicked off in the TX thread (i2400ms->tx_workqueue) which is to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * destroyed by the error recovery mechanism (currently a bus reset).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * Also, there may be already a queue of TX works that all hit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * the -ETIMEOUT error condition because the device is stuck already.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Since bus reset is used as the error recovery mechanism and we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * want consecutive bus resets simply because the multiple TX works
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * in the queue all hit the same device erratum, the flag "error_recovery"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * is introduced for preventing unwanted consecutive bus resets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * Error recovery shall only be invoked again if previous one was completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * The flag error_recovery is set when error recovery mechanism is scheduled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * and is checked when we need to schedule another error recovery. If it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * in place already, then we shouldn't schedule another one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) void i2400m_error_recovery(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (atomic_add_return(1, &i2400m->error_recovery) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) schedule_work(&i2400m->recovery_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) atomic_dec(&i2400m->error_recovery);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) EXPORT_SYMBOL_GPL(i2400m_error_recovery);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * Alloc the command and ack buffers for boot mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * Get the buffers needed to deal with boot mode messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) int i2400m_bm_buf_alloc(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (i2400m->bm_cmd_buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) goto error_bm_cmd_kzalloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) i2400m->bm_ack_buf = kzalloc(I2400M_BM_ACK_BUF_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (i2400m->bm_ack_buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) goto error_bm_ack_buf_kzalloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) error_bm_ack_buf_kzalloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) kfree(i2400m->bm_cmd_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) error_bm_cmd_kzalloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * Free boot mode command and ack buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) void i2400m_bm_buf_free(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) kfree(i2400m->bm_ack_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) kfree(i2400m->bm_cmd_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * i2400m_init - Initialize a 'struct i2400m' from all zeroes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * This is a bus-generic API call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) void i2400m_init(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) wimax_dev_init(&i2400m->wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) i2400m->boot_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) i2400m->rx_reorder = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) init_waitqueue_head(&i2400m->state_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) spin_lock_init(&i2400m->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) i2400m->tx_pl_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) i2400m->tx_size_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) spin_lock_init(&i2400m->rx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) i2400m->rx_pl_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) i2400m->rx_size_min = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) INIT_LIST_HEAD(&i2400m->rx_reports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) INIT_WORK(&i2400m->rx_report_ws, i2400m_report_hook_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) mutex_init(&i2400m->msg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) init_completion(&i2400m->msg_completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mutex_init(&i2400m->init_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* wake_tx_ws is initialized in i2400m_tx_setup() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) INIT_WORK(&i2400m->reset_ws, __i2400m_dev_reset_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) INIT_WORK(&i2400m->recovery_ws, __i2400m_error_recovery);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) atomic_set(&i2400m->bus_reset_retries, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) i2400m->alive = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* initialize error_recovery to 1 for denoting we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * are not yet ready to take any error recovery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) atomic_set(&i2400m->error_recovery, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) EXPORT_SYMBOL_GPL(i2400m_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) int i2400m_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct net_device *net_dev = i2400m->wimax_dev.net_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * Make sure we stop TXs and down the carrier before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * resetting; this is needed to avoid things like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * i2400m_wake_tx() scheduling stuff in parallel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (net_dev->reg_state == NETREG_REGISTERED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) netif_tx_disable(net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) netif_carrier_off(net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return i2400m->bus_reset(i2400m, rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) EXPORT_SYMBOL_GPL(i2400m_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * i2400m_setup - bus-generic setup function for the i2400m device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * @i2400m: device descriptor (bus-specific parts have been initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * Returns: 0 if ok, < 0 errno code on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * Sets up basic device comunication infrastructure, boots the ROM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * read the MAC address, registers with the WiMAX and network stacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * and then brings up the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct net_device *net_dev = i2400m->wimax_dev.net_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) snprintf(wimax_dev->name, sizeof(wimax_dev->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) "i2400m-%s:%s", dev->bus->name, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) result = i2400m_bm_buf_alloc(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) dev_err(dev, "cannot allocate bootmode scratch buffers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto error_bm_buf_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (i2400m->bus_setup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) result = i2400m->bus_setup(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) dev_err(dev, "bus-specific setup failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) goto error_bus_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) result = i2400m_bootrom_init(i2400m, bm_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) dev_err(dev, "read mac addr: bootrom init "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) "failed: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) goto error_bootrom_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) result = i2400m_read_mac_addr(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) goto error_read_mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) eth_random_addr(i2400m->src_mac_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) i2400m->pm_notifier.notifier_call = i2400m_pm_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) register_pm_notifier(&i2400m->pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) result = register_netdev(net_dev); /* Okey dokey, bring it up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) dev_err(dev, "cannot register i2400m network device: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) goto error_register_netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) netif_carrier_off(net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) i2400m->wimax_dev.op_reset = i2400m_op_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) result = wimax_dev_add(&i2400m->wimax_dev, net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) goto error_wimax_dev_add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* Now setup all that requires a registered net and wimax device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) result = sysfs_create_group(&net_dev->dev.kobj, &i2400m_dev_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dev_err(dev, "cannot setup i2400m's sysfs: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) goto error_sysfs_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) i2400m_debugfs_add(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) result = i2400m_dev_start(i2400m, bm_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) goto error_dev_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) error_dev_start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) i2400m_debugfs_rm(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) &i2400m_dev_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) error_sysfs_setup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) wimax_dev_rm(&i2400m->wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) error_wimax_dev_add:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) unregister_netdev(net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) error_register_netdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) unregister_pm_notifier(&i2400m->pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) error_read_mac_addr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) error_bootrom_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (i2400m->bus_release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) i2400m->bus_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) error_bus_setup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) i2400m_bm_buf_free(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) error_bm_buf_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) EXPORT_SYMBOL_GPL(i2400m_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * i2400m_release - release the bus-generic driver resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * Sends a disconnect message and undoes any setup done by i2400m_setup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) void i2400m_release(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) netif_stop_queue(i2400m->wimax_dev.net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) i2400m_dev_stop(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) cancel_work_sync(&i2400m->reset_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) cancel_work_sync(&i2400m->recovery_ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) i2400m_debugfs_rm(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) &i2400m_dev_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) wimax_dev_rm(&i2400m->wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) unregister_netdev(i2400m->wimax_dev.net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) unregister_pm_notifier(&i2400m->pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (i2400m->bus_release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) i2400m->bus_release(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) i2400m_bm_buf_free(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) EXPORT_SYMBOL_GPL(i2400m_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * Debug levels control; see debug.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) struct d_level D_LEVEL[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) D_SUBMODULE_DEFINE(control),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) D_SUBMODULE_DEFINE(driver),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) D_SUBMODULE_DEFINE(debugfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) D_SUBMODULE_DEFINE(fw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) D_SUBMODULE_DEFINE(netdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) D_SUBMODULE_DEFINE(rfkill),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) D_SUBMODULE_DEFINE(rx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) D_SUBMODULE_DEFINE(sysfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) D_SUBMODULE_DEFINE(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int __init i2400m_driver_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400m_debug_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) "i2400m.debug");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return i2400m_barker_db_init(i2400m_barkers_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) module_init(i2400m_driver_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) void __exit i2400m_driver_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) i2400m_barker_db_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) module_exit(i2400m_driver_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) MODULE_DESCRIPTION("Intel 2400M WiMAX networking bus-generic driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) MODULE_LICENSE("GPL");