Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");