Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
0004  * All rights reserved.
0005  *
0006  * Purpose: Handles the management command interface functions
0007  *
0008  * Author: Lyndon Chen
0009  *
0010  * Date: May 8, 2003
0011  *
0012  * Functions:
0013  *  vnt_cmd_complete - Command Complete function
0014  *  vnt_schedule_command - Push Command and wait Command Scheduler to do
0015  *  vnt_cmd_timer_wait- Call back timer
0016  *
0017  * Revision History:
0018  *
0019  */
0020 
0021 #include "device.h"
0022 #include "mac.h"
0023 #include "wcmd.h"
0024 #include "power.h"
0025 #include "usbpipe.h"
0026 #include "rxtx.h"
0027 #include "rf.h"
0028 
0029 static void vnt_cmd_timer_wait(struct vnt_private *priv, unsigned long msecs)
0030 {
0031     schedule_delayed_work(&priv->run_command_work, msecs_to_jiffies(msecs));
0032 }
0033 
0034 static u32 add_one_with_wrap_around(u32 var, u8 modulo)
0035 {
0036     if (var >= (modulo - 1))
0037         var = 0;
0038     else
0039         var++;
0040     return var;
0041 }
0042 
0043 static int vnt_cmd_complete(struct vnt_private *priv)
0044 {
0045     priv->command_state = WLAN_CMD_IDLE;
0046     if (priv->free_cmd_queue == CMD_Q_SIZE) {
0047         /* Command Queue Empty */
0048         priv->cmd_running = false;
0049         return true;
0050     }
0051 
0052     priv->command = priv->cmd_queue[priv->cmd_dequeue_idx];
0053 
0054     priv->cmd_dequeue_idx = add_one_with_wrap_around(priv->cmd_dequeue_idx, CMD_Q_SIZE);
0055     priv->free_cmd_queue++;
0056     priv->cmd_running = true;
0057 
0058     switch (priv->command) {
0059     case WLAN_CMD_INIT_MAC80211:
0060         priv->command_state = WLAN_CMD_INIT_MAC80211_START;
0061         break;
0062 
0063     case WLAN_CMD_TBTT_WAKEUP:
0064         priv->command_state = WLAN_CMD_TBTT_WAKEUP_START;
0065         break;
0066 
0067     case WLAN_CMD_BECON_SEND:
0068         priv->command_state = WLAN_CMD_BECON_SEND_START;
0069         break;
0070 
0071     case WLAN_CMD_SETPOWER:
0072         priv->command_state = WLAN_CMD_SETPOWER_START;
0073         break;
0074 
0075     case WLAN_CMD_CHANGE_ANTENNA:
0076         priv->command_state = WLAN_CMD_CHANGE_ANTENNA_START;
0077         break;
0078 
0079     default:
0080         break;
0081     }
0082 
0083     vnt_cmd_timer_wait(priv, 0);
0084 
0085     return true;
0086 }
0087 
0088 void vnt_run_command(struct work_struct *work)
0089 {
0090     struct vnt_private *priv =
0091         container_of(work, struct vnt_private, run_command_work.work);
0092 
0093     if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
0094         return;
0095 
0096     if (!priv->cmd_running)
0097         return;
0098 
0099     switch (priv->command_state) {
0100     case WLAN_CMD_INIT_MAC80211_START:
0101         if (priv->mac_hw)
0102             break;
0103 
0104         dev_info(&priv->usb->dev, "Starting mac80211\n");
0105 
0106         if (vnt_init(priv)) {
0107             /* If fail all ends TODO retry */
0108             dev_err(&priv->usb->dev, "failed to start\n");
0109             usb_set_intfdata(priv->intf, NULL);
0110             ieee80211_free_hw(priv->hw);
0111             return;
0112         }
0113 
0114         break;
0115 
0116     case WLAN_CMD_TBTT_WAKEUP_START:
0117         vnt_next_tbtt_wakeup(priv);
0118         break;
0119 
0120     case WLAN_CMD_BECON_SEND_START:
0121         if (!priv->vif)
0122             break;
0123 
0124         vnt_beacon_make(priv, priv->vif);
0125 
0126         vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
0127 
0128         break;
0129 
0130     case WLAN_CMD_SETPOWER_START:
0131 
0132         vnt_rf_setpower(priv, priv->hw->conf.chandef.chan);
0133 
0134         break;
0135 
0136     case WLAN_CMD_CHANGE_ANTENNA_START:
0137         dev_dbg(&priv->usb->dev, "Change from Antenna%d to",
0138             priv->rx_antenna_sel);
0139 
0140         if (priv->rx_antenna_sel == 0) {
0141             priv->rx_antenna_sel = 1;
0142             if (priv->tx_rx_ant_inv)
0143                 vnt_set_antenna_mode(priv, ANT_RXA);
0144             else
0145                 vnt_set_antenna_mode(priv, ANT_RXB);
0146         } else {
0147             priv->rx_antenna_sel = 0;
0148             if (priv->tx_rx_ant_inv)
0149                 vnt_set_antenna_mode(priv, ANT_RXB);
0150             else
0151                 vnt_set_antenna_mode(priv, ANT_RXA);
0152         }
0153         break;
0154 
0155     default:
0156         break;
0157     }
0158 
0159     vnt_cmd_complete(priv);
0160 }
0161 
0162 int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command)
0163 {
0164     if (priv->free_cmd_queue == 0)
0165         return false;
0166 
0167     priv->cmd_queue[priv->cmd_enqueue_idx] = command;
0168 
0169     priv->cmd_enqueue_idx = add_one_with_wrap_around(priv->cmd_enqueue_idx, CMD_Q_SIZE);
0170     priv->free_cmd_queue--;
0171 
0172     if (!priv->cmd_running)
0173         vnt_cmd_complete(priv);
0174 
0175     return true;
0176 }
0177 
0178 void vnt_reset_command_timer(struct vnt_private *priv)
0179 {
0180     priv->free_cmd_queue = CMD_Q_SIZE;
0181     priv->cmd_dequeue_idx = 0;
0182     priv->cmd_enqueue_idx = 0;
0183     priv->command_state = WLAN_CMD_IDLE;
0184     priv->cmd_running = false;
0185 }