mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
45
drivers/net/wireless/libertas/Kconfig
Normal file
45
drivers/net/wireless/libertas/Kconfig
Normal file
|
@ -0,0 +1,45 @@
|
|||
config LIBERTAS
|
||||
tristate "Marvell 8xxx Libertas WLAN driver support"
|
||||
depends on CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select LIB80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A library for Marvell Libertas 8xxx devices.
|
||||
|
||||
config LIBERTAS_USB
|
||||
tristate "Marvell Libertas 8388 USB 802.11b/g cards"
|
||||
depends on LIBERTAS && USB
|
||||
---help---
|
||||
A driver for Marvell Libertas 8388 USB devices.
|
||||
|
||||
config LIBERTAS_CS
|
||||
tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
|
||||
depends on LIBERTAS && PCMCIA && HAS_IOPORT_MAP
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385 CompactFlash devices.
|
||||
|
||||
config LIBERTAS_SDIO
|
||||
tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
|
||||
depends on LIBERTAS && MMC
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
|
||||
|
||||
config LIBERTAS_SPI
|
||||
tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
|
||||
depends on LIBERTAS && SPI
|
||||
---help---
|
||||
A driver for Marvell Libertas 8686 SPI devices.
|
||||
|
||||
config LIBERTAS_DEBUG
|
||||
bool "Enable full debugging output in the Libertas module."
|
||||
depends on LIBERTAS
|
||||
---help---
|
||||
Debugging support.
|
||||
|
||||
config LIBERTAS_MESH
|
||||
bool "Enable mesh support"
|
||||
depends on LIBERTAS
|
||||
help
|
||||
This enables Libertas' MESH support, used by e.g. the OLPC people.
|
16
drivers/net/wireless/libertas/LICENSE
Normal file
16
drivers/net/wireless/libertas/LICENSE
Normal file
|
@ -0,0 +1,16 @@
|
|||
Copyright (c) 2003-2006, Marvell International Ltd.
|
||||
All Rights Reserved
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
21
drivers/net/wireless/libertas/Makefile
Normal file
21
drivers/net/wireless/libertas/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
libertas-y += cfg.o
|
||||
libertas-y += cmd.o
|
||||
libertas-y += cmdresp.o
|
||||
libertas-y += debugfs.o
|
||||
libertas-y += ethtool.o
|
||||
libertas-y += main.o
|
||||
libertas-y += rx.o
|
||||
libertas-y += tx.o
|
||||
libertas-y += firmware.o
|
||||
libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
|
||||
|
||||
usb8xxx-objs += if_usb.o
|
||||
libertas_cs-objs += if_cs.o
|
||||
libertas_sdio-objs += if_sdio.o
|
||||
libertas_spi-objs += if_spi.o
|
||||
|
||||
obj-$(CONFIG_LIBERTAS) += libertas.o
|
||||
obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
|
||||
obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o
|
||||
obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
|
||||
obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
|
239
drivers/net/wireless/libertas/README
Normal file
239
drivers/net/wireless/libertas/README
Normal file
|
@ -0,0 +1,239 @@
|
|||
================================================================================
|
||||
README for Libertas
|
||||
|
||||
(c) Copyright © 2003-2006, Marvell International Ltd.
|
||||
All Rights Reserved
|
||||
|
||||
This software file (the "File") is distributed by Marvell International
|
||||
Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
(the "License"). You may use, redistribute and/or modify this File in
|
||||
accordance with the terms and conditions of the License, a copy of which
|
||||
is available along with the File in the license.txt file or on the worldwide
|
||||
web at http://www.gnu.org/licenses/gpl.txt.
|
||||
|
||||
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
this warranty disclaimer.
|
||||
================================================================================
|
||||
|
||||
=====================
|
||||
DRIVER LOADING
|
||||
=====================
|
||||
|
||||
o. Copy the firmware image (e.g. usb8388.bin) to /lib/firmware/
|
||||
|
||||
o. Load driver by using the following command:
|
||||
|
||||
insmod usb8388.ko [fw_name=usb8388.bin]
|
||||
|
||||
=========================
|
||||
ETHTOOL
|
||||
=========================
|
||||
|
||||
|
||||
Use the -i option to retrieve version information from the driver.
|
||||
|
||||
# ethtool -i eth0
|
||||
driver: libertas
|
||||
version: COMM-USB8388-318.p4
|
||||
firmware-version: 5.110.7
|
||||
bus-info:
|
||||
|
||||
Use the -e option to read the EEPROM contents of the card.
|
||||
|
||||
Usage:
|
||||
ethtool -e ethX [raw on|off] [offset N] [length N]
|
||||
|
||||
-e retrieves and prints an EEPROM dump for the specified ethernet
|
||||
device. When raw is enabled, then it dumps the raw EEPROM data
|
||||
to stdout. The length and offset parameters allow dumping cer-
|
||||
tain portions of the EEPROM. Default is to dump the entire EEP-
|
||||
ROM.
|
||||
|
||||
# ethtool -e eth0 offset 0 length 16
|
||||
Offset Values
|
||||
------ ------
|
||||
0x0000 38 33 30 58 00 00 34 f4 00 00 10 00 00 c4 17 00
|
||||
|
||||
========================
|
||||
DEBUGFS COMMANDS
|
||||
========================
|
||||
|
||||
those commands are used via debugfs interface
|
||||
|
||||
===========
|
||||
rdmac
|
||||
rdbbp
|
||||
rdrf
|
||||
These commands are used to read the MAC, BBP and RF registers from the
|
||||
card. These commands take one parameter that specifies the offset
|
||||
location that is to be read. This parameter must be specified in
|
||||
hexadecimal (its possible to precede preceding the number with a "0x").
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/registers/
|
||||
|
||||
Usage:
|
||||
echo "0xa123" > rdmac ; cat rdmac
|
||||
echo "0xa123" > rdbbp ; cat rdbbp
|
||||
echo "0xa123" > rdrf ; cat rdrf
|
||||
wrmac
|
||||
wrbbp
|
||||
wrrf
|
||||
These commands are used to write the MAC, BBP and RF registers in the
|
||||
card. These commands take two parameters that specify the offset
|
||||
location and the value that is to be written. This parameters must
|
||||
be specified in hexadecimal (its possible to precede the number
|
||||
with a "0x").
|
||||
|
||||
Usage:
|
||||
echo "0xa123 0xaa" > wrmac
|
||||
echo "0xa123 0xaa" > wrbbp
|
||||
echo "0xa123 0xaa" > wrrf
|
||||
|
||||
sleepparams
|
||||
This command is used to set the sleepclock configurations
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/
|
||||
|
||||
Usage:
|
||||
cat sleepparams: reads the current sleepclock configuration
|
||||
|
||||
echo "p1 p2 p3 p4 p5 p6" > sleepparams: writes the sleepclock configuration.
|
||||
|
||||
where:
|
||||
p1 is Sleep clock error in ppm (0-65535)
|
||||
p2 is Wakeup offset in usec (0-65535)
|
||||
p3 is Clock stabilization time in usec (0-65535)
|
||||
p4 is Control periodic calibration (0-2)
|
||||
p5 is Control the use of external sleep clock (0-2)
|
||||
p6 is reserved for debug (0-65535)
|
||||
|
||||
subscribed_events
|
||||
|
||||
The subscribed_events directory contains the interface for the
|
||||
subscribed events API.
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/subscribed_events/
|
||||
|
||||
Each event is represented by a filename. Each filename consists of the
|
||||
following three fields:
|
||||
Value Frequency Subscribed
|
||||
|
||||
To read the current values for a given event, do:
|
||||
cat event
|
||||
To set the current values, do:
|
||||
echo "60 2 1" > event
|
||||
|
||||
Frequency field specifies the reporting frequency for this event.
|
||||
If it is set to 0, then the event is reported only once, and then
|
||||
automatically unsubscribed. If it is set to 1, then the event is
|
||||
reported every time it occurs. If it is set to N, then the event is
|
||||
reported every Nth time it occurs.
|
||||
|
||||
beacon_missed
|
||||
Value field specifies the number of consecutive missing beacons which
|
||||
triggers the LINK_LOSS event. This event is generated only once after
|
||||
which the firmware resets its state. At initialization, the LINK_LOSS
|
||||
event is subscribed by default. The default value of MissedBeacons is
|
||||
60.
|
||||
|
||||
failure_count
|
||||
Value field specifies the consecutive failure count threshold which
|
||||
triggers the generation of the MAX_FAIL event. Once this event is
|
||||
generated, the consecutive failure count is reset to 0.
|
||||
At initialization, the MAX_FAIL event is NOT subscribed by
|
||||
default.
|
||||
|
||||
high_rssi
|
||||
This event is generated when the average received RSSI in beacons goes
|
||||
above a threshold, specified by Value.
|
||||
|
||||
low_rssi
|
||||
This event is generated when the average received RSSI in beacons goes
|
||||
below a threshold, specified by Value.
|
||||
|
||||
high_snr
|
||||
This event is generated when the average received SNR in beacons goes
|
||||
above a threshold, specified by Value.
|
||||
|
||||
low_snr
|
||||
This event is generated when the average received SNR in beacons goes
|
||||
below a threshold, specified by Value.
|
||||
|
||||
extscan
|
||||
This command is used to do a specific scan.
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/
|
||||
|
||||
Usage: echo "SSID" > extscan
|
||||
|
||||
Example:
|
||||
echo "LINKSYS-AP" > extscan
|
||||
|
||||
To see the results of use getscantable command.
|
||||
|
||||
getscantable
|
||||
|
||||
Display the current contents of the driver scan table (ie. get the
|
||||
scan results).
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/
|
||||
|
||||
Usage:
|
||||
cat getscantable
|
||||
|
||||
setuserscan
|
||||
Initiate a customized scan and retrieve the results
|
||||
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/
|
||||
|
||||
Usage:
|
||||
echo "[ARGS]" > setuserscan
|
||||
|
||||
where [ARGS]:
|
||||
|
||||
bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan
|
||||
ssid="[SSID]" specify a SSID filter for the scan
|
||||
keep=[0 or 1] keep the previous scan results (1), discard (0)
|
||||
dur=[scan time] time to scan for each channel in milliseconds
|
||||
type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any)
|
||||
|
||||
Any combination of the above arguments can be supplied on the command
|
||||
line. If dur tokens are absent, the driver default setting will be used.
|
||||
The bssid and ssid fields, if blank, will produce an unfiltered scan.
|
||||
The type field will default to 3 (Any) and the keep field will default
|
||||
to 0 (Discard).
|
||||
|
||||
Examples:
|
||||
1) Perform a passive scan on all channels for 20 ms per channel:
|
||||
echo "dur=20" > setuserscan
|
||||
|
||||
2) Perform an active scan for a specific SSID:
|
||||
echo "ssid="TestAP"" > setuserscan
|
||||
|
||||
3) Scan all available channels (B/G, A bands) for a specific BSSID, keep
|
||||
the current scan table intact, update existing or append new scan data:
|
||||
echo "bssid=00:50:43:20:12:82 keep=1" > setuserscan
|
||||
|
||||
4) Scan for all infrastructure networks.
|
||||
Keep the previous scan table intact. Update any duplicate BSSID/SSID
|
||||
matches with the new scan data:
|
||||
echo "type=1 keep=1" > setuserscan
|
||||
|
||||
All entries in the scan table (not just the new scan data when keep=1)
|
||||
will be displayed upon completion by use of the getscantable ioctl.
|
||||
|
||||
hostsleep
|
||||
This command is used to enable/disable host sleep.
|
||||
Note: Host sleep parameters should be configured using
|
||||
"ethtool -s ethX wol X" command before enabling host sleep.
|
||||
|
||||
Path: /sys/kernel/debug/libertas_wireless/ethX/
|
||||
|
||||
Usage:
|
||||
cat hostsleep: reads the current hostsleep state
|
||||
echo "1" > hostsleep : enable host sleep.
|
||||
echo "0" > hostsleep : disable host sleep
|
||||
|
2216
drivers/net/wireless/libertas/cfg.c
Normal file
2216
drivers/net/wireless/libertas/cfg.c
Normal file
File diff suppressed because it is too large
Load diff
20
drivers/net/wireless/libertas/cfg.h
Normal file
20
drivers/net/wireless/libertas/cfg.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef __LBS_CFG80211_H__
|
||||
#define __LBS_CFG80211_H__
|
||||
|
||||
struct device;
|
||||
struct lbs_private;
|
||||
struct regulatory_request;
|
||||
struct wiphy;
|
||||
|
||||
struct wireless_dev *lbs_cfg_alloc(struct device *dev);
|
||||
int lbs_cfg_register(struct lbs_private *priv);
|
||||
void lbs_cfg_free(struct lbs_private *priv);
|
||||
|
||||
void lbs_send_disconnect_notification(struct lbs_private *priv);
|
||||
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
|
||||
|
||||
void lbs_scan_done(struct lbs_private *priv);
|
||||
void lbs_scan_deinit(struct lbs_private *priv);
|
||||
int lbs_disconnect(struct lbs_private *priv, u16 reason);
|
||||
|
||||
#endif
|
1725
drivers/net/wireless/libertas/cmd.c
Normal file
1725
drivers/net/wireless/libertas/cmd.c
Normal file
File diff suppressed because it is too large
Load diff
140
drivers/net/wireless/libertas/cmd.h
Normal file
140
drivers/net/wireless/libertas/cmd.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* Copyright (C) 2007, Red Hat, Inc. */
|
||||
|
||||
#ifndef _LBS_CMD_H_
|
||||
#define _LBS_CMD_H_
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "dev.h"
|
||||
|
||||
|
||||
/* Command & response transfer between host and card */
|
||||
|
||||
struct cmd_ctrl_node {
|
||||
struct list_head list;
|
||||
int result;
|
||||
/* command response */
|
||||
int (*callback)(struct lbs_private *,
|
||||
unsigned long,
|
||||
struct cmd_header *);
|
||||
unsigned long callback_arg;
|
||||
/* command data */
|
||||
struct cmd_header *cmdbuf;
|
||||
/* wait queue */
|
||||
u16 cmdwaitqwoken;
|
||||
wait_queue_head_t cmdwait_q;
|
||||
};
|
||||
|
||||
|
||||
/* lbs_cmd() infers the size of the buffer to copy data back into, from
|
||||
the size of the target of the pointer. Since the command to be sent
|
||||
may often be smaller, that size is set in cmd->size by the caller.*/
|
||||
#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
|
||||
uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
|
||||
(cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \
|
||||
__lbs_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
|
||||
})
|
||||
|
||||
#define lbs_cmd_with_response(priv, cmdnr, cmd) \
|
||||
lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
|
||||
|
||||
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
|
||||
struct cmd_header *in_cmd, int in_cmd_size);
|
||||
|
||||
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
|
||||
struct cmd_header *in_cmd, int in_cmd_size,
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
|
||||
unsigned long callback_arg);
|
||||
|
||||
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
|
||||
uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
|
||||
unsigned long callback_arg);
|
||||
|
||||
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
|
||||
struct cmd_header *resp);
|
||||
|
||||
int lbs_allocate_cmd_buffer(struct lbs_private *priv);
|
||||
int lbs_free_cmd_buffer(struct lbs_private *priv);
|
||||
|
||||
int lbs_execute_next_command(struct lbs_private *priv);
|
||||
void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
|
||||
int result);
|
||||
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
|
||||
int result);
|
||||
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
|
||||
|
||||
|
||||
/* From cmdresp.c */
|
||||
|
||||
void lbs_mac_event_disconnected(struct lbs_private *priv);
|
||||
|
||||
|
||||
|
||||
/* Events */
|
||||
|
||||
int lbs_process_event(struct lbs_private *priv, u32 event);
|
||||
|
||||
|
||||
/* Actual commands */
|
||||
|
||||
int lbs_update_hw_spec(struct lbs_private *priv);
|
||||
|
||||
int lbs_set_channel(struct lbs_private *priv, u8 channel);
|
||||
|
||||
int lbs_update_channel(struct lbs_private *priv);
|
||||
|
||||
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
|
||||
struct wol_config *p_wol_config);
|
||||
|
||||
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct sleep_params *sp);
|
||||
|
||||
void lbs_ps_confirm_sleep(struct lbs_private *priv);
|
||||
|
||||
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
|
||||
|
||||
void lbs_set_mac_control(struct lbs_private *priv);
|
||||
int lbs_set_mac_control_sync(struct lbs_private *priv);
|
||||
|
||||
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
|
||||
s16 *maxlevel);
|
||||
|
||||
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
|
||||
|
||||
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
|
||||
|
||||
|
||||
/* Commands only used in wext.c, assoc. and scan.c */
|
||||
|
||||
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
|
||||
int8_t p1, int8_t p2);
|
||||
|
||||
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
|
||||
int8_t p2, int usesnr);
|
||||
|
||||
int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
|
||||
|
||||
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
|
||||
uint16_t cmd_action);
|
||||
|
||||
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
|
||||
|
||||
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
|
||||
|
||||
int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep);
|
||||
|
||||
int lbs_set_monitor_mode(struct lbs_private *priv, int enable);
|
||||
|
||||
int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf);
|
||||
|
||||
int lbs_set_11d_domain_info(struct lbs_private *priv);
|
||||
|
||||
int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);
|
||||
|
||||
int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value);
|
||||
|
||||
int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block);
|
||||
|
||||
#endif /* _LBS_CMD_H */
|
350
drivers/net/wireless/libertas/cmdresp.c
Normal file
350
drivers/net/wireless/libertas/cmdresp.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* This file contains the handling of command
|
||||
* responses as well as events generated by firmware.
|
||||
*/
|
||||
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "cfg.h"
|
||||
#include "cmd.h"
|
||||
|
||||
/**
|
||||
* lbs_mac_event_disconnected - handles disconnect event. It
|
||||
* reports disconnect to upper layer, clean tx/rx packets,
|
||||
* reset link state etc.
|
||||
*
|
||||
* @priv: A pointer to struct lbs_private structure
|
||||
*
|
||||
* returns: n/a
|
||||
*/
|
||||
void lbs_mac_event_disconnected(struct lbs_private *priv)
|
||||
{
|
||||
if (priv->connect_status != LBS_CONNECTED)
|
||||
return;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
/*
|
||||
* Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
|
||||
* It causes problem in the Supplicant
|
||||
*/
|
||||
msleep_interruptible(1000);
|
||||
|
||||
if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
|
||||
lbs_send_disconnect_notification(priv);
|
||||
|
||||
/* report disconnect to upper layer */
|
||||
netif_stop_queue(priv->dev);
|
||||
netif_carrier_off(priv->dev);
|
||||
|
||||
/* Free Tx and Rx packets */
|
||||
kfree_skb(priv->currenttxskb);
|
||||
priv->currenttxskb = NULL;
|
||||
priv->tx_pending_len = 0;
|
||||
|
||||
priv->connect_status = LBS_DISCONNECTED;
|
||||
|
||||
if (priv->psstate != PS_STATE_FULL_POWER) {
|
||||
/* make firmware to exit PS mode */
|
||||
lbs_deb_cmd("disconnected, so exit PS mode\n");
|
||||
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
|
||||
}
|
||||
lbs_deb_leave(LBS_DEB_ASSOC);
|
||||
}
|
||||
|
||||
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
|
||||
{
|
||||
uint16_t respcmd, curcmd;
|
||||
struct cmd_header *resp;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
uint16_t result;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_HOST);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (!priv->cur_cmd) {
|
||||
lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
|
||||
ret = -1;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
goto done;
|
||||
}
|
||||
|
||||
resp = (void *)data;
|
||||
curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
|
||||
respcmd = le16_to_cpu(resp->command);
|
||||
result = le16_to_cpu(resp->result);
|
||||
|
||||
lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
|
||||
respcmd, le16_to_cpu(resp->seqnum), len);
|
||||
lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
|
||||
|
||||
if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
|
||||
netdev_info(priv->dev,
|
||||
"Received CMD_RESP with invalid sequence %d (expected %d)\n",
|
||||
le16_to_cpu(resp->seqnum),
|
||||
le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
if (respcmd != CMD_RET(curcmd) &&
|
||||
respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
|
||||
netdev_info(priv->dev, "Invalid CMD_RESP %x to command %x!\n",
|
||||
respcmd, curcmd);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (resp->result == cpu_to_le16(0x0004)) {
|
||||
/* 0x0004 means -EAGAIN. Drop the response, let it time out
|
||||
and be resubmitted */
|
||||
netdev_info(priv->dev,
|
||||
"Firmware returns DEFER to command %x. Will let it time out...\n",
|
||||
le16_to_cpu(resp->command));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now we got response from FW, cancel the command timer */
|
||||
del_timer(&priv->command_timer);
|
||||
priv->cmd_timed_out = 0;
|
||||
|
||||
if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
|
||||
struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
|
||||
u16 action = le16_to_cpu(psmode->action);
|
||||
|
||||
lbs_deb_host(
|
||||
"CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
|
||||
result, action);
|
||||
|
||||
if (result) {
|
||||
lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
|
||||
result);
|
||||
/*
|
||||
* We should not re-try enter-ps command in
|
||||
* ad-hoc mode. It takes place in
|
||||
* lbs_execute_next_command().
|
||||
*/
|
||||
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
|
||||
action == PS_MODE_ACTION_ENTER_PS)
|
||||
priv->psmode = LBS802_11POWERMODECAM;
|
||||
} else if (action == PS_MODE_ACTION_ENTER_PS) {
|
||||
priv->needtowakeup = 0;
|
||||
priv->psstate = PS_STATE_AWAKE;
|
||||
|
||||
lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
|
||||
if (priv->connect_status != LBS_CONNECTED) {
|
||||
/*
|
||||
* When Deauth Event received before Enter_PS command
|
||||
* response, We need to wake up the firmware.
|
||||
*/
|
||||
lbs_deb_host(
|
||||
"disconnected, invoking lbs_ps_wakeup\n");
|
||||
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
mutex_unlock(&priv->lock);
|
||||
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS,
|
||||
false);
|
||||
mutex_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
}
|
||||
} else if (action == PS_MODE_ACTION_EXIT_PS) {
|
||||
priv->needtowakeup = 0;
|
||||
priv->psstate = PS_STATE_FULL_POWER;
|
||||
lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
|
||||
} else {
|
||||
lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
|
||||
}
|
||||
|
||||
__lbs_complete_command(priv, priv->cur_cmd, result);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If the command is not successful, cleanup and return failure */
|
||||
if ((result != 0 || !(respcmd & 0x8000))) {
|
||||
lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
|
||||
result, respcmd);
|
||||
/*
|
||||
* Handling errors here
|
||||
*/
|
||||
switch (respcmd) {
|
||||
case CMD_RET(CMD_GET_HW_SPEC):
|
||||
case CMD_RET(CMD_802_11_RESET):
|
||||
lbs_deb_host("CMD_RESP: reset failed\n");
|
||||
break;
|
||||
|
||||
}
|
||||
__lbs_complete_command(priv, priv->cur_cmd, result);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
if (priv->cur_cmd && priv->cur_cmd->callback) {
|
||||
ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
|
||||
resp);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (priv->cur_cmd) {
|
||||
/* Clean up and Put current command back to cmdfreeq */
|
||||
__lbs_complete_command(priv, priv->cur_cmd, result);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
done:
|
||||
mutex_unlock(&priv->lock);
|
||||
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_process_event(struct lbs_private *priv, u32 event)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cmd_header cmd;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
switch (event) {
|
||||
case MACREG_INT_CODE_LINK_SENSED:
|
||||
lbs_deb_cmd("EVENT: link sensed\n");
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_DEAUTHENTICATED:
|
||||
lbs_deb_cmd("EVENT: deauthenticated\n");
|
||||
lbs_mac_event_disconnected(priv);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_DISASSOCIATED:
|
||||
lbs_deb_cmd("EVENT: disassociated\n");
|
||||
lbs_mac_event_disconnected(priv);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
|
||||
lbs_deb_cmd("EVENT: link lost\n");
|
||||
lbs_mac_event_disconnected(priv);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_PS_SLEEP:
|
||||
lbs_deb_cmd("EVENT: ps sleep\n");
|
||||
|
||||
/* handle unexpected PS SLEEP event */
|
||||
if (priv->psstate == PS_STATE_FULL_POWER) {
|
||||
lbs_deb_cmd(
|
||||
"EVENT: in FULL POWER mode, ignoring PS_SLEEP\n");
|
||||
break;
|
||||
}
|
||||
priv->psstate = PS_STATE_PRE_SLEEP;
|
||||
|
||||
lbs_ps_confirm_sleep(priv);
|
||||
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_HOST_AWAKE:
|
||||
lbs_deb_cmd("EVENT: host awake\n");
|
||||
if (priv->reset_deep_sleep_wakeup)
|
||||
priv->reset_deep_sleep_wakeup(priv);
|
||||
priv->is_deep_sleep = 0;
|
||||
lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd,
|
||||
sizeof(cmd));
|
||||
priv->is_host_sleep_activated = 0;
|
||||
wake_up_interruptible(&priv->host_sleep_q);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
|
||||
if (priv->reset_deep_sleep_wakeup)
|
||||
priv->reset_deep_sleep_wakeup(priv);
|
||||
lbs_deb_cmd("EVENT: ds awake\n");
|
||||
priv->is_deep_sleep = 0;
|
||||
priv->wakeup_dev_required = 0;
|
||||
wake_up_interruptible(&priv->ds_awake_q);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_PS_AWAKE:
|
||||
lbs_deb_cmd("EVENT: ps awake\n");
|
||||
/* handle unexpected PS AWAKE event */
|
||||
if (priv->psstate == PS_STATE_FULL_POWER) {
|
||||
lbs_deb_cmd(
|
||||
"EVENT: In FULL POWER mode - ignore PS AWAKE\n");
|
||||
break;
|
||||
}
|
||||
|
||||
priv->psstate = PS_STATE_AWAKE;
|
||||
|
||||
if (priv->needtowakeup) {
|
||||
/*
|
||||
* wait for the command processing to finish
|
||||
* before resuming sending
|
||||
* priv->needtowakeup will be set to FALSE
|
||||
* in lbs_ps_wakeup()
|
||||
*/
|
||||
lbs_deb_cmd("waking up ...\n");
|
||||
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_MIC_ERR_UNICAST:
|
||||
lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
|
||||
lbs_send_mic_failureevent(priv, event);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_MIC_ERR_MULTICAST:
|
||||
lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
|
||||
lbs_send_mic_failureevent(priv, event);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_MIB_CHANGED:
|
||||
lbs_deb_cmd("EVENT: MIB CHANGED\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_INIT_DONE:
|
||||
lbs_deb_cmd("EVENT: INIT DONE\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_ADHOC_BCN_LOST:
|
||||
lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_RSSI_LOW:
|
||||
netdev_alert(priv->dev, "EVENT: rssi low\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_SNR_LOW:
|
||||
netdev_alert(priv->dev, "EVENT: snr low\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_MAX_FAIL:
|
||||
netdev_alert(priv->dev, "EVENT: max fail\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_RSSI_HIGH:
|
||||
netdev_alert(priv->dev, "EVENT: rssi high\n");
|
||||
break;
|
||||
case MACREG_INT_CODE_SNR_HIGH:
|
||||
netdev_alert(priv->dev, "EVENT: snr high\n");
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_MESH_AUTO_STARTED:
|
||||
/* Ignore spurious autostart events */
|
||||
netdev_info(priv->dev, "EVENT: MESH_AUTO_STARTED (ignoring)\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
netdev_alert(priv->dev, "EVENT: unknown event id %d\n", event);
|
||||
break;
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
990
drivers/net/wireless/libertas/debugfs.c
Normal file
990
drivers/net/wireless/libertas/debugfs.c
Normal file
|
@ -0,0 +1,990 @@
|
|||
#include <linux/dcache.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "decl.h"
|
||||
#include "cmd.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
static struct dentry *lbs_dir;
|
||||
static char *szStates[] = {
|
||||
"Connected",
|
||||
"Disconnected"
|
||||
};
|
||||
|
||||
#ifdef PROC_DEBUG
|
||||
static void lbs_debug_init(struct lbs_private *priv);
|
||||
#endif
|
||||
|
||||
static ssize_t write_file_dummy(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const size_t len = PAGE_SIZE;
|
||||
|
||||
static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
size_t pos = 0;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
ssize_t res;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += snprintf(buf+pos, len-pos, "state = %s\n",
|
||||
szStates[priv->connect_status]);
|
||||
pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
|
||||
(u32) priv->regioncode);
|
||||
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t lbs_sleepparams_write(struct file *file,
|
||||
const char __user *user_buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t buf_size, ret;
|
||||
struct sleep_params sp;
|
||||
int p1, p2, p3, p4, p5, p6;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size)) {
|
||||
ret = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
|
||||
if (ret != 6) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
sp.sp_error = p1;
|
||||
sp.sp_offset = p2;
|
||||
sp.sp_stabletime = p3;
|
||||
sp.sp_calcontrol = p4;
|
||||
sp.sp_extsleepclk = p5;
|
||||
sp.sp_reserved = p6;
|
||||
|
||||
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
|
||||
if (!ret)
|
||||
ret = count;
|
||||
else if (ret > 0)
|
||||
ret = -EINVAL;
|
||||
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t ret;
|
||||
size_t pos = 0;
|
||||
struct sleep_params sp;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
|
||||
sp.sp_offset, sp.sp_stabletime,
|
||||
sp.sp_calcontrol, sp.sp_extsleepclk,
|
||||
sp.sp_reserved);
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_host_sleep_write(struct file *file,
|
||||
const char __user *user_buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t buf_size, ret;
|
||||
int host_sleep;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size)) {
|
||||
ret = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
ret = sscanf(buf, "%d", &host_sleep);
|
||||
if (ret != 1) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (host_sleep == 0)
|
||||
ret = lbs_set_host_sleep(priv, 0);
|
||||
else if (host_sleep == 1) {
|
||||
if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
|
||||
netdev_info(priv->dev,
|
||||
"wake parameters not configured\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
ret = lbs_set_host_sleep(priv, 1);
|
||||
} else {
|
||||
netdev_err(priv->dev, "invalid option\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ret = count;
|
||||
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_host_sleep_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t ret;
|
||||
size_t pos = 0;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += snprintf(buf, len, "%d\n", priv->is_host_sleep_activated);
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
free_page(addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
|
||||
* get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
|
||||
* firmware. Here's an example:
|
||||
* 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
|
||||
* 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
*
|
||||
* The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
|
||||
* 00 00 are the data bytes of this TLV. For this TLV, their meaning is
|
||||
* defined in mrvlietypes_thresholds
|
||||
*
|
||||
* This function searches in this TLV data chunk for a given TLV type
|
||||
* and returns a pointer to the first data byte of the TLV, or to NULL
|
||||
* if the TLV hasn't been found.
|
||||
*/
|
||||
static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
|
||||
{
|
||||
struct mrvl_ie_header *tlv_h;
|
||||
uint16_t length;
|
||||
ssize_t pos = 0;
|
||||
|
||||
while (pos < size) {
|
||||
tlv_h = (struct mrvl_ie_header *) tlv;
|
||||
if (!tlv_h->len)
|
||||
return NULL;
|
||||
if (tlv_h->type == cpu_to_le16(tlv_type))
|
||||
return tlv_h;
|
||||
length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
|
||||
pos += length;
|
||||
tlv += length;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct cmd_ds_802_11_subscribe_event *subscribed;
|
||||
struct mrvl_ie_thresholds *got;
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t ret = 0;
|
||||
size_t pos = 0;
|
||||
char *buf;
|
||||
u8 value;
|
||||
u8 freq;
|
||||
int events = 0;
|
||||
|
||||
buf = (char *)get_zeroed_page(GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
|
||||
if (!subscribed) {
|
||||
ret = -ENOMEM;
|
||||
goto out_page;
|
||||
}
|
||||
|
||||
subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
|
||||
subscribed->action = cpu_to_le16(CMD_ACT_GET);
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
|
||||
if (ret)
|
||||
goto out_cmd;
|
||||
|
||||
got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
|
||||
if (got) {
|
||||
value = got->value;
|
||||
freq = got->freq;
|
||||
events = le16_to_cpu(subscribed->events);
|
||||
|
||||
pos += snprintf(buf, len, "%d %d %d\n", value, freq,
|
||||
!!(events & event_mask));
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
out_cmd:
|
||||
kfree(subscribed);
|
||||
|
||||
out_page:
|
||||
free_page((unsigned long)buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
|
||||
struct file *file,
|
||||
const char __user *userbuf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct cmd_ds_802_11_subscribe_event *events;
|
||||
struct mrvl_ie_thresholds *tlv;
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t buf_size;
|
||||
int value, freq, new_mask;
|
||||
uint16_t curr_mask;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
buf = (char *)get_zeroed_page(GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
ret = -EFAULT;
|
||||
goto out_page;
|
||||
}
|
||||
ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
|
||||
if (ret != 3) {
|
||||
ret = -EINVAL;
|
||||
goto out_page;
|
||||
}
|
||||
events = kzalloc(sizeof(*events), GFP_KERNEL);
|
||||
if (!events) {
|
||||
ret = -ENOMEM;
|
||||
goto out_page;
|
||||
}
|
||||
|
||||
events->hdr.size = cpu_to_le16(sizeof(*events));
|
||||
events->action = cpu_to_le16(CMD_ACT_GET);
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
|
||||
if (ret)
|
||||
goto out_events;
|
||||
|
||||
curr_mask = le16_to_cpu(events->events);
|
||||
|
||||
if (new_mask)
|
||||
new_mask = curr_mask | event_mask;
|
||||
else
|
||||
new_mask = curr_mask & ~event_mask;
|
||||
|
||||
/* Now everything is set and we can send stuff down to the firmware */
|
||||
|
||||
tlv = (void *)events->tlv;
|
||||
|
||||
events->action = cpu_to_le16(CMD_ACT_SET);
|
||||
events->events = cpu_to_le16(new_mask);
|
||||
tlv->header.type = cpu_to_le16(tlv_type);
|
||||
tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
|
||||
tlv->value = value;
|
||||
if (tlv_type != TLV_TYPE_BCNMISS)
|
||||
tlv->freq = freq;
|
||||
|
||||
/* The command header, the action, the event mask, and one TLV */
|
||||
events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
|
||||
|
||||
if (!ret)
|
||||
ret = count;
|
||||
out_events:
|
||||
kfree(events);
|
||||
out_page:
|
||||
free_page((unsigned long)buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t pos = 0;
|
||||
int ret;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
u32 val = 0;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
|
||||
mdelay(10);
|
||||
if (!ret) {
|
||||
pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
|
||||
priv->mac_offset, val);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
}
|
||||
free_page(addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_rdmac_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res, buf_size;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
priv->mac_offset = simple_strtoul(buf, NULL, 16);
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t lbs_wrmac_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res, buf_size;
|
||||
u32 offset, value;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
res = sscanf(buf, "%x %x", &offset, &value);
|
||||
if (res != 2) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
|
||||
mdelay(10);
|
||||
|
||||
if (!res)
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t pos = 0;
|
||||
int ret;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
u32 val;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
|
||||
mdelay(10);
|
||||
if (!ret) {
|
||||
pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
|
||||
priv->bbp_offset, val);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
}
|
||||
free_page(addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_rdbbp_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res, buf_size;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
priv->bbp_offset = simple_strtoul(buf, NULL, 16);
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t lbs_wrbbp_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res, buf_size;
|
||||
u32 offset, value;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
res = sscanf(buf, "%x %x", &offset, &value);
|
||||
if (res != 2) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
|
||||
mdelay(10);
|
||||
|
||||
if (!res)
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t pos = 0;
|
||||
int ret;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
u32 val;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
|
||||
mdelay(10);
|
||||
if (!ret) {
|
||||
pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
|
||||
priv->rf_offset, val);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
}
|
||||
free_page(addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_rdrf_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res, buf_size;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
priv->rf_offset = simple_strtoul(buf, NULL, 16);
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t lbs_wrrf_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res, buf_size;
|
||||
u32 offset, value;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
res = sscanf(buf, "%x %x", &offset, &value);
|
||||
if (res != 2) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
|
||||
mdelay(10);
|
||||
|
||||
if (!res)
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
#define FOPS(fread, fwrite) { \
|
||||
.owner = THIS_MODULE, \
|
||||
.open = simple_open, \
|
||||
.read = (fread), \
|
||||
.write = (fwrite), \
|
||||
.llseek = generic_file_llseek, \
|
||||
}
|
||||
|
||||
struct lbs_debugfs_files {
|
||||
const char *name;
|
||||
umode_t perm;
|
||||
struct file_operations fops;
|
||||
};
|
||||
|
||||
static const struct lbs_debugfs_files debugfs_files[] = {
|
||||
{ "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
|
||||
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
|
||||
lbs_sleepparams_write), },
|
||||
{ "hostsleep", 0644, FOPS(lbs_host_sleep_read,
|
||||
lbs_host_sleep_write), },
|
||||
};
|
||||
|
||||
static const struct lbs_debugfs_files debugfs_events_files[] = {
|
||||
{"low_rssi", 0644, FOPS(lbs_lowrssi_read,
|
||||
lbs_lowrssi_write), },
|
||||
{"low_snr", 0644, FOPS(lbs_lowsnr_read,
|
||||
lbs_lowsnr_write), },
|
||||
{"failure_count", 0644, FOPS(lbs_failcount_read,
|
||||
lbs_failcount_write), },
|
||||
{"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
|
||||
lbs_bcnmiss_write), },
|
||||
{"high_rssi", 0644, FOPS(lbs_highrssi_read,
|
||||
lbs_highrssi_write), },
|
||||
{"high_snr", 0644, FOPS(lbs_highsnr_read,
|
||||
lbs_highsnr_write), },
|
||||
};
|
||||
|
||||
static const struct lbs_debugfs_files debugfs_regs_files[] = {
|
||||
{"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
|
||||
{"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
|
||||
{"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
|
||||
{"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
|
||||
{"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
|
||||
{"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
|
||||
};
|
||||
|
||||
void lbs_debugfs_init(void)
|
||||
{
|
||||
if (!lbs_dir)
|
||||
lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
|
||||
}
|
||||
|
||||
void lbs_debugfs_remove(void)
|
||||
{
|
||||
if (lbs_dir)
|
||||
debugfs_remove(lbs_dir);
|
||||
}
|
||||
|
||||
void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
|
||||
{
|
||||
int i;
|
||||
const struct lbs_debugfs_files *files;
|
||||
if (!lbs_dir)
|
||||
goto exit;
|
||||
|
||||
priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
|
||||
if (!priv->debugfs_dir)
|
||||
goto exit;
|
||||
|
||||
for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
|
||||
files = &debugfs_files[i];
|
||||
priv->debugfs_files[i] = debugfs_create_file(files->name,
|
||||
files->perm,
|
||||
priv->debugfs_dir,
|
||||
priv,
|
||||
&files->fops);
|
||||
}
|
||||
|
||||
priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
|
||||
if (!priv->events_dir)
|
||||
goto exit;
|
||||
|
||||
for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
|
||||
files = &debugfs_events_files[i];
|
||||
priv->debugfs_events_files[i] = debugfs_create_file(files->name,
|
||||
files->perm,
|
||||
priv->events_dir,
|
||||
priv,
|
||||
&files->fops);
|
||||
}
|
||||
|
||||
priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
|
||||
if (!priv->regs_dir)
|
||||
goto exit;
|
||||
|
||||
for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
|
||||
files = &debugfs_regs_files[i];
|
||||
priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
|
||||
files->perm,
|
||||
priv->regs_dir,
|
||||
priv,
|
||||
&files->fops);
|
||||
}
|
||||
|
||||
#ifdef PROC_DEBUG
|
||||
lbs_debug_init(priv);
|
||||
#endif
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void lbs_debugfs_remove_one(struct lbs_private *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
|
||||
debugfs_remove(priv->debugfs_regs_files[i]);
|
||||
|
||||
debugfs_remove(priv->regs_dir);
|
||||
|
||||
for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
|
||||
debugfs_remove(priv->debugfs_events_files[i]);
|
||||
|
||||
debugfs_remove(priv->events_dir);
|
||||
#ifdef PROC_DEBUG
|
||||
debugfs_remove(priv->debugfs_debug);
|
||||
#endif
|
||||
for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
|
||||
debugfs_remove(priv->debugfs_files[i]);
|
||||
debugfs_remove(priv->debugfs_dir);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* debug entry */
|
||||
|
||||
#ifdef PROC_DEBUG
|
||||
|
||||
#define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
|
||||
#define item_addr(n) (offsetof(struct lbs_private, n))
|
||||
|
||||
|
||||
struct debug_data {
|
||||
char name[32];
|
||||
u32 size;
|
||||
size_t addr;
|
||||
};
|
||||
|
||||
/* To debug any member of struct lbs_private, simply add one line here.
|
||||
*/
|
||||
static struct debug_data items[] = {
|
||||
{"psmode", item_size(psmode), item_addr(psmode)},
|
||||
{"psstate", item_size(psstate), item_addr(psstate)},
|
||||
};
|
||||
|
||||
static int num_of_items = ARRAY_SIZE(items);
|
||||
|
||||
/**
|
||||
* lbs_debugfs_read - proc read function
|
||||
*
|
||||
* @file: file to read
|
||||
* @userbuf: pointer to buffer
|
||||
* @count: number of bytes to read
|
||||
* @ppos: read data starting position
|
||||
*
|
||||
* returns: amount of data read or negative error code
|
||||
*/
|
||||
static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int val = 0;
|
||||
size_t pos = 0;
|
||||
ssize_t res;
|
||||
char *p;
|
||||
int i;
|
||||
struct debug_data *d;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
p = buf;
|
||||
|
||||
d = file->private_data;
|
||||
|
||||
for (i = 0; i < num_of_items; i++) {
|
||||
if (d[i].size == 1)
|
||||
val = *((u8 *) d[i].addr);
|
||||
else if (d[i].size == 2)
|
||||
val = *((u16 *) d[i].addr);
|
||||
else if (d[i].size == 4)
|
||||
val = *((u32 *) d[i].addr);
|
||||
else if (d[i].size == 8)
|
||||
val = *((u64 *) d[i].addr);
|
||||
|
||||
pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
|
||||
}
|
||||
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
|
||||
|
||||
free_page(addr);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* lbs_debugfs_write - proc write function
|
||||
*
|
||||
* @f: file pointer
|
||||
* @buf: pointer to data buffer
|
||||
* @cnt: data number to write
|
||||
* @ppos: file position
|
||||
*
|
||||
* returns: amount of data written
|
||||
*/
|
||||
static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
|
||||
size_t cnt, loff_t *ppos)
|
||||
{
|
||||
int r, i;
|
||||
char *pdata;
|
||||
char *p;
|
||||
char *p0;
|
||||
char *p1;
|
||||
char *p2;
|
||||
struct debug_data *d = f->private_data;
|
||||
|
||||
if (cnt == 0)
|
||||
return 0;
|
||||
|
||||
pdata = kmalloc(cnt + 1, GFP_KERNEL);
|
||||
if (pdata == NULL)
|
||||
return 0;
|
||||
|
||||
if (copy_from_user(pdata, buf, cnt)) {
|
||||
lbs_deb_debugfs("Copy from user failed\n");
|
||||
kfree(pdata);
|
||||
return 0;
|
||||
}
|
||||
pdata[cnt] = '\0';
|
||||
|
||||
p0 = pdata;
|
||||
for (i = 0; i < num_of_items; i++) {
|
||||
do {
|
||||
p = strstr(p0, d[i].name);
|
||||
if (p == NULL)
|
||||
break;
|
||||
p1 = strchr(p, '\n');
|
||||
if (p1 == NULL)
|
||||
break;
|
||||
p0 = p1++;
|
||||
p2 = strchr(p, '=');
|
||||
if (!p2)
|
||||
break;
|
||||
p2++;
|
||||
r = simple_strtoul(p2, NULL, 0);
|
||||
if (d[i].size == 1)
|
||||
*((u8 *) d[i].addr) = (u8) r;
|
||||
else if (d[i].size == 2)
|
||||
*((u16 *) d[i].addr) = (u16) r;
|
||||
else if (d[i].size == 4)
|
||||
*((u32 *) d[i].addr) = (u32) r;
|
||||
else if (d[i].size == 8)
|
||||
*((u64 *) d[i].addr) = (u64) r;
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
kfree(pdata);
|
||||
|
||||
return (ssize_t)cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations lbs_debug_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.write = lbs_debugfs_write,
|
||||
.read = lbs_debugfs_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
/**
|
||||
* lbs_debug_init - create debug proc file
|
||||
*
|
||||
* @priv: pointer to &struct lbs_private
|
||||
*
|
||||
* returns: N/A
|
||||
*/
|
||||
static void lbs_debug_init(struct lbs_private *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!priv->debugfs_dir)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_of_items; i++)
|
||||
items[i].addr += (size_t) priv;
|
||||
|
||||
priv->debugfs_debug = debugfs_create_file("debug", 0644,
|
||||
priv->debugfs_dir, &items[0],
|
||||
&lbs_debug_fops);
|
||||
}
|
||||
#endif
|
10
drivers/net/wireless/libertas/debugfs.h
Normal file
10
drivers/net/wireless/libertas/debugfs.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _LBS_DEBUGFS_H_
|
||||
#define _LBS_DEBUGFS_H_
|
||||
|
||||
void lbs_debugfs_init(void);
|
||||
void lbs_debugfs_remove(void);
|
||||
|
||||
void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev);
|
||||
void lbs_debugfs_remove_one(struct lbs_private *priv);
|
||||
|
||||
#endif
|
82
drivers/net/wireless/libertas/decl.h
Normal file
82
drivers/net/wireless/libertas/decl.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
|
||||
/*
|
||||
* This file contains declaration referring to
|
||||
* functions defined in other source files
|
||||
*/
|
||||
|
||||
#ifndef _LBS_DECL_H_
|
||||
#define _LBS_DECL_H_
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
/* Should be terminated by a NULL entry */
|
||||
struct lbs_fw_table {
|
||||
int model;
|
||||
const char *helper;
|
||||
const char *fwname;
|
||||
};
|
||||
|
||||
struct lbs_private;
|
||||
typedef void (*lbs_fw_cb)(struct lbs_private *priv, int ret,
|
||||
const struct firmware *helper, const struct firmware *mainfw);
|
||||
|
||||
struct lbs_private;
|
||||
struct sk_buff;
|
||||
struct net_device;
|
||||
struct cmd_ds_command;
|
||||
|
||||
|
||||
/* ethtool.c */
|
||||
extern const struct ethtool_ops lbs_ethtool_ops;
|
||||
|
||||
|
||||
/* tx.c */
|
||||
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
|
||||
netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
|
||||
/* rx.c */
|
||||
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
|
||||
|
||||
|
||||
/* main.c */
|
||||
struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
|
||||
void lbs_remove_card(struct lbs_private *priv);
|
||||
int lbs_start_card(struct lbs_private *priv);
|
||||
void lbs_stop_card(struct lbs_private *priv);
|
||||
void lbs_host_to_card_done(struct lbs_private *priv);
|
||||
|
||||
int lbs_start_iface(struct lbs_private *priv);
|
||||
int lbs_stop_iface(struct lbs_private *priv);
|
||||
int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type);
|
||||
|
||||
int lbs_rtap_supported(struct lbs_private *priv);
|
||||
|
||||
int lbs_set_mac_address(struct net_device *dev, void *addr);
|
||||
void lbs_set_multicast_list(struct net_device *dev);
|
||||
void lbs_update_mcast(struct lbs_private *priv);
|
||||
|
||||
int lbs_suspend(struct lbs_private *priv);
|
||||
int lbs_resume(struct lbs_private *priv);
|
||||
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
|
||||
|
||||
int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
|
||||
int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
|
||||
|
||||
u32 lbs_fw_index_to_data_rate(u8 index);
|
||||
u8 lbs_data_rate_to_fw_index(u32 rate);
|
||||
|
||||
int lbs_get_firmware(struct device *dev, u32 card_model,
|
||||
const struct lbs_fw_table *fw_table,
|
||||
const struct firmware **helper,
|
||||
const struct firmware **mainfw);
|
||||
int lbs_get_firmware_async(struct lbs_private *priv, struct device *device,
|
||||
u32 card_model, const struct lbs_fw_table *fw_table,
|
||||
lbs_fw_cb callback);
|
||||
void lbs_wait_for_firmware_load(struct lbs_private *priv);
|
||||
|
||||
#endif
|
394
drivers/net/wireless/libertas/defs.h
Normal file
394
drivers/net/wireless/libertas/defs.h
Normal file
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
* This header file contains global constant/enum definitions,
|
||||
* global variable declaration.
|
||||
*/
|
||||
#ifndef _LBS_DEFS_H_
|
||||
#define _LBS_DEFS_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_LIBERTAS_DEBUG
|
||||
#define DEBUG
|
||||
#define PROC_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef DRV_NAME
|
||||
#define DRV_NAME "libertas"
|
||||
#endif
|
||||
|
||||
|
||||
#define LBS_DEB_ENTER 0x00000001
|
||||
#define LBS_DEB_LEAVE 0x00000002
|
||||
#define LBS_DEB_MAIN 0x00000004
|
||||
#define LBS_DEB_NET 0x00000008
|
||||
#define LBS_DEB_MESH 0x00000010
|
||||
#define LBS_DEB_WEXT 0x00000020
|
||||
#define LBS_DEB_IOCTL 0x00000040
|
||||
#define LBS_DEB_SCAN 0x00000080
|
||||
#define LBS_DEB_ASSOC 0x00000100
|
||||
#define LBS_DEB_JOIN 0x00000200
|
||||
#define LBS_DEB_11D 0x00000400
|
||||
#define LBS_DEB_DEBUGFS 0x00000800
|
||||
#define LBS_DEB_ETHTOOL 0x00001000
|
||||
#define LBS_DEB_HOST 0x00002000
|
||||
#define LBS_DEB_CMD 0x00004000
|
||||
#define LBS_DEB_RX 0x00008000
|
||||
#define LBS_DEB_TX 0x00010000
|
||||
#define LBS_DEB_USB 0x00020000
|
||||
#define LBS_DEB_CS 0x00040000
|
||||
#define LBS_DEB_FW 0x00080000
|
||||
#define LBS_DEB_THREAD 0x00100000
|
||||
#define LBS_DEB_HEX 0x00200000
|
||||
#define LBS_DEB_SDIO 0x00400000
|
||||
#define LBS_DEB_SYSFS 0x00800000
|
||||
#define LBS_DEB_SPI 0x01000000
|
||||
#define LBS_DEB_CFG80211 0x02000000
|
||||
|
||||
extern unsigned int lbs_debug;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LBS_DEB_LL(grp, grpnam, fmt, args...) \
|
||||
do { if ((lbs_debug & (grp)) == (grp)) \
|
||||
printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
|
||||
in_interrupt() ? " (INT)" : "", ## args); } while (0)
|
||||
#else
|
||||
#define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define lbs_deb_enter(grp) \
|
||||
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
|
||||
#define lbs_deb_enter_args(grp, fmt, args...) \
|
||||
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
|
||||
#define lbs_deb_leave(grp) \
|
||||
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
|
||||
#define lbs_deb_leave_args(grp, fmt, args...) \
|
||||
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
|
||||
__func__, ##args);
|
||||
#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
|
||||
#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
|
||||
#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
|
||||
#define lbs_deb_wext(fmt, args...) LBS_DEB_LL(LBS_DEB_WEXT, " wext", fmt, ##args)
|
||||
#define lbs_deb_ioctl(fmt, args...) LBS_DEB_LL(LBS_DEB_IOCTL, " ioctl", fmt, ##args)
|
||||
#define lbs_deb_scan(fmt, args...) LBS_DEB_LL(LBS_DEB_SCAN, " scan", fmt, ##args)
|
||||
#define lbs_deb_assoc(fmt, args...) LBS_DEB_LL(LBS_DEB_ASSOC, " assoc", fmt, ##args)
|
||||
#define lbs_deb_join(fmt, args...) LBS_DEB_LL(LBS_DEB_JOIN, " join", fmt, ##args)
|
||||
#define lbs_deb_11d(fmt, args...) LBS_DEB_LL(LBS_DEB_11D, " 11d", fmt, ##args)
|
||||
#define lbs_deb_debugfs(fmt, args...) LBS_DEB_LL(LBS_DEB_DEBUGFS, " debugfs", fmt, ##args)
|
||||
#define lbs_deb_ethtool(fmt, args...) LBS_DEB_LL(LBS_DEB_ETHTOOL, " ethtool", fmt, ##args)
|
||||
#define lbs_deb_host(fmt, args...) LBS_DEB_LL(LBS_DEB_HOST, " host", fmt, ##args)
|
||||
#define lbs_deb_cmd(fmt, args...) LBS_DEB_LL(LBS_DEB_CMD, " cmd", fmt, ##args)
|
||||
#define lbs_deb_rx(fmt, args...) LBS_DEB_LL(LBS_DEB_RX, " rx", fmt, ##args)
|
||||
#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, " tx", fmt, ##args)
|
||||
#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, " fw", fmt, ##args)
|
||||
#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usb", fmt, ##args)
|
||||
#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
|
||||
#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args)
|
||||
#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
|
||||
#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
|
||||
#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
|
||||
#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
|
||||
#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void lbs_deb_hex(unsigned int grp, const char *prompt,
|
||||
const u8 *buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (len &&
|
||||
(lbs_debug & LBS_DEB_HEX) &&
|
||||
(lbs_debug & grp))
|
||||
{
|
||||
for (i = 1; i <= len; i++) {
|
||||
if ((i & 0xf) == 1) {
|
||||
if (i != 1)
|
||||
printk("\n");
|
||||
printk(DRV_NAME " %s: ", prompt);
|
||||
}
|
||||
printk("%02x ", (u8) * buf);
|
||||
buf++;
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define lbs_deb_hex(grp,prompt,buf,len) do {} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Buffer Constants */
|
||||
|
||||
/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
|
||||
* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
|
||||
* driver has more local TxPDs. Each TxPD on the host memory is associated
|
||||
* with a Tx control node. The driver maintains 8 RxPD descriptors for
|
||||
* station firmware to store Rx packet information.
|
||||
*
|
||||
* Current version of MAC has a 32x6 multicast address buffer.
|
||||
*
|
||||
* 802.11b can have up to 14 channels, the driver keeps the
|
||||
* BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
|
||||
*/
|
||||
|
||||
#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
|
||||
#define LBS_NUM_CMD_BUFFERS 10
|
||||
#define LBS_CMD_BUFFER_SIZE (2 * 1024)
|
||||
#define MRVDRV_MAX_CHANNEL_SIZE 14
|
||||
#define MRVDRV_ASSOCIATION_TIME_OUT 255
|
||||
#define MRVDRV_SNAP_HEADER_LEN 8
|
||||
|
||||
#define LBS_UPLD_SIZE 2312
|
||||
#define DEV_NAME_LEN 32
|
||||
|
||||
/* Wake criteria for HOST_SLEEP_CFG command */
|
||||
#define EHS_WAKE_ON_BROADCAST_DATA 0x0001
|
||||
#define EHS_WAKE_ON_UNICAST_DATA 0x0002
|
||||
#define EHS_WAKE_ON_MAC_EVENT 0x0004
|
||||
#define EHS_WAKE_ON_MULTICAST_DATA 0x0008
|
||||
#define EHS_REMOVE_WAKEUP 0xFFFFFFFF
|
||||
/* Wake rules for Host_Sleep_CFG command */
|
||||
#define WOL_RULE_NET_TYPE_INFRA_OR_IBSS 0x00
|
||||
#define WOL_RULE_NET_TYPE_MESH 0x10
|
||||
#define WOL_RULE_ADDR_TYPE_BCAST 0x01
|
||||
#define WOL_RULE_ADDR_TYPE_MCAST 0x08
|
||||
#define WOL_RULE_ADDR_TYPE_UCAST 0x02
|
||||
#define WOL_RULE_OP_AND 0x01
|
||||
#define WOL_RULE_OP_OR 0x02
|
||||
#define WOL_RULE_OP_INVALID 0xFF
|
||||
#define WOL_RESULT_VALID_CMD 0
|
||||
#define WOL_RESULT_NOSPC_ERR 1
|
||||
#define WOL_RESULT_EEXIST_ERR 2
|
||||
|
||||
/* Misc constants */
|
||||
/* This section defines 802.11 specific contants */
|
||||
|
||||
#define MRVDRV_MAX_BSS_DESCRIPTS 16
|
||||
#define MRVDRV_MAX_REGION_CODE 6
|
||||
|
||||
#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10
|
||||
|
||||
#define MRVDRV_CHANNELS_PER_SCAN 4
|
||||
#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
|
||||
|
||||
#define MRVDRV_MIN_BEACON_INTERVAL 20
|
||||
#define MRVDRV_MAX_BEACON_INTERVAL 1000
|
||||
#define MRVDRV_BEACON_INTERVAL 100
|
||||
|
||||
#define MARVELL_MESH_IE_LENGTH 9
|
||||
|
||||
/*
|
||||
* Values used to populate the struct mrvl_mesh_ie. The only time you need this
|
||||
* is when enabling the mesh using CMD_MESH_CONFIG.
|
||||
*/
|
||||
#define MARVELL_MESH_IE_TYPE 4
|
||||
#define MARVELL_MESH_IE_SUBTYPE 0
|
||||
#define MARVELL_MESH_IE_VERSION 0
|
||||
#define MARVELL_MESH_PROTO_ID_HWMP 0
|
||||
#define MARVELL_MESH_METRIC_ID 0
|
||||
#define MARVELL_MESH_CAPABILITY 0
|
||||
|
||||
/* INT status Bit Definition */
|
||||
#define MRVDRV_TX_DNLD_RDY 0x0001
|
||||
#define MRVDRV_RX_UPLD_RDY 0x0002
|
||||
#define MRVDRV_CMD_DNLD_RDY 0x0004
|
||||
#define MRVDRV_CMD_UPLD_RDY 0x0008
|
||||
#define MRVDRV_CARDEVENT 0x0010
|
||||
|
||||
/* Automatic TX control default levels */
|
||||
#define POW_ADAPT_DEFAULT_P0 13
|
||||
#define POW_ADAPT_DEFAULT_P1 15
|
||||
#define POW_ADAPT_DEFAULT_P2 18
|
||||
#define TPC_DEFAULT_P0 5
|
||||
#define TPC_DEFAULT_P1 10
|
||||
#define TPC_DEFAULT_P2 13
|
||||
|
||||
/* TxPD status */
|
||||
|
||||
/*
|
||||
* Station firmware use TxPD status field to report final Tx transmit
|
||||
* result, Bit masks are used to present combined situations.
|
||||
*/
|
||||
|
||||
#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
|
||||
#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
|
||||
|
||||
/* Tx mesh flag */
|
||||
/*
|
||||
* Currently we are using normal WDS flag as mesh flag.
|
||||
* TODO: change to proper mesh flag when MAC understands it.
|
||||
*/
|
||||
#define TxPD_CONTROL_WDS_FRAME (1<<17)
|
||||
#define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
|
||||
|
||||
/* Mesh interface ID */
|
||||
#define MESH_IFACE_ID 0x0001
|
||||
/* Mesh id should be in bits 14-13-12 */
|
||||
#define MESH_IFACE_BIT_OFFSET 0x000c
|
||||
/* Mesh enable bit in FW capability */
|
||||
#define MESH_CAPINFO_ENABLE_MASK (1<<16)
|
||||
|
||||
/* FW definition from Marvell v4 */
|
||||
#define MRVL_FW_V4 (0x04)
|
||||
/* FW definition from Marvell v5 */
|
||||
#define MRVL_FW_V5 (0x05)
|
||||
/* FW definition from Marvell v10 */
|
||||
#define MRVL_FW_V10 (0x0a)
|
||||
/* FW major revision definition */
|
||||
#define MRVL_FW_MAJOR_REV(x) ((x)>>24)
|
||||
|
||||
/* RxPD status */
|
||||
|
||||
#define MRVDRV_RXPD_STATUS_OK 0x0001
|
||||
|
||||
/* RxPD status - Received packet types */
|
||||
/* Rx mesh flag */
|
||||
/*
|
||||
* Currently we are using normal WDS flag as mesh flag.
|
||||
* TODO: change to proper mesh flag when MAC understands it.
|
||||
*/
|
||||
#define RxPD_CONTROL_WDS_FRAME (0x40)
|
||||
#define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME
|
||||
|
||||
/* RSSI-related defines */
|
||||
/*
|
||||
* RSSI constants are used to implement 802.11 RSSI threshold
|
||||
* indication. if the Rx packet signal got too weak for 5 consecutive
|
||||
* times, miniport driver (driver) will report this event to wrapper
|
||||
*/
|
||||
|
||||
#define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96)
|
||||
|
||||
/* RTS/FRAG related defines */
|
||||
#define MRVDRV_RTS_MIN_VALUE 0
|
||||
#define MRVDRV_RTS_MAX_VALUE 2347
|
||||
#define MRVDRV_FRAG_MIN_VALUE 256
|
||||
#define MRVDRV_FRAG_MAX_VALUE 2346
|
||||
|
||||
/* This is for firmware specific length */
|
||||
#define EXTRA_LEN 36
|
||||
|
||||
#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
|
||||
(ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
|
||||
|
||||
#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
|
||||
(ETH_FRAME_LEN + sizeof(struct rxpd) \
|
||||
+ MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
|
||||
|
||||
#define CMD_F_HOSTCMD (1 << 0)
|
||||
#define FW_CAPINFO_WPA (1 << 0)
|
||||
#define FW_CAPINFO_PS (1 << 1)
|
||||
#define FW_CAPINFO_FIRMWARE_UPGRADE (1 << 13)
|
||||
#define FW_CAPINFO_BOOT2_UPGRADE (1<<14)
|
||||
#define FW_CAPINFO_PERSISTENT_CONFIG (1<<15)
|
||||
|
||||
#define KEY_LEN_WPA_AES 16
|
||||
#define KEY_LEN_WPA_TKIP 32
|
||||
#define KEY_LEN_WEP_104 13
|
||||
#define KEY_LEN_WEP_40 5
|
||||
|
||||
#define RF_ANTENNA_1 0x1
|
||||
#define RF_ANTENNA_2 0x2
|
||||
#define RF_ANTENNA_AUTO 0xFFFF
|
||||
|
||||
#define BAND_B (0x01)
|
||||
#define BAND_G (0x02)
|
||||
#define ALL_802_11_BANDS (BAND_B | BAND_G)
|
||||
|
||||
#define MAX_RATES 14
|
||||
|
||||
#define MAX_LEDS 8
|
||||
|
||||
/* Global Variable Declaration */
|
||||
extern const char lbs_driver_version[];
|
||||
extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
|
||||
|
||||
|
||||
/* ENUM definition */
|
||||
/* SNRNF_TYPE */
|
||||
enum SNRNF_TYPE {
|
||||
TYPE_BEACON = 0,
|
||||
TYPE_RXPD,
|
||||
MAX_TYPE_B
|
||||
};
|
||||
|
||||
/* SNRNF_DATA */
|
||||
enum SNRNF_DATA {
|
||||
TYPE_NOAVG = 0,
|
||||
TYPE_AVG,
|
||||
MAX_TYPE_AVG
|
||||
};
|
||||
|
||||
/* LBS_802_11_POWER_MODE */
|
||||
enum LBS_802_11_POWER_MODE {
|
||||
LBS802_11POWERMODECAM,
|
||||
LBS802_11POWERMODEMAX_PSP,
|
||||
LBS802_11POWERMODEFAST_PSP,
|
||||
/* not a real mode, defined as an upper bound */
|
||||
LBS802_11POWEMODEMAX
|
||||
};
|
||||
|
||||
/* PS_STATE */
|
||||
enum PS_STATE {
|
||||
PS_STATE_FULL_POWER,
|
||||
PS_STATE_AWAKE,
|
||||
PS_STATE_PRE_SLEEP,
|
||||
PS_STATE_SLEEP
|
||||
};
|
||||
|
||||
/* DNLD_STATE */
|
||||
enum DNLD_STATE {
|
||||
DNLD_RES_RECEIVED,
|
||||
DNLD_DATA_SENT,
|
||||
DNLD_CMD_SENT,
|
||||
DNLD_BOOTCMD_SENT,
|
||||
};
|
||||
|
||||
/* LBS_MEDIA_STATE */
|
||||
enum LBS_MEDIA_STATE {
|
||||
LBS_CONNECTED,
|
||||
LBS_DISCONNECTED
|
||||
};
|
||||
|
||||
/* LBS_802_11_PRIVACY_FILTER */
|
||||
enum LBS_802_11_PRIVACY_FILTER {
|
||||
LBS802_11PRIVFILTERACCEPTALL,
|
||||
LBS802_11PRIVFILTER8021XWEP
|
||||
};
|
||||
|
||||
/* mv_ms_type */
|
||||
enum mv_ms_type {
|
||||
MVMS_DAT = 0,
|
||||
MVMS_CMD = 1,
|
||||
MVMS_TXDONE = 2,
|
||||
MVMS_EVENT
|
||||
};
|
||||
|
||||
/* KEY_TYPE_ID */
|
||||
enum KEY_TYPE_ID {
|
||||
KEY_TYPE_ID_WEP = 0,
|
||||
KEY_TYPE_ID_TKIP,
|
||||
KEY_TYPE_ID_AES
|
||||
};
|
||||
|
||||
/* KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */
|
||||
enum KEY_INFO_WPA {
|
||||
KEY_INFO_WPA_MCAST = 0x01,
|
||||
KEY_INFO_WPA_UNICAST = 0x02,
|
||||
KEY_INFO_WPA_ENABLED = 0x04
|
||||
};
|
||||
|
||||
/* Default values for fwt commands. */
|
||||
#define FWT_DEFAULT_METRIC 0
|
||||
#define FWT_DEFAULT_DIR 1
|
||||
/* Default Rate, 11Mbps */
|
||||
#define FWT_DEFAULT_RATE 3
|
||||
#define FWT_DEFAULT_SSN 0xffffffff
|
||||
#define FWT_DEFAULT_DSN 0
|
||||
#define FWT_DEFAULT_HOPCOUNT 0
|
||||
#define FWT_DEFAULT_TTL 0
|
||||
#define FWT_DEFAULT_EXPIRATION 0
|
||||
#define FWT_DEFAULT_SLEEPMODE 0
|
||||
#define FWT_DEFAULT_SNR 0
|
||||
|
||||
#endif
|
211
drivers/net/wireless/libertas/dev.h
Normal file
211
drivers/net/wireless/libertas/dev.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* This file contains definitions and data structures specific
|
||||
* to Marvell 802.11 NIC. It contains the Device Information
|
||||
* structure struct lbs_private..
|
||||
*/
|
||||
#ifndef _LBS_DEV_H_
|
||||
#define _LBS_DEV_H_
|
||||
|
||||
#include "defs.h"
|
||||
#include "decl.h"
|
||||
#include "host.h"
|
||||
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
/* sleep_params */
|
||||
struct sleep_params {
|
||||
uint16_t sp_error;
|
||||
uint16_t sp_offset;
|
||||
uint16_t sp_stabletime;
|
||||
uint8_t sp_calcontrol;
|
||||
uint8_t sp_extsleepclk;
|
||||
uint16_t sp_reserved;
|
||||
};
|
||||
|
||||
/* Mesh statistics */
|
||||
struct lbs_mesh_stats {
|
||||
u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
|
||||
u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
|
||||
u32 fwd_drop_ttl; /* Fwd: TTL zero */
|
||||
u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
|
||||
u32 fwd_drop_noroute; /* Fwd: No route to Destination */
|
||||
u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
|
||||
u32 drop_blind; /* Rx: Dropped by blinding table */
|
||||
u32 tx_failed_cnt; /* Tx: Failed transmissions */
|
||||
};
|
||||
|
||||
/* Private structure for the MV device */
|
||||
struct lbs_private {
|
||||
|
||||
/* Basic networking */
|
||||
struct net_device *dev;
|
||||
u32 connect_status;
|
||||
struct work_struct mcast_work;
|
||||
u32 nr_of_multicastmacaddr;
|
||||
u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
|
||||
|
||||
/* CFG80211 */
|
||||
struct wireless_dev *wdev;
|
||||
bool wiphy_registered;
|
||||
struct cfg80211_scan_request *scan_req;
|
||||
u8 assoc_bss[ETH_ALEN];
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
u8 disassoc_reason;
|
||||
|
||||
/* Mesh */
|
||||
struct net_device *mesh_dev; /* Virtual device */
|
||||
#ifdef CONFIG_LIBERTAS_MESH
|
||||
struct lbs_mesh_stats mstats;
|
||||
uint16_t mesh_tlv;
|
||||
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 mesh_ssid_len;
|
||||
u8 mesh_channel;
|
||||
#endif
|
||||
|
||||
/* Debugfs */
|
||||
struct dentry *debugfs_dir;
|
||||
struct dentry *debugfs_debug;
|
||||
struct dentry *debugfs_files[6];
|
||||
struct dentry *events_dir;
|
||||
struct dentry *debugfs_events_files[6];
|
||||
struct dentry *regs_dir;
|
||||
struct dentry *debugfs_regs_files[6];
|
||||
|
||||
/* Hardware debugging */
|
||||
u32 mac_offset;
|
||||
u32 bbp_offset;
|
||||
u32 rf_offset;
|
||||
|
||||
/* Power management */
|
||||
u16 psmode;
|
||||
u32 psstate;
|
||||
u8 needtowakeup;
|
||||
|
||||
/* Deep sleep */
|
||||
int is_deep_sleep;
|
||||
int deep_sleep_required;
|
||||
int is_auto_deep_sleep_enabled;
|
||||
int wakeup_dev_required;
|
||||
int is_activity_detected;
|
||||
int auto_deep_sleep_timeout; /* in ms */
|
||||
wait_queue_head_t ds_awake_q;
|
||||
struct timer_list auto_deepsleep_timer;
|
||||
|
||||
/* Host sleep*/
|
||||
int is_host_sleep_configured;
|
||||
int is_host_sleep_activated;
|
||||
wait_queue_head_t host_sleep_q;
|
||||
|
||||
/* Hardware access */
|
||||
void *card;
|
||||
bool iface_running;
|
||||
u8 fw_ready;
|
||||
u8 surpriseremoved;
|
||||
u8 setup_fw_on_resume;
|
||||
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
|
||||
void (*reset_card) (struct lbs_private *priv);
|
||||
int (*power_save) (struct lbs_private *priv);
|
||||
int (*power_restore) (struct lbs_private *priv);
|
||||
int (*enter_deep_sleep) (struct lbs_private *priv);
|
||||
int (*exit_deep_sleep) (struct lbs_private *priv);
|
||||
int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
|
||||
|
||||
/* Adapter info (from EEPROM) */
|
||||
u32 fwrelease;
|
||||
u32 fwcapinfo;
|
||||
u16 regioncode;
|
||||
u8 current_addr[ETH_ALEN];
|
||||
u8 copied_hwaddr;
|
||||
|
||||
/* Command download */
|
||||
u8 dnld_sent;
|
||||
/* bit0 1/0=data_sent/data_tx_done,
|
||||
bit1 1/0=cmd_sent/cmd_tx_done,
|
||||
all other bits reserved 0 */
|
||||
u16 seqnum;
|
||||
struct cmd_ctrl_node *cmd_array;
|
||||
struct cmd_ctrl_node *cur_cmd;
|
||||
struct list_head cmdfreeq; /* free command buffers */
|
||||
struct list_head cmdpendingq; /* pending command buffers */
|
||||
struct timer_list command_timer;
|
||||
int cmd_timed_out;
|
||||
|
||||
/* Command responses sent from the hardware to the driver */
|
||||
u8 resp_idx;
|
||||
u8 resp_buf[2][LBS_UPLD_SIZE];
|
||||
u32 resp_len[2];
|
||||
|
||||
/* Events sent from hardware to driver */
|
||||
struct kfifo event_fifo;
|
||||
|
||||
/* thread to service interrupts */
|
||||
struct task_struct *main_thread;
|
||||
wait_queue_head_t waitq;
|
||||
struct workqueue_struct *work_thread;
|
||||
|
||||
/* Encryption stuff */
|
||||
u8 authtype_auto;
|
||||
u8 wep_tx_key;
|
||||
u8 wep_key[4][WLAN_KEY_LEN_WEP104];
|
||||
u8 wep_key_len[4];
|
||||
|
||||
/* Wake On LAN */
|
||||
uint32_t wol_criteria;
|
||||
uint8_t wol_gpio;
|
||||
uint8_t wol_gap;
|
||||
bool ehs_remove_supported;
|
||||
|
||||
/* Transmitting */
|
||||
int tx_pending_len; /* -1 while building packet */
|
||||
u8 tx_pending_buf[LBS_UPLD_SIZE];
|
||||
/* protected by hard_start_xmit serialization */
|
||||
u8 txretrycount;
|
||||
struct sk_buff *currenttxskb;
|
||||
struct timer_list tx_lockup_timer;
|
||||
|
||||
/* Locks */
|
||||
struct mutex lock;
|
||||
spinlock_t driver_lock;
|
||||
|
||||
/* NIC/link operation characteristics */
|
||||
u16 mac_control;
|
||||
u8 radio_on;
|
||||
u8 cur_rate;
|
||||
u8 channel;
|
||||
s16 txpower_cur;
|
||||
s16 txpower_min;
|
||||
s16 txpower_max;
|
||||
|
||||
/* Scanning */
|
||||
struct delayed_work scan_work;
|
||||
int scan_channel;
|
||||
/* Queue of things waiting for scan completion */
|
||||
wait_queue_head_t scan_q;
|
||||
/* Whether the scan was initiated internally and not by cfg80211 */
|
||||
bool internal_scan;
|
||||
|
||||
/* Firmware load */
|
||||
u32 fw_model;
|
||||
wait_queue_head_t fw_waitq;
|
||||
struct device *fw_device;
|
||||
const struct firmware *helper_fw;
|
||||
const struct lbs_fw_table *fw_table;
|
||||
const struct lbs_fw_table *fw_iter;
|
||||
lbs_fw_cb fw_callback;
|
||||
};
|
||||
|
||||
extern struct cmd_confirm_sleep confirm_sleep;
|
||||
|
||||
/* Check if there is an interface active. */
|
||||
static inline int lbs_iface_active(struct lbs_private *priv)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = netif_running(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
r |= netif_running(priv->mesh_dev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
120
drivers/net/wireless/libertas/ethtool.c
Normal file
120
drivers/net/wireless/libertas/ethtool.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include <linux/hardirq.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "decl.h"
|
||||
#include "cmd.h"
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
static void lbs_ethtool_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
|
||||
snprintf(info->fw_version, sizeof(info->fw_version),
|
||||
"%u.%u.%u.p%u",
|
||||
priv->fwrelease >> 24 & 0xff,
|
||||
priv->fwrelease >> 16 & 0xff,
|
||||
priv->fwrelease >> 8 & 0xff,
|
||||
priv->fwrelease & 0xff);
|
||||
strlcpy(info->driver, "libertas", sizeof(info->driver));
|
||||
strlcpy(info->version, lbs_driver_version, sizeof(info->version));
|
||||
}
|
||||
|
||||
/*
|
||||
* All 8388 parts have 16KiB EEPROM size at the time of writing.
|
||||
* In case that changes this needs fixing.
|
||||
*/
|
||||
#define LBS_EEPROM_LEN 16384
|
||||
|
||||
static int lbs_ethtool_get_eeprom_len(struct net_device *dev)
|
||||
{
|
||||
return LBS_EEPROM_LEN;
|
||||
}
|
||||
|
||||
static int lbs_ethtool_get_eeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 * bytes)
|
||||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
struct cmd_ds_802_11_eeprom_access cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ETHTOOL);
|
||||
|
||||
if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
|
||||
eeprom->len > LBS_EEPROM_READ_LEN) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
|
||||
LBS_EEPROM_READ_LEN + eeprom->len);
|
||||
cmd.action = cpu_to_le16(CMD_ACT_GET);
|
||||
cmd.offset = cpu_to_le16(eeprom->offset);
|
||||
cmd.len = cpu_to_le16(eeprom->len);
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
|
||||
if (!ret)
|
||||
memcpy(bytes, cmd.value, eeprom->len);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lbs_ethtool_get_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
|
||||
wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
|
||||
|
||||
if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
|
||||
return;
|
||||
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
|
||||
wol->wolopts |= WAKE_UCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
|
||||
wol->wolopts |= WAKE_MCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA)
|
||||
wol->wolopts |= WAKE_BCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT)
|
||||
wol->wolopts |= WAKE_PHY;
|
||||
}
|
||||
|
||||
static int lbs_ethtool_set_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
|
||||
if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
priv->wol_criteria = 0;
|
||||
if (wol->wolopts & WAKE_UCAST)
|
||||
priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA;
|
||||
if (wol->wolopts & WAKE_MCAST)
|
||||
priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA;
|
||||
if (wol->wolopts & WAKE_BCAST)
|
||||
priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA;
|
||||
if (wol->wolopts & WAKE_PHY)
|
||||
priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT;
|
||||
if (wol->wolopts == 0)
|
||||
priv->wol_criteria |= EHS_REMOVE_WAKEUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ethtool_ops lbs_ethtool_ops = {
|
||||
.get_drvinfo = lbs_ethtool_get_drvinfo,
|
||||
.get_eeprom = lbs_ethtool_get_eeprom,
|
||||
.get_eeprom_len = lbs_ethtool_get_eeprom_len,
|
||||
#ifdef CONFIG_LIBERTAS_MESH
|
||||
.get_sset_count = lbs_mesh_ethtool_get_sset_count,
|
||||
.get_ethtool_stats = lbs_mesh_ethtool_get_stats,
|
||||
.get_strings = lbs_mesh_ethtool_get_strings,
|
||||
#endif
|
||||
.get_wol = lbs_ethtool_get_wol,
|
||||
.set_wol = lbs_ethtool_set_wol,
|
||||
};
|
||||
|
227
drivers/net/wireless/libertas/firmware.c
Normal file
227
drivers/net/wireless/libertas/firmware.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Firmware loading and handling functions.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "dev.h"
|
||||
#include "decl.h"
|
||||
|
||||
static void load_next_firmware_from_table(struct lbs_private *private);
|
||||
|
||||
static void lbs_fw_loaded(struct lbs_private *priv, int ret,
|
||||
const struct firmware *helper, const struct firmware *mainfw)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
lbs_deb_fw("firmware load complete, code %d\n", ret);
|
||||
|
||||
/* User must free helper/mainfw */
|
||||
priv->fw_callback(priv, ret, helper, mainfw);
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
priv->fw_callback = NULL;
|
||||
wake_up(&priv->fw_waitq);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
}
|
||||
|
||||
static void do_load_firmware(struct lbs_private *priv, const char *name,
|
||||
void (*cb)(const struct firmware *fw, void *context))
|
||||
{
|
||||
int ret;
|
||||
|
||||
lbs_deb_fw("Requesting %s\n", name);
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, name,
|
||||
priv->fw_device, GFP_KERNEL, priv, cb);
|
||||
if (ret) {
|
||||
lbs_deb_fw("request_firmware_nowait error %d\n", ret);
|
||||
lbs_fw_loaded(priv, ret, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void main_firmware_cb(const struct firmware *firmware, void *context)
|
||||
{
|
||||
struct lbs_private *priv = context;
|
||||
|
||||
if (!firmware) {
|
||||
/* Failed to find firmware: try next table entry */
|
||||
load_next_firmware_from_table(priv);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Firmware found! */
|
||||
lbs_fw_loaded(priv, 0, priv->helper_fw, firmware);
|
||||
if (priv->helper_fw) {
|
||||
release_firmware (priv->helper_fw);
|
||||
priv->helper_fw = NULL;
|
||||
}
|
||||
release_firmware (firmware);
|
||||
}
|
||||
|
||||
static void helper_firmware_cb(const struct firmware *firmware, void *context)
|
||||
{
|
||||
struct lbs_private *priv = context;
|
||||
|
||||
if (!firmware) {
|
||||
/* Failed to find firmware: try next table entry */
|
||||
load_next_firmware_from_table(priv);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Firmware found! */
|
||||
if (priv->fw_iter->fwname) {
|
||||
priv->helper_fw = firmware;
|
||||
do_load_firmware(priv, priv->fw_iter->fwname, main_firmware_cb);
|
||||
} else {
|
||||
/* No main firmware needed for this helper --> success! */
|
||||
lbs_fw_loaded(priv, 0, firmware, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void load_next_firmware_from_table(struct lbs_private *priv)
|
||||
{
|
||||
const struct lbs_fw_table *iter;
|
||||
|
||||
if (!priv->fw_iter)
|
||||
iter = priv->fw_table;
|
||||
else
|
||||
iter = ++priv->fw_iter;
|
||||
|
||||
if (priv->helper_fw) {
|
||||
release_firmware(priv->helper_fw);
|
||||
priv->helper_fw = NULL;
|
||||
}
|
||||
|
||||
next:
|
||||
if (!iter->helper) {
|
||||
/* End of table hit. */
|
||||
lbs_fw_loaded(priv, -ENOENT, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iter->model != priv->fw_model) {
|
||||
iter++;
|
||||
goto next;
|
||||
}
|
||||
|
||||
priv->fw_iter = iter;
|
||||
do_load_firmware(priv, iter->helper, helper_firmware_cb);
|
||||
}
|
||||
|
||||
void lbs_wait_for_firmware_load(struct lbs_private *priv)
|
||||
{
|
||||
wait_event(priv->fw_waitq, priv->fw_callback == NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* lbs_get_firmware_async - Retrieves firmware asynchronously. Can load
|
||||
* either a helper firmware and a main firmware (2-stage), or just the helper.
|
||||
*
|
||||
* @priv: Pointer to lbs_private instance
|
||||
* @dev: A pointer to &device structure
|
||||
* @card_model: Bus-specific card model ID used to filter firmware table
|
||||
* elements
|
||||
* @fw_table: Table of firmware file names and device model numbers
|
||||
* terminated by an entry with a NULL helper name
|
||||
* @callback: User callback to invoke when firmware load succeeds or fails.
|
||||
*/
|
||||
int lbs_get_firmware_async(struct lbs_private *priv, struct device *device,
|
||||
u32 card_model, const struct lbs_fw_table *fw_table,
|
||||
lbs_fw_cb callback)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (priv->fw_callback) {
|
||||
lbs_deb_fw("firmware load already in progress\n");
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
priv->fw_device = device;
|
||||
priv->fw_callback = callback;
|
||||
priv->fw_table = fw_table;
|
||||
priv->fw_iter = NULL;
|
||||
priv->fw_model = card_model;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
lbs_deb_fw("Starting async firmware load\n");
|
||||
load_next_firmware_from_table(priv);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_get_firmware_async);
|
||||
|
||||
/**
|
||||
* lbs_get_firmware - Retrieves two-stage firmware
|
||||
*
|
||||
* @dev: A pointer to &device structure
|
||||
* @card_model: Bus-specific card model ID used to filter firmware table
|
||||
* elements
|
||||
* @fw_table: Table of firmware file names and device model numbers
|
||||
* terminated by an entry with a NULL helper name
|
||||
* @helper: On success, the helper firmware; caller must free
|
||||
* @mainfw: On success, the main firmware; caller must free
|
||||
*
|
||||
* Deprecated: use lbs_get_firmware_async() instead.
|
||||
*
|
||||
* returns: 0 on success, non-zero on failure
|
||||
*/
|
||||
int lbs_get_firmware(struct device *dev, u32 card_model,
|
||||
const struct lbs_fw_table *fw_table,
|
||||
const struct firmware **helper,
|
||||
const struct firmware **mainfw)
|
||||
{
|
||||
const struct lbs_fw_table *iter;
|
||||
int ret;
|
||||
|
||||
BUG_ON(helper == NULL);
|
||||
BUG_ON(mainfw == NULL);
|
||||
|
||||
/* Search for firmware to use from the table. */
|
||||
iter = fw_table;
|
||||
while (iter && iter->helper) {
|
||||
if (iter->model != card_model)
|
||||
goto next;
|
||||
|
||||
if (*helper == NULL) {
|
||||
ret = request_firmware(helper, iter->helper, dev);
|
||||
if (ret)
|
||||
goto next;
|
||||
|
||||
/* If the device has one-stage firmware (ie cf8305) and
|
||||
* we've got it then we don't need to bother with the
|
||||
* main firmware.
|
||||
*/
|
||||
if (iter->fwname == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*mainfw == NULL) {
|
||||
ret = request_firmware(mainfw, iter->fwname, dev);
|
||||
if (ret) {
|
||||
/* Clear the helper to ensure we don't have
|
||||
* mismatched firmware pairs.
|
||||
*/
|
||||
release_firmware(*helper);
|
||||
*helper = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (*helper && *mainfw)
|
||||
return 0;
|
||||
|
||||
next:
|
||||
iter++;
|
||||
}
|
||||
|
||||
/* Failed */
|
||||
release_firmware(*helper);
|
||||
*helper = NULL;
|
||||
release_firmware(*mainfw);
|
||||
*mainfw = NULL;
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_get_firmware);
|
978
drivers/net/wireless/libertas/host.h
Normal file
978
drivers/net/wireless/libertas/host.h
Normal file
|
@ -0,0 +1,978 @@
|
|||
/*
|
||||
* This file function prototypes, data structure
|
||||
* and definitions for all the host/station commands
|
||||
*/
|
||||
|
||||
#ifndef _LBS_HOST_H_
|
||||
#define _LBS_HOST_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "defs.h"
|
||||
|
||||
#define DEFAULT_AD_HOC_CHANNEL 6
|
||||
|
||||
#define CMD_OPTION_WAITFORRSP 0x0002
|
||||
|
||||
/* Host command IDs */
|
||||
|
||||
/*
|
||||
* Return command are almost always the same as the host command, but with
|
||||
* bit 15 set high. There are a few exceptions, though...
|
||||
*/
|
||||
#define CMD_RET(cmd) (0x8000 | cmd)
|
||||
|
||||
/* Return command convention exceptions: */
|
||||
#define CMD_RET_802_11_ASSOCIATE 0x8012
|
||||
|
||||
/* Command codes */
|
||||
#define CMD_GET_HW_SPEC 0x0003
|
||||
#define CMD_EEPROM_UPDATE 0x0004
|
||||
#define CMD_802_11_RESET 0x0005
|
||||
#define CMD_802_11_SCAN 0x0006
|
||||
#define CMD_802_11_GET_LOG 0x000b
|
||||
#define CMD_MAC_MULTICAST_ADR 0x0010
|
||||
#define CMD_802_11_AUTHENTICATE 0x0011
|
||||
#define CMD_802_11_EEPROM_ACCESS 0x0059
|
||||
#define CMD_802_11_ASSOCIATE 0x0050
|
||||
#define CMD_802_11_SET_WEP 0x0013
|
||||
#define CMD_802_11_GET_STAT 0x0014
|
||||
#define CMD_802_3_GET_STAT 0x0015
|
||||
#define CMD_802_11_SNMP_MIB 0x0016
|
||||
#define CMD_MAC_REG_MAP 0x0017
|
||||
#define CMD_BBP_REG_MAP 0x0018
|
||||
#define CMD_MAC_REG_ACCESS 0x0019
|
||||
#define CMD_BBP_REG_ACCESS 0x001a
|
||||
#define CMD_RF_REG_ACCESS 0x001b
|
||||
#define CMD_802_11_RADIO_CONTROL 0x001c
|
||||
#define CMD_802_11_RF_CHANNEL 0x001d
|
||||
#define CMD_802_11_RF_TX_POWER 0x001e
|
||||
#define CMD_802_11_RSSI 0x001f
|
||||
#define CMD_802_11_RF_ANTENNA 0x0020
|
||||
#define CMD_802_11_PS_MODE 0x0021
|
||||
#define CMD_802_11_DATA_RATE 0x0022
|
||||
#define CMD_RF_REG_MAP 0x0023
|
||||
#define CMD_802_11_DEAUTHENTICATE 0x0024
|
||||
#define CMD_802_11_REASSOCIATE 0x0025
|
||||
#define CMD_MAC_CONTROL 0x0028
|
||||
#define CMD_802_11_AD_HOC_START 0x002b
|
||||
#define CMD_802_11_AD_HOC_JOIN 0x002c
|
||||
#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
|
||||
#define CMD_802_11_ENABLE_RSN 0x002f
|
||||
#define CMD_802_11_SET_AFC 0x003c
|
||||
#define CMD_802_11_GET_AFC 0x003d
|
||||
#define CMD_802_11_DEEP_SLEEP 0x003e
|
||||
#define CMD_802_11_AD_HOC_STOP 0x0040
|
||||
#define CMD_802_11_HOST_SLEEP_CFG 0x0043
|
||||
#define CMD_802_11_WAKEUP_CONFIRM 0x0044
|
||||
#define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045
|
||||
#define CMD_802_11_BEACON_STOP 0x0049
|
||||
#define CMD_802_11_MAC_ADDRESS 0x004d
|
||||
#define CMD_802_11_LED_GPIO_CTRL 0x004e
|
||||
#define CMD_802_11_BAND_CONFIG 0x0058
|
||||
#define CMD_GSPI_BUS_CONFIG 0x005a
|
||||
#define CMD_802_11D_DOMAIN_INFO 0x005b
|
||||
#define CMD_802_11_KEY_MATERIAL 0x005e
|
||||
#define CMD_802_11_SLEEP_PARAMS 0x0066
|
||||
#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
|
||||
#define CMD_802_11_SLEEP_PERIOD 0x0068
|
||||
#define CMD_802_11_TPC_CFG 0x0072
|
||||
#define CMD_802_11_PA_CFG 0x0073
|
||||
#define CMD_802_11_FW_WAKE_METHOD 0x0074
|
||||
#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
|
||||
#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
|
||||
#define CMD_802_11_TX_RATE_QUERY 0x007f
|
||||
#define CMD_GET_TSF 0x0080
|
||||
#define CMD_BT_ACCESS 0x0087
|
||||
#define CMD_FWT_ACCESS 0x0095
|
||||
#define CMD_802_11_MONITOR_MODE 0x0098
|
||||
#define CMD_MESH_ACCESS 0x009b
|
||||
#define CMD_MESH_CONFIG_OLD 0x00a3
|
||||
#define CMD_MESH_CONFIG 0x00ac
|
||||
#define CMD_SET_BOOT2_VER 0x00a5
|
||||
#define CMD_FUNC_INIT 0x00a9
|
||||
#define CMD_FUNC_SHUTDOWN 0x00aa
|
||||
#define CMD_802_11_BEACON_CTRL 0x00b0
|
||||
|
||||
/* For the IEEE Power Save */
|
||||
#define PS_MODE_ACTION_ENTER_PS 0x0030
|
||||
#define PS_MODE_ACTION_EXIT_PS 0x0031
|
||||
#define PS_MODE_ACTION_SLEEP_CONFIRMED 0x0034
|
||||
|
||||
#define CMD_ENABLE_RSN 0x0001
|
||||
#define CMD_DISABLE_RSN 0x0000
|
||||
|
||||
#define CMD_ACT_GET 0x0000
|
||||
#define CMD_ACT_SET 0x0001
|
||||
|
||||
/* Define action or option for CMD_802_11_SET_WEP */
|
||||
#define CMD_ACT_ADD 0x0002
|
||||
#define CMD_ACT_REMOVE 0x0004
|
||||
|
||||
#define CMD_TYPE_WEP_40_BIT 0x01
|
||||
#define CMD_TYPE_WEP_104_BIT 0x02
|
||||
|
||||
#define CMD_NUM_OF_WEP_KEYS 4
|
||||
|
||||
#define CMD_WEP_KEY_INDEX_MASK 0x3fff
|
||||
|
||||
/* Define action or option for CMD_802_11_SCAN */
|
||||
#define CMD_BSS_TYPE_BSS 0x0001
|
||||
#define CMD_BSS_TYPE_IBSS 0x0002
|
||||
#define CMD_BSS_TYPE_ANY 0x0003
|
||||
|
||||
/* Define action or option for CMD_802_11_SCAN */
|
||||
#define CMD_SCAN_TYPE_ACTIVE 0x0000
|
||||
#define CMD_SCAN_TYPE_PASSIVE 0x0001
|
||||
|
||||
#define CMD_SCAN_RADIO_TYPE_BG 0
|
||||
|
||||
#define CMD_SCAN_PROBE_DELAY_TIME 0
|
||||
|
||||
/* Define action or option for CMD_MAC_CONTROL */
|
||||
#define CMD_ACT_MAC_RX_ON 0x0001
|
||||
#define CMD_ACT_MAC_TX_ON 0x0002
|
||||
#define CMD_ACT_MAC_LOOPBACK_ON 0x0004
|
||||
#define CMD_ACT_MAC_WEP_ENABLE 0x0008
|
||||
#define CMD_ACT_MAC_INT_ENABLE 0x0010
|
||||
#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020
|
||||
#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040
|
||||
#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
|
||||
#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
|
||||
#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
|
||||
|
||||
/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
|
||||
#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
|
||||
#define CMD_SUBSCRIBE_SNR_LOW 0x0002
|
||||
#define CMD_SUBSCRIBE_FAILCOUNT 0x0004
|
||||
#define CMD_SUBSCRIBE_BCNMISS 0x0008
|
||||
#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
|
||||
#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
|
||||
|
||||
#define RADIO_PREAMBLE_LONG 0x00
|
||||
#define RADIO_PREAMBLE_SHORT 0x02
|
||||
#define RADIO_PREAMBLE_AUTO 0x04
|
||||
|
||||
/* Define action or option for CMD_802_11_RF_CHANNEL */
|
||||
#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
|
||||
#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
|
||||
|
||||
/* Define action or option for CMD_802_11_DATA_RATE */
|
||||
#define CMD_ACT_SET_TX_AUTO 0x0000
|
||||
#define CMD_ACT_SET_TX_FIX_RATE 0x0001
|
||||
#define CMD_ACT_GET_TX_RATE 0x0002
|
||||
|
||||
/* Options for CMD_802_11_FW_WAKE_METHOD */
|
||||
#define CMD_WAKE_METHOD_UNCHANGED 0x0000
|
||||
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
|
||||
#define CMD_WAKE_METHOD_GPIO 0x0002
|
||||
|
||||
/* Object IDs for CMD_802_11_SNMP_MIB */
|
||||
#define SNMP_MIB_OID_BSS_TYPE 0x0000
|
||||
#define SNMP_MIB_OID_OP_RATE_SET 0x0001
|
||||
#define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */
|
||||
#define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */
|
||||
#define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */
|
||||
#define SNMP_MIB_OID_RTS_THRESHOLD 0x0005
|
||||
#define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006
|
||||
#define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007
|
||||
#define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008
|
||||
#define SNMP_MIB_OID_11D_ENABLE 0x0009
|
||||
#define SNMP_MIB_OID_11H_ENABLE 0x000A
|
||||
|
||||
/* Define action or option for CMD_BT_ACCESS */
|
||||
enum cmd_bt_access_opts {
|
||||
/* The bt commands start at 5 instead of 1 because the old dft commands
|
||||
* are mapped to 1-4. These old commands are no longer maintained and
|
||||
* should not be called.
|
||||
*/
|
||||
CMD_ACT_BT_ACCESS_ADD = 5,
|
||||
CMD_ACT_BT_ACCESS_DEL,
|
||||
CMD_ACT_BT_ACCESS_LIST,
|
||||
CMD_ACT_BT_ACCESS_RESET,
|
||||
CMD_ACT_BT_ACCESS_SET_INVERT,
|
||||
CMD_ACT_BT_ACCESS_GET_INVERT
|
||||
};
|
||||
|
||||
/* Define action or option for CMD_FWT_ACCESS */
|
||||
enum cmd_fwt_access_opts {
|
||||
CMD_ACT_FWT_ACCESS_ADD = 1,
|
||||
CMD_ACT_FWT_ACCESS_DEL,
|
||||
CMD_ACT_FWT_ACCESS_LOOKUP,
|
||||
CMD_ACT_FWT_ACCESS_LIST,
|
||||
CMD_ACT_FWT_ACCESS_LIST_ROUTE,
|
||||
CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR,
|
||||
CMD_ACT_FWT_ACCESS_RESET,
|
||||
CMD_ACT_FWT_ACCESS_CLEANUP,
|
||||
CMD_ACT_FWT_ACCESS_TIME,
|
||||
};
|
||||
|
||||
/* Define action or option for CMD_802_11_HOST_SLEEP_CFG */
|
||||
enum cmd_wol_cfg_opts {
|
||||
CMD_ACT_ACTION_NONE = 0,
|
||||
CMD_ACT_SET_WOL_RULE,
|
||||
CMD_ACT_GET_WOL_RULE,
|
||||
CMD_ACT_RESET_WOL_RULE,
|
||||
};
|
||||
|
||||
/* Define action or option for CMD_MESH_ACCESS */
|
||||
enum cmd_mesh_access_opts {
|
||||
CMD_ACT_MESH_GET_TTL = 1,
|
||||
CMD_ACT_MESH_SET_TTL,
|
||||
CMD_ACT_MESH_GET_STATS,
|
||||
CMD_ACT_MESH_GET_ANYCAST,
|
||||
CMD_ACT_MESH_SET_ANYCAST,
|
||||
CMD_ACT_MESH_SET_LINK_COSTS,
|
||||
CMD_ACT_MESH_GET_LINK_COSTS,
|
||||
CMD_ACT_MESH_SET_BCAST_RATE,
|
||||
CMD_ACT_MESH_GET_BCAST_RATE,
|
||||
CMD_ACT_MESH_SET_RREQ_DELAY,
|
||||
CMD_ACT_MESH_GET_RREQ_DELAY,
|
||||
CMD_ACT_MESH_SET_ROUTE_EXP,
|
||||
CMD_ACT_MESH_GET_ROUTE_EXP,
|
||||
CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
|
||||
CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
|
||||
CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT = 17,
|
||||
};
|
||||
|
||||
/* Define actions and types for CMD_MESH_CONFIG */
|
||||
enum cmd_mesh_config_actions {
|
||||
CMD_ACT_MESH_CONFIG_STOP = 0,
|
||||
CMD_ACT_MESH_CONFIG_START,
|
||||
CMD_ACT_MESH_CONFIG_SET,
|
||||
CMD_ACT_MESH_CONFIG_GET,
|
||||
};
|
||||
|
||||
enum cmd_mesh_config_types {
|
||||
CMD_TYPE_MESH_SET_BOOTFLAG = 1,
|
||||
CMD_TYPE_MESH_SET_BOOTTIME,
|
||||
CMD_TYPE_MESH_SET_DEF_CHANNEL,
|
||||
CMD_TYPE_MESH_SET_MESH_IE,
|
||||
CMD_TYPE_MESH_GET_DEFAULTS,
|
||||
CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */
|
||||
};
|
||||
|
||||
/* Card Event definition */
|
||||
#define MACREG_INT_CODE_TX_PPA_FREE 0
|
||||
#define MACREG_INT_CODE_TX_DMA_DONE 1
|
||||
#define MACREG_INT_CODE_LINK_LOST_W_SCAN 2
|
||||
#define MACREG_INT_CODE_LINK_LOST_NO_SCAN 3
|
||||
#define MACREG_INT_CODE_LINK_SENSED 4
|
||||
#define MACREG_INT_CODE_CMD_FINISHED 5
|
||||
#define MACREG_INT_CODE_MIB_CHANGED 6
|
||||
#define MACREG_INT_CODE_INIT_DONE 7
|
||||
#define MACREG_INT_CODE_DEAUTHENTICATED 8
|
||||
#define MACREG_INT_CODE_DISASSOCIATED 9
|
||||
#define MACREG_INT_CODE_PS_AWAKE 10
|
||||
#define MACREG_INT_CODE_PS_SLEEP 11
|
||||
#define MACREG_INT_CODE_MIC_ERR_MULTICAST 13
|
||||
#define MACREG_INT_CODE_MIC_ERR_UNICAST 14
|
||||
#define MACREG_INT_CODE_WM_AWAKE 15
|
||||
#define MACREG_INT_CODE_DEEP_SLEEP_AWAKE 16
|
||||
#define MACREG_INT_CODE_ADHOC_BCN_LOST 17
|
||||
#define MACREG_INT_CODE_HOST_AWAKE 18
|
||||
#define MACREG_INT_CODE_STOP_TX 19
|
||||
#define MACREG_INT_CODE_START_TX 20
|
||||
#define MACREG_INT_CODE_CHANNEL_SWITCH 21
|
||||
#define MACREG_INT_CODE_MEASUREMENT_RDY 22
|
||||
#define MACREG_INT_CODE_WMM_CHANGE 23
|
||||
#define MACREG_INT_CODE_BG_SCAN_REPORT 24
|
||||
#define MACREG_INT_CODE_RSSI_LOW 25
|
||||
#define MACREG_INT_CODE_SNR_LOW 26
|
||||
#define MACREG_INT_CODE_MAX_FAIL 27
|
||||
#define MACREG_INT_CODE_RSSI_HIGH 28
|
||||
#define MACREG_INT_CODE_SNR_HIGH 29
|
||||
#define MACREG_INT_CODE_MESH_AUTO_STARTED 35
|
||||
#define MACREG_INT_CODE_FIRMWARE_READY 48
|
||||
|
||||
|
||||
/* 802.11-related definitions */
|
||||
|
||||
/* TxPD descriptor */
|
||||
struct txpd {
|
||||
/* union to cope up with later FW revisions */
|
||||
union {
|
||||
/* Current Tx packet status */
|
||||
__le32 tx_status;
|
||||
struct {
|
||||
/* BSS type: client, AP, etc. */
|
||||
u8 bss_type;
|
||||
/* BSS number */
|
||||
u8 bss_num;
|
||||
/* Reserved */
|
||||
__le16 reserved;
|
||||
} bss;
|
||||
} u;
|
||||
/* Tx control */
|
||||
__le32 tx_control;
|
||||
__le32 tx_packet_location;
|
||||
/* Tx packet length */
|
||||
__le16 tx_packet_length;
|
||||
/* First 2 byte of destination MAC address */
|
||||
u8 tx_dest_addr_high[2];
|
||||
/* Last 4 byte of destination MAC address */
|
||||
u8 tx_dest_addr_low[4];
|
||||
/* Pkt Priority */
|
||||
u8 priority;
|
||||
/* Pkt Trasnit Power control */
|
||||
u8 powermgmt;
|
||||
/* Amount of time the packet has been queued (units = 2ms) */
|
||||
u8 pktdelay_2ms;
|
||||
/* reserved */
|
||||
u8 reserved1;
|
||||
} __packed;
|
||||
|
||||
/* RxPD Descriptor */
|
||||
struct rxpd {
|
||||
/* union to cope up with later FW revisions */
|
||||
union {
|
||||
/* Current Rx packet status */
|
||||
__le16 status;
|
||||
struct {
|
||||
/* BSS type: client, AP, etc. */
|
||||
u8 bss_type;
|
||||
/* BSS number */
|
||||
u8 bss_num;
|
||||
} __packed bss;
|
||||
} __packed u;
|
||||
|
||||
/* SNR */
|
||||
u8 snr;
|
||||
|
||||
/* Tx control */
|
||||
u8 rx_control;
|
||||
|
||||
/* Pkt length */
|
||||
__le16 pkt_len;
|
||||
|
||||
/* Noise Floor */
|
||||
u8 nf;
|
||||
|
||||
/* Rx Packet Rate */
|
||||
u8 rx_rate;
|
||||
|
||||
/* Pkt addr */
|
||||
__le32 pkt_ptr;
|
||||
|
||||
/* Next Rx RxPD addr */
|
||||
__le32 next_rxpd_ptr;
|
||||
|
||||
/* Pkt Priority */
|
||||
u8 priority;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
struct cmd_header {
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
__le16 seqnum;
|
||||
__le16 result;
|
||||
} __packed;
|
||||
|
||||
/* Generic structure to hold all key types. */
|
||||
struct enc_key {
|
||||
u16 len;
|
||||
u16 flags; /* KEY_INFO_* from defs.h */
|
||||
u16 type; /* KEY_TYPE_* from defs.h */
|
||||
u8 key[32];
|
||||
};
|
||||
|
||||
/* lbs_offset_value */
|
||||
struct lbs_offset_value {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
} __packed;
|
||||
|
||||
#define MAX_11D_TRIPLETS 83
|
||||
|
||||
struct mrvl_ie_domain_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11d_domain_info {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
struct mrvl_ie_domain_param_set domain;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Define data structure for CMD_GET_HW_SPEC
|
||||
* This structure defines the response for the GET_HW_SPEC command
|
||||
*/
|
||||
struct cmd_ds_get_hw_spec {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* HW Interface version number */
|
||||
__le16 hwifversion;
|
||||
/* HW version number */
|
||||
__le16 version;
|
||||
/* Max number of TxPD FW can handle */
|
||||
__le16 nr_txpd;
|
||||
/* Max no of Multicast address */
|
||||
__le16 nr_mcast_adr;
|
||||
/* MAC address */
|
||||
u8 permanentaddr[6];
|
||||
|
||||
/* region Code */
|
||||
__le16 regioncode;
|
||||
|
||||
/* Number of antenna used */
|
||||
__le16 nr_antenna;
|
||||
|
||||
/* FW release number, example 0x01030304 = 2.3.4p1 */
|
||||
__le32 fwrelease;
|
||||
|
||||
/* Base Address of TxPD queue */
|
||||
__le32 wcb_base;
|
||||
/* Read Pointer of RxPd queue */
|
||||
__le32 rxpd_rdptr;
|
||||
|
||||
/* Write Pointer of RxPd queue */
|
||||
__le32 rxpd_wrptr;
|
||||
|
||||
/*FW/HW capability */
|
||||
__le32 fwcapinfo;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_subscribe_event {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 events;
|
||||
|
||||
/* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
|
||||
* number of TLVs. From the v5.1 manual, those TLVs would add up to
|
||||
* 40 bytes. However, future firmware might add additional TLVs, so I
|
||||
* bump this up a bit.
|
||||
*/
|
||||
uint8_t tlv[128];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This scan handle Country Information IE(802.11d compliant)
|
||||
* Define data structure for CMD_802_11_SCAN
|
||||
*/
|
||||
struct cmd_ds_802_11_scan {
|
||||
struct cmd_header hdr;
|
||||
|
||||
uint8_t bsstype;
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint8_t tlvbuffer[0];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_scan_rsp {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 bssdescriptsize;
|
||||
uint8_t nr_sets;
|
||||
uint8_t bssdesc_and_tlvbuffer[0];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_get_log {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le32 mcasttxframe;
|
||||
__le32 failed;
|
||||
__le32 retry;
|
||||
__le32 multiretry;
|
||||
__le32 framedup;
|
||||
__le32 rtssuccess;
|
||||
__le32 rtsfailure;
|
||||
__le32 ackfailure;
|
||||
__le32 rxfrag;
|
||||
__le32 mcastrxframe;
|
||||
__le32 fcserror;
|
||||
__le32 txframe;
|
||||
__le32 wepundecryptable;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_mac_control {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
u16 reserved;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_mac_multicast_adr {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 nr_of_adrs;
|
||||
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_authenticate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 authtype;
|
||||
u8 reserved[10];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_deauthenticate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 macaddr[ETH_ALEN];
|
||||
__le16 reasoncode;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_associate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 bssid[6];
|
||||
__le16 capability;
|
||||
__le16 listeninterval;
|
||||
__le16 bcnperiod;
|
||||
u8 dtimperiod;
|
||||
u8 iebuf[512]; /* Enough for required and most optional IEs */
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_associate_response {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 capability;
|
||||
__le16 statuscode;
|
||||
__le16 aid;
|
||||
u8 iebuf[512];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_set_wep {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
|
||||
__le16 action;
|
||||
|
||||
/* key Index selected for Tx */
|
||||
__le16 keyindex;
|
||||
|
||||
/* 40, 128bit or TXWEP */
|
||||
uint8_t keytype[4];
|
||||
uint8_t keymaterial[4][16];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_snmp_mib {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 oid;
|
||||
__le16 bufsize;
|
||||
u8 value[128];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_reg_access {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 offset;
|
||||
union {
|
||||
u8 bbp_rf; /* for BBP and RF registers */
|
||||
__le32 mac; /* for MAC registers */
|
||||
} value;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_radio_control {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 control;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_beacon_control {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 beacon_enable;
|
||||
__le16 beacon_period;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_sleep_params {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_GET/ACT_SET */
|
||||
__le16 action;
|
||||
|
||||
/* Sleep clock error in ppm */
|
||||
__le16 error;
|
||||
|
||||
/* Wakeup offset in usec */
|
||||
__le16 offset;
|
||||
|
||||
/* Clock stabilization time in usec */
|
||||
__le16 stabletime;
|
||||
|
||||
/* control periodic calibration */
|
||||
uint8_t calcontrol;
|
||||
|
||||
/* control the use of external sleep clock */
|
||||
uint8_t externalsleepclk;
|
||||
|
||||
/* reserved field, should be set to zero */
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_rf_channel {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 channel;
|
||||
__le16 rftype; /* unused */
|
||||
__le16 reserved; /* unused */
|
||||
u8 channellist[32]; /* unused */
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_rssi {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/*
|
||||
* request: number of beacons (N) to average the SNR and NF over
|
||||
* response: SNR of most recent beacon
|
||||
*/
|
||||
__le16 n_or_snr;
|
||||
|
||||
/*
|
||||
* The following fields are only set in the response.
|
||||
* In the request these are reserved and should be set to 0.
|
||||
*/
|
||||
__le16 nf; /* most recent beacon noise floor */
|
||||
__le16 avg_snr; /* average SNR weighted by N from request */
|
||||
__le16 avg_nf; /* average noise floor weighted by N from request */
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_mac_address {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
u8 macadd[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_rf_tx_power {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 curlevel;
|
||||
s8 maxlevel;
|
||||
s8 minlevel;
|
||||
} __packed;
|
||||
|
||||
/* MONITOR_MODE only exists in OLPC v5 firmware */
|
||||
struct cmd_ds_802_11_monitor_mode {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 mode;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_set_boot2_ver {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 version;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_fw_wake_method {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 method;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_ps_mode {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
|
||||
/*
|
||||
* Interval for keepalive in PS mode:
|
||||
* 0x0000 = don't change
|
||||
* 0x001E = firmware default
|
||||
* 0xFFFF = disable
|
||||
*/
|
||||
__le16 nullpktinterval;
|
||||
|
||||
/*
|
||||
* Number of DTIM intervals to wake up for:
|
||||
* 0 = don't change
|
||||
* 1 = firmware default
|
||||
* 5 = max
|
||||
*/
|
||||
__le16 multipledtim;
|
||||
|
||||
__le16 reserved;
|
||||
__le16 locallisteninterval;
|
||||
|
||||
/*
|
||||
* AdHoc awake period (FW v9+ only):
|
||||
* 0 = don't change
|
||||
* 1 = always awake (IEEE standard behavior)
|
||||
* 2 - 31 = sleep for (n - 1) periods and awake for 1 period
|
||||
* 32 - 254 = invalid
|
||||
* 255 = sleep at each ATIM
|
||||
*/
|
||||
__le16 adhoc_awake_period;
|
||||
} __packed;
|
||||
|
||||
struct cmd_confirm_sleep {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 nullpktinterval;
|
||||
__le16 multipledtim;
|
||||
__le16 reserved;
|
||||
__le16 locallisteninterval;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_data_rate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 reserved;
|
||||
u8 rates[MAX_RATES];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_rate_adapt_rateset {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 enablehwauto;
|
||||
__le16 bitmap;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_start {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 bsstype;
|
||||
__le16 beaconperiod;
|
||||
u8 dtimperiod; /* Reserved on v9 and later */
|
||||
struct ieee_ie_ibss_param_set ibss;
|
||||
u8 reserved1[4];
|
||||
struct ieee_ie_ds_param_set ds;
|
||||
u8 reserved2[4];
|
||||
__le16 probedelay; /* Reserved on v9 and later */
|
||||
__le16 capability;
|
||||
u8 rates[MAX_RATES];
|
||||
u8 tlv_memory_size_pad[100];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_result {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 pad[3];
|
||||
u8 bssid[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct adhoc_bssdesc {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 type;
|
||||
__le16 beaconperiod;
|
||||
u8 dtimperiod;
|
||||
__le64 timestamp;
|
||||
__le64 localtime;
|
||||
struct ieee_ie_ds_param_set ds;
|
||||
u8 reserved1[4];
|
||||
struct ieee_ie_ibss_param_set ibss;
|
||||
u8 reserved2[4];
|
||||
__le16 capability;
|
||||
u8 rates[MAX_RATES];
|
||||
|
||||
/*
|
||||
* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
|
||||
* Adhoc join command and will cause a binary layout mismatch with
|
||||
* the firmware
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_join {
|
||||
struct cmd_header hdr;
|
||||
|
||||
struct adhoc_bssdesc bss;
|
||||
__le16 failtimeout; /* Reserved on v9 and later */
|
||||
__le16 probedelay; /* Reserved on v9 and later */
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_stop {
|
||||
struct cmd_header hdr;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_enable_rsn {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 enable;
|
||||
} __packed;
|
||||
|
||||
struct MrvlIEtype_keyParamSet {
|
||||
/* type ID */
|
||||
__le16 type;
|
||||
|
||||
/* length of Payload */
|
||||
__le16 length;
|
||||
|
||||
/* type of key: WEP=0, TKIP=1, AES=2 */
|
||||
__le16 keytypeid;
|
||||
|
||||
/* key control Info specific to a keytypeid */
|
||||
__le16 keyinfo;
|
||||
|
||||
/* length of key */
|
||||
__le16 keylen;
|
||||
|
||||
/* key material of size keylen */
|
||||
u8 key[32];
|
||||
} __packed;
|
||||
|
||||
#define MAX_WOL_RULES 16
|
||||
|
||||
struct host_wol_rule {
|
||||
uint8_t rule_no;
|
||||
uint8_t rule_ops;
|
||||
__le16 sig_offset;
|
||||
__le16 sig_length;
|
||||
__le16 reserve;
|
||||
__be32 sig_mask;
|
||||
__be32 signature;
|
||||
} __packed;
|
||||
|
||||
struct wol_config {
|
||||
uint8_t action;
|
||||
uint8_t pattern;
|
||||
uint8_t no_rules_in_cmd;
|
||||
uint8_t result;
|
||||
struct host_wol_rule rule[MAX_WOL_RULES];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_host_sleep {
|
||||
struct cmd_header hdr;
|
||||
__le32 criteria;
|
||||
uint8_t gpio;
|
||||
uint16_t gap;
|
||||
struct wol_config wol_conf;
|
||||
} __packed;
|
||||
|
||||
|
||||
|
||||
struct cmd_ds_802_11_key_material {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
struct MrvlIEtype_keyParamSet keyParamSet[2];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_eeprom_access {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 offset;
|
||||
__le16 len;
|
||||
/* firmware says it returns a maximum of 20 bytes */
|
||||
#define LBS_EEPROM_READ_LEN 20
|
||||
u8 value[LBS_EEPROM_READ_LEN];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_tpc_cfg {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
uint8_t enable;
|
||||
int8_t P0;
|
||||
int8_t P1;
|
||||
int8_t P2;
|
||||
uint8_t usesnr;
|
||||
} __packed;
|
||||
|
||||
|
||||
struct cmd_ds_802_11_pa_cfg {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
uint8_t enable;
|
||||
int8_t P0;
|
||||
int8_t P1;
|
||||
int8_t P2;
|
||||
} __packed;
|
||||
|
||||
|
||||
struct cmd_ds_802_11_led_ctrl {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 numled;
|
||||
u8 data[256];
|
||||
} __packed;
|
||||
|
||||
/* Automatic Frequency Control */
|
||||
struct cmd_ds_802_11_afc {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 afc_auto;
|
||||
union {
|
||||
struct {
|
||||
__le16 threshold;
|
||||
__le16 period;
|
||||
};
|
||||
struct {
|
||||
__le16 timing_offset; /* signed */
|
||||
__le16 carrier_offset; /* signed */
|
||||
};
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_tx_rate_query {
|
||||
__le16 txrate;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_get_tsf {
|
||||
__le64 tsfvalue;
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_bt_access {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le32 id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_fwt_access {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le32 id;
|
||||
u8 valid;
|
||||
u8 da[ETH_ALEN];
|
||||
u8 dir;
|
||||
u8 ra[ETH_ALEN];
|
||||
__le32 ssn;
|
||||
__le32 dsn;
|
||||
__le32 metric;
|
||||
u8 rate;
|
||||
u8 hopcount;
|
||||
u8 ttl;
|
||||
__le32 expiration;
|
||||
u8 sleepmode;
|
||||
__le32 snr;
|
||||
__le32 references;
|
||||
u8 prec[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_mesh_config {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 channel;
|
||||
__le16 type;
|
||||
__le16 length;
|
||||
u8 data[128]; /* last position reserved */
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_mesh_access {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le32 data[32]; /* last position reserved */
|
||||
} __packed;
|
||||
|
||||
/* Number of stats counters returned by the firmware */
|
||||
#define MESH_STATS_NUM 8
|
||||
#endif
|
1006
drivers/net/wireless/libertas/if_cs.c
Normal file
1006
drivers/net/wireless/libertas/if_cs.c
Normal file
File diff suppressed because it is too large
Load diff
1453
drivers/net/wireless/libertas/if_sdio.c
Normal file
1453
drivers/net/wireless/libertas/if_sdio.c
Normal file
File diff suppressed because it is too large
Load diff
52
drivers/net/wireless/libertas/if_sdio.h
Normal file
52
drivers/net/wireless/libertas/if_sdio.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* linux/drivers/net/wireless/libertas/if_sdio.h
|
||||
*
|
||||
* Copyright 2007 Pierre Ossman
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _LBS_IF_SDIO_H
|
||||
#define _LBS_IF_SDIO_H
|
||||
|
||||
#define IF_SDIO_IOPORT 0x00
|
||||
|
||||
#define IF_SDIO_H_INT_MASK 0x04
|
||||
#define IF_SDIO_H_INT_OFLOW 0x08
|
||||
#define IF_SDIO_H_INT_UFLOW 0x04
|
||||
#define IF_SDIO_H_INT_DNLD 0x02
|
||||
#define IF_SDIO_H_INT_UPLD 0x01
|
||||
|
||||
#define IF_SDIO_H_INT_STATUS 0x05
|
||||
#define IF_SDIO_H_INT_RSR 0x06
|
||||
#define IF_SDIO_H_INT_STATUS2 0x07
|
||||
|
||||
#define IF_SDIO_RD_BASE 0x10
|
||||
|
||||
#define IF_SDIO_STATUS 0x20
|
||||
#define IF_SDIO_IO_RDY 0x08
|
||||
#define IF_SDIO_CIS_RDY 0x04
|
||||
#define IF_SDIO_UL_RDY 0x02
|
||||
#define IF_SDIO_DL_RDY 0x01
|
||||
|
||||
#define IF_SDIO_C_INT_MASK 0x24
|
||||
#define IF_SDIO_C_INT_STATUS 0x28
|
||||
#define IF_SDIO_C_INT_RSR 0x2C
|
||||
|
||||
#define IF_SDIO_SCRATCH 0x34
|
||||
#define IF_SDIO_SCRATCH_OLD 0x80fe
|
||||
#define IF_SDIO_FW_STATUS 0x40
|
||||
#define IF_SDIO_FIRMWARE_OK 0xfedc
|
||||
|
||||
#define IF_SDIO_RX_LEN 0x42
|
||||
#define IF_SDIO_RX_UNIT 0x43
|
||||
|
||||
#define IF_SDIO_EVENT 0x80fc
|
||||
|
||||
#define IF_SDIO_BLOCK_SIZE 256
|
||||
#define CONFIGURATION_REG 0x03
|
||||
#define HOST_POWER_UP (0x1U << 1)
|
||||
#endif
|
1319
drivers/net/wireless/libertas/if_spi.c
Normal file
1319
drivers/net/wireless/libertas/if_spi.c
Normal file
File diff suppressed because it is too large
Load diff
206
drivers/net/wireless/libertas/if_spi.h
Normal file
206
drivers/net/wireless/libertas/if_spi.h
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* linux/drivers/net/wireless/libertas/if_spi.c
|
||||
*
|
||||
* Driver for Marvell SPI WLAN cards.
|
||||
*
|
||||
* Copyright 2008 Analog Devices Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Andrey Yurovsky <andrey@cozybit.com>
|
||||
* Colin McCabe <colin@cozybit.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _LBS_IF_SPI_H_
|
||||
#define _LBS_IF_SPI_H_
|
||||
|
||||
#define IPFIELD_ALIGN_OFFSET 2
|
||||
#define IF_SPI_CMD_BUF_SIZE 2400
|
||||
|
||||
/***************** Firmware *****************/
|
||||
|
||||
#define IF_SPI_FW_NAME_MAX 30
|
||||
|
||||
#define MAX_MAIN_FW_LOAD_CRC_ERR 10
|
||||
|
||||
/* Chunk size when loading the helper firmware */
|
||||
#define HELPER_FW_LOAD_CHUNK_SZ 64
|
||||
|
||||
/* Value to write to indicate end of helper firmware dnld */
|
||||
#define FIRMWARE_DNLD_OK 0x0000
|
||||
|
||||
/* Value to check once the main firmware is downloaded */
|
||||
#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
|
||||
|
||||
/***************** SPI Interface Unit *****************/
|
||||
/* Masks used in SPI register read/write operations */
|
||||
#define IF_SPI_READ_OPERATION_MASK 0x0
|
||||
#define IF_SPI_WRITE_OPERATION_MASK 0x8000
|
||||
|
||||
/* SPI register offsets. 4-byte aligned. */
|
||||
#define IF_SPI_DEVICEID_CTRL_REG 0x00 /* DeviceID controller reg */
|
||||
#define IF_SPI_IO_READBASE_REG 0x04 /* Read I/O base reg */
|
||||
#define IF_SPI_IO_WRITEBASE_REG 0x08 /* Write I/O base reg */
|
||||
#define IF_SPI_IO_RDWRPORT_REG 0x0C /* Read/Write I/O port reg */
|
||||
|
||||
#define IF_SPI_CMD_READBASE_REG 0x10 /* Read command base reg */
|
||||
#define IF_SPI_CMD_WRITEBASE_REG 0x14 /* Write command base reg */
|
||||
#define IF_SPI_CMD_RDWRPORT_REG 0x18 /* Read/Write command port reg */
|
||||
|
||||
#define IF_SPI_DATA_READBASE_REG 0x1C /* Read data base reg */
|
||||
#define IF_SPI_DATA_WRITEBASE_REG 0x20 /* Write data base reg */
|
||||
#define IF_SPI_DATA_RDWRPORT_REG 0x24 /* Read/Write data port reg */
|
||||
|
||||
#define IF_SPI_SCRATCH_1_REG 0x28 /* Scratch reg 1 */
|
||||
#define IF_SPI_SCRATCH_2_REG 0x2C /* Scratch reg 2 */
|
||||
#define IF_SPI_SCRATCH_3_REG 0x30 /* Scratch reg 3 */
|
||||
#define IF_SPI_SCRATCH_4_REG 0x34 /* Scratch reg 4 */
|
||||
|
||||
#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
|
||||
#define IF_SPI_TX_FRAME_STATUS_REG 0x3C /* Tx frame status reg */
|
||||
|
||||
#define IF_SPI_HOST_INT_CTRL_REG 0x40 /* Host interrupt controller reg */
|
||||
|
||||
#define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */
|
||||
#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interrupt status reg */
|
||||
#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
|
||||
#define IF_SPI_CARD_INT_STATUS_MASK_REG 0x50 /* Card interrupt status mask */
|
||||
|
||||
#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
|
||||
|
||||
#define IF_SPI_HOST_INT_CAUSE_REG 0x58 /* Host interrupt cause reg */
|
||||
#define IF_SPI_HOST_INT_STATUS_REG 0x5C /* Host interrupt status reg */
|
||||
#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
|
||||
#define IF_SPI_HOST_INT_STATUS_MASK_REG 0x64 /* Host interrupt status mask */
|
||||
#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
|
||||
|
||||
#define IF_SPI_DELAY_READ_REG 0x6C /* Delay read reg */
|
||||
#define IF_SPI_SPU_BUS_MODE_REG 0x70 /* SPU BUS mode reg */
|
||||
|
||||
/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
|
||||
#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
|
||||
#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
|
||||
|
||||
/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
|
||||
/* Host Interrupt Control bit : Wake up */
|
||||
#define IF_SPI_HICT_WAKE_UP (1<<0)
|
||||
/* Host Interrupt Control bit : WLAN ready */
|
||||
#define IF_SPI_HICT_WLAN_READY (1<<1)
|
||||
/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */
|
||||
/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */
|
||||
/*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */
|
||||
/* Host Interrupt Control bit : Tx auto download */
|
||||
#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5)
|
||||
/* Host Interrupt Control bit : Rx auto upload */
|
||||
#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6)
|
||||
/* Host Interrupt Control bit : Command auto download */
|
||||
#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7)
|
||||
/* Host Interrupt Control bit : Command auto upload */
|
||||
#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8)
|
||||
|
||||
/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
|
||||
/* Card Interrupt Case bit : Tx download over */
|
||||
#define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0)
|
||||
/* Card Interrupt Case bit : Rx upload over */
|
||||
#define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1)
|
||||
/* Card Interrupt Case bit : Command download over */
|
||||
#define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2)
|
||||
/* Card Interrupt Case bit : Host event */
|
||||
#define IF_SPI_CIC_HOST_EVENT (1<<3)
|
||||
/* Card Interrupt Case bit : Command upload over */
|
||||
#define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4)
|
||||
/* Card Interrupt Case bit : Power down */
|
||||
#define IF_SPI_CIC_POWER_DOWN (1<<5)
|
||||
|
||||
/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
|
||||
#define IF_SPI_CIS_TX_DOWNLOAD_OVER (1<<0)
|
||||
#define IF_SPI_CIS_RX_UPLOAD_OVER (1<<1)
|
||||
#define IF_SPI_CIS_CMD_DOWNLOAD_OVER (1<<2)
|
||||
#define IF_SPI_CIS_HOST_EVENT (1<<3)
|
||||
#define IF_SPI_CIS_CMD_UPLOAD_OVER (1<<4)
|
||||
#define IF_SPI_CIS_POWER_DOWN (1<<5)
|
||||
|
||||
/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
|
||||
#define IF_SPI_HICU_TX_DOWNLOAD_RDY (1<<0)
|
||||
#define IF_SPI_HICU_RX_UPLOAD_RDY (1<<1)
|
||||
#define IF_SPI_HICU_CMD_DOWNLOAD_RDY (1<<2)
|
||||
#define IF_SPI_HICU_CARD_EVENT (1<<3)
|
||||
#define IF_SPI_HICU_CMD_UPLOAD_RDY (1<<4)
|
||||
#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW (1<<5)
|
||||
#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW (1<<6)
|
||||
#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW (1<<7)
|
||||
#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW (1<<8)
|
||||
#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW (1<<9)
|
||||
#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10)
|
||||
|
||||
/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
|
||||
/* Host Interrupt Status bit : Tx download ready */
|
||||
#define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0)
|
||||
/* Host Interrupt Status bit : Rx upload ready */
|
||||
#define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1)
|
||||
/* Host Interrupt Status bit : Command download ready */
|
||||
#define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2)
|
||||
/* Host Interrupt Status bit : Card event */
|
||||
#define IF_SPI_HIST_CARD_EVENT (1<<3)
|
||||
/* Host Interrupt Status bit : Command upload ready */
|
||||
#define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4)
|
||||
/* Host Interrupt Status bit : I/O write FIFO overflow */
|
||||
#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5)
|
||||
/* Host Interrupt Status bit : I/O read FIFO underflow */
|
||||
#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6)
|
||||
/* Host Interrupt Status bit : Data write FIFO overflow */
|
||||
#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7)
|
||||
/* Host Interrupt Status bit : Data read FIFO underflow */
|
||||
#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8)
|
||||
/* Host Interrupt Status bit : Command write FIFO overflow */
|
||||
#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9)
|
||||
/* Host Interrupt Status bit : Command read FIFO underflow */
|
||||
#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10)
|
||||
|
||||
/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
|
||||
/* Host Interrupt Status Mask bit : Tx download ready */
|
||||
#define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0)
|
||||
/* Host Interrupt Status Mask bit : Rx upload ready */
|
||||
#define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1)
|
||||
/* Host Interrupt Status Mask bit : Command download ready */
|
||||
#define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2)
|
||||
/* Host Interrupt Status Mask bit : Card event */
|
||||
#define IF_SPI_HISM_CARDEVENT (1<<3)
|
||||
/* Host Interrupt Status Mask bit : Command upload ready */
|
||||
#define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4)
|
||||
/* Host Interrupt Status Mask bit : I/O write FIFO overflow */
|
||||
#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5)
|
||||
/* Host Interrupt Status Mask bit : I/O read FIFO underflow */
|
||||
#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6)
|
||||
/* Host Interrupt Status Mask bit : Data write FIFO overflow */
|
||||
#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7)
|
||||
/* Host Interrupt Status Mask bit : Data write FIFO underflow */
|
||||
#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8)
|
||||
/* Host Interrupt Status Mask bit : Command write FIFO overflow */
|
||||
#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9)
|
||||
/* Host Interrupt Status Mask bit : Command write FIFO underflow */
|
||||
#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10)
|
||||
|
||||
/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
|
||||
/* SCK edge on which the WLAN module outputs data on MISO */
|
||||
#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
|
||||
#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
|
||||
|
||||
/* In a SPU read operation, there is a delay between writing the SPU
|
||||
* register name and getting back data from the WLAN module.
|
||||
* This can be specified in terms of nanoseconds or in terms of dummy
|
||||
* clock cycles which the master must output before receiving a response. */
|
||||
#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
|
||||
#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
|
||||
|
||||
/* Some different modes of SPI operation */
|
||||
#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
|
||||
#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
|
||||
#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
|
||||
#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
|
||||
|
||||
#endif
|
1018
drivers/net/wireless/libertas/if_usb.c
Normal file
1018
drivers/net/wireless/libertas/if_usb.c
Normal file
File diff suppressed because it is too large
Load diff
106
drivers/net/wireless/libertas/if_usb.h
Normal file
106
drivers/net/wireless/libertas/if_usb.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
#ifndef _LBS_IF_USB_H
|
||||
#define _LBS_IF_USB_H
|
||||
|
||||
#include <linux/wait.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
struct lbs_private;
|
||||
|
||||
/*
|
||||
* This file contains definition for USB interface.
|
||||
*/
|
||||
#define CMD_TYPE_REQUEST 0xF00DFACE
|
||||
#define CMD_TYPE_DATA 0xBEADC0DE
|
||||
#define CMD_TYPE_INDICATION 0xBEEFFACE
|
||||
|
||||
#define IPFIELD_ALIGN_OFFSET 2
|
||||
|
||||
#define BOOT_CMD_FW_BY_USB 0x01
|
||||
#define BOOT_CMD_FW_IN_EEPROM 0x02
|
||||
#define BOOT_CMD_UPDATE_BOOT2 0x03
|
||||
#define BOOT_CMD_UPDATE_FW 0x04
|
||||
#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */
|
||||
|
||||
struct bootcmd
|
||||
{
|
||||
__le32 magic;
|
||||
uint8_t cmd;
|
||||
uint8_t pad[11];
|
||||
};
|
||||
|
||||
#define BOOT_CMD_RESP_OK 0x0001
|
||||
#define BOOT_CMD_RESP_FAIL 0x0000
|
||||
#define BOOT_CMD_RESP_NOT_SUPPORTED 0x0002
|
||||
|
||||
struct bootcmdresp
|
||||
{
|
||||
__le32 magic;
|
||||
uint8_t cmd;
|
||||
uint8_t result;
|
||||
uint8_t pad[2];
|
||||
};
|
||||
|
||||
/* USB card description structure*/
|
||||
struct if_usb_card {
|
||||
struct usb_device *udev;
|
||||
uint32_t model; /* MODEL_* */
|
||||
struct urb *rx_urb, *tx_urb;
|
||||
struct lbs_private *priv;
|
||||
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
/* bootcmdresp == 0 means command is pending
|
||||
* bootcmdresp < 0 means error
|
||||
* bootcmdresp > 0 is a BOOT_CMD_RESP_* from firmware
|
||||
*/
|
||||
int8_t bootcmdresp;
|
||||
|
||||
int ep_in_size;
|
||||
|
||||
void *ep_out_buf;
|
||||
int ep_out_size;
|
||||
|
||||
const struct firmware *fw;
|
||||
struct timer_list fw_timeout;
|
||||
wait_queue_head_t fw_wq;
|
||||
uint32_t fwseqnum;
|
||||
uint32_t totalbytes;
|
||||
uint32_t fwlastblksent;
|
||||
uint8_t CRC_OK;
|
||||
uint8_t fwdnldover;
|
||||
uint8_t fwfinalblk;
|
||||
uint8_t surprise_removed;
|
||||
|
||||
__le16 boot2_version;
|
||||
};
|
||||
|
||||
/* fwheader */
|
||||
struct fwheader {
|
||||
__le32 dnldcmd;
|
||||
__le32 baseaddr;
|
||||
__le32 datalength;
|
||||
__le32 CRC;
|
||||
};
|
||||
|
||||
#define FW_MAX_DATA_BLK_SIZE 600
|
||||
/* FWData */
|
||||
struct fwdata {
|
||||
struct fwheader hdr;
|
||||
__le32 seqnum;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
/* fwsyncheader */
|
||||
struct fwsyncheader {
|
||||
__le32 cmd;
|
||||
__le32 seqnum;
|
||||
};
|
||||
|
||||
#define FW_HAS_DATA_TO_RECV 0x00000001
|
||||
#define FW_HAS_LAST_BLOCK 0x00000004
|
||||
|
||||
|
||||
#endif
|
1225
drivers/net/wireless/libertas/main.c
Normal file
1225
drivers/net/wireless/libertas/main.c
Normal file
File diff suppressed because it is too large
Load diff
1187
drivers/net/wireless/libertas/mesh.c
Normal file
1187
drivers/net/wireless/libertas/mesh.c
Normal file
File diff suppressed because it is too large
Load diff
77
drivers/net/wireless/libertas/mesh.h
Normal file
77
drivers/net/wireless/libertas/mesh.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Contains all definitions needed for the Libertas' MESH implementation.
|
||||
*/
|
||||
#ifndef _LBS_MESH_H_
|
||||
#define _LBS_MESH_H_
|
||||
|
||||
|
||||
#include <net/iw_handler.h>
|
||||
#include <net/lib80211.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "dev.h"
|
||||
|
||||
#ifdef CONFIG_LIBERTAS_MESH
|
||||
|
||||
struct net_device;
|
||||
|
||||
int lbs_init_mesh(struct lbs_private *priv);
|
||||
void lbs_start_mesh(struct lbs_private *priv);
|
||||
int lbs_deinit_mesh(struct lbs_private *priv);
|
||||
|
||||
void lbs_remove_mesh(struct lbs_private *priv);
|
||||
|
||||
static inline bool lbs_mesh_activated(struct lbs_private *priv)
|
||||
{
|
||||
/* Mesh SSID is only programmed after successful init */
|
||||
return priv->mesh_ssid_len != 0;
|
||||
}
|
||||
|
||||
int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel);
|
||||
|
||||
/* Sending / Receiving */
|
||||
|
||||
struct rxpd;
|
||||
struct txpd;
|
||||
|
||||
struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
|
||||
struct net_device *dev, struct rxpd *rxpd);
|
||||
void lbs_mesh_set_txpd(struct lbs_private *priv,
|
||||
struct net_device *dev, struct txpd *txpd);
|
||||
|
||||
|
||||
/* Command handling */
|
||||
|
||||
struct cmd_ds_command;
|
||||
struct cmd_ds_mesh_access;
|
||||
struct cmd_ds_mesh_config;
|
||||
|
||||
|
||||
/* Ethtool statistics */
|
||||
|
||||
struct ethtool_stats;
|
||||
|
||||
void lbs_mesh_ethtool_get_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, uint64_t *data);
|
||||
int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset);
|
||||
void lbs_mesh_ethtool_get_strings(struct net_device *dev,
|
||||
uint32_t stringset, uint8_t *s);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define lbs_init_mesh(priv)
|
||||
#define lbs_deinit_mesh(priv)
|
||||
#define lbs_start_mesh(priv)
|
||||
#define lbs_add_mesh(priv)
|
||||
#define lbs_remove_mesh(priv)
|
||||
#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
|
||||
#define lbs_mesh_set_txpd(priv, dev, txpd)
|
||||
#define lbs_mesh_set_channel(priv, channel) (0)
|
||||
#define lbs_mesh_activated(priv) (false)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
44
drivers/net/wireless/libertas/radiotap.h
Normal file
44
drivers/net/wireless/libertas/radiotap.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <net/ieee80211_radiotap.h>
|
||||
|
||||
struct tx_radiotap_hdr {
|
||||
struct ieee80211_radiotap_header hdr;
|
||||
u8 rate;
|
||||
u8 txpower;
|
||||
u8 rts_retries;
|
||||
u8 data_retries;
|
||||
} __packed;
|
||||
|
||||
#define TX_RADIOTAP_PRESENT ( \
|
||||
(1 << IEEE80211_RADIOTAP_RATE) | \
|
||||
(1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \
|
||||
(1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \
|
||||
(1 << IEEE80211_RADIOTAP_DATA_RETRIES) | \
|
||||
0)
|
||||
|
||||
#define IEEE80211_FC_VERSION_MASK 0x0003
|
||||
#define IEEE80211_FC_TYPE_MASK 0x000c
|
||||
#define IEEE80211_FC_TYPE_MGT 0x0000
|
||||
#define IEEE80211_FC_TYPE_CTL 0x0004
|
||||
#define IEEE80211_FC_TYPE_DATA 0x0008
|
||||
#define IEEE80211_FC_SUBTYPE_MASK 0x00f0
|
||||
#define IEEE80211_FC_TOFROMDS_MASK 0x0300
|
||||
#define IEEE80211_FC_TODS_MASK 0x0100
|
||||
#define IEEE80211_FC_FROMDS_MASK 0x0200
|
||||
#define IEEE80211_FC_NODS 0x0000
|
||||
#define IEEE80211_FC_TODS 0x0100
|
||||
#define IEEE80211_FC_FROMDS 0x0200
|
||||
#define IEEE80211_FC_DSTODS 0x0300
|
||||
|
||||
struct rx_radiotap_hdr {
|
||||
struct ieee80211_radiotap_header hdr;
|
||||
u8 flags;
|
||||
u8 rate;
|
||||
u8 antsignal;
|
||||
} __packed;
|
||||
|
||||
#define RX_RADIOTAP_PRESENT ( \
|
||||
(1 << IEEE80211_RADIOTAP_FLAGS) | \
|
||||
(1 << IEEE80211_RADIOTAP_RATE) | \
|
||||
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\
|
||||
0)
|
||||
|
286
drivers/net/wireless/libertas/rx.c
Normal file
286
drivers/net/wireless/libertas/rx.c
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* This file contains the handling of RX in wlan driver.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/export.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "host.h"
|
||||
#include "radiotap.h"
|
||||
#include "decl.h"
|
||||
#include "dev.h"
|
||||
#include "mesh.h"
|
||||
|
||||
struct eth803hdr {
|
||||
u8 dest_addr[6];
|
||||
u8 src_addr[6];
|
||||
u16 h803_len;
|
||||
} __packed;
|
||||
|
||||
struct rfc1042hdr {
|
||||
u8 llc_dsap;
|
||||
u8 llc_ssap;
|
||||
u8 llc_ctrl;
|
||||
u8 snap_oui[3];
|
||||
u16 snap_type;
|
||||
} __packed;
|
||||
|
||||
struct rxpackethdr {
|
||||
struct eth803hdr eth803_hdr;
|
||||
struct rfc1042hdr rfc1042_hdr;
|
||||
} __packed;
|
||||
|
||||
struct rx80211packethdr {
|
||||
struct rxpd rx_pd;
|
||||
void *eth80211_hdr;
|
||||
} __packed;
|
||||
|
||||
static int process_rxed_802_11_packet(struct lbs_private *priv,
|
||||
struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* lbs_process_rxed_packet - processes received packet and forwards it
|
||||
* to kernel/upper layer
|
||||
*
|
||||
* @priv: A pointer to &struct lbs_private
|
||||
* @skb: A pointer to skb which includes the received packet
|
||||
* returns: 0 or -1
|
||||
*/
|
||||
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
int ret = 0;
|
||||
struct net_device *dev = priv->dev;
|
||||
struct rxpackethdr *p_rx_pkt;
|
||||
struct rxpd *p_rx_pd;
|
||||
int hdrchop;
|
||||
struct ethhdr *p_ethhdr;
|
||||
static const u8 rfc1042_eth_hdr[] = {
|
||||
0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
lbs_deb_enter(LBS_DEB_RX);
|
||||
|
||||
BUG_ON(!skb);
|
||||
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
ret = process_rxed_802_11_packet(priv, skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
p_rx_pd = (struct rxpd *) skb->data;
|
||||
p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
|
||||
le32_to_cpu(p_rx_pd->pkt_ptr));
|
||||
|
||||
dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
|
||||
|
||||
lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
|
||||
min_t(unsigned int, skb->len, 100));
|
||||
|
||||
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
|
||||
lbs_deb_rx("rx err: frame received with bad length\n");
|
||||
dev->stats.rx_length_errors++;
|
||||
ret = -EINVAL;
|
||||
dev_kfree_skb(skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n",
|
||||
skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr),
|
||||
skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr));
|
||||
|
||||
lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
|
||||
sizeof(p_rx_pkt->eth803_hdr.dest_addr));
|
||||
lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
|
||||
sizeof(p_rx_pkt->eth803_hdr.src_addr));
|
||||
|
||||
if (memcmp(&p_rx_pkt->rfc1042_hdr,
|
||||
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
|
||||
/*
|
||||
* Replace the 803 header and rfc1042 header (llc/snap) with an
|
||||
* EthernetII header, keep the src/dst and snap_type (ethertype)
|
||||
*
|
||||
* The firmware only passes up SNAP frames converting
|
||||
* all RX Data from 802.11 to 802.2/LLC/SNAP frames.
|
||||
*
|
||||
* To create the Ethernet II, just move the src, dst address right
|
||||
* before the snap_type.
|
||||
*/
|
||||
p_ethhdr = (struct ethhdr *)
|
||||
((u8 *) &p_rx_pkt->eth803_hdr
|
||||
+ sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
|
||||
- sizeof(p_rx_pkt->eth803_hdr.dest_addr)
|
||||
- sizeof(p_rx_pkt->eth803_hdr.src_addr)
|
||||
- sizeof(p_rx_pkt->rfc1042_hdr.snap_type));
|
||||
|
||||
memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
|
||||
sizeof(p_ethhdr->h_source));
|
||||
memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
|
||||
sizeof(p_ethhdr->h_dest));
|
||||
|
||||
/* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
|
||||
* that was removed
|
||||
*/
|
||||
hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
|
||||
} else {
|
||||
lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
|
||||
(u8 *) &p_rx_pkt->rfc1042_hdr,
|
||||
sizeof(p_rx_pkt->rfc1042_hdr));
|
||||
|
||||
/* Chop off the rxpd */
|
||||
hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd;
|
||||
}
|
||||
|
||||
/* Chop off the leading header bytes so the skb points to the start of
|
||||
* either the reconstructed EthII frame or the 802.2/llc/snap frame
|
||||
*/
|
||||
skb_pull(skb, hdrchop);
|
||||
|
||||
priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
|
||||
|
||||
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
|
||||
dev->stats.rx_bytes += skb->len;
|
||||
dev->stats.rx_packets++;
|
||||
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
else
|
||||
netif_rx_ni(skb);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
|
||||
|
||||
/**
|
||||
* convert_mv_rate_to_radiotap - converts Tx/Rx rates from Marvell WLAN format
|
||||
* (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
|
||||
*
|
||||
* @rate: Input rate
|
||||
* returns: Output Rate (0 if invalid)
|
||||
*/
|
||||
static u8 convert_mv_rate_to_radiotap(u8 rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 0: /* 1 Mbps */
|
||||
return 2;
|
||||
case 1: /* 2 Mbps */
|
||||
return 4;
|
||||
case 2: /* 5.5 Mbps */
|
||||
return 11;
|
||||
case 3: /* 11 Mbps */
|
||||
return 22;
|
||||
/* case 4: reserved */
|
||||
case 5: /* 6 Mbps */
|
||||
return 12;
|
||||
case 6: /* 9 Mbps */
|
||||
return 18;
|
||||
case 7: /* 12 Mbps */
|
||||
return 24;
|
||||
case 8: /* 18 Mbps */
|
||||
return 36;
|
||||
case 9: /* 24 Mbps */
|
||||
return 48;
|
||||
case 10: /* 36 Mbps */
|
||||
return 72;
|
||||
case 11: /* 48 Mbps */
|
||||
return 96;
|
||||
case 12: /* 54 Mbps */
|
||||
return 108;
|
||||
}
|
||||
pr_alert("Invalid Marvell WLAN rate %i\n", rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_rxed_802_11_packet - processes a received 802.11 packet and forwards
|
||||
* it to kernel/upper layer
|
||||
*
|
||||
* @priv: A pointer to &struct lbs_private
|
||||
* @skb: A pointer to skb which includes the received packet
|
||||
* returns: 0 or -1
|
||||
*/
|
||||
static int process_rxed_802_11_packet(struct lbs_private *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int ret = 0;
|
||||
struct net_device *dev = priv->dev;
|
||||
struct rx80211packethdr *p_rx_pkt;
|
||||
struct rxpd *prxpd;
|
||||
struct rx_radiotap_hdr radiotap_hdr;
|
||||
struct rx_radiotap_hdr *pradiotap_hdr;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_RX);
|
||||
|
||||
p_rx_pkt = (struct rx80211packethdr *) skb->data;
|
||||
prxpd = &p_rx_pkt->rx_pd;
|
||||
|
||||
/* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */
|
||||
|
||||
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
|
||||
lbs_deb_rx("rx err: frame received with bad length\n");
|
||||
dev->stats.rx_length_errors++;
|
||||
ret = -EINVAL;
|
||||
kfree_skb(skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
|
||||
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
|
||||
|
||||
/* create the exported radio header */
|
||||
|
||||
/* radiotap header */
|
||||
memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
|
||||
/* XXX must check radiotap_hdr.hdr.it_pad for pad */
|
||||
radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
|
||||
radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
|
||||
radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
|
||||
/* XXX must check no carryout */
|
||||
radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
|
||||
|
||||
/* chop the rxpd */
|
||||
skb_pull(skb, sizeof(struct rxpd));
|
||||
|
||||
/* add space for the new radio header */
|
||||
if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
|
||||
pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
|
||||
netdev_alert(dev, "%s: couldn't pskb_expand_head\n", __func__);
|
||||
ret = -ENOMEM;
|
||||
kfree_skb(skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
|
||||
memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
|
||||
|
||||
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
|
||||
|
||||
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
|
||||
dev->stats.rx_bytes += skb->len;
|
||||
dev->stats.rx_packets++;
|
||||
|
||||
skb->protocol = eth_type_trans(skb, priv->dev);
|
||||
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
else
|
||||
netif_rx_ni(skb);
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
207
drivers/net/wireless/libertas/tx.c
Normal file
207
drivers/net/wireless/libertas/tx.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* This file contains the handling of TX in wlan driver.
|
||||
*/
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/export.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "radiotap.h"
|
||||
#include "decl.h"
|
||||
#include "defs.h"
|
||||
#include "dev.h"
|
||||
#include "mesh.h"
|
||||
|
||||
/**
|
||||
* convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
|
||||
* units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
|
||||
*
|
||||
* @rate: Input rate
|
||||
* returns: Output Rate (0 if invalid)
|
||||
*/
|
||||
static u32 convert_radiotap_rate_to_mv(u8 rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 2: /* 1 Mbps */
|
||||
return 0 | (1 << 4);
|
||||
case 4: /* 2 Mbps */
|
||||
return 1 | (1 << 4);
|
||||
case 11: /* 5.5 Mbps */
|
||||
return 2 | (1 << 4);
|
||||
case 22: /* 11 Mbps */
|
||||
return 3 | (1 << 4);
|
||||
case 12: /* 6 Mbps */
|
||||
return 4 | (1 << 4);
|
||||
case 18: /* 9 Mbps */
|
||||
return 5 | (1 << 4);
|
||||
case 24: /* 12 Mbps */
|
||||
return 6 | (1 << 4);
|
||||
case 36: /* 18 Mbps */
|
||||
return 7 | (1 << 4);
|
||||
case 48: /* 24 Mbps */
|
||||
return 8 | (1 << 4);
|
||||
case 72: /* 36 Mbps */
|
||||
return 9 | (1 << 4);
|
||||
case 96: /* 48 Mbps */
|
||||
return 10 | (1 << 4);
|
||||
case 108: /* 54 Mbps */
|
||||
return 11 | (1 << 4);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lbs_hard_start_xmit - checks the conditions and sends packet to IF
|
||||
* layer if everything is ok
|
||||
*
|
||||
* @skb: A pointer to skb which includes TX packet
|
||||
* @dev: A pointer to the &struct net_device
|
||||
* returns: 0 or -1
|
||||
*/
|
||||
netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
struct txpd *txpd;
|
||||
char *p802x_hdr;
|
||||
uint16_t pkt_len;
|
||||
netdev_tx_t ret = NETDEV_TX_OK;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_TX);
|
||||
|
||||
/* We need to protect against the queues being restarted before
|
||||
we get round to stopping them */
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (priv->surpriseremoved)
|
||||
goto free;
|
||||
|
||||
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
|
||||
lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
|
||||
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
|
||||
/* We'll never manage to send this one; drop it and return 'OK' */
|
||||
|
||||
dev->stats.tx_dropped++;
|
||||
dev->stats.tx_errors++;
|
||||
goto free;
|
||||
}
|
||||
|
||||
|
||||
netif_stop_queue(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_stop_queue(priv->mesh_dev);
|
||||
|
||||
if (priv->tx_pending_len) {
|
||||
/* This can happen if packets come in on the mesh and eth
|
||||
device simultaneously -- there's no mutual exclusion on
|
||||
hard_start_xmit() calls between devices. */
|
||||
lbs_deb_tx("Packet on %s while busy\n", dev->name);
|
||||
ret = NETDEV_TX_BUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
priv->tx_pending_len = -1;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
|
||||
|
||||
txpd = (void *)priv->tx_pending_buf;
|
||||
memset(txpd, 0, sizeof(struct txpd));
|
||||
|
||||
p802x_hdr = skb->data;
|
||||
pkt_len = skb->len;
|
||||
|
||||
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
|
||||
|
||||
/* set txpd fields from the radiotap header */
|
||||
txpd->tx_control = cpu_to_le32(convert_radiotap_rate_to_mv(rtap_hdr->rate));
|
||||
|
||||
/* skip the radiotap header */
|
||||
p802x_hdr += sizeof(*rtap_hdr);
|
||||
pkt_len -= sizeof(*rtap_hdr);
|
||||
|
||||
/* copy destination address from 802.11 header */
|
||||
memcpy(txpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
|
||||
} else {
|
||||
/* copy destination address from 802.3 header */
|
||||
memcpy(txpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
|
||||
}
|
||||
|
||||
txpd->tx_packet_length = cpu_to_le16(pkt_len);
|
||||
txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
|
||||
|
||||
lbs_mesh_set_txpd(priv, dev, txpd);
|
||||
|
||||
lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
|
||||
|
||||
lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
|
||||
|
||||
memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
priv->tx_pending_len = pkt_len + sizeof(struct txpd);
|
||||
|
||||
lbs_deb_tx("%s lined up packet\n", __func__);
|
||||
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
|
||||
/* Keep the skb to echo it back once Tx feedback is
|
||||
received from FW */
|
||||
skb_orphan(skb);
|
||||
|
||||
/* Keep the skb around for when we get feedback */
|
||||
priv->currenttxskb = skb;
|
||||
} else {
|
||||
free:
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
wake_up(&priv->waitq);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* lbs_send_tx_feedback - sends to the host the last transmitted packet,
|
||||
* filling the radiotap headers with transmission information.
|
||||
*
|
||||
* @priv: A pointer to &struct lbs_private structure
|
||||
* @try_count: A 32-bit value containing transmission retry status.
|
||||
*
|
||||
* returns: void
|
||||
*/
|
||||
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
|
||||
{
|
||||
struct tx_radiotap_hdr *radiotap_hdr;
|
||||
|
||||
if (priv->wdev->iftype != NL80211_IFTYPE_MONITOR ||
|
||||
priv->currenttxskb == NULL)
|
||||
return;
|
||||
|
||||
radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
|
||||
|
||||
radiotap_hdr->data_retries = try_count ?
|
||||
(1 + priv->txretrycount - try_count) : 0;
|
||||
|
||||
priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
|
||||
priv->dev);
|
||||
netif_rx(priv->currenttxskb);
|
||||
|
||||
priv->currenttxskb = NULL;
|
||||
|
||||
if (priv->connect_status == LBS_CONNECTED)
|
||||
netif_wake_queue(priv->dev);
|
||||
|
||||
if (priv->mesh_dev && netif_running(priv->mesh_dev))
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
|
268
drivers/net/wireless/libertas/types.h
Normal file
268
drivers/net/wireless/libertas/types.h
Normal file
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* This header file contains definition for global types
|
||||
*/
|
||||
#ifndef _LBS_TYPES_H_
|
||||
#define _LBS_TYPES_H_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
struct ieee_ie_header {
|
||||
u8 id;
|
||||
u8 len;
|
||||
} __packed;
|
||||
|
||||
struct ieee_ie_cf_param_set {
|
||||
struct ieee_ie_header header;
|
||||
|
||||
u8 cfpcnt;
|
||||
u8 cfpperiod;
|
||||
__le16 cfpmaxduration;
|
||||
__le16 cfpdurationremaining;
|
||||
} __packed;
|
||||
|
||||
|
||||
struct ieee_ie_ibss_param_set {
|
||||
struct ieee_ie_header header;
|
||||
|
||||
__le16 atimwindow;
|
||||
} __packed;
|
||||
|
||||
union ieee_ss_param_set {
|
||||
struct ieee_ie_cf_param_set cf;
|
||||
struct ieee_ie_ibss_param_set ibss;
|
||||
} __packed;
|
||||
|
||||
struct ieee_ie_fh_param_set {
|
||||
struct ieee_ie_header header;
|
||||
|
||||
__le16 dwelltime;
|
||||
u8 hopset;
|
||||
u8 hoppattern;
|
||||
u8 hopindex;
|
||||
} __packed;
|
||||
|
||||
struct ieee_ie_ds_param_set {
|
||||
struct ieee_ie_header header;
|
||||
|
||||
u8 channel;
|
||||
} __packed;
|
||||
|
||||
union ieee_phy_param_set {
|
||||
struct ieee_ie_fh_param_set fh;
|
||||
struct ieee_ie_ds_param_set ds;
|
||||
} __packed;
|
||||
|
||||
/* TLV type ID definition */
|
||||
#define PROPRIETARY_TLV_BASE_ID 0x0100
|
||||
|
||||
/* Terminating TLV type */
|
||||
#define MRVL_TERMINATE_TLV_ID 0xffff
|
||||
|
||||
#define TLV_TYPE_SSID 0x0000
|
||||
#define TLV_TYPE_RATES 0x0001
|
||||
#define TLV_TYPE_PHY_FH 0x0002
|
||||
#define TLV_TYPE_PHY_DS 0x0003
|
||||
#define TLV_TYPE_CF 0x0004
|
||||
#define TLV_TYPE_IBSS 0x0006
|
||||
|
||||
#define TLV_TYPE_DOMAIN 0x0007
|
||||
|
||||
#define TLV_TYPE_POWER_CAPABILITY 0x0021
|
||||
|
||||
#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
|
||||
#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1)
|
||||
#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2)
|
||||
#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4)
|
||||
#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5)
|
||||
#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6)
|
||||
#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7)
|
||||
#define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8)
|
||||
#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9)
|
||||
#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10)
|
||||
#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11)
|
||||
#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12)
|
||||
#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13)
|
||||
#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14)
|
||||
#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15)
|
||||
#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16)
|
||||
#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17)
|
||||
#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18)
|
||||
#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
|
||||
#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
|
||||
#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
|
||||
#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31)
|
||||
#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37)
|
||||
#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291)
|
||||
|
||||
/* TLV related data structures */
|
||||
struct mrvl_ie_header {
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_data {
|
||||
struct mrvl_ie_header header;
|
||||
u8 Data[1];
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_rates_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
u8 rates[1];
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_ssid_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
u8 ssid[1];
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_wildcard_ssid_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
u8 MaxSsidlength;
|
||||
u8 ssid[1];
|
||||
} __packed;
|
||||
|
||||
struct chanscanmode {
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
u8 reserved_2_7:6;
|
||||
u8 disablechanfilt:1;
|
||||
u8 passivescan:1;
|
||||
#else
|
||||
u8 passivescan:1;
|
||||
u8 disablechanfilt:1;
|
||||
u8 reserved_2_7:6;
|
||||
#endif
|
||||
} __packed;
|
||||
|
||||
struct chanscanparamset {
|
||||
u8 radiotype;
|
||||
u8 channumber;
|
||||
struct chanscanmode chanscanmode;
|
||||
__le16 minscantime;
|
||||
__le16 maxscantime;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_chanlist_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
struct chanscanparamset chanscanparam[1];
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_cf_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
u8 cfpcnt;
|
||||
u8 cfpperiod;
|
||||
__le16 cfpmaxduration;
|
||||
__le16 cfpdurationremaining;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_ds_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
u8 channel;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_rsn_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
u8 rsnie[1];
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_tsf_timestamp {
|
||||
struct mrvl_ie_header header;
|
||||
__le64 tsftable[1];
|
||||
} __packed;
|
||||
|
||||
/* v9 and later firmware only */
|
||||
struct mrvl_ie_auth_type {
|
||||
struct mrvl_ie_header header;
|
||||
__le16 auth;
|
||||
} __packed;
|
||||
|
||||
/* Local Power capability */
|
||||
struct mrvl_ie_power_capability {
|
||||
struct mrvl_ie_header header;
|
||||
s8 minpower;
|
||||
s8 maxpower;
|
||||
} __packed;
|
||||
|
||||
/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
|
||||
struct mrvl_ie_thresholds {
|
||||
struct mrvl_ie_header header;
|
||||
u8 value;
|
||||
u8 freq;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_beacons_missed {
|
||||
struct mrvl_ie_header header;
|
||||
u8 beaconmissed;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_num_probes {
|
||||
struct mrvl_ie_header header;
|
||||
__le16 numprobes;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_bcast_probe {
|
||||
struct mrvl_ie_header header;
|
||||
__le16 bcastprobe;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_num_ssid_probe {
|
||||
struct mrvl_ie_header header;
|
||||
__le16 numssidprobe;
|
||||
} __packed;
|
||||
|
||||
struct led_pin {
|
||||
u8 led;
|
||||
u8 pin;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_ie_ledgpio {
|
||||
struct mrvl_ie_header header;
|
||||
struct led_pin ledpin[1];
|
||||
} __packed;
|
||||
|
||||
struct led_bhv {
|
||||
uint8_t firmwarestate;
|
||||
uint8_t led;
|
||||
uint8_t ledstate;
|
||||
uint8_t ledarg;
|
||||
} __packed;
|
||||
|
||||
|
||||
struct mrvl_ie_ledbhv {
|
||||
struct mrvl_ie_header header;
|
||||
struct led_bhv ledbhv[1];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Meant to be packed as the value member of a struct ieee80211_info_element.
|
||||
* Note that the len member of the ieee80211_info_element varies depending on
|
||||
* the mesh_id_len
|
||||
*/
|
||||
struct mrvl_meshie_val {
|
||||
uint8_t oui[3];
|
||||
uint8_t type;
|
||||
uint8_t subtype;
|
||||
uint8_t version;
|
||||
uint8_t active_protocol_id;
|
||||
uint8_t active_metric_id;
|
||||
uint8_t mesh_capability;
|
||||
uint8_t mesh_id_len;
|
||||
uint8_t mesh_id[IEEE80211_MAX_SSID_LEN];
|
||||
} __packed;
|
||||
|
||||
struct mrvl_meshie {
|
||||
u8 id, len;
|
||||
struct mrvl_meshie_val val;
|
||||
} __packed;
|
||||
|
||||
struct mrvl_mesh_defaults {
|
||||
__le32 bootflag;
|
||||
uint8_t boottime;
|
||||
uint8_t reserved;
|
||||
__le16 channel;
|
||||
struct mrvl_meshie meshie;
|
||||
} __packed;
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue