mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 01:22:25 +00:00
cleanup: drop obselete code
Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
@@ -12,6 +12,5 @@ patch_folders:
|
||||
- patches/ipq40xx
|
||||
- patches/ipq806x
|
||||
- patches/ipq807x
|
||||
- patches/rtkmipsel
|
||||
- patches/rest
|
||||
- patches/x86
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=realtek-poe
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/realtek-poe
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Realtek PoE Switch Port daemon
|
||||
DEPENDS:=+libubox +libubus +libuci
|
||||
endef
|
||||
|
||||
define Package/realtek-poe/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/realtek-poe $(1)/usr/bin/
|
||||
$(CP) ./files/* $(1)
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,realtek-poe))
|
||||
@@ -1,58 +0,0 @@
|
||||
config global
|
||||
option budget '65'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '1'
|
||||
option name 'lan1'
|
||||
option poe_plus '1'
|
||||
option priority '3'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '2'
|
||||
option name 'lan2'
|
||||
option poe_plus '1'
|
||||
option priority '3'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '3'
|
||||
option name 'lan3'
|
||||
option poe_plus '1'
|
||||
option priority '2'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '4'
|
||||
option name 'lan4'
|
||||
option poe_plus '1'
|
||||
option priority '2'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '5'
|
||||
option name 'lan5'
|
||||
option poe_plus '1'
|
||||
option priority '1'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '6'
|
||||
option name 'lan6'
|
||||
option poe_plus '1'
|
||||
option priority '1'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '7'
|
||||
option name 'lan7'
|
||||
option poe_plus '1'
|
||||
option priority '0'
|
||||
|
||||
config port
|
||||
option enable '1'
|
||||
option id '8'
|
||||
option name 'lan8'
|
||||
option poe_plus '1'
|
||||
option priority '0'
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=80
|
||||
USE_PROCD=1
|
||||
PROG=/usr/bin/realtek-poe
|
||||
|
||||
reload_service() {
|
||||
ubus call poe reload
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_config_trigger "config.change" "poe" ubus call poe reload
|
||||
}
|
||||
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
PROJECT(realtek-poe C)
|
||||
ADD_DEFINITIONS(-Os -ggdb -Wextra -Wall -Werror --std=gnu99 -Wmissing-declarations -Wno-unused-parameter)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
||||
SET(SOURCES main.c)
|
||||
|
||||
IF(DEBUG)
|
||||
ADD_DEFINITIONS(-DDEBUG -g3)
|
||||
ENDIF()
|
||||
|
||||
FIND_LIBRARY(ubus NAMES ubus)
|
||||
FIND_LIBRARY(uci NAMES uci)
|
||||
FIND_LIBRARY(ubox NAMES ubox)
|
||||
FIND_PATH(uci_include_dir NAMES uci.h)
|
||||
FIND_PATH(ubus_include_dir NAMES libubus.h)
|
||||
FIND_PATH(ubox_include_dir NAMES libubox/usock.h)
|
||||
INCLUDE_DIRECTORIES(${ubox_include_dir} ${ubus_include_dir} ${uci_include_dir})
|
||||
|
||||
ADD_EXECUTABLE(realtek-poe ${SOURCES})
|
||||
|
||||
TARGET_LINK_LIBRARIES(realtek-poe ${ubox} ${ubus} ${uci})
|
||||
|
||||
INSTALL(TARGETS realtek-poe
|
||||
RUNTIME DESTINATION sbin
|
||||
)
|
||||
@@ -1,845 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <libubox/ustream.h>
|
||||
#include <libubox/uloop.h>
|
||||
#include <libubox/list.h>
|
||||
#include <libubox/ulog.h>
|
||||
#include <libubus.h>
|
||||
|
||||
#include <uci.h>
|
||||
#include <uci_blob.h>
|
||||
|
||||
#define ULOG_DBG(fmt, ...) ulog(LOG_DEBUG, fmt, ## __VA_ARGS__)
|
||||
|
||||
typedef int (*poe_reply_handler)(unsigned char *reply);
|
||||
|
||||
#define MAX_PORT 8
|
||||
#define GET_STR(a, b) (a < ARRAY_SIZE(b) ? b[a] : NULL)
|
||||
|
||||
struct port_config {
|
||||
char name[16];
|
||||
unsigned char enable;
|
||||
unsigned char priority;
|
||||
unsigned char power_up_mode;
|
||||
unsigned char power_budget;
|
||||
};
|
||||
|
||||
struct config {
|
||||
int debug;
|
||||
|
||||
int budget;
|
||||
int budget_guard;
|
||||
|
||||
int port_count;
|
||||
struct port_config ports[MAX_PORT];
|
||||
};
|
||||
|
||||
struct port_state {
|
||||
char *status;
|
||||
float watt;
|
||||
char *poe_mode;
|
||||
};
|
||||
|
||||
struct state {
|
||||
char *sys_mode;
|
||||
unsigned char sys_version;
|
||||
char *sys_mcu;
|
||||
char *sys_status;
|
||||
unsigned char sys_ext_version;
|
||||
float power_consumption;
|
||||
|
||||
struct port_state ports[MAX_PORT];
|
||||
};
|
||||
|
||||
struct cmd {
|
||||
struct list_head list;
|
||||
unsigned char cmd[12];
|
||||
};
|
||||
|
||||
static struct uloop_timeout state_timeout;
|
||||
static struct ubus_auto_conn conn;
|
||||
static struct ustream_fd stream;
|
||||
static LIST_HEAD(cmd_pending);
|
||||
static unsigned char cmd_seq;
|
||||
static struct state state;
|
||||
static struct blob_buf b;
|
||||
|
||||
static struct config config = {
|
||||
.budget = 65,
|
||||
.budget_guard = 7,
|
||||
.port_count = 8,
|
||||
};
|
||||
|
||||
static void
|
||||
config_load_port(struct uci_section *s)
|
||||
{
|
||||
enum {
|
||||
PORT_ATTR_ID,
|
||||
PORT_ATTR_NAME,
|
||||
PORT_ATTR_ENABLE,
|
||||
PORT_ATTR_PRIO,
|
||||
PORT_ATTR_POE_PLUS,
|
||||
__PORT_ATTR_MAX,
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy port_attrs[__PORT_ATTR_MAX] = {
|
||||
[PORT_ATTR_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
|
||||
[PORT_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
|
||||
[PORT_ATTR_ENABLE] = { .name = "enable", .type = BLOBMSG_TYPE_INT32 },
|
||||
[PORT_ATTR_PRIO] = { .name = "priority", .type = BLOBMSG_TYPE_INT32 },
|
||||
[PORT_ATTR_POE_PLUS] = { .name = "poe_plus", .type = BLOBMSG_TYPE_INT32 },
|
||||
};
|
||||
|
||||
const struct uci_blob_param_list port_attr_list = {
|
||||
.n_params = __PORT_ATTR_MAX,
|
||||
.params = port_attrs,
|
||||
};
|
||||
|
||||
struct blob_attr *tb[__PORT_ATTR_MAX] = { 0 };
|
||||
unsigned int id;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
uci_to_blob(&b, s, &port_attr_list);
|
||||
blobmsg_parse(port_attrs, __PORT_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head));
|
||||
|
||||
if (!tb[PORT_ATTR_ID] || !tb[PORT_ATTR_NAME]) {
|
||||
ULOG_ERR("invalid port settings");
|
||||
return;
|
||||
}
|
||||
|
||||
id = blobmsg_get_u32(tb[PORT_ATTR_ID]);
|
||||
if (!id || id > MAX_PORT) {
|
||||
ULOG_ERR("invalid port id");
|
||||
return;
|
||||
}
|
||||
id--;
|
||||
|
||||
strncpy(config.ports[id].name, blobmsg_get_string(tb[PORT_ATTR_NAME]), 16);
|
||||
|
||||
if (tb[PORT_ATTR_ENABLE])
|
||||
config.ports[id].enable = !!blobmsg_get_u32(tb[PORT_ATTR_ENABLE]);
|
||||
|
||||
if (tb[PORT_ATTR_PRIO])
|
||||
config.ports[id].priority = blobmsg_get_u32(tb[PORT_ATTR_PRIO]);
|
||||
if (config.ports[id].priority > 3)
|
||||
config.ports[id].priority = 3;
|
||||
|
||||
if (tb[PORT_ATTR_POE_PLUS] && blobmsg_get_u32(tb[PORT_ATTR_POE_PLUS]))
|
||||
config.ports[id].power_up_mode = 3;
|
||||
}
|
||||
|
||||
static void
|
||||
config_load_global(struct uci_section *s)
|
||||
{
|
||||
enum {
|
||||
GLOBAL_ATTR_BUDGET,
|
||||
GLOBAL_ATTR_GUARD,
|
||||
__GLOBAL_ATTR_MAX,
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy global_attrs[__GLOBAL_ATTR_MAX] = {
|
||||
[GLOBAL_ATTR_BUDGET] = { .name = "budget", .type = BLOBMSG_TYPE_INT32 },
|
||||
[GLOBAL_ATTR_GUARD] = { .name = "guard", .type = BLOBMSG_TYPE_INT32 },
|
||||
};
|
||||
|
||||
const struct uci_blob_param_list global_attr_list = {
|
||||
.n_params = __GLOBAL_ATTR_MAX,
|
||||
.params = global_attrs,
|
||||
};
|
||||
|
||||
struct blob_attr *tb[__GLOBAL_ATTR_MAX] = { 0 };
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
uci_to_blob(&b, s, &global_attr_list);
|
||||
blobmsg_parse(global_attrs, __GLOBAL_ATTR_MAX, tb, blob_data(b.head), blob_len(b.head));
|
||||
|
||||
config.budget = 65;
|
||||
if (tb[GLOBAL_ATTR_BUDGET])
|
||||
config.budget = blobmsg_get_u32(tb[GLOBAL_ATTR_BUDGET]);
|
||||
|
||||
if (tb[GLOBAL_ATTR_GUARD])
|
||||
config.budget_guard = blobmsg_get_u32(tb[GLOBAL_ATTR_GUARD]);
|
||||
else
|
||||
config.budget_guard = config.budget / 10;
|
||||
}
|
||||
|
||||
static void
|
||||
config_load(int init)
|
||||
{
|
||||
struct uci_context *uci = uci_alloc_context();
|
||||
struct uci_package *package = NULL;
|
||||
|
||||
memset(config.ports, 0, sizeof(config.ports));
|
||||
|
||||
if (!uci_load(uci, "poe", &package)) {
|
||||
struct uci_element *e;
|
||||
|
||||
if (init)
|
||||
uci_foreach_element(&package->sections, e) {
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (!strcmp(s->type, "global"))
|
||||
config_load_global(s);
|
||||
}
|
||||
uci_foreach_element(&package->sections, e) {
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (!strcmp(s->type, "port"))
|
||||
config_load_port(s);
|
||||
}
|
||||
}
|
||||
|
||||
uci_unload(uci, package);
|
||||
uci_free_context(uci);
|
||||
}
|
||||
|
||||
static void
|
||||
poe_cmd_dump(char *type, unsigned char *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!config.debug)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "%s ->", type);
|
||||
for (i = 0; i < 12; i++)
|
||||
fprintf(stderr, " 0x%02x", data[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static int
|
||||
poe_cmd_send(struct cmd *cmd)
|
||||
{
|
||||
poe_cmd_dump("TX", cmd->cmd);
|
||||
ustream_write(&stream.stream, (char *)cmd->cmd, 12, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
poe_cmd_next(void)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
|
||||
if (list_empty(&cmd_pending))
|
||||
return -1;
|
||||
|
||||
cmd = list_first_entry(&cmd_pending, struct cmd, list);
|
||||
|
||||
return poe_cmd_send(cmd);
|
||||
}
|
||||
|
||||
static int
|
||||
poe_cmd_queue(unsigned char *_cmd, int len)
|
||||
{
|
||||
int i, empty = list_empty(&cmd_pending);
|
||||
struct cmd *cmd = malloc(sizeof(*cmd));
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
memset(cmd->cmd, 0xff, 12);
|
||||
memcpy(cmd->cmd, _cmd, len);
|
||||
|
||||
cmd_seq++;
|
||||
cmd->cmd[1] = cmd_seq;
|
||||
cmd->cmd[11] = 0;
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
cmd->cmd[11] += cmd->cmd[i];
|
||||
|
||||
list_add_tail(&cmd->list, &cmd_pending);
|
||||
|
||||
if (empty)
|
||||
return poe_cmd_send(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0x00 - Set port enable
|
||||
* 0: Disable
|
||||
* 1: Enable
|
||||
*/
|
||||
static int
|
||||
poe_cmd_port_enable(unsigned char port, unsigned char enable)
|
||||
{
|
||||
unsigned char cmd[] = { 0x00, 0x00, port, enable };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x06 - Set global port enable
|
||||
* 0: Disable PSE Functionality on all Ports
|
||||
* 1: Enable PSE Functionality on all Ports
|
||||
* 2: Enable Force power Functionality on all ports
|
||||
* 3: Enable Force Power with Disconnect Functionality on all Ports
|
||||
*/
|
||||
static int
|
||||
poe_cmd_global_port_enable(unsigned char enable)
|
||||
{
|
||||
unsigned char cmd[] = { 0x06, 0x00, enable };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x10 - Set port detection type
|
||||
* 1: Legacy Capacitive Detection only
|
||||
* 2: IEEE 802.3af 4-Point Detection only (Default)
|
||||
* 3: IEEE 802.3af 4-Point followed by Legacy
|
||||
* 4: IEEE 802.3af 2-Point detection (Not Supported)
|
||||
* 5: IEEE 802.3af 2-Point followed by Legacy
|
||||
*/
|
||||
static int
|
||||
poe_cmd_port_detection_type(unsigned char port, unsigned char type)
|
||||
{
|
||||
unsigned char cmd[] = { 0x10, 0x00, port, type };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x11 - Set port classification
|
||||
* 0: Disable
|
||||
* 1: Enable
|
||||
*/
|
||||
static int
|
||||
poe_cmd_port_classification(unsigned char port, unsigned char classification)
|
||||
{
|
||||
unsigned char cmd[] = { 0x11, 0x00, port, classification };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x13 - Set port disconnect type
|
||||
* 0: none
|
||||
* 1: AC-disconnect
|
||||
* 2: DC-disconnect
|
||||
* 3: DC with delay
|
||||
*/
|
||||
static int
|
||||
poe_cmd_port_disconnect_type(unsigned char port, unsigned char type)
|
||||
{
|
||||
unsigned char cmd[] = { 0x13, 0x00, port, type };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x15 - Set port power limit type
|
||||
* 0: None. Power limit is 16.2W if the connected device is “low power”,
|
||||
* or the set high power limit if the device is “high power”.
|
||||
* 1: Class based. The power limit for class 4 devices is determined by the high power limit.
|
||||
* 2: User defined
|
||||
*/
|
||||
static int
|
||||
poe_cmd_port_power_limit_type(unsigned char port, unsigned char type)
|
||||
{
|
||||
unsigned char cmd[] = { 0x15, 0x00, port, type };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x16 - Set port power budget
|
||||
* values in 0.2W increments
|
||||
*/
|
||||
static int
|
||||
poe_cmd_port_power_budget(unsigned char port, unsigned char budget)
|
||||
{
|
||||
unsigned char cmd[] = { 0x16, 0x00, port, budget };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x17 - Set power management mode
|
||||
* 0: None (No Power Management mode) (Default in Semi-Auto mode)
|
||||
* 1: Static Power Management with Port Priority(Default in Automode)
|
||||
* 2: Dynamic Power Management with Port Priority
|
||||
* 3: Static Power Management without Port Priority
|
||||
* 4: Dynamic Power Management without Port Priority
|
||||
*/
|
||||
static int
|
||||
poe_cmd_power_mgmt_mode(unsigned char mode)
|
||||
{
|
||||
unsigned char cmd[] = { 0x17, 0x00, mode };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x18 - Set global power budget */
|
||||
static int
|
||||
poe_cmd_global_power_budget(int budget, int guard)
|
||||
{
|
||||
unsigned char cmd[] = { 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
cmd[3] = budget * 10 / 256;
|
||||
cmd[4] = budget * 10 % 256;
|
||||
cmd[5] = guard * 10 / 256;
|
||||
cmd[6] = guard * 10 % 256;
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x1a - Set port priority
|
||||
* 0: Low
|
||||
* 1: Normal
|
||||
* 2: High
|
||||
* 3: Critical
|
||||
*/
|
||||
static int
|
||||
poe_set_port_priority(unsigned char port, unsigned char priority)
|
||||
{
|
||||
unsigned char cmd[] = { 0x1a, 0x00, port, priority };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x1c - Set port power-up mode
|
||||
* 0: PoE
|
||||
* 1: legacy
|
||||
* 2: pre-PoE+
|
||||
* 3: PoE+
|
||||
*/
|
||||
static int
|
||||
poe_set_port_power_up_mode(unsigned char port, unsigned char mode)
|
||||
{
|
||||
unsigned char cmd[] = { 0x1c, 0x00, port, mode };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* 0x20 - Get system info */
|
||||
static int
|
||||
poe_cmd_status(void)
|
||||
{
|
||||
unsigned char cmd[] = { 0x20 };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int
|
||||
poe_reply_status(unsigned char *reply)
|
||||
{
|
||||
static char *mode[]={
|
||||
"Semi-auto I2C",
|
||||
"Semi-auto UART",
|
||||
"Auto I2C",
|
||||
"Auto UART"
|
||||
};
|
||||
static char *mcu[]={
|
||||
"ST Micro ST32F100 Microcontroller",
|
||||
"Nuvoton M05xx LAN Microcontroller",
|
||||
"ST Micro STF030C8 Microcontroller",
|
||||
"Nuvoton M058SAN Microcontroller",
|
||||
"Nuvoton NUC122 Microcontroller"
|
||||
};
|
||||
static char *status[]={
|
||||
"Global Disable pin is de-asserted:No system reset from the previous query cmd:Configuration saved",
|
||||
"Global Disable pin is de-asserted:No system reset from the previous query cmd:Configuration Dirty",
|
||||
"Global Disable pin is de-asserted:System reseted:Configuration saved",
|
||||
"Global Disable pin is de-asserted:System reseted:Configuration Dirty",
|
||||
"Global Disable Pin is asserted:No system reset from the previous query cmd:Configuration saved",
|
||||
"Global Disable Pin is asserted:No system reset from the previous query cmd:Configuration Dirty",
|
||||
"Global Disable Pin is asserted:System reseted:Configuration saved",
|
||||
"Global Disable Pin is asserted:System reseted:Configuration Dirty"
|
||||
};
|
||||
|
||||
state.sys_mode = GET_STR(reply[2], mode);
|
||||
config.port_count = reply[3];
|
||||
state.sys_version = reply[7];
|
||||
state.sys_mcu = GET_STR(reply[8], mcu);
|
||||
state.sys_status = GET_STR(reply[9], status);
|
||||
state.sys_ext_version = reply[10];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0x23 - Get power statistics */
|
||||
static int
|
||||
poe_cmd_power_stats(void)
|
||||
{
|
||||
unsigned char cmd[] = { 0x23 };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int
|
||||
poe_reply_power_stats(unsigned char *reply)
|
||||
{
|
||||
state.power_consumption = reply[2];
|
||||
state.power_consumption *= 256;
|
||||
state.power_consumption += reply[3];
|
||||
state.power_consumption /= 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0x26 - Get extended port config */
|
||||
static int
|
||||
poe_cmd_port_ext_config(unsigned char port)
|
||||
{
|
||||
unsigned char cmd[] = { 0x26, 0x00, port };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int
|
||||
poe_reply_port_ext_config(unsigned char *reply)
|
||||
{
|
||||
static char *mode[] = {
|
||||
"PoE",
|
||||
"Legacy",
|
||||
"pre-PoE+",
|
||||
"PoE+"
|
||||
};
|
||||
|
||||
state.ports[reply[2]].poe_mode = GET_STR(reply[3], mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0x2a - Get all port status */
|
||||
static int
|
||||
poe_cmd_port_overview(void)
|
||||
{
|
||||
unsigned char cmd[] = { 0x2a, 0x00, 0x00 };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int
|
||||
poe_reply_port_overview(unsigned char *reply)
|
||||
{
|
||||
static char *status[]={
|
||||
"Disabled",
|
||||
"Searching",
|
||||
"Delivering power",
|
||||
"Fault",
|
||||
"Other fault",
|
||||
"Requesting power",
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
state.ports[i].status = GET_STR((reply[3 + i] & 0xf), status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0x30 - Get port power statistics */
|
||||
static int
|
||||
poe_cmd_port_power_stats(unsigned char port)
|
||||
{
|
||||
unsigned char cmd[] = { 0x30, 0x00, port };
|
||||
|
||||
return poe_cmd_queue(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int
|
||||
poe_reply_port_power_stats(unsigned char *reply)
|
||||
{
|
||||
float watt;
|
||||
|
||||
watt = reply[9];
|
||||
watt *= 256;
|
||||
watt += reply[10];
|
||||
watt /= 10;
|
||||
|
||||
state.ports[reply[2]].watt = watt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static poe_reply_handler reply_handler[] = {
|
||||
[0x20] = poe_reply_status,
|
||||
[0x23] = poe_reply_power_stats,
|
||||
[0x26] = poe_reply_port_ext_config,
|
||||
[0x2a] = poe_reply_port_overview,
|
||||
[0x30] = poe_reply_port_power_stats,
|
||||
};
|
||||
|
||||
static int
|
||||
poe_reply_consume(unsigned char *reply)
|
||||
{
|
||||
struct cmd *cmd = NULL;
|
||||
unsigned char sum = 0, i;
|
||||
|
||||
poe_cmd_dump("RX", reply);
|
||||
|
||||
if (list_empty(&cmd_pending)) {
|
||||
ULOG_ERR("received unsolicited reply\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd = list_first_entry(&cmd_pending, struct cmd, list);
|
||||
list_del(&cmd->list);
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
sum += reply[i];
|
||||
|
||||
if (reply[11] != sum) {
|
||||
ULOG_DBG("received reply with bad checksum\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (reply[0] != cmd->cmd[0]) {
|
||||
ULOG_DBG("received reply with bad command id\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (reply[1] != cmd->cmd[1]) {
|
||||
ULOG_DBG("received reply with bad sequence number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
|
||||
if (reply_handler[reply[0]])
|
||||
return reply_handler[reply[0]](reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
poe_stream_msg_cb(struct ustream *s, int bytes)
|
||||
{
|
||||
int len;
|
||||
unsigned char *reply = (unsigned char *)ustream_get_read_buf(s, &len);
|
||||
|
||||
if (len < 12)
|
||||
return;
|
||||
|
||||
poe_reply_consume(reply);
|
||||
ustream_consume(s, 12);
|
||||
poe_cmd_next();
|
||||
}
|
||||
|
||||
static void
|
||||
poe_stream_notify_cb(struct ustream *s)
|
||||
{
|
||||
if (!s->eof)
|
||||
return;
|
||||
|
||||
ULOG_ERR("tty error, shutting down\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static int
|
||||
poe_stream_open(char *dev, struct ustream_fd *s, speed_t speed)
|
||||
{
|
||||
struct termios tio;
|
||||
int tty;
|
||||
|
||||
tty = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (tty < 0) {
|
||||
ULOG_ERR("%s: device open failed: %s\n", dev, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcgetattr(tty, &tio);
|
||||
tio.c_cflag |= CREAD;
|
||||
tio.c_cflag |= CS8;
|
||||
tio.c_iflag |= IGNPAR;
|
||||
tio.c_lflag &= ~(ICANON);
|
||||
tio.c_lflag &= ~(ECHO);
|
||||
tio.c_lflag &= ~(ECHOE);
|
||||
tio.c_lflag &= ~(ISIG);
|
||||
tio.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
tio.c_cflag &= ~CRTSCTS;
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VTIME] = 0;
|
||||
cfsetispeed(&tio, speed);
|
||||
cfsetospeed(&tio, speed);
|
||||
tcsetattr(tty, TCSANOW, &tio);
|
||||
|
||||
s->stream.string_data = false;
|
||||
s->stream.notify_read = poe_stream_msg_cb;
|
||||
s->stream.notify_state = poe_stream_notify_cb;
|
||||
|
||||
ustream_fd_init(s, tty);
|
||||
tcflush(tty, TCIFLUSH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
poe_port_setup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config.port_count; i++) {
|
||||
if (!config.ports[i].enable) {
|
||||
poe_cmd_port_enable(i, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
poe_set_port_priority(i, config.ports[i].priority);
|
||||
poe_set_port_power_up_mode(i, config.ports[i].power_up_mode);
|
||||
if (config.ports[i].power_budget) {
|
||||
poe_cmd_port_power_budget(i, config.ports[i].power_budget);
|
||||
poe_cmd_port_power_limit_type(i, 2);
|
||||
} else {
|
||||
poe_cmd_port_power_limit_type(i, 1);
|
||||
}
|
||||
poe_cmd_port_disconnect_type(i, 2);
|
||||
poe_cmd_port_classification(i, 1);
|
||||
poe_cmd_port_detection_type(i, 3);
|
||||
poe_cmd_port_enable(i, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
poe_initial_setup(void)
|
||||
{
|
||||
poe_cmd_status();
|
||||
poe_cmd_power_mgmt_mode(2);
|
||||
poe_cmd_global_power_budget(0, 0);
|
||||
poe_cmd_global_port_enable(0);
|
||||
poe_cmd_global_power_budget(config.budget, config.budget_guard);
|
||||
|
||||
poe_port_setup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
state_timeout_cb(struct uloop_timeout *t)
|
||||
{
|
||||
int i;
|
||||
|
||||
poe_cmd_power_stats();
|
||||
poe_cmd_port_overview();
|
||||
|
||||
for (i = 0; i < config.port_count; i++) {
|
||||
poe_cmd_port_ext_config(i);
|
||||
poe_cmd_port_power_stats(i);
|
||||
}
|
||||
|
||||
uloop_timeout_set(&state_timeout, 2 * 1000);
|
||||
}
|
||||
|
||||
static int
|
||||
ubus_poe_info_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
char tmp[16];
|
||||
void *c;
|
||||
int i;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "v%u.%u.%u.%u",
|
||||
state.sys_version >> 4, state.sys_version & 0xf,
|
||||
state.sys_ext_version >> 4, state.sys_ext_version & 0xf);
|
||||
blobmsg_add_string(&b, "firmware", tmp);
|
||||
if (state.sys_mcu)
|
||||
blobmsg_add_string(&b, "mcu", state.sys_mcu);
|
||||
blobmsg_add_double(&b, "budget", config.budget);
|
||||
blobmsg_add_double(&b, "consumption", state.power_consumption);
|
||||
|
||||
c = blobmsg_open_table(&b, "ports");
|
||||
for (i = 0; i < config.port_count; i++) {
|
||||
void *p;
|
||||
|
||||
if (!config.ports[i].enable)
|
||||
continue;
|
||||
|
||||
p = blobmsg_open_table(&b, config.ports[i].name);
|
||||
|
||||
blobmsg_add_u32(&b, "priority", config.ports[i].priority);
|
||||
|
||||
if (state.ports[i].poe_mode)
|
||||
blobmsg_add_string(&b, "mode", state.ports[i].poe_mode);
|
||||
if (state.ports[i].status)
|
||||
blobmsg_add_string(&b, "status", state.ports[i].status);
|
||||
else
|
||||
blobmsg_add_string(&b, "status", "unknown");
|
||||
if (state.ports[i].watt)
|
||||
blobmsg_add_double(&b, "consumption", state.ports[i].watt);
|
||||
|
||||
blobmsg_close_table(&b, p);
|
||||
}
|
||||
blobmsg_close_table(&b, c);
|
||||
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return UBUS_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
ubus_poe_reload_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
config_load(0);
|
||||
poe_port_setup();
|
||||
|
||||
return UBUS_STATUS_OK;
|
||||
}
|
||||
|
||||
static const struct ubus_method ubus_poe_methods[] = {
|
||||
UBUS_METHOD_NOARG("info", ubus_poe_info_cb),
|
||||
UBUS_METHOD_NOARG("reload", ubus_poe_reload_cb),
|
||||
};
|
||||
|
||||
static struct ubus_object_type ubus_poe_object_type =
|
||||
UBUS_OBJECT_TYPE("poe", ubus_poe_methods);
|
||||
|
||||
static struct ubus_object ubus_poe_object = {
|
||||
.name = "poe",
|
||||
.type = &ubus_poe_object_type,
|
||||
.methods = ubus_poe_methods,
|
||||
.n_methods = ARRAY_SIZE(ubus_poe_methods),
|
||||
};
|
||||
|
||||
static void
|
||||
ubus_connect_handler(struct ubus_context *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ubus_add_object(ctx, &ubus_poe_object);
|
||||
if (ret)
|
||||
fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret));
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char ** argv)
|
||||
{
|
||||
int ch;
|
||||
|
||||
ulog_open(ULOG_STDIO | ULOG_SYSLOG, LOG_DAEMON, "realtek-poe");
|
||||
ulog_threshold(LOG_INFO);
|
||||
|
||||
while ((ch = getopt(argc, argv, "d")) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
config.debug = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
config_load(1);
|
||||
|
||||
uloop_init();
|
||||
conn.cb = ubus_connect_handler;
|
||||
ubus_auto_connect(&conn);
|
||||
|
||||
if (poe_stream_open("/dev/ttyS1", &stream, B19200) < 0)
|
||||
return -1;
|
||||
|
||||
poe_initial_setup();
|
||||
state_timeout.cb = state_timeout_cb;
|
||||
uloop_timeout_set(&state_timeout, 1000);
|
||||
uloop_run();
|
||||
uloop_done();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=rtl83xx-poe
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_LICENSE:=GPL-2.0+
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/rtl83xx-poe
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
DEPENDS:=+libubox-lua +libubus-lua +libuci-lua +lua-rs232
|
||||
TITLE:=PoE daemon for realtek switches
|
||||
endef
|
||||
|
||||
define Package/rtl83xx-poe/description
|
||||
This package contains an utility to allow triggering the PoE state of realtek switch ports.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
|
||||
endef
|
||||
|
||||
define Package/rtl83xx-poe/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,rtl83xx-poe))
|
||||
@@ -1,316 +0,0 @@
|
||||
#!/usr/bin/lua
|
||||
local rs = require "luars232"
|
||||
|
||||
port_name = "/dev/ttyS1"
|
||||
out = io.stderr
|
||||
nseq = 0
|
||||
|
||||
budget = 65.0
|
||||
port_power = {0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
|
||||
if arg[1] ~= nil then
|
||||
budget = tonumber(arg[1])
|
||||
end
|
||||
for i = 1, 8 do
|
||||
port_power[i] = arg[i + 1]
|
||||
end
|
||||
|
||||
function initSerial(p)
|
||||
local e, p = rs.open(p)
|
||||
if e ~= rs.RS232_ERR_NOERROR then
|
||||
-- handle error
|
||||
out:write(string.format("can't open serial port '%s', error: '%s'\n",
|
||||
port_name, rs.error_tostring(e)))
|
||||
return
|
||||
end
|
||||
|
||||
assert(p:set_baud_rate(rs.RS232_BAUD_19200) == rs.RS232_ERR_NOERROR)
|
||||
assert(p:set_data_bits(rs.RS232_DATA_8) == rs.RS232_ERR_NOERROR)
|
||||
assert(p:set_parity(rs.RS232_PARITY_NONE) == rs.RS232_ERR_NOERROR)
|
||||
assert(p:set_stop_bits(rs.RS232_STOP_1) == rs.RS232_ERR_NOERROR)
|
||||
assert(p:set_flow_control(rs.RS232_FLOW_OFF) == rs.RS232_ERR_NOERROR)
|
||||
|
||||
out:write(string.format("OK, port open with values '%s'\n", tostring(p)))
|
||||
|
||||
return p
|
||||
end
|
||||
|
||||
function receive(pCon)
|
||||
local reply = {}
|
||||
local retries = 0
|
||||
|
||||
while table.getn(reply) < 12 and retries < 4 do
|
||||
-- Read up to 12 byte response, timeout 400ms
|
||||
err, data_read, size = pCon:read(12, 400)
|
||||
assert(err == rs.RS232_ERR_NOERROR)
|
||||
-- io.write(string.format("-> [%2d]:", string.len(data_read)))
|
||||
for i = 1, string.len(data_read) do
|
||||
table.insert(reply, string.byte(string.sub(data_read, i, i)))
|
||||
-- io.write(string.format(" %02x", reply[i]))
|
||||
end
|
||||
-- io.write("\n")
|
||||
retries = retries + 1
|
||||
end
|
||||
if table.getn(reply) ~= 12 then
|
||||
print ("Unexpected length!")
|
||||
return(nil)
|
||||
end
|
||||
local sum = 0
|
||||
for i = 1, 11 do
|
||||
sum = sum + reply[i]
|
||||
end
|
||||
if sum % 256 ~= reply[12] then
|
||||
print ("Checksum error!")
|
||||
return(nil)
|
||||
end
|
||||
return(reply)
|
||||
end
|
||||
|
||||
function sendCommand(pCon, cmd)
|
||||
nseq = nseq + 1
|
||||
cmd[2] = nseq % 256
|
||||
|
||||
while table.getn(cmd) < 11 do
|
||||
table.insert(cmd, 0xff)
|
||||
end
|
||||
local c_string = ""
|
||||
local sum = 0
|
||||
-- io.write("send ")
|
||||
for i = 1, 11 do
|
||||
sum = sum + cmd[i]
|
||||
-- io.write(string.format(" %02x", cmd[i]))
|
||||
c_string = c_string .. string.char(cmd[i])
|
||||
end
|
||||
-- io.write(string.format(" %02x\n", sum % 256))
|
||||
c_string = c_string .. string.char(sum % 256)
|
||||
err, len_written = pCon:write(c_string)
|
||||
assert(err == rs.RS232_ERR_NOERROR)
|
||||
|
||||
local reply = receive(pCon)
|
||||
if reply then
|
||||
-- io.write("recv ")
|
||||
-- dumpReply(reply)
|
||||
if (reply[1] == cmd[1] and reply[2] == cmd[2]) then
|
||||
return(reply)
|
||||
else
|
||||
if reply[1] == 0xfd then
|
||||
print ("An incomplete request was received!")
|
||||
elseif reply[1] == 0xfe then
|
||||
print ("Request frame checksum was incorrect!")
|
||||
elseif reply[1] == 0xff then
|
||||
print ("Controller was not ready to respond !")
|
||||
else
|
||||
print ("Sequence number mismatch!")
|
||||
end
|
||||
end
|
||||
else
|
||||
print ("Missing reply!")
|
||||
end
|
||||
return(nil)
|
||||
end
|
||||
|
||||
function dumpReply(reply)
|
||||
for i,v in ipairs(reply) do
|
||||
io.write(string.format(" %02x", v))
|
||||
end
|
||||
io.write("\n");
|
||||
end
|
||||
|
||||
function getStatus(pCon)
|
||||
local cmd = {0x20, 0x01}
|
||||
local reply = sendCommand(pCon, cmd)
|
||||
if not reply then return(nil) end
|
||||
-- returns status, PoEExtVersion, PoEVersion, state2
|
||||
return({reply[5], reply[6], reply[7], reply[10]})
|
||||
end
|
||||
|
||||
function disablePort(pCon, port)
|
||||
local cmd = {0x00, port, port, 0x00}
|
||||
-- disable command is always sent twice
|
||||
sendCommand(pCon, cmd)
|
||||
sendCommand(pCon, cmd)
|
||||
end
|
||||
|
||||
function enablePort(pCon, port)
|
||||
local cmd = {0x00, port, port, 0x01}
|
||||
sendCommand(pCon, cmd)
|
||||
end
|
||||
|
||||
function setPortRelPrio(pCon, port, prio)
|
||||
local cmd = {0x1d, 0x00, port, prio}
|
||||
sendCommand(pCon, cmd)
|
||||
end
|
||||
|
||||
function setGlobalPowerBudget(pCon, maxPower, guard)
|
||||
-- maxPower and guard Watts
|
||||
local cmd = {0x18, 0x01, 0x00}
|
||||
table.insert(cmd, math.floor(maxPower * 10 / 256))
|
||||
table.insert(cmd, math.floor(maxPower * 10) % 256)
|
||||
table.insert(cmd, math.floor(guard * 10 / 256))
|
||||
table.insert(cmd, math.floor(guard * 10) % 256)
|
||||
sendCommand(pCon, cmd)
|
||||
end
|
||||
|
||||
function setPowerLowAction(pCon, disableNext)
|
||||
local cmd = {0x17, 0x00}
|
||||
if disableNext then
|
||||
table.insert(cmd, 0x04)
|
||||
else
|
||||
table.insert(cmd, 0x02)
|
||||
end
|
||||
sendCommand(pCon, cmd)
|
||||
end
|
||||
|
||||
function getPowerStat(pCon)
|
||||
local cmd = {0x23, 0x01}
|
||||
local reply = sendCommand(pCon, cmd)
|
||||
if not reply then return(nil) end
|
||||
local watts = (reply[3] * 256 + reply[4]) / 10.0
|
||||
return watts
|
||||
end
|
||||
|
||||
function getPortPower(pCon, port)
|
||||
local cmd = {0x30, 0x01, port}
|
||||
local reply = sendCommand(pCon, cmd)
|
||||
if not reply then return(nil) end
|
||||
local watts = (reply[10] * 256 + reply[11]) / 10.0
|
||||
local mamps = reply[6] * 256 + reply[7]
|
||||
return({watts, mamps})
|
||||
end
|
||||
|
||||
function getPortOverview(pCon)
|
||||
local cmd = {0x2a, 0x01, 0x00}
|
||||
local reply = sendCommand(pCon, cmd)
|
||||
if not reply then return(nil) end
|
||||
local s = { }
|
||||
for i = 4, 11 do
|
||||
if reply[i] == 0x10 then
|
||||
s[i-3] = "off"
|
||||
elseif reply[i] == 0x11 then
|
||||
s[i-3] = "enabled"
|
||||
elseif reply[i] > 0x11 then
|
||||
s[i-3] = "active"
|
||||
else
|
||||
s[i-3] = "unknown"
|
||||
end
|
||||
end
|
||||
return(s)
|
||||
end
|
||||
|
||||
-- Priority for power: 3: High, 2: Normal, 1: Low?
|
||||
function setPortPriority(pCon, port, prio)
|
||||
local cmd = {0x1a, port, port, prio}
|
||||
local reply = sendCommand(pCon, cmd)
|
||||
if not reply then return(nil) end
|
||||
return(unpack(reply, 4, 11))
|
||||
end
|
||||
|
||||
function getPortPowerLimits(pCon, port)
|
||||
local cmd = {0x26, 0x01, port}
|
||||
local reply = sendCommand(pCon, cmd)
|
||||
if not reply then return(nil) end
|
||||
return(reply)
|
||||
end
|
||||
|
||||
function startupPoE(pCon)
|
||||
local reply = nil
|
||||
reply = getStatus(pCon)
|
||||
|
||||
setGlobalPowerBudget(pCon, 0, 0)
|
||||
setPowerLowAction(pCon, nil)
|
||||
-- do something unknown
|
||||
sendCommand(pCon, {0x06, 0x00, 0x01})
|
||||
for i = 0, 7 do
|
||||
if port_power[i + 1] ~= "1" then
|
||||
disablePort(pCon, i)
|
||||
end
|
||||
end
|
||||
-- do something unknown
|
||||
sendCommand(pCon, {0x02, 0x00, 0x01})
|
||||
|
||||
for i = 0, 7 do
|
||||
if port_power[i + 1] ~= "1" then
|
||||
disablePort(pCon, i)
|
||||
end
|
||||
end
|
||||
-- do something unknown
|
||||
sendCommand(pCon, {0x02, 0x00, 0x01})
|
||||
|
||||
-- use monitor command 25
|
||||
sendCommand(pCon, {0x25, 0x01})
|
||||
|
||||
setGlobalPowerBudget(pCon, 65.0, 7.0)
|
||||
getPowerStat(pCon)
|
||||
-- -> 23 01 00 00 02 44 00 02 ff ff 00 6a
|
||||
|
||||
-- Set 4 unknown port properties:
|
||||
for i = 0, 7 do
|
||||
sendCommand(pCon, {0x11, i, i, 0x01})
|
||||
sendCommand(pCon, {0x13, i, i, 0x02})
|
||||
sendCommand(pCon, {0x15, i, i, 0x01})
|
||||
sendCommand(pCon, {0x10, i, i, 0x03})
|
||||
end
|
||||
for i = 0, 7 do
|
||||
if port_power[i + 1] == "1" then
|
||||
enablePort(pCon, i)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local p = initSerial(port_name)
|
||||
startupPoE(p)
|
||||
|
||||
require "ubus"
|
||||
require "uloop"
|
||||
|
||||
uloop.init()
|
||||
|
||||
local conn = ubus.connect()
|
||||
if not conn then
|
||||
error("Failed to connect to ubus")
|
||||
end
|
||||
|
||||
local my_method = {
|
||||
poe = {
|
||||
info = {
|
||||
function(req, msg)
|
||||
local reply = {}
|
||||
|
||||
reply.power_consumption = tostring(getPowerStat(p)).."W"
|
||||
reply.power_budget = tostring(budget).."W"
|
||||
|
||||
reply.ports = {}
|
||||
local s = getPortOverview(p)
|
||||
for i = 1, 8 do
|
||||
if s[i] == "active" then
|
||||
local r = getPortPower(p, i - 1)
|
||||
reply.ports[i] = tostring(r[1]).."W"
|
||||
else
|
||||
reply.ports[i] = s[i]
|
||||
end
|
||||
end
|
||||
conn:reply(req, reply);
|
||||
end, {}
|
||||
},
|
||||
port = {
|
||||
function(req, msg)
|
||||
local reply = {}
|
||||
if msg.port < 1 or msg.port > 8 then
|
||||
conn:reply(req, false);
|
||||
return -1
|
||||
end
|
||||
if msg.enable == true then
|
||||
enablePort(p, msg.port - 1)
|
||||
else
|
||||
disablePort(p, msg.port - 1)
|
||||
end
|
||||
conn:reply(req, reply);
|
||||
end, {port = ubus.INT32, enable = ubus.BOOLEAN }
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn:add(my_method)
|
||||
|
||||
uloop.run()
|
||||
@@ -1,10 +0,0 @@
|
||||
config poe poe
|
||||
option budget 65
|
||||
option port1 0
|
||||
option port2 0
|
||||
option port3 0
|
||||
option port4 0
|
||||
option port5 0
|
||||
option port6 0
|
||||
option port7 0
|
||||
option port8 0
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
START=40
|
||||
|
||||
USE_PROCD=1
|
||||
PROG=/bin/poe.lua
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger poe
|
||||
}
|
||||
|
||||
start_service() {
|
||||
[ "$(uci get poe.poe.enable)" -eq 1 ] || return 0
|
||||
|
||||
local budget=$(uci get poe.poe.budget)
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_append_param command ${budget:-65}
|
||||
for p in `seq 1 8`; do
|
||||
local pwr=$(uci get poe.poe.port$p)
|
||||
procd_append_param command ${pwr:-0}
|
||||
done
|
||||
procd_close_instance
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
board=$(board_name)
|
||||
|
||||
budget=0
|
||||
case "$board" in
|
||||
d-link,dgs-1210-10p)
|
||||
budget=65
|
||||
;;
|
||||
netgear,gs110tpp-v1|\
|
||||
zyxel,gs1900-10hp)
|
||||
budget=130
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
uci set poe.poe.enable=1
|
||||
uci set poe.poe.budget=$budget
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,754 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/netifd/netifd-wireless.sh
|
||||
. /lib/netifd/hostapd.sh
|
||||
|
||||
init_wireless_driver "$@"
|
||||
|
||||
MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links
|
||||
mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries
|
||||
mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout
|
||||
mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode
|
||||
mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor
|
||||
mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval
|
||||
mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout"
|
||||
MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
|
||||
MP_CONFIG_STRING="mesh_power_mode"
|
||||
|
||||
drv_mac80211_init_device_config() {
|
||||
hostapd_common_add_device_config
|
||||
|
||||
config_add_string path phy 'macaddr:macaddr'
|
||||
config_add_string hwmode
|
||||
config_add_int beacon_int chanbw frag rts
|
||||
config_add_int rxantenna txantenna antenna_gain txpower distance
|
||||
config_add_boolean noscan ht_coex
|
||||
config_add_array ht_capab
|
||||
config_add_boolean \
|
||||
rxldpc \
|
||||
short_gi_80 \
|
||||
short_gi_160 \
|
||||
tx_stbc_2by1 \
|
||||
su_beamformer \
|
||||
su_beamformee \
|
||||
mu_beamformer \
|
||||
mu_beamformee \
|
||||
vht_txop_ps \
|
||||
htc_vht \
|
||||
rx_antenna_pattern \
|
||||
tx_antenna_pattern
|
||||
config_add_int vht_max_a_mpdu_len_exp vht_max_mpdu vht_link_adapt vht160 rx_stbc tx_stbc
|
||||
config_add_boolean \
|
||||
ldpc \
|
||||
greenfield \
|
||||
short_gi_20 \
|
||||
short_gi_40 \
|
||||
max_amsdu \
|
||||
dsss_cck_40
|
||||
}
|
||||
|
||||
drv_mac80211_init_iface_config() {
|
||||
hostapd_common_add_bss_config
|
||||
|
||||
config_add_string 'macaddr:macaddr' ifname
|
||||
|
||||
config_add_boolean wds powersave
|
||||
config_add_int maxassoc
|
||||
config_add_int max_listen_int
|
||||
config_add_int dtim_period
|
||||
config_add_int start_disabled
|
||||
|
||||
# mesh
|
||||
config_add_string mesh_id
|
||||
config_add_int $MP_CONFIG_INT
|
||||
config_add_boolean $MP_CONFIG_BOOL
|
||||
config_add_string $MP_CONFIG_STRING
|
||||
}
|
||||
|
||||
mac80211_add_capabilities() {
|
||||
local __var="$1"; shift
|
||||
local __mask="$1"; shift
|
||||
local __out= oifs
|
||||
|
||||
oifs="$IFS"
|
||||
IFS=:
|
||||
for capab in "$@"; do
|
||||
set -- $capab
|
||||
|
||||
[ "$(($4))" -gt 0 ] || continue
|
||||
[ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue
|
||||
__out="$__out[$1]"
|
||||
done
|
||||
IFS="$oifs"
|
||||
|
||||
export -n -- "$__var=$__out"
|
||||
}
|
||||
|
||||
mac80211_hostapd_setup_base() {
|
||||
local phy="$1"
|
||||
|
||||
json_select config
|
||||
|
||||
[ "$auto_channel" -gt 0 ] && channel=acs_survey
|
||||
|
||||
json_get_vars noscan ht_coex
|
||||
json_get_values ht_capab_list ht_capab
|
||||
|
||||
ieee80211n=1
|
||||
ht_capab=
|
||||
case "$htmode" in
|
||||
VHT20|HT20) ;;
|
||||
HT40*|VHT40|VHT80|VHT160)
|
||||
case "$hwmode" in
|
||||
a)
|
||||
case "$(( ($channel / 4) % 2 ))" in
|
||||
1) ht_capab="[HT40+]";;
|
||||
0) ht_capab="[HT40-]";;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
case "$htmode" in
|
||||
HT40+) ht_capab="[HT40+]";;
|
||||
HT40-) ht_capab="[HT40-]";;
|
||||
*)
|
||||
if [ "$channel" -lt 7 ]; then
|
||||
ht_capab="[HT40+]"
|
||||
else
|
||||
ht_capab="[HT40-]"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
[ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
|
||||
;;
|
||||
*) ieee80211n= ;;
|
||||
esac
|
||||
|
||||
[ -n "$ieee80211n" ] && {
|
||||
append base_cfg "ieee80211n=1" "$N"
|
||||
|
||||
set_default ht_coex 0
|
||||
append base_cfg "ht_coex=$ht_coex" "$N"
|
||||
|
||||
json_get_vars \
|
||||
ldpc:1 \
|
||||
greenfield:0 \
|
||||
short_gi_20:1 \
|
||||
short_gi_40:1 \
|
||||
tx_stbc:1 \
|
||||
rx_stbc:3 \
|
||||
max_amsdu:1 \
|
||||
dsss_cck_40:1
|
||||
|
||||
ht_cap_mask=0
|
||||
for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do
|
||||
ht_cap_mask="$(($ht_cap_mask | $cap))"
|
||||
done
|
||||
|
||||
cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
|
||||
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
|
||||
ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
|
||||
|
||||
mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
|
||||
LDPC:0x1::$ldpc \
|
||||
GF:0x10::$greenfield \
|
||||
SHORT-GI-20:0x20::$short_gi_20 \
|
||||
SHORT-GI-40:0x40::$short_gi_40 \
|
||||
TX-STBC:0x80::$tx_stbc \
|
||||
RX-STBC1:0x300:0x100:1 \
|
||||
RX-STBC12:0x300:0x200:1 \
|
||||
RX-STBC123:0x300:0x300:1 \
|
||||
MAX-AMSDU-7935:0x800::$max_amsdu \
|
||||
DSSS_CCK-40:0x1000::$dsss_cck_40
|
||||
|
||||
ht_capab="$ht_capab$ht_capab_flags"
|
||||
[ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
|
||||
}
|
||||
|
||||
# 802.11ac
|
||||
enable_ac=0
|
||||
idx="$channel"
|
||||
case "$htmode" in
|
||||
VHT20) enable_ac=1;;
|
||||
VHT40)
|
||||
case "$(( ($channel / 4) % 2 ))" in
|
||||
1) idx=$(($channel + 2));;
|
||||
0) idx=$(($channel - 2));;
|
||||
esac
|
||||
enable_ac=1
|
||||
append base_cfg "vht_oper_chwidth=0" "$N"
|
||||
append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
|
||||
;;
|
||||
VHT80)
|
||||
case "$(( ($channel / 4) % 4 ))" in
|
||||
1) idx=$(($channel + 6));;
|
||||
2) idx=$(($channel + 2));;
|
||||
3) idx=$(($channel - 2));;
|
||||
0) idx=$(($channel - 6));;
|
||||
esac
|
||||
enable_ac=1
|
||||
append base_cfg "vht_oper_chwidth=1" "$N"
|
||||
append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
|
||||
;;
|
||||
VHT160)
|
||||
case "$channel" in
|
||||
36|40|44|48|52|56|60|64) idx=50;;
|
||||
100|104|108|112|116|120|124|128) idx=114;;
|
||||
esac
|
||||
enable_ac=1
|
||||
append base_cfg "vht_oper_chwidth=2" "$N"
|
||||
append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$enable_ac" != "0" ]; then
|
||||
json_get_vars \
|
||||
rxldpc:1 \
|
||||
short_gi_80:1 \
|
||||
short_gi_160:1 \
|
||||
tx_stbc_2by1:1 \
|
||||
su_beamformer:1 \
|
||||
su_beamformee:1 \
|
||||
mu_beamformer:1 \
|
||||
mu_beamformee:1 \
|
||||
vht_txop_ps:1 \
|
||||
htc_vht:1 \
|
||||
rx_antenna_pattern:1 \
|
||||
tx_antenna_pattern:1 \
|
||||
vht_max_a_mpdu_len_exp:7 \
|
||||
vht_max_mpdu:11454 \
|
||||
rx_stbc:4 \
|
||||
tx_stbc:4 \
|
||||
vht_link_adapt:3 \
|
||||
vht160:2
|
||||
|
||||
append base_cfg "ieee80211ac=1" "$N"
|
||||
vht_cap=0
|
||||
for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
|
||||
vht_cap="$(($vht_cap | $cap))"
|
||||
done
|
||||
|
||||
cap_rx_stbc=$((($vht_cap >> 8) & 7))
|
||||
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
|
||||
ht_cap_mask="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))"
|
||||
|
||||
mac80211_add_capabilities vht_capab $vht_cap \
|
||||
RXLDPC:0x10::$rxldpc \
|
||||
SHORT-GI-80:0x20::$short_gi_80 \
|
||||
SHORT-GI-160:0x40::$short_gi_160 \
|
||||
TX-STBC-2BY1:0x80::$tx_stbc \
|
||||
SU-BEAMFORMER:0x800::$su_beamformer \
|
||||
SU-BEAMFORMEE:0x1000::$su_beamformee \
|
||||
MU-BEAMFORMER:0x80000::$mu_beamformer \
|
||||
MU-BEAMFORMEE:0x100000::$mu_beamformee \
|
||||
VHT-TXOP-PS:0x200000::$vht_txop_ps \
|
||||
HTC-VHT:0x400000::$htc_vht \
|
||||
RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \
|
||||
TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \
|
||||
RX-STBC1:0x700:0x100:1 \
|
||||
RX-STBC12:0x700:0x200:1 \
|
||||
RX-STBC123:0x700:0x300:1 \
|
||||
RX-STBC1234:0x700:0x400:1 \
|
||||
|
||||
# supported Channel widths
|
||||
vht160_hw=0
|
||||
[ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
|
||||
vht160_hw=1
|
||||
[ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
|
||||
vht160_hw=2
|
||||
[ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
|
||||
[ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
|
||||
|
||||
# maximum MPDU length
|
||||
vht_max_mpdu_hw=3895
|
||||
[ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
|
||||
vht_max_mpdu_hw=7991
|
||||
[ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
|
||||
vht_max_mpdu_hw=11454
|
||||
[ "$vht_max_mpdu_hw" != 3895 ] && \
|
||||
vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
|
||||
|
||||
# maximum A-MPDU length exponent
|
||||
vht_max_a_mpdu_len_exp_hw=0
|
||||
[ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=1
|
||||
[ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=2
|
||||
[ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=3
|
||||
[ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=4
|
||||
[ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=5
|
||||
[ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=6
|
||||
[ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \
|
||||
vht_max_a_mpdu_len_exp_hw=7
|
||||
vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]"
|
||||
|
||||
# whether or not the STA supports link adaptation using VHT variant
|
||||
vht_link_adapt_hw=0
|
||||
[ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
|
||||
vht_link_adapt_hw=2
|
||||
[ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
|
||||
vht_link_adapt_hw=3
|
||||
[ "$vht_link_adapt_hw" != 0 ] && \
|
||||
vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
|
||||
|
||||
[ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
|
||||
fi
|
||||
|
||||
hostapd_prepare_device_config "$hostapd_conf_file" nl80211
|
||||
cat >> "$hostapd_conf_file" <<EOF
|
||||
${channel:+channel=$channel}
|
||||
${noscan:+noscan=$noscan}
|
||||
$base_cfg
|
||||
|
||||
EOF
|
||||
json_select ..
|
||||
}
|
||||
|
||||
mac80211_hostapd_setup_bss() {
|
||||
local phy="$1"
|
||||
local ifname="$2"
|
||||
local macaddr="$3"
|
||||
local type="$4"
|
||||
|
||||
hostapd_cfg=
|
||||
append hostapd_cfg "$type=$ifname" "$N"
|
||||
|
||||
hostapd_set_bss_options hostapd_cfg "$vif" || return 1
|
||||
json_get_vars wds dtim_period max_listen_int start_disabled
|
||||
|
||||
set_default wds 0
|
||||
set_default start_disabled 0
|
||||
|
||||
[ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
|
||||
[ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
|
||||
|
||||
cat >> /var/run/hostapd-$phy.conf <<EOF
|
||||
$hostapd_cfg
|
||||
bssid=$macaddr
|
||||
${dtim_period:+dtim_period=$dtim_period}
|
||||
${max_listen_int:+max_listen_interval=$max_listen_int}
|
||||
EOF
|
||||
}
|
||||
|
||||
mac80211_get_addr() {
|
||||
local phy="$1"
|
||||
local idx="$(($2 + 1))"
|
||||
|
||||
head -n $(($macidx + 1)) /sys/class/ieee80211/${phy}/addresses | tail -n1
|
||||
}
|
||||
|
||||
mac80211_generate_mac() {
|
||||
local phy="$1"
|
||||
local id="${macidx:-0}"
|
||||
|
||||
local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
|
||||
local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
|
||||
|
||||
[ "$mask" = "00:00:00:00:00:00" ] && {
|
||||
mask="ff:ff:ff:ff:ff:ff";
|
||||
|
||||
[ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt 1 ] && {
|
||||
addr="$(mac80211_get_addr "$phy" "$id")"
|
||||
[ -n "$addr" ] && {
|
||||
echo "$addr"
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
|
||||
|
||||
local mask1=$1
|
||||
local mask6=$6
|
||||
|
||||
local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS"
|
||||
|
||||
macidx=$(($id + 1))
|
||||
[ "$((0x$mask1))" -gt 0 ] && {
|
||||
b1="0x$1"
|
||||
[ "$id" -gt 0 ] && \
|
||||
b1=$(($b1 ^ ((($id - 1) << 2) | 0x2)))
|
||||
printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6
|
||||
return
|
||||
}
|
||||
|
||||
[ "$((0x$mask6))" -lt 255 ] && {
|
||||
printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id ))
|
||||
return
|
||||
}
|
||||
|
||||
off2=$(( (0x$6 + $id) / 0x100 ))
|
||||
printf "%s:%s:%s:%s:%02x:%02x" \
|
||||
$1 $2 $3 $4 \
|
||||
$(( (0x$5 + $off2) % 0x100 )) \
|
||||
$(( (0x$6 + $id) % 0x100 ))
|
||||
}
|
||||
|
||||
find_phy() {
|
||||
[ -n "$phy" -a -d /sys/class/ieee80211/$phy ] && return 0
|
||||
[ -n "$path" ] && {
|
||||
for phy in /sys/devices/$path/ieee80211/phy*; do
|
||||
[ -e "$phy" ] && {
|
||||
phy="${phy##*/}"
|
||||
return 0
|
||||
}
|
||||
done
|
||||
}
|
||||
[ -n "$macaddr" ] && {
|
||||
for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
|
||||
grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && return 0
|
||||
done
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
mac80211_check_ap() {
|
||||
has_ap=1
|
||||
}
|
||||
|
||||
mac80211_prepare_vif() {
|
||||
json_select config
|
||||
|
||||
json_get_vars ifname mode ssid wds powersave macaddr
|
||||
|
||||
[ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}"
|
||||
if_idx=$((${if_idx:-0} + 1))
|
||||
|
||||
set_default wds 0
|
||||
set_default powersave 0
|
||||
|
||||
json_select ..
|
||||
|
||||
[ -n "$macaddr" ] || {
|
||||
macaddr="$(mac80211_generate_mac $phy)"
|
||||
macidx="$(($macidx + 1))"
|
||||
}
|
||||
|
||||
json_add_object data
|
||||
json_add_string ifname "$ifname"
|
||||
json_close_object
|
||||
json_select config
|
||||
|
||||
# It is far easier to delete and create the desired interface
|
||||
case "$mode" in
|
||||
adhoc)
|
||||
iw phy "$phy" interface add "$ifname" type adhoc
|
||||
;;
|
||||
ap)
|
||||
# Hostapd will handle recreating the interface and
|
||||
# subsequent virtual APs belonging to the same PHY
|
||||
if [ -n "$hostapd_ctrl" ]; then
|
||||
type=bss
|
||||
else
|
||||
type=interface
|
||||
fi
|
||||
|
||||
mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
|
||||
|
||||
[ -n "$hostapd_ctrl" ] || {
|
||||
iw phy "$phy" interface add "$ifname" type __ap
|
||||
hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
|
||||
}
|
||||
;;
|
||||
mesh)
|
||||
iw phy "$phy" interface add "$ifname" type mp
|
||||
;;
|
||||
monitor)
|
||||
iw phy "$phy" interface add "$ifname" type monitor
|
||||
;;
|
||||
sta)
|
||||
local wdsflag=
|
||||
staidx="$(($staidx + 1))"
|
||||
[ "$wds" -gt 0 ] && wdsflag="4addr on"
|
||||
iw phy "$phy" interface add "$ifname" type managed $wdsflag
|
||||
[ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
|
||||
iw "$ifname" set power_save "$powersave"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$mode" in
|
||||
monitor|mesh)
|
||||
[ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $htmode
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$mode" != "ap" ]; then
|
||||
# ALL ap functionality will be passed to hostapd
|
||||
# All interfaces must have unique mac addresses
|
||||
# which can either be explicitly set in the device
|
||||
# section, or automatically generated
|
||||
ifconfig "$ifname" hw ether "$macaddr"
|
||||
fi
|
||||
|
||||
json_select ..
|
||||
}
|
||||
|
||||
mac80211_setup_supplicant() {
|
||||
wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
|
||||
wpa_supplicant_add_network "$ifname"
|
||||
wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl}
|
||||
}
|
||||
|
||||
mac80211_setup_adhoc_htmode() {
|
||||
case "$htmode" in
|
||||
VHT20|HT20) ibss_htmode=HT20;;
|
||||
HT40*|VHT40|VHT80|VHT160)
|
||||
case "$hwmode" in
|
||||
a)
|
||||
case "$(( ($channel / 4) % 2 ))" in
|
||||
1) ibss_htmode="HT40+" ;;
|
||||
0) ibss_htmode="HT40-";;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
case "$htmode" in
|
||||
HT40+) ibss_htmode="HT40+";;
|
||||
HT40-) ibss_htmode="HT40-";;
|
||||
*)
|
||||
if [ "$channel" -lt 7 ]; then
|
||||
ibss_htmode="HT40+"
|
||||
else
|
||||
ibss_htmode="HT40-"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
[ "$auto_channel" -gt 0 ] && ibss_htmode="HT40+"
|
||||
;;
|
||||
NONE|NOHT)
|
||||
ibss_htmode="NOHT"
|
||||
;;
|
||||
*) ibss_htmode="" ;;
|
||||
esac
|
||||
|
||||
}
|
||||
|
||||
mac80211_setup_adhoc() {
|
||||
json_get_vars bssid ssid key mcast_rate
|
||||
|
||||
keyspec=
|
||||
[ "$auth_type" = "wep" ] && {
|
||||
set_default key 1
|
||||
case "$key" in
|
||||
[1234])
|
||||
local idx
|
||||
for idx in 1 2 3 4; do
|
||||
json_get_var ikey "key$idx"
|
||||
|
||||
[ -n "$ikey" ] && {
|
||||
ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
|
||||
[ $idx -eq $key ] && ikey="d:$ikey"
|
||||
append keyspec "$ikey"
|
||||
}
|
||||
done
|
||||
;;
|
||||
*)
|
||||
append keyspec "d:0:$(prepare_key_wep "$key")"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
brstr=
|
||||
for br in $basic_rate_list; do
|
||||
wpa_supplicant_add_rate brstr "$br"
|
||||
done
|
||||
|
||||
mcval=
|
||||
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
|
||||
|
||||
iw dev "$ifname" ibss join "$ssid" $freq $ibss_htmode fixed-freq $bssid \
|
||||
${beacon_int:+beacon-interval $beacon_int} \
|
||||
${brstr:+basic-rates $brstr} \
|
||||
${mcval:+mcast-rate $mcval} \
|
||||
${keyspec:+keys $keyspec}
|
||||
}
|
||||
|
||||
mac80211_setup_vif() {
|
||||
local name="$1"
|
||||
local failed
|
||||
|
||||
json_select data
|
||||
json_get_vars ifname
|
||||
json_select ..
|
||||
|
||||
json_select config
|
||||
json_get_vars mode
|
||||
json_get_var vif_txpower txpower
|
||||
|
||||
ifconfig "$ifname" up || {
|
||||
wireless_setup_vif_failed IFUP_ERROR
|
||||
json_select ..
|
||||
return
|
||||
}
|
||||
|
||||
set_default vif_txpower "$txpower"
|
||||
[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
|
||||
|
||||
case "$mode" in
|
||||
mesh)
|
||||
# authsae or wpa_supplicant
|
||||
json_get_vars key
|
||||
if [ -n "$key" ]; then
|
||||
if [ -e "/lib/wifi/authsae.sh" ]; then
|
||||
. /lib/wifi/authsae.sh
|
||||
authsae_start_interface || failed=1
|
||||
else
|
||||
wireless_vif_parse_encryption
|
||||
mac80211_setup_supplicant || failed=1
|
||||
fi
|
||||
else
|
||||
json_get_vars mesh_id mcast_rate
|
||||
|
||||
mcval=
|
||||
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
|
||||
|
||||
iw dev "$ifname" mesh join "$mesh_id" ${mcval:+mcast-rate $mcval}
|
||||
fi
|
||||
|
||||
for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
|
||||
json_get_var mp_val "$var"
|
||||
[ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val"
|
||||
done
|
||||
;;
|
||||
adhoc)
|
||||
wireless_vif_parse_encryption
|
||||
mac80211_setup_adhoc_htmode
|
||||
if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
|
||||
mac80211_setup_supplicant || failed=1
|
||||
else
|
||||
mac80211_setup_adhoc
|
||||
fi
|
||||
;;
|
||||
sta)
|
||||
mac80211_setup_supplicant || failed=1
|
||||
;;
|
||||
esac
|
||||
|
||||
json_select ..
|
||||
[ -n "$failed" ] || wireless_add_vif "$name" "$ifname"
|
||||
}
|
||||
|
||||
get_freq() {
|
||||
local phy="$1"
|
||||
local chan="$2"
|
||||
iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}'
|
||||
}
|
||||
|
||||
mac80211_interface_cleanup() {
|
||||
local phy="$1"
|
||||
|
||||
for wdev in $(list_phy_interfaces "$phy"); do
|
||||
ifconfig "$wdev" down 2>/dev/null
|
||||
iw dev "$wdev" del
|
||||
done
|
||||
}
|
||||
|
||||
drv_mac80211_cleanup() {
|
||||
hostapd_common_cleanup
|
||||
}
|
||||
|
||||
drv_mac80211_setup() {
|
||||
json_select config
|
||||
json_get_vars \
|
||||
phy macaddr path \
|
||||
country chanbw distance \
|
||||
txpower antenna_gain \
|
||||
rxantenna txantenna \
|
||||
frag rts beacon_int htmode
|
||||
json_get_values basic_rate_list basic_rate
|
||||
json_select ..
|
||||
|
||||
find_phy || {
|
||||
echo "Could not find PHY for device '$1'"
|
||||
wireless_set_retry 0
|
||||
return 1
|
||||
}
|
||||
|
||||
wireless_set_data phy="$phy"
|
||||
mac80211_interface_cleanup "$phy"
|
||||
|
||||
# convert channel to frequency
|
||||
[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel")"
|
||||
|
||||
[ -n "$country" ] && {
|
||||
iw reg get | grep -q "^country $country:" || {
|
||||
iw reg set "$country"
|
||||
sleep 1
|
||||
}
|
||||
}
|
||||
|
||||
hostapd_conf_file="/var/run/hostapd-$phy.conf"
|
||||
|
||||
no_ap=1
|
||||
macidx=0
|
||||
staidx=0
|
||||
|
||||
[ -n "$chanbw" ] && {
|
||||
for file in /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do
|
||||
[ -f "$file" ] && echo "$chanbw" > "$file"
|
||||
done
|
||||
}
|
||||
|
||||
set_default rxantenna all
|
||||
set_default txantenna all
|
||||
set_default distance 0
|
||||
set_default antenna_gain 0
|
||||
|
||||
iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
|
||||
iw phy "$phy" set antenna_gain $antenna_gain
|
||||
iw phy "$phy" set distance "$distance"
|
||||
|
||||
[ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
|
||||
[ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
|
||||
|
||||
has_ap=
|
||||
hostapd_ctrl=
|
||||
for_each_interface "ap" mac80211_check_ap
|
||||
|
||||
rm -f "$hostapd_conf_file"
|
||||
[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
|
||||
# rtk : reoder the prepare_vif flow to workaround
|
||||
for_each_interface "ap" mac80211_prepare_vif
|
||||
for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
|
||||
# for_each_interface "ap" mac80211_prepare_vif
|
||||
|
||||
[ -n "$hostapd_ctrl" ] && {
|
||||
/usr/sbin/hostapd -P /var/run/wifi-$phy.pid -B "$hostapd_conf_file"
|
||||
ret="$?"
|
||||
wireless_add_process "$(cat /var/run/wifi-$phy.pid)" "/usr/sbin/hostapd" 1
|
||||
[ "$ret" != 0 ] && {
|
||||
wireless_setup_failed HOSTAPD_START_FAILED
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
|
||||
|
||||
wireless_set_up
|
||||
}
|
||||
|
||||
list_phy_interfaces() {
|
||||
local phy="$1"
|
||||
if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
|
||||
ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
|
||||
else
|
||||
ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
|
||||
fi
|
||||
}
|
||||
|
||||
drv_mac80211_teardown() {
|
||||
wireless_process_kill_all
|
||||
|
||||
json_select data
|
||||
json_get_vars phy
|
||||
json_select ..
|
||||
|
||||
mac80211_interface_cleanup "$phy"
|
||||
}
|
||||
|
||||
add_driver mac80211
|
||||
@@ -1,190 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
append DRIVERS "mac80211"
|
||||
|
||||
lookup_phy() {
|
||||
[ -n "$phy" ] && {
|
||||
[ -d /sys/class/ieee80211/$phy ] && return
|
||||
}
|
||||
|
||||
local devpath
|
||||
config_get devpath "$device" path
|
||||
[ -n "$devpath" ] && {
|
||||
phy="$(iwinfo nl80211 phyname "path=$devpath")"
|
||||
[ -n "$phy" ] && return
|
||||
}
|
||||
|
||||
local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
|
||||
[ -n "$macaddr" ] && {
|
||||
for _phy in /sys/class/ieee80211/*; do
|
||||
[ -e "$_phy" ] || continue
|
||||
|
||||
[ "$macaddr" = "$(cat ${_phy}/macaddress)" ] || continue
|
||||
phy="${_phy##*/}"
|
||||
return
|
||||
done
|
||||
}
|
||||
phy=
|
||||
return
|
||||
}
|
||||
|
||||
find_mac80211_phy() {
|
||||
local device="$1"
|
||||
|
||||
config_get phy "$device" phy
|
||||
lookup_phy
|
||||
[ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || {
|
||||
echo "PHY for wifi device $1 not found"
|
||||
return 1
|
||||
}
|
||||
config_set "$device" phy "$phy"
|
||||
|
||||
config_get macaddr "$device" macaddr
|
||||
[ -z "$macaddr" ] && {
|
||||
config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)"
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
check_mac80211_device() {
|
||||
config_get phy "$1" phy
|
||||
[ -z "$phy" ] && {
|
||||
find_mac80211_phy "$1" >/dev/null || return 0
|
||||
config_get phy "$1" phy
|
||||
}
|
||||
[ "$phy" = "$dev" ] && found=1
|
||||
}
|
||||
|
||||
|
||||
__get_band_defaults() {
|
||||
local phy="$1"
|
||||
|
||||
( iw phy "$phy" info; echo ) | awk '
|
||||
BEGIN {
|
||||
bands = ""
|
||||
}
|
||||
|
||||
($1 == "Band" || $1 == "") && band {
|
||||
if (channel) {
|
||||
mode="NOHT"
|
||||
if (ht) mode="HT20"
|
||||
if (vht && band != "1:") mode="VHT80"
|
||||
if (he) mode="HE80"
|
||||
if (he && band == "1:") mode="HE20"
|
||||
sub("\\[", "", channel)
|
||||
sub("\\]", "", channel)
|
||||
bands = bands band channel ":" mode " "
|
||||
}
|
||||
band=""
|
||||
}
|
||||
|
||||
$1 == "Band" {
|
||||
band = $2
|
||||
channel = ""
|
||||
vht = ""
|
||||
ht = ""
|
||||
he = ""
|
||||
}
|
||||
|
||||
$0 ~ "Capabilities:" {
|
||||
ht=1
|
||||
}
|
||||
|
||||
$0 ~ "VHT Capabilities" {
|
||||
vht=1
|
||||
}
|
||||
|
||||
$0 ~ "HE Iftypes" {
|
||||
he=1
|
||||
}
|
||||
|
||||
$1 == "*" && $3 == "MHz" && $0 !~ /disabled/ && band && !channel {
|
||||
channel = $4
|
||||
}
|
||||
|
||||
END {
|
||||
print bands
|
||||
}'
|
||||
}
|
||||
|
||||
get_band_defaults() {
|
||||
local phy="$1"
|
||||
|
||||
for c in $(__get_band_defaults "$phy"); do
|
||||
local band="${c%%:*}"
|
||||
c="${c#*:}"
|
||||
local chan="${c%%:*}"
|
||||
c="${c#*:}"
|
||||
local mode="${c%%:*}"
|
||||
|
||||
case "$band" in
|
||||
1) band=2g;;
|
||||
2) band=5g;;
|
||||
3) band=60g;;
|
||||
4) band=6g;;
|
||||
*) band="";;
|
||||
esac
|
||||
|
||||
[ -n "$band" ] || continue
|
||||
[ -n "$mode_band" -a "$band" = "6g" ] && return
|
||||
|
||||
mode_band="$band"
|
||||
channel="$chan"
|
||||
htmode="$mode"
|
||||
done
|
||||
}
|
||||
|
||||
detect_mac80211() {
|
||||
devidx=0
|
||||
config_load wireless
|
||||
while :; do
|
||||
config_get type "radio$devidx" type
|
||||
[ -n "$type" ] || break
|
||||
devidx=$(($devidx + 1))
|
||||
done
|
||||
|
||||
for _dev in /sys/class/ieee80211/*; do
|
||||
[ -e "$_dev" ] || continue
|
||||
|
||||
dev="${_dev##*/}"
|
||||
|
||||
found=0
|
||||
config_foreach check_mac80211_device wifi-device
|
||||
[ "$found" -gt 0 ] && continue
|
||||
|
||||
mode_band=""
|
||||
channel=""
|
||||
htmode=""
|
||||
ht_capab=""
|
||||
|
||||
get_band_defaults "$dev"
|
||||
|
||||
path="$(iwinfo nl80211 path "$dev")"
|
||||
if [ -n "$path" ]; then
|
||||
dev_id="set wireless.radio${devidx}.path='$path'"
|
||||
else
|
||||
dev_id="set wireless.radio${devidx}.macaddr=$(cat /sys/class/ieee80211/${dev}/macaddress)"
|
||||
fi
|
||||
|
||||
uci -q batch <<-EOF
|
||||
set wireless.radio${devidx}=wifi-device
|
||||
set wireless.radio${devidx}.type=mac80211
|
||||
${dev_id}
|
||||
set wireless.radio${devidx}.channel=${channel}
|
||||
set wireless.radio${devidx}.band=${mode_band}
|
||||
set wireless.radio${devidx}.htmode=$htmode
|
||||
set wireless.radio${devidx}.disabled=0
|
||||
|
||||
set wireless.default_radio${devidx}=wifi-iface
|
||||
set wireless.default_radio${devidx}.device=radio${devidx}
|
||||
set wireless.default_radio${devidx}.network=lan
|
||||
set wireless.default_radio${devidx}.mode=ap
|
||||
set wireless.default_radio${devidx}.ssid=OpenWrt
|
||||
set wireless.default_radio${devidx}.encryption=none
|
||||
EOF
|
||||
uci -q commit wireless
|
||||
|
||||
devidx=$(($devidx + 1))
|
||||
done
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "${ACTION}" = "add" ] && {
|
||||
/sbin/wifi config
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
--- a/kconf/Makefile
|
||||
+++ b/kconf/Makefile
|
||||
@@ -1,9 +1,9 @@
|
||||
-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
|
||||
+CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
|
||||
|
||||
LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
|
||||
|
||||
conf: conf.o zconf.tab.o
|
||||
-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
|
||||
+mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
|
||||
mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
|
||||
mconf: CFLAGS += $(mconf_CFLAGS)
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -5,7 +5,7 @@
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
-SHELL := /bin/bash
|
||||
+SHELL := /usr/bin/env bash
|
||||
BACKPORT_DIR := $(shell pwd)
|
||||
|
||||
KMODDIR ?= updates
|
||||
@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
|
||||
KERNEL_CONFIG := $(KLIB_BUILD)/.config
|
||||
KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
|
||||
CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
|
||||
+STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
|
||||
|
||||
export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
|
||||
|
||||
@@ -36,7 +37,8 @@ mrproper:
|
||||
@rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
|
||||
@rm -f backport-include/backport/autoconf.h
|
||||
|
||||
-.DEFAULT:
|
||||
+.SILENT: $(STAMP_KERNEL_CONFIG)
|
||||
+$(STAMP_KERNEL_CONFIG):
|
||||
@set -e ; test -f .local-symbols || ( \
|
||||
echo "/--------------" ;\
|
||||
echo "| You shouldn't run make in the backports tree, but only in" ;\
|
||||
@@ -60,57 +62,61 @@ mrproper:
|
||||
echo "| (that isn't currently running.)" ;\
|
||||
echo "\\--" ;\
|
||||
false)
|
||||
- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
|
||||
- then \
|
||||
- echo -n "Generating local configuration database from kernel ..." ;\
|
||||
- grep -v -f .local-symbols $(KERNEL_CONFIG) | grep = | ( \
|
||||
- while read l ; do \
|
||||
- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
|
||||
- continue ;\
|
||||
- fi ;\
|
||||
- l=$${l:7} ;\
|
||||
- n=$${l%%=*} ;\
|
||||
- v=$${l#*=} ;\
|
||||
- if [ "$$v" = "m" ] ; then \
|
||||
- echo config $$n ;\
|
||||
- echo ' tristate' ;\
|
||||
- elif [ "$$v" = "y" ] ; then \
|
||||
- echo config $$n ;\
|
||||
- echo ' bool' ;\
|
||||
- else \
|
||||
- continue ;\
|
||||
- fi ;\
|
||||
- echo " default $$v" ;\
|
||||
- echo "" ;\
|
||||
- done \
|
||||
- ) > Kconfig.kernel ;\
|
||||
- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
|
||||
- sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\
|
||||
- test "$$kver" != "" || echo "Kernel version parse failed!" ;\
|
||||
- test "$$kver" != "" ;\
|
||||
- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
|
||||
- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
|
||||
- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
|
||||
- print=0 ;\
|
||||
- for v in $$kvers ; do \
|
||||
- if [ "$$print" = "1" ] ; then \
|
||||
- echo config KERNEL_$$(echo $$v | tr . _) ;\
|
||||
- echo " def_bool y" ;\
|
||||
- fi ;\
|
||||
- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
|
||||
- done > Kconfig.versions ;\
|
||||
- # RHEL as well, sadly we need to grep for it ;\
|
||||
- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
|
||||
- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
|
||||
- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
|
||||
- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
|
||||
- for v in $$(seq 0 $$RHEL_MINOR) ; do \
|
||||
- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
|
||||
- echo " def_bool y" ;\
|
||||
- done >> Kconfig.versions ;\
|
||||
- echo " done." ;\
|
||||
- fi ;\
|
||||
- echo "$(CONFIG_MD5)" > .kernel_config_md5
|
||||
+ @rm -f .kernel_config_md5_*
|
||||
+ @touch $@
|
||||
+
|
||||
+Kconfig.kernel: $(STAMP_KERNEL_CONFIG) .local-symbols
|
||||
+ @printf "Generating local configuration database from kernel ..."
|
||||
+ @grep -v -f .local-symbols $(KERNEL_CONFIG) | grep = | ( \
|
||||
+ while read l ; do \
|
||||
+ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
|
||||
+ continue ;\
|
||||
+ fi ;\
|
||||
+ l=$${l:7} ;\
|
||||
+ n=$${l%%=*} ;\
|
||||
+ v=$${l#*=} ;\
|
||||
+ if [ "$$v" = "m" ] ; then \
|
||||
+ echo config $$n ;\
|
||||
+ echo ' tristate' ;\
|
||||
+ elif [ "$$v" = "y" ] ; then \
|
||||
+ echo config $$n ;\
|
||||
+ echo ' bool' ;\
|
||||
+ else \
|
||||
+ continue ;\
|
||||
+ fi ;\
|
||||
+ echo " default $$v" ;\
|
||||
+ echo "" ;\
|
||||
+ done \
|
||||
+ ) > $@
|
||||
+ @echo " done."
|
||||
+
|
||||
+Kconfig.versions: Kconfig.kernel
|
||||
+ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
|
||||
+ sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\
|
||||
+ test "$$kver" != "" || echo "Kernel version parse failed!" ;\
|
||||
+ test "$$kver" != "" ;\
|
||||
+ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
|
||||
+ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
|
||||
+ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
|
||||
+ print=0 ;\
|
||||
+ for v in $$kvers ; do \
|
||||
+ if [ "$$print" = "1" ] ; then \
|
||||
+ echo config KERNEL_$$(echo $$v | tr . _) ;\
|
||||
+ echo " def_bool y" ;\
|
||||
+ fi ;\
|
||||
+ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
|
||||
+ done > $@
|
||||
+ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
|
||||
+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
|
||||
+ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
|
||||
+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
|
||||
+ for v in $$(seq 0 $$RHEL_MINOR) ; do \
|
||||
+ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
|
||||
+ echo " def_bool y" ;\
|
||||
+ done >> $@
|
||||
+
|
||||
+.DEFAULT:
|
||||
+ @$(MAKE) Kconfig.versions
|
||||
@$(MAKE) -f Makefile.real "$@"
|
||||
|
||||
.PHONY: defconfig-help
|
||||
--- a/Makefile.real
|
||||
+++ b/Makefile.real
|
||||
@@ -59,7 +59,7 @@ defconfig-%::
|
||||
|
||||
backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
|
||||
@$(MAKE) oldconfig
|
||||
- @echo -n "Building backport-include/backport/autoconf.h ..."
|
||||
+ @printf "Building backport-include/backport/autoconf.h ..."
|
||||
@grep -f .local-symbols .config | ( \
|
||||
echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
|
||||
echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
|
||||
@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
|
||||
esac ;\
|
||||
done ;\
|
||||
echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
|
||||
- ) > backport-include/backport/autoconf.h
|
||||
+ ) > $@.new
|
||||
+ @if cmp -s $@ $@.new; then \
|
||||
+ rm -f $@.new; \
|
||||
+ else \
|
||||
+ mv $@.new $@; \
|
||||
+ fi
|
||||
@echo " done."
|
||||
|
||||
.PHONY: modules
|
||||
@@ -1,64 +0,0 @@
|
||||
--- a/kconf/conf.c
|
||||
+++ b/kconf/conf.c
|
||||
@@ -593,40 +593,12 @@ int main(int ac, char **av)
|
||||
case oldconfig:
|
||||
case listnewconfig:
|
||||
case olddefconfig:
|
||||
- conf_read(NULL);
|
||||
- break;
|
||||
case allnoconfig:
|
||||
case allyesconfig:
|
||||
case allmodconfig:
|
||||
case alldefconfig:
|
||||
case randconfig:
|
||||
- name = getenv("KCONFIG_ALLCONFIG");
|
||||
- if (!name)
|
||||
- break;
|
||||
- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
|
||||
- if (conf_read_simple(name, S_DEF_USER)) {
|
||||
- fprintf(stderr,
|
||||
- _("*** Can't read seed configuration \"%s\"!\n"),
|
||||
- name);
|
||||
- exit(1);
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- switch (input_mode) {
|
||||
- case allnoconfig: name = "allno.config"; break;
|
||||
- case allyesconfig: name = "allyes.config"; break;
|
||||
- case allmodconfig: name = "allmod.config"; break;
|
||||
- case alldefconfig: name = "alldef.config"; break;
|
||||
- case randconfig: name = "allrandom.config"; break;
|
||||
- default: break;
|
||||
- }
|
||||
- if (conf_read_simple(name, S_DEF_USER) &&
|
||||
- conf_read_simple("all.config", S_DEF_USER)) {
|
||||
- fprintf(stderr,
|
||||
- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
|
||||
- name);
|
||||
- exit(1);
|
||||
- }
|
||||
+ conf_read(NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
--- a/kconf/confdata.c
|
||||
+++ b/kconf/confdata.c
|
||||
@@ -1169,6 +1169,8 @@ bool conf_set_all_new_symbols(enum conf_
|
||||
}
|
||||
bool has_changed = false;
|
||||
|
||||
+ sym_clear_all_valid();
|
||||
+
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
|
||||
continue;
|
||||
@@ -1212,8 +1214,6 @@ bool conf_set_all_new_symbols(enum conf_
|
||||
|
||||
}
|
||||
|
||||
- sym_clear_all_valid();
|
||||
-
|
||||
/*
|
||||
* We have different type of choice blocks.
|
||||
* If curr.tri equals to mod then we can select several
|
||||
@@ -1,34 +0,0 @@
|
||||
--- a/compat/main.c
|
||||
+++ b/compat/main.c
|
||||
@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
|
||||
#error "You need a CPTCFG_VERSION"
|
||||
#endif
|
||||
|
||||
-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
|
||||
-
|
||||
-module_param(backported_kernel_name, charp, 0400);
|
||||
-MODULE_PARM_DESC(backported_kernel_name,
|
||||
- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
|
||||
-
|
||||
-#ifdef BACKPORTS_GIT_TRACKED
|
||||
-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
|
||||
-module_param(backports_tracker_id, charp, 0400);
|
||||
-MODULE_PARM_DESC(backports_tracker_id,
|
||||
- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
|
||||
-#else
|
||||
-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
|
||||
-static char *backports_version = CPTCFG_VERSION;
|
||||
-
|
||||
-module_param(backported_kernel_version, charp, 0400);
|
||||
-MODULE_PARM_DESC(backported_kernel_version,
|
||||
- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
|
||||
-
|
||||
-module_param(backports_version, charp, 0400);
|
||||
-MODULE_PARM_DESC(backports_version,
|
||||
- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
|
||||
-
|
||||
-#endif
|
||||
-
|
||||
void backport_dependency_symbol(void)
|
||||
{
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 28 Jan 2016 15:16:35 +0100
|
||||
Subject: [PATCH] backports: add skb_free_frag()
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/backport-include/linux/skbuff.h
|
||||
+++ b/backport-include/linux/skbuff.h
|
||||
@@ -300,4 +300,11 @@ int skb_ensure_writable(struct sk_buff *
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
|
||||
+static inline void skb_free_frag(void *data)
|
||||
+{
|
||||
+ put_page(virt_to_head_page(data));
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#endif /* __BACKPORT_SKBUFF_H */
|
||||
@@ -1,20 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 28 Jan 2016 15:19:22 +0100
|
||||
Subject: [PATCH] backports: add napi_alloc_frag
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/backport-include/linux/netdevice.h
|
||||
+++ b/backport-include/linux/netdevice.h
|
||||
@@ -232,6 +232,10 @@ static inline void backport_unregister_n
|
||||
#define unregister_netdevice_many LINUX_BACKPORT(unregister_netdevice_many)
|
||||
#endif
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
|
||||
+#define napi_alloc_frag netdev_alloc_frag
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Complicated way of saying: We only backport netdev_rss_key stuff on kernels
|
||||
* that either already have net_get_random_once() (>= 3.13) or where we've been
|
||||
@@ -1,13 +0,0 @@
|
||||
--- a/backport-include/linux/rfkill.h
|
||||
+++ b/backport-include/linux/rfkill.h
|
||||
@@ -2,6 +2,10 @@
|
||||
#define __COMPAT_RFKILL_H
|
||||
#include <linux/version.h>
|
||||
|
||||
+#undef CONFIG_RFKILL
|
||||
+#undef CONFIG_RFKILL_LEDS
|
||||
+#undef CONFIG_RFKILL_MODULE
|
||||
+
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
||||
#include_next <linux/rfkill.h>
|
||||
#else
|
||||
@@ -1,47 +0,0 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
@@ -225,36 +225,37 @@ config RT2800SOC
|
||||
|
||||
|
||||
config RT2800_LIB
|
||||
- tristate
|
||||
+ tristate "RT2800 USB/PCI support"
|
||||
depends on m
|
||||
|
||||
config RT2800_LIB_MMIO
|
||||
- tristate
|
||||
+ tristate "RT2800 MMIO support"
|
||||
depends on m
|
||||
select RT2X00_LIB_MMIO
|
||||
select RT2800_LIB
|
||||
|
||||
config RT2X00_LIB_MMIO
|
||||
- tristate
|
||||
+ tristate "RT2x00 MMIO support"
|
||||
depends on m
|
||||
|
||||
config RT2X00_LIB_PCI
|
||||
- tristate
|
||||
+ tristate "RT2x00 PCI support"
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_SOC
|
||||
- tristate
|
||||
+ tristate "RT2x00 SoC support"
|
||||
+ depends on SOC_RT288X || SOC_RT305X
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_USB
|
||||
- tristate
|
||||
+ tristate "RT2x00 USB support"
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB
|
||||
- tristate
|
||||
+ tristate "RT2x00 support"
|
||||
depends on m
|
||||
|
||||
config RT2X00_LIB_FIRMWARE
|
||||
@@ -1,9 +0,0 @@
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
|
||||
@@ -1,5 +1,5 @@
|
||||
config BRCMUTIL
|
||||
- tristate
|
||||
+ tristate "Broadcom 802.11 driver utility functions"
|
||||
depends on m
|
||||
|
||||
config BRCMSMAC
|
||||
@@ -1,30 +0,0 @@
|
||||
--- a/net/wireless/Kconfig
|
||||
+++ b/net/wireless/Kconfig
|
||||
@@ -171,7 +171,7 @@ config CFG80211_WEXT_EXPORT
|
||||
wext compatibility symbols to be exported.
|
||||
|
||||
config LIB80211
|
||||
- tristate
|
||||
+ tristate "lib80211"
|
||||
depends on m
|
||||
default n
|
||||
help
|
||||
@@ -181,15 +181,15 @@ config LIB80211
|
||||
Drivers should select this themselves if needed.
|
||||
|
||||
config LIB80211_CRYPT_WEP
|
||||
- tristate
|
||||
+ tristate "lib80211 WEP support"
|
||||
depends on m
|
||||
|
||||
config LIB80211_CRYPT_CCMP
|
||||
- tristate
|
||||
+ tristate "lib80211 CCMP support"
|
||||
depends on m
|
||||
|
||||
config LIB80211_CRYPT_TKIP
|
||||
- tristate
|
||||
+ tristate "lib80211 TKIP support"
|
||||
depends on m
|
||||
|
||||
config LIB80211_DEBUG
|
||||
@@ -1,131 +0,0 @@
|
||||
--- a/.local-symbols
|
||||
+++ b/.local-symbols
|
||||
@@ -476,44 +476,6 @@ USB_IPHETH=
|
||||
USB_SIERRA_NET=
|
||||
USB_VL600=
|
||||
USB_NET_CH9200=
|
||||
-SSB_POSSIBLE=
|
||||
-SSB=
|
||||
-SSB_SPROM=
|
||||
-SSB_BLOCKIO=
|
||||
-SSB_PCIHOST_POSSIBLE=
|
||||
-SSB_PCIHOST=
|
||||
-SSB_B43_PCI_BRIDGE=
|
||||
-SSB_PCMCIAHOST_POSSIBLE=
|
||||
-SSB_PCMCIAHOST=
|
||||
-SSB_SDIOHOST_POSSIBLE=
|
||||
-SSB_SDIOHOST=
|
||||
-SSB_HOST_SOC=
|
||||
-SSB_SILENT=
|
||||
-SSB_DEBUG=
|
||||
-SSB_SERIAL=
|
||||
-SSB_DRIVER_PCICORE_POSSIBLE=
|
||||
-SSB_DRIVER_PCICORE=
|
||||
-SSB_PCICORE_HOSTMODE=
|
||||
-SSB_DRIVER_MIPS=
|
||||
-SSB_SFLASH=
|
||||
-SSB_EMBEDDED=
|
||||
-SSB_DRIVER_EXTIF=
|
||||
-SSB_DRIVER_GIGE=
|
||||
-SSB_DRIVER_GPIO=
|
||||
-BCMA_POSSIBLE=
|
||||
-BCMA=
|
||||
-BCMA_BLOCKIO=
|
||||
-BCMA_HOST_PCI_POSSIBLE=
|
||||
-BCMA_HOST_PCI=
|
||||
-BCMA_HOST_SOC=
|
||||
-BCMA_DRIVER_PCI=
|
||||
-BCMA_DRIVER_PCI_HOSTMODE=
|
||||
-BCMA_DRIVER_MIPS=
|
||||
-BCMA_SFLASH=
|
||||
-BCMA_NFLASH=
|
||||
-BCMA_DRIVER_GMAC_CMN=
|
||||
-BCMA_DRIVER_GPIO=
|
||||
-BCMA_DEBUG=
|
||||
NFC=
|
||||
NFC_DIGITAL=
|
||||
NFC_NCI=
|
||||
--- a/drivers/net/wireless/broadcom/b43/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43/main.c
|
||||
@@ -2866,7 +2866,7 @@ static struct ssb_device *b43_ssb_gpio_d
|
||||
{
|
||||
struct ssb_bus *bus = dev->dev->sdev->bus;
|
||||
|
||||
-#ifdef CPTCFG_SSB_DRIVER_PCICORE
|
||||
+#ifdef CONFIG_SSB_DRIVER_PCICORE
|
||||
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
|
||||
#else
|
||||
return bus->chipco.dev;
|
||||
@@ -4903,7 +4903,7 @@ static int b43_wireless_core_init(struct
|
||||
}
|
||||
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
|
||||
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
|
||||
-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
|
||||
+#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
|
||||
if (dev->dev->bus_type == B43_BUS_SSB &&
|
||||
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
|
||||
dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
|
||||
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
|
||||
@@ -1937,7 +1937,7 @@ static int b43legacy_gpio_init(struct b4
|
||||
if (dev->dev->id.revision >= 2)
|
||||
mask |= 0x0010; /* FIXME: This is redundant. */
|
||||
|
||||
-#ifdef CPTCFG_SSB_DRIVER_PCICORE
|
||||
+#ifdef CONFIG_SSB_DRIVER_PCICORE
|
||||
pcidev = bus->pcicore.dev;
|
||||
#endif
|
||||
gpiodev = bus->chipco.dev ? : pcidev;
|
||||
@@ -1956,7 +1956,7 @@ static void b43legacy_gpio_cleanup(struc
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
struct ssb_device *gpiodev, *pcidev = NULL;
|
||||
|
||||
-#ifdef CPTCFG_SSB_DRIVER_PCICORE
|
||||
+#ifdef CONFIG_SSB_DRIVER_PCICORE
|
||||
pcidev = bus->pcicore.dev;
|
||||
#endif
|
||||
gpiodev = bus->chipco.dev ? : pcidev;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
|
||||
@@ -43,6 +43,6 @@ brcmsmac-y := \
|
||||
brcms_trace_events.o \
|
||||
debug.o
|
||||
|
||||
-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o
|
||||
+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
|
||||
|
||||
obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
|
||||
@@ -22,7 +22,7 @@ struct brcms_led {
|
||||
bool active_low;
|
||||
};
|
||||
|
||||
-#ifdef CPTCFG_BCMA_DRIVER_GPIO
|
||||
+#ifdef CONFIG_BCMA_DRIVER_GPIO
|
||||
void brcms_led_unregister(struct brcms_info *wl);
|
||||
int brcms_led_register(struct brcms_info *wl);
|
||||
#else
|
||||
--- a/Kconfig.sources
|
||||
+++ b/Kconfig.sources
|
||||
@@ -9,9 +9,6 @@ source "$BACKPORT_DIR/drivers/net/wirele
|
||||
source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
|
||||
source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
|
||||
|
||||
-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
|
||||
-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
|
||||
-
|
||||
source "$BACKPORT_DIR/net/nfc/Kconfig"
|
||||
|
||||
source "$BACKPORT_DIR/drivers/media/Kconfig"
|
||||
--- a/Makefile.kernel
|
||||
+++ b/Makefile.kernel
|
||||
@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
|
||||
obj-$(CPTCFG_WLAN) += drivers/net/wireless/
|
||||
obj-$(CPTCFG_BT) += net/bluetooth/
|
||||
obj-$(CPTCFG_BT) += drivers/bluetooth/
|
||||
-obj-$(CPTCFG_SSB) += drivers/ssb/
|
||||
-obj-$(CPTCFG_BCMA) += drivers/bcma/
|
||||
obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/
|
||||
obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
|
||||
obj-$(CPTCFG_NFC) += net/nfc/
|
||||
@@ -1,9 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/Kconfig
|
||||
@@ -1,5 +1,5 @@
|
||||
config ATH_COMMON
|
||||
- tristate
|
||||
+ tristate "ath.ko"
|
||||
depends on m
|
||||
|
||||
config WLAN_VENDOR_ATH
|
||||
@@ -1,20 +0,0 @@
|
||||
--- a/compat/compat-3.6.c
|
||||
+++ b/compat/compat-3.6.c
|
||||
@@ -147,17 +147,3 @@ int sg_alloc_table_from_pages(struct sg_
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sg_alloc_table_from_pages);
|
||||
-
|
||||
-/* whoopsie ! */
|
||||
-#ifndef CONFIG_COMMON_CLK
|
||||
-int clk_enable(struct clk *clk)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(clk_enable);
|
||||
-
|
||||
-void clk_disable(struct clk *clk)
|
||||
-{
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(clk_disable);
|
||||
-#endif
|
||||
@@ -1,376 +0,0 @@
|
||||
--- a/net/mac80211/Kconfig
|
||||
+++ b/net/mac80211/Kconfig
|
||||
@@ -5,8 +5,6 @@ config MAC80211
|
||||
depends on CRYPTO
|
||||
depends on CRYPTO_ARC4
|
||||
depends on CRYPTO_AES
|
||||
- select BPAUTO_CRYPTO_CCM
|
||||
- depends on CRYPTO_GCM
|
||||
depends on CRC32
|
||||
---help---
|
||||
This option enables the hardware independent IEEE 802.11
|
||||
--- a/net/mac80211/Makefile
|
||||
+++ b/net/mac80211/Makefile
|
||||
@@ -16,9 +16,7 @@ mac80211-y := \
|
||||
michael.o \
|
||||
tkip.o \
|
||||
aes_ccm.o \
|
||||
- aes_gcm.o \
|
||||
aes_cmac.o \
|
||||
- aes_gmac.o \
|
||||
cfg.o \
|
||||
ethtool.o \
|
||||
rx.o \
|
||||
--- a/net/mac80211/aes_ccm.c
|
||||
+++ b/net/mac80211/aes_ccm.c
|
||||
@@ -13,89 +13,132 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/aead.h>
|
||||
+#include <crypto/aes.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include "key.h"
|
||||
#include "aes_ccm.h"
|
||||
|
||||
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic,
|
||||
- size_t mic_len)
|
||||
+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
|
||||
+ u8 *a, u8 *b)
|
||||
{
|
||||
- struct scatterlist sg[3];
|
||||
+ int i;
|
||||
+
|
||||
+ crypto_cipher_encrypt_one(tfm, b, b_0);
|
||||
+
|
||||
+ /* Extra Authenticate-only data (always two AES blocks) */
|
||||
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
+ aad[i] ^= b[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, b, aad);
|
||||
+
|
||||
+ aad += AES_BLOCK_SIZE;
|
||||
+
|
||||
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
+ aad[i] ^= b[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, a, aad);
|
||||
|
||||
- char aead_req_data[sizeof(struct aead_request) +
|
||||
- crypto_aead_reqsize(tfm)]
|
||||
- __aligned(__alignof__(struct aead_request));
|
||||
- struct aead_request *aead_req = (void *) aead_req_data;
|
||||
+ /* Mask out bits from auth-only-b_0 */
|
||||
+ b_0[0] &= 0x07;
|
||||
|
||||
- memset(aead_req, 0, sizeof(aead_req_data));
|
||||
+ /* S_0 is used to encrypt T (= MIC) */
|
||||
+ b_0[14] = 0;
|
||||
+ b_0[15] = 0;
|
||||
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
|
||||
+}
|
||||
|
||||
- sg_init_table(sg, 3);
|
||||
- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
|
||||
- sg_set_buf(&sg[1], data, data_len);
|
||||
- sg_set_buf(&sg[2], mic, mic_len);
|
||||
|
||||
- aead_request_set_tfm(aead_req, tfm);
|
||||
- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
|
||||
- aead_request_set_ad(aead_req, sg[0].length);
|
||||
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic,
|
||||
+ size_t mic_len)
|
||||
+{
|
||||
+ int i, j, last_len, num_blocks;
|
||||
+ u8 b[AES_BLOCK_SIZE];
|
||||
+ u8 s_0[AES_BLOCK_SIZE];
|
||||
+ u8 e[AES_BLOCK_SIZE];
|
||||
+ u8 *pos, *cpos;
|
||||
+
|
||||
+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
|
||||
+ last_len = data_len % AES_BLOCK_SIZE;
|
||||
+ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b);
|
||||
+
|
||||
+ /* Process payload blocks */
|
||||
+ pos = data;
|
||||
+ cpos = data;
|
||||
+ for (j = 1; j <= num_blocks; j++) {
|
||||
+ int blen = (j == num_blocks && last_len) ?
|
||||
+ last_len : AES_BLOCK_SIZE;
|
||||
+
|
||||
+ /* Authentication followed by encryption */
|
||||
+ for (i = 0; i < blen; i++)
|
||||
+ b[i] ^= pos[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, b, b);
|
||||
+
|
||||
+ b_0[14] = (j >> 8) & 0xff;
|
||||
+ b_0[15] = j & 0xff;
|
||||
+ crypto_cipher_encrypt_one(tfm, e, b_0);
|
||||
+ for (i = 0; i < blen; i++)
|
||||
+ *cpos++ = *pos++ ^ e[i];
|
||||
+ }
|
||||
|
||||
- crypto_aead_encrypt(aead_req);
|
||||
+ for (i = 0; i < mic_len; i++)
|
||||
+ mic[i] = b[i] ^ s_0[i];
|
||||
}
|
||||
|
||||
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len)
|
||||
{
|
||||
- struct scatterlist sg[3];
|
||||
- char aead_req_data[sizeof(struct aead_request) +
|
||||
- crypto_aead_reqsize(tfm)]
|
||||
- __aligned(__alignof__(struct aead_request));
|
||||
- struct aead_request *aead_req = (void *) aead_req_data;
|
||||
-
|
||||
- if (data_len == 0)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- memset(aead_req, 0, sizeof(aead_req_data));
|
||||
-
|
||||
- sg_init_table(sg, 3);
|
||||
- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
|
||||
- sg_set_buf(&sg[1], data, data_len);
|
||||
- sg_set_buf(&sg[2], mic, mic_len);
|
||||
-
|
||||
- aead_request_set_tfm(aead_req, tfm);
|
||||
- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
|
||||
- aead_request_set_ad(aead_req, sg[0].length);
|
||||
+ int i, j, last_len, num_blocks;
|
||||
+ u8 *pos, *cpos;
|
||||
+ u8 a[AES_BLOCK_SIZE];
|
||||
+ u8 b[AES_BLOCK_SIZE];
|
||||
+ u8 s_0[AES_BLOCK_SIZE];
|
||||
+
|
||||
+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
|
||||
+ last_len = data_len % AES_BLOCK_SIZE;
|
||||
+ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b);
|
||||
+
|
||||
+ /* Process payload blocks */
|
||||
+ cpos = data;
|
||||
+ pos = data;
|
||||
+ for (j = 1; j <= num_blocks; j++) {
|
||||
+ int blen = (j == num_blocks && last_len) ?
|
||||
+ last_len : AES_BLOCK_SIZE;
|
||||
+
|
||||
+ /* Decryption followed by authentication */
|
||||
+ b_0[14] = (j >> 8) & 0xff;
|
||||
+ b_0[15] = j & 0xff;
|
||||
+ crypto_cipher_encrypt_one(tfm, b, b_0);
|
||||
+ for (i = 0; i < blen; i++) {
|
||||
+ *pos = *cpos++ ^ b[i];
|
||||
+ a[i] ^= *pos++;
|
||||
+ }
|
||||
+ crypto_cipher_encrypt_one(tfm, a, a);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < mic_len; i++) {
|
||||
+ if ((mic[i] ^ s_0[i]) != a[i])
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- return crypto_aead_decrypt(aead_req);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len,
|
||||
- size_t mic_len)
|
||||
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
+ size_t key_len,
|
||||
+ size_t mic_len)
|
||||
{
|
||||
- struct crypto_aead *tfm;
|
||||
- int err;
|
||||
+ struct crypto_cipher *tfm;
|
||||
|
||||
- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
- if (IS_ERR(tfm))
|
||||
- return tfm;
|
||||
-
|
||||
- err = crypto_aead_setkey(tfm, key, key_len);
|
||||
- if (err)
|
||||
- goto free_aead;
|
||||
- err = crypto_aead_setauthsize(tfm, mic_len);
|
||||
- if (err)
|
||||
- goto free_aead;
|
||||
+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
+ if (!IS_ERR(tfm))
|
||||
+ crypto_cipher_setkey(tfm, key, key_len);
|
||||
|
||||
return tfm;
|
||||
-
|
||||
-free_aead:
|
||||
- crypto_free_aead(tfm);
|
||||
- return ERR_PTR(err);
|
||||
}
|
||||
|
||||
-void ieee80211_aes_key_free(struct crypto_aead *tfm)
|
||||
+
|
||||
+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
|
||||
{
|
||||
- crypto_free_aead(tfm);
|
||||
+ crypto_free_cipher(tfm);
|
||||
}
|
||||
--- a/net/mac80211/aes_ccm.h
|
||||
+++ b/net/mac80211/aes_ccm.h
|
||||
@@ -12,15 +12,15 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len,
|
||||
- size_t mic_len);
|
||||
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
+ size_t key_len,
|
||||
+ size_t mic_len);
|
||||
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len);
|
||||
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len);
|
||||
-void ieee80211_aes_key_free(struct crypto_aead *tfm);
|
||||
+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
|
||||
|
||||
#endif /* AES_CCM_H */
|
||||
--- a/net/mac80211/aes_gcm.h
|
||||
+++ b/net/mac80211/aes_gcm.h
|
||||
@@ -11,12 +11,28 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic);
|
||||
-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic);
|
||||
-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len);
|
||||
-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
|
||||
+static inline void
|
||||
+ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static inline struct crypto_aead *
|
||||
+ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
|
||||
+{
|
||||
+}
|
||||
|
||||
#endif /* AES_GCM_H */
|
||||
--- a/net/mac80211/aes_gmac.h
|
||||
+++ b/net/mac80211/aes_gmac.h
|
||||
@@ -11,10 +11,22 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
|
||||
- size_t key_len);
|
||||
-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
|
||||
- const u8 *data, size_t data_len, u8 *mic);
|
||||
-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
|
||||
+static inline struct crypto_aead *
|
||||
+ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
|
||||
+ const u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
|
||||
+{
|
||||
+}
|
||||
|
||||
#endif /* AES_GMAC_H */
|
||||
--- a/net/mac80211/key.h
|
||||
+++ b/net/mac80211/key.h
|
||||
@@ -84,7 +84,7 @@ struct ieee80211_key {
|
||||
* Management frames.
|
||||
*/
|
||||
u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
|
||||
- struct crypto_aead *tfm;
|
||||
+ struct crypto_cipher *tfm;
|
||||
u32 replays; /* dot11RSNAStatsCCMPReplays */
|
||||
} ccmp;
|
||||
struct {
|
||||
--- a/net/mac80211/wpa.c
|
||||
+++ b/net/mac80211/wpa.c
|
||||
@@ -307,7 +307,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
|
||||
}
|
||||
|
||||
|
||||
-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
|
||||
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
|
||||
+ u16 data_len)
|
||||
{
|
||||
__le16 mask_fc;
|
||||
int a4_included, mgmt;
|
||||
@@ -337,14 +338,8 @@ static void ccmp_special_blocks(struct s
|
||||
else
|
||||
qos_tid = 0;
|
||||
|
||||
- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
|
||||
- * mode authentication are not allowed to collide, yet both are derived
|
||||
- * from this vector b_0. We only set L := 1 here to indicate that the
|
||||
- * data size can be represented in (L+1) bytes. The CCM layer will take
|
||||
- * care of storing the data length in the top (L+1) bytes and setting
|
||||
- * and clearing the other bits as is required to derive the two IVs.
|
||||
- */
|
||||
- b_0[0] = 0x1;
|
||||
+ /* First block, b_0 */
|
||||
+ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
|
||||
|
||||
/* Nonce: Nonce Flags | A2 | PN
|
||||
* Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
|
||||
@@ -352,6 +347,8 @@ static void ccmp_special_blocks(struct s
|
||||
b_0[1] = qos_tid | (mgmt << 4);
|
||||
memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
|
||||
memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
|
||||
+ /* l(m) */
|
||||
+ put_unaligned_be16(data_len, &b_0[14]);
|
||||
|
||||
/* AAD (extra authenticate-only data) / masked 802.11 header
|
||||
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
|
||||
@@ -463,7 +460,7 @@ static int ccmp_encrypt_skb(struct ieee8
|
||||
return 0;
|
||||
|
||||
pos += IEEE80211_CCMP_HDR_LEN;
|
||||
- ccmp_special_blocks(skb, pn, b_0, aad);
|
||||
+ ccmp_special_blocks(skb, pn, b_0, aad, len);
|
||||
ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
|
||||
skb_put(skb, mic_len), mic_len);
|
||||
|
||||
@@ -534,7 +531,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
|
||||
u8 aad[2 * AES_BLOCK_SIZE];
|
||||
u8 b_0[AES_BLOCK_SIZE];
|
||||
/* hardware didn't decrypt/verify MIC */
|
||||
- ccmp_special_blocks(skb, pn, b_0, aad);
|
||||
+ ccmp_special_blocks(skb, pn, b_0, aad, data_len);
|
||||
|
||||
if (ieee80211_aes_ccm_decrypt(
|
||||
key->u.ccmp.tfm, b_0, aad,
|
||||
@@ -1,12 +0,0 @@
|
||||
Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -846,7 +846,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
|
||||
|
||||
__sta_info_flush(sdata, true);
|
||||
- ieee80211_free_keys(sdata, true);
|
||||
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
sdata->vif.bss_conf.ssid_len = 0;
|
||||
@@ -1,43 +0,0 @@
|
||||
--- a/net/wireless/sysfs.c
|
||||
+++ b/net/wireless/sysfs.c
|
||||
@@ -24,18 +24,35 @@ static inline struct cfg80211_registered
|
||||
return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
|
||||
}
|
||||
|
||||
-#define SHOW_FMT(name, fmt, member) \
|
||||
+#define SHOW_FMT(name, fmt, member, mode) \
|
||||
static ssize_t name ## _show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
|
||||
} \
|
||||
-static DEVICE_ATTR_RO(name)
|
||||
+static DEVICE_ATTR_##mode(name)
|
||||
|
||||
-SHOW_FMT(index, "%d", wiphy_idx);
|
||||
-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
|
||||
-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
|
||||
+static ssize_t macaddress_store(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ const char *buf, size_t len)
|
||||
+{
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+
|
||||
+ if (!mac_pton(buf, mac))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
|
||||
+
|
||||
+ return strnlen(buf, len);
|
||||
+}
|
||||
+
|
||||
+SHOW_FMT(index, "%d", wiphy_idx, RO);
|
||||
+SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
|
||||
+SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
|
||||
|
||||
static ssize_t name_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@@ -1,67 +0,0 @@
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -291,7 +291,7 @@ void ieee80211_restart_hw(struct ieee802
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_restart_hw);
|
||||
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
static int ieee80211_ifa_changed(struct notifier_block *nb,
|
||||
unsigned long data, void *arg)
|
||||
{
|
||||
@@ -350,7 +350,7 @@ static int ieee80211_ifa_changed(struct
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
static int ieee80211_ifa6_changed(struct notifier_block *nb,
|
||||
unsigned long data, void *arg)
|
||||
{
|
||||
@@ -1087,14 +1087,14 @@ int ieee80211_register_hw(struct ieee802
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
|
||||
result = register_inetaddr_notifier(&local->ifa_notifier);
|
||||
if (result)
|
||||
goto fail_ifa;
|
||||
#endif
|
||||
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
|
||||
result = register_inet6addr_notifier(&local->ifa6_notifier);
|
||||
if (result)
|
||||
@@ -1103,13 +1103,13 @@ int ieee80211_register_hw(struct ieee802
|
||||
|
||||
return 0;
|
||||
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
fail_ifa6:
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
unregister_inetaddr_notifier(&local->ifa_notifier);
|
||||
#endif
|
||||
#endif
|
||||
-#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
|
||||
+#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
|
||||
fail_ifa:
|
||||
#endif
|
||||
rtnl_lock();
|
||||
@@ -1137,10 +1137,10 @@ void ieee80211_unregister_hw(struct ieee
|
||||
tasklet_kill(&local->tx_pending_tasklet);
|
||||
tasklet_kill(&local->tasklet);
|
||||
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
unregister_inetaddr_notifier(&local->ifa_notifier);
|
||||
#endif
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
unregister_inet6addr_notifier(&local->ifa6_notifier);
|
||||
#endif
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath5k/initvals.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
|
||||
@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini
|
||||
{ AR5K_IMR, 0 },
|
||||
{ AR5K_IER, AR5K_IER_DISABLE },
|
||||
{ AR5K_BSR, 0, AR5K_INI_READ },
|
||||
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
|
||||
{ AR5K_TXCFG, AR5K_DMASIZE_128B },
|
||||
{ AR5K_RXCFG, AR5K_DMASIZE_128B },
|
||||
+#else
|
||||
+ /* WAR for AR71xx PCI bug */
|
||||
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
|
||||
+ { AR5K_RXCFG, AR5K_DMASIZE_4B },
|
||||
+#endif
|
||||
{ AR5K_CFG, AR5K_INIT_CFG },
|
||||
{ AR5K_TOPS, 8 },
|
||||
{ AR5K_RXNOFRM, 8 },
|
||||
--- a/drivers/net/wireless/ath/ath5k/dma.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/dma.c
|
||||
@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
|
||||
* guess we can tweak it and see how it goes ;-)
|
||||
*/
|
||||
if (ah->ah_version != AR5K_AR5210) {
|
||||
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
|
||||
AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
|
||||
AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
|
||||
+#else
|
||||
+ /* WAR for AR71xx PCI bug */
|
||||
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
|
||||
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
|
||||
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
|
||||
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
|
||||
+#endif
|
||||
}
|
||||
|
||||
/* Pre-enable interrupts on 5211/5212*/
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -1999,7 +1999,7 @@ static int ieee80211_scan(struct wiphy *
|
||||
* the frames sent while scanning on other channel will be
|
||||
* lost)
|
||||
*/
|
||||
- if (sdata->u.ap.beacon &&
|
||||
+ if (0 && sdata->u.ap.beacon &&
|
||||
(!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
|
||||
!(req->flags & NL80211_SCAN_FLAG_AP)))
|
||||
return -EOPNOTSUPP;
|
||||
@@ -1,31 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sun, 7 Jun 2015 13:53:35 +0200
|
||||
Subject: [PATCH] ath9k: force rx_clear when disabling rx
|
||||
|
||||
This makes stopping Rx more reliable and should reduce the frequency of
|
||||
Rx related DMA stop warnings
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||
@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath
|
||||
|
||||
ath9k_ani_reset(ah, is_scanning);
|
||||
|
||||
- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
+ REG_CLR_BIT(ah, AR_DIAG_SW,
|
||||
+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_startpcureceive);
|
||||
|
||||
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
|
||||
{
|
||||
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
|
||||
+ REG_SET_BIT(ah, AR_DIAG_SW,
|
||||
+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
|
||||
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 2 Jul 2015 15:20:56 +0200
|
||||
Subject: [PATCH] ath9k: limit retries for powersave response frames
|
||||
|
||||
In some cases, the channel might be busy enough that an ath9k AP's
|
||||
response to PS-Poll frames might be too slow and the station has already
|
||||
gone to sleep. To avoid wasting too much airtime on this, limit the
|
||||
number of retries on such frames and ensure that no sample rate gets
|
||||
used.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -136,10 +136,25 @@ static void ath_send_bar(struct ath_atx_
|
||||
}
|
||||
|
||||
static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
- struct ath_buf *bf)
|
||||
+ struct ath_buf *bf, bool ps)
|
||||
{
|
||||
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
+
|
||||
+ if (ps) {
|
||||
+ /* Clear the first rate to avoid using a sample rate for PS frames */
|
||||
+ info->control.rates[0].idx = -1;
|
||||
+ info->control.rates[0].count = 0;
|
||||
+ }
|
||||
+
|
||||
ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
+ if (!ps)
|
||||
+ return;
|
||||
+
|
||||
+ if (bf->rates[0].count > 2)
|
||||
+ bf->rates[0].count = 2;
|
||||
+
|
||||
+ bf->rates[1].idx = -1;
|
||||
}
|
||||
|
||||
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
|
||||
@@ -1419,7 +1434,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
break;
|
||||
|
||||
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
@@ -1450,7 +1465,7 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
return false;
|
||||
}
|
||||
|
||||
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
|
||||
if (aggr)
|
||||
last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
|
||||
tid_q, &aggr_len);
|
||||
@@ -1647,7 +1662,7 @@ void ath9k_release_buffered_frames(struc
|
||||
|
||||
__skb_unlink(bf->bf_mpdu, tid_q);
|
||||
list_add_tail(&bf->list, &bf_q);
|
||||
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
|
||||
if (bf_isampdu(bf)) {
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
bf->bf_state.bf_type &= ~BUF_AGGR;
|
||||
@@ -2293,7 +2308,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf;
|
||||
- bool queue, skip_uapsd = false, ps_resp;
|
||||
+ bool queue, ps_resp;
|
||||
int q, ret;
|
||||
|
||||
if (vif)
|
||||
@@ -2346,13 +2361,13 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
if (!txctl->an)
|
||||
txctl->an = &avp->mcast_node;
|
||||
queue = true;
|
||||
- skip_uapsd = true;
|
||||
+ ps_resp = false;
|
||||
}
|
||||
|
||||
if (txctl->an && queue)
|
||||
tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||
|
||||
- if (!skip_uapsd && ps_resp) {
|
||||
+ if (ps_resp) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
txq = sc->tx.uapsdq;
|
||||
ath_txq_lock(sc, txq);
|
||||
@@ -2390,7 +2405,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||
|
||||
- ath_set_rates(vif, sta, bf);
|
||||
+ ath_set_rates(vif, sta, bf, ps_resp);
|
||||
ath_tx_send_normal(sc, txq, tid, skb);
|
||||
|
||||
out:
|
||||
@@ -2429,7 +2444,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
||||
break;
|
||||
|
||||
bf->bf_lastbf = bf;
|
||||
- ath_set_rates(vif, NULL, bf);
|
||||
+ ath_set_rates(vif, NULL, bf, false);
|
||||
ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
|
||||
duration += info.rates[0].PktDuration;
|
||||
if (bf_tail)
|
||||
@@ -2932,7 +2947,7 @@ int ath9k_tx99_send(struct ath_softc *sc
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- ath_set_rates(sc->tx99_vif, NULL, bf);
|
||||
+ ath_set_rates(sc->tx99_vif, NULL, bf, false);
|
||||
|
||||
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
|
||||
ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
|
||||
@@ -1,95 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 14 Jan 2016 03:14:03 +0100
|
||||
Subject: [PATCH] ath9k_hw: add low power tx gain table for AR953x
|
||||
|
||||
Used in some newer TP-Link AR9533 devices.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
||||
@@ -698,6 +698,9 @@ static void ar9003_tx_gain_table_mode2(s
|
||||
else if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_low_ob_db_tx_gain_table_1p0);
|
||||
+ else if (AR_SREV_9531_11(ah))
|
||||
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
+ qca953x_1p1_modes_no_xpa_low_power_tx_gain_table);
|
||||
else if (AR_SREV_9485_11_OR_LATER(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485Modes_low_ob_db_tx_gain_1_1);
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
|
||||
@@ -757,6 +757,71 @@ static const u32 qca953x_1p1_modes_xpa_t
|
||||
{0x00016448, 0x6c927a70},
|
||||
};
|
||||
|
||||
+static const u32 qca953x_1p1_modes_no_xpa_low_power_tx_gain_table[][2] = {
|
||||
+ /* Addr allmodes */
|
||||
+ {0x0000a2dc, 0xfff55592},
|
||||
+ {0x0000a2e0, 0xfff99924},
|
||||
+ {0x0000a2e4, 0xfffe1e00},
|
||||
+ {0x0000a2e8, 0xffffe000},
|
||||
+ {0x0000a410, 0x000050d6},
|
||||
+ {0x0000a500, 0x00000069},
|
||||
+ {0x0000a504, 0x0400006b},
|
||||
+ {0x0000a508, 0x0800006d},
|
||||
+ {0x0000a50c, 0x0c000269},
|
||||
+ {0x0000a510, 0x1000026b},
|
||||
+ {0x0000a514, 0x1400026d},
|
||||
+ {0x0000a518, 0x18000669},
|
||||
+ {0x0000a51c, 0x1c00066b},
|
||||
+ {0x0000a520, 0x1d000a68},
|
||||
+ {0x0000a524, 0x21000a6a},
|
||||
+ {0x0000a528, 0x25000a6c},
|
||||
+ {0x0000a52c, 0x29000a6e},
|
||||
+ {0x0000a530, 0x2d0012a9},
|
||||
+ {0x0000a534, 0x310012ab},
|
||||
+ {0x0000a538, 0x350012ad},
|
||||
+ {0x0000a53c, 0x39001b0a},
|
||||
+ {0x0000a540, 0x3d001b0c},
|
||||
+ {0x0000a544, 0x41001b0e},
|
||||
+ {0x0000a548, 0x43001bae},
|
||||
+ {0x0000a54c, 0x45001914},
|
||||
+ {0x0000a550, 0x47001916},
|
||||
+ {0x0000a554, 0x49001b96},
|
||||
+ {0x0000a558, 0x49001b96},
|
||||
+ {0x0000a55c, 0x49001b96},
|
||||
+ {0x0000a560, 0x49001b96},
|
||||
+ {0x0000a564, 0x49001b96},
|
||||
+ {0x0000a568, 0x49001b96},
|
||||
+ {0x0000a56c, 0x49001b96},
|
||||
+ {0x0000a570, 0x49001b96},
|
||||
+ {0x0000a574, 0x49001b96},
|
||||
+ {0x0000a578, 0x49001b96},
|
||||
+ {0x0000a57c, 0x49001b96},
|
||||
+ {0x0000a600, 0x00000000},
|
||||
+ {0x0000a604, 0x00000000},
|
||||
+ {0x0000a608, 0x00000000},
|
||||
+ {0x0000a60c, 0x00000000},
|
||||
+ {0x0000a610, 0x00000000},
|
||||
+ {0x0000a614, 0x00000000},
|
||||
+ {0x0000a618, 0x00804201},
|
||||
+ {0x0000a61c, 0x01408201},
|
||||
+ {0x0000a620, 0x01408502},
|
||||
+ {0x0000a624, 0x01408502},
|
||||
+ {0x0000a628, 0x01408502},
|
||||
+ {0x0000a62c, 0x01408502},
|
||||
+ {0x0000a630, 0x01408502},
|
||||
+ {0x0000a634, 0x01408502},
|
||||
+ {0x0000a638, 0x01408502},
|
||||
+ {0x0000a63c, 0x01408502},
|
||||
+ {0x0000b2dc, 0xfff55592},
|
||||
+ {0x0000b2e0, 0xfff99924},
|
||||
+ {0x0000b2e4, 0xfffe1e00},
|
||||
+ {0x0000b2e8, 0xffffe000},
|
||||
+ {0x00016044, 0x044922db},
|
||||
+ {0x00016048, 0x6c927a70},
|
||||
+ {0x00016444, 0x044922db},
|
||||
+ {0x00016448, 0x6c927a70},
|
||||
+};
|
||||
+
|
||||
static const u32 qca953x_2p0_baseband_core[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00009800, 0xafe68e30},
|
||||
@@ -1,156 +0,0 @@
|
||||
From: Eli Cooper <elicooper@gmx.com>
|
||||
Date: Thu, 14 Jan 2016 00:07:12 +0800
|
||||
Subject: [PATCH] rt2x00: fix monitor mode regression
|
||||
|
||||
Since commit df1404650ccbfeb76a84f301f22316be0d00a864 monitor mode for rt2x00
|
||||
has been made effectively useless because the hardware filter is configured to
|
||||
drop packets whose intended recipient is not the device, regardless of the
|
||||
presence of monitor mode interfaces.
|
||||
|
||||
This patch fixes this regression by adding explicit monitor mode support, and
|
||||
configuring the hardware filter accordingly.
|
||||
|
||||
Signed-off-by: Eli Cooper <elicooper@gmx.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
|
||||
@@ -273,8 +273,10 @@ static void rt2400pci_config_filter(stru
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
|
||||
+ !rt2x00dev->is_monitoring);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
|
||||
+ !rt2x00dev->is_monitoring &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
|
||||
@@ -274,8 +274,10 @@ static void rt2500pci_config_filter(stru
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
|
||||
+ !rt2x00dev->is_monitoring);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
|
||||
+ !rt2x00dev->is_monitoring &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field32(®, RXCSR0_DROP_MCAST,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
|
||||
@@ -437,8 +437,10 @@ static void rt2500usb_config_filter(stru
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
- rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME,
|
||||
+ !rt2x00dev->is_monitoring);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS,
|
||||
+ !rt2x00dev->is_monitoring &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1490,7 +1490,8 @@ void rt2800_config_filter(struct rt2x00_
|
||||
!(filter_flags & FIF_FCSFAIL));
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR,
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
- rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME,
|
||||
+ !rt2x00dev->is_monitoring);
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1);
|
||||
rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -844,11 +844,13 @@ struct rt2x00_dev {
|
||||
* - Open sta interface count.
|
||||
* - Association count.
|
||||
* - Beaconing enabled count.
|
||||
+ * - Whether the device is monitoring.
|
||||
*/
|
||||
unsigned int intf_ap_count;
|
||||
unsigned int intf_sta_count;
|
||||
unsigned int intf_associated;
|
||||
unsigned int intf_beaconing;
|
||||
+ bool is_monitoring;
|
||||
|
||||
/*
|
||||
* Interface combinations
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
|
||||
@@ -244,6 +244,16 @@ void rt2x00lib_config(struct rt2x00_dev
|
||||
(ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
|
||||
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
|
||||
|
||||
+ if (ieee80211_flags & IEEE80211_CONF_CHANGE_MONITOR) {
|
||||
+ if (conf->flags & IEEE80211_CONF_MONITOR) {
|
||||
+ rt2x00_dbg(rt2x00dev, "Monitor mode is enabled\n");
|
||||
+ rt2x00dev->is_monitoring = true;
|
||||
+ } else {
|
||||
+ rt2x00_dbg(rt2x00dev, "Monitor mode is disabled\n");
|
||||
+ rt2x00dev->is_monitoring = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Start configuration.
|
||||
*/
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1204,6 +1204,7 @@ int rt2x00lib_start(struct rt2x00_dev *r
|
||||
rt2x00dev->intf_ap_count = 0;
|
||||
rt2x00dev->intf_sta_count = 0;
|
||||
rt2x00dev->intf_associated = 0;
|
||||
+ rt2x00dev->is_monitoring = false;
|
||||
|
||||
/* Enable the radio */
|
||||
retval = rt2x00lib_enable_radio(rt2x00dev);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
|
||||
@@ -385,11 +385,6 @@ void rt2x00mac_configure_filter(struct i
|
||||
*total_flags |= FIF_PSPOLL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Check if there is any work left for us.
|
||||
- */
|
||||
- if (rt2x00dev->packet_filter == *total_flags)
|
||||
- return;
|
||||
rt2x00dev->packet_filter = *total_flags;
|
||||
|
||||
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
@@ -530,8 +530,10 @@ static void rt61pci_config_filter(struct
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
|
||||
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
|
||||
- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
|
||||
+ !rt2x00dev->is_monitoring);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
|
||||
+ !rt2x00dev->is_monitoring &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
|
||||
@@ -480,8 +480,10 @@ static void rt73usb_config_filter(struct
|
||||
!(filter_flags & FIF_PLCPFAIL));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
|
||||
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
|
||||
- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1);
|
||||
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
|
||||
+ !rt2x00dev->is_monitoring);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
|
||||
+ !rt2x00dev->is_monitoring &&
|
||||
!rt2x00dev->intf_ap_count);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
|
||||
@@ -1,32 +0,0 @@
|
||||
From: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
Date: Fri, 15 Jan 2016 18:17:17 +0800
|
||||
Subject: [PATCH] ath9k: avoid ANI restart if no trigger
|
||||
|
||||
Fixes commit 54da20d83f0e ("ath9k_hw: improve ANI processing and rx desensitizing parameters")
|
||||
|
||||
Call ath9k_ani_restart() only when the phy error rate reach the
|
||||
ANI immunity threshold. Sync the logic with internal code base.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ani.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ani.c
|
||||
@@ -444,14 +444,16 @@ void ath9k_hw_ani_monitor(struct ath_hw
|
||||
ofdmPhyErrRate < ah->config.ofdm_trig_low) {
|
||||
ath9k_hw_ani_lower_immunity(ah);
|
||||
aniState->ofdmsTurn = !aniState->ofdmsTurn;
|
||||
+ ath9k_ani_restart(ah);
|
||||
} else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
|
||||
ath9k_hw_ani_ofdm_err_trigger(ah);
|
||||
aniState->ofdmsTurn = false;
|
||||
+ ath9k_ani_restart(ah);
|
||||
} else if (cckPhyErrRate > ah->config.cck_trig_high) {
|
||||
ath9k_hw_ani_cck_err_trigger(ah);
|
||||
aniState->ofdmsTurn = true;
|
||||
+ ath9k_ani_restart(ah);
|
||||
}
|
||||
- ath9k_ani_restart(ah);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_ani_monitor);
|
||||
@@ -1,91 +0,0 @@
|
||||
From: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
Date: Fri, 15 Jan 2016 18:17:18 +0800
|
||||
Subject: [PATCH] ath9k: clean up ANI per-channel pointer checking
|
||||
|
||||
commit c24bd3620c50 ("ath9k: Do not maintain ANI state per-channel")
|
||||
removed per-channel handling, the code to check 'curchan' also
|
||||
should be removed as never used.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ani.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ani.c
|
||||
@@ -126,12 +126,8 @@ static void ath9k_hw_update_mibstats(str
|
||||
|
||||
static void ath9k_ani_restart(struct ath_hw *ah)
|
||||
{
|
||||
- struct ar5416AniState *aniState;
|
||||
-
|
||||
- if (!ah->curchan)
|
||||
- return;
|
||||
+ struct ar5416AniState *aniState = &ah->ani;
|
||||
|
||||
- aniState = &ah->ani;
|
||||
aniState->listenTime = 0;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
@@ -221,12 +217,7 @@ static void ath9k_hw_set_ofdm_nil(struct
|
||||
|
||||
static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
|
||||
{
|
||||
- struct ar5416AniState *aniState;
|
||||
-
|
||||
- if (!ah->curchan)
|
||||
- return;
|
||||
-
|
||||
- aniState = &ah->ani;
|
||||
+ struct ar5416AniState *aniState = &ah->ani;
|
||||
|
||||
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
|
||||
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false);
|
||||
@@ -281,12 +272,7 @@ static void ath9k_hw_set_cck_nil(struct
|
||||
|
||||
static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
|
||||
{
|
||||
- struct ar5416AniState *aniState;
|
||||
-
|
||||
- if (!ah->curchan)
|
||||
- return;
|
||||
-
|
||||
- aniState = &ah->ani;
|
||||
+ struct ar5416AniState *aniState = &ah->ani;
|
||||
|
||||
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
|
||||
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
|
||||
@@ -299,9 +285,7 @@ static void ath9k_hw_ani_cck_err_trigger
|
||||
*/
|
||||
static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
|
||||
{
|
||||
- struct ar5416AniState *aniState;
|
||||
-
|
||||
- aniState = &ah->ani;
|
||||
+ struct ar5416AniState *aniState = &ah->ani;
|
||||
|
||||
/* lower OFDM noise immunity */
|
||||
if (aniState->ofdmNoiseImmunityLevel > 0 &&
|
||||
@@ -329,7 +313,7 @@ void ath9k_ani_reset(struct ath_hw *ah,
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ofdm_nil, cck_nil;
|
||||
|
||||
- if (!ah->curchan)
|
||||
+ if (!chan)
|
||||
return;
|
||||
|
||||
BUG_ON(aniState == NULL);
|
||||
@@ -416,14 +400,10 @@ static bool ath9k_hw_ani_read_counters(s
|
||||
|
||||
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
- struct ar5416AniState *aniState;
|
||||
+ struct ar5416AniState *aniState = &ah->ani;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 ofdmPhyErrRate, cckPhyErrRate;
|
||||
|
||||
- if (!ah->curchan)
|
||||
- return;
|
||||
-
|
||||
- aniState = &ah->ani;
|
||||
if (!ath9k_hw_ani_read_counters(ah))
|
||||
return;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
From: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
Date: Fri, 15 Jan 2016 18:17:19 +0800
|
||||
Subject: [PATCH] ath9k: do not reset while BB panic(0x4000409) on ar9561
|
||||
|
||||
BB panic(0x4000409) observed while AP enabling/disabling
|
||||
bursting.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
|
||||
@@ -2071,7 +2071,8 @@ void ar9003_hw_attach_phy_ops(struct ath
|
||||
* to be disabled.
|
||||
*
|
||||
* 0x04000409: Packet stuck on receive.
|
||||
- * Full chip reset is required for all chips except AR9340.
|
||||
+ * Full chip reset is required for all chips except
|
||||
+ * AR9340, AR9531 and AR9561.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -2100,7 +2101,7 @@ bool ar9003_hw_bb_watchdog_check(struct
|
||||
case 0x04000b09:
|
||||
return true;
|
||||
case 0x04000409:
|
||||
- if (AR_SREV_9340(ah) || AR_SREV_9531(ah))
|
||||
+ if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
@@ -1,27 +0,0 @@
|
||||
From: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
Date: Fri, 15 Jan 2016 18:17:20 +0800
|
||||
Subject: [PATCH] ath9k: fix inconsistent use of tab and space in
|
||||
indentation
|
||||
|
||||
Minor changes for indenting.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
|
||||
@@ -5485,11 +5485,11 @@ unsigned int ar9003_get_paprd_scale_fact
|
||||
AR9300_PAPRD_SCALE_1);
|
||||
else {
|
||||
if (chan->channel >= 5700)
|
||||
- return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20),
|
||||
- AR9300_PAPRD_SCALE_1);
|
||||
+ return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20),
|
||||
+ AR9300_PAPRD_SCALE_1);
|
||||
else if (chan->channel >= 5400)
|
||||
return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
|
||||
- AR9300_PAPRD_SCALE_2);
|
||||
+ AR9300_PAPRD_SCALE_2);
|
||||
else
|
||||
return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
|
||||
AR9300_PAPRD_SCALE_1);
|
||||
@@ -1,65 +0,0 @@
|
||||
From: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
Date: Fri, 15 Jan 2016 18:17:21 +0800
|
||||
Subject: [PATCH] ath9k: fix data bus error on ar9300 and ar9580
|
||||
|
||||
One crash issue be found on ar9300: RTC_RC reg read leads crash, leading
|
||||
the data bus error, due to RTC_RC reg write not happen properly.
|
||||
|
||||
Warm Reset trigger in continuous beacon stuck for one of the customer for
|
||||
other chip, noticed the MAC was stuck in RTC reset. After analysis noticed
|
||||
DMA did not complete when RTC was put in reset.
|
||||
|
||||
So, before resetting the MAC need to make sure there are no pending DMA
|
||||
transactions because this reset does not reset all parts of the chip.
|
||||
|
||||
The 12th and 11th bit of MAC _DMA_CFG register used to do that.
|
||||
12 cfg_halt_ack 0x0
|
||||
0 DMA has not yet halted
|
||||
1 DMA has halted
|
||||
11 cfg_halt_req 0x0
|
||||
0 DMA logic operates normally
|
||||
1 Request DMA logic to stop so software can reset the MAC
|
||||
|
||||
The Bit [12] of this register indicates when the halt has taken effect or
|
||||
not. the DMA halt IS NOT recoverable; once software sets bit [11] to
|
||||
request a DMA halt, software must wait for bit [12] to be set and reset
|
||||
the MAC.
|
||||
|
||||
So, the same thing we implemented for ar9580 chip.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -1368,6 +1368,16 @@ static bool ath9k_hw_set_reset(struct at
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_check_gpm_offset(ah);
|
||||
|
||||
+ /* DMA HALT added to resolve ar9300 and ar9580 bus error during
|
||||
+ * RTC_RC reg read
|
||||
+ */
|
||||
+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
|
||||
+ REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
|
||||
+ ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
|
||||
+ 20 * AH_WAIT_TIMEOUT);
|
||||
+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
|
||||
+ }
|
||||
+
|
||||
REG_WRITE(ah, AR_RTC_RC, rst_flags);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
--- a/drivers/net/wireless/ath/ath9k/reg.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/reg.h
|
||||
@@ -34,8 +34,10 @@
|
||||
#define AR_CFG_SWRG 0x00000010
|
||||
#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
|
||||
#define AR_CFG_PHOK 0x00000100
|
||||
-#define AR_CFG_CLK_GATE_DIS 0x00000400
|
||||
#define AR_CFG_EEBS 0x00000200
|
||||
+#define AR_CFG_CLK_GATE_DIS 0x00000400
|
||||
+#define AR_CFG_HALT_REQ 0x00000800
|
||||
+#define AR_CFG_HALT_ACK 0x00001000
|
||||
#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000
|
||||
#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Fri, 15 Jan 2016 15:59:45 +0100
|
||||
Subject: [PATCH] brcmfmac: add missing include
|
||||
|
||||
linux/module.h is required for defining module parameters
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/netdevice.h>
|
||||
+#include <linux/module.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "core.h"
|
||||
@@ -1,118 +0,0 @@
|
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Tue, 19 Jan 2016 12:39:24 +0100
|
||||
Subject: [PATCH] brcmfmac: fix sdio sg table alloc crash
|
||||
|
||||
With commit 7d34b0560567 ("brcmfmac: Move all module parameters to
|
||||
one place") a bug was introduced causing a null pointer exception.
|
||||
This patch fixes the bug by initializing the sg table till after
|
||||
the settings have been initialized.
|
||||
|
||||
Fixes: 7d34b0560567 ("brcmfmac: Move all module parameters to one place")
|
||||
Reported-by: Marc Zyngier <marc.zyngier@arm.com>
|
||||
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
@@ -879,11 +879,24 @@ int brcmf_sdiod_abort(struct brcmf_sdio_
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
|
||||
+void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
+ struct sdio_func *func;
|
||||
+ struct mmc_host *host;
|
||||
+ uint max_blocks;
|
||||
uint nents;
|
||||
int err;
|
||||
|
||||
+ func = sdiodev->func[2];
|
||||
+ host = func->card->host;
|
||||
+ sdiodev->sg_support = host->max_segs > 1;
|
||||
+ max_blocks = min_t(uint, host->max_blk_count, 511u);
|
||||
+ sdiodev->max_request_size = min_t(uint, host->max_req_size,
|
||||
+ max_blocks * func->cur_blksize);
|
||||
+ sdiodev->max_segment_count = min_t(uint, host->max_segs,
|
||||
+ SG_MAX_SINGLE_ALLOC);
|
||||
+ sdiodev->max_segment_size = host->max_seg_size;
|
||||
+
|
||||
if (!sdiodev->sg_support)
|
||||
return;
|
||||
|
||||
@@ -1021,9 +1034,6 @@ static void brcmf_sdiod_host_fixup(struc
|
||||
|
||||
static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
- struct sdio_func *func;
|
||||
- struct mmc_host *host;
|
||||
- uint max_blocks;
|
||||
int ret = 0;
|
||||
|
||||
sdiodev->num_funcs = 2;
|
||||
@@ -1054,26 +1064,6 @@ static int brcmf_sdiod_probe(struct brcm
|
||||
goto out;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * determine host related variables after brcmf_sdiod_probe()
|
||||
- * as func->cur_blksize is properly set and F2 init has been
|
||||
- * completed successfully.
|
||||
- */
|
||||
- func = sdiodev->func[2];
|
||||
- host = func->card->host;
|
||||
- sdiodev->sg_support = host->max_segs > 1;
|
||||
- max_blocks = min_t(uint, host->max_blk_count, 511u);
|
||||
- sdiodev->max_request_size = min_t(uint, host->max_req_size,
|
||||
- max_blocks * func->cur_blksize);
|
||||
- sdiodev->max_segment_count = min_t(uint, host->max_segs,
|
||||
- SG_MAX_SINGLE_ALLOC);
|
||||
- sdiodev->max_segment_size = host->max_seg_size;
|
||||
-
|
||||
- /* allocate scatter-gather table. sg support
|
||||
- * will be disabled upon allocation failure.
|
||||
- */
|
||||
- brcmf_sdiod_sgtable_alloc(sdiodev);
|
||||
-
|
||||
ret = brcmf_sdiod_freezer_attach(sdiodev);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -1084,7 +1074,7 @@ static int brcmf_sdiod_probe(struct brcm
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
- brcmf_sdiod_host_fixup(host);
|
||||
+ brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host);
|
||||
out:
|
||||
if (ret)
|
||||
brcmf_sdiod_remove(sdiodev);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -4114,6 +4114,11 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ /* allocate scatter-gather table. sg support
|
||||
+ * will be disabled upon allocation failure.
|
||||
+ */
|
||||
+ brcmf_sdiod_sgtable_alloc(bus->sdiodev);
|
||||
+
|
||||
/* Query the F2 block size, set roundup accordingly */
|
||||
bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
|
||||
bus->roundup = min(max_roundup, bus->blocksize);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
|
||||
@@ -342,6 +342,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
|
||||
|
||||
/* Issue an abort to the specified function */
|
||||
int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
|
||||
+void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
|
||||
void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
|
||||
enum brcmf_sdiod_state state);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@@ -1,38 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 21 Jan 2016 16:28:44 +0100
|
||||
Subject: [PATCH] ath9k_hw: ignore eeprom magic mismatch on flash based devices
|
||||
|
||||
Many AR913x based devices (maybe others too) do not have a valid EEPROM
|
||||
magic in their calibration data partition.
|
||||
|
||||
Fixes: 6fa658fd5ab2 ("ath9k: Simplify and fix eeprom endianness swapping")
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
|
||||
@@ -150,18 +150,18 @@ int ath9k_hw_nvram_swap_data(struct ath_
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
- if (magic == AR5416_EEPROM_MAGIC) {
|
||||
- *swap_needed = false;
|
||||
- } else if (swab16(magic) == AR5416_EEPROM_MAGIC) {
|
||||
+ *swap_needed = false;
|
||||
+ if (swab16(magic) == AR5416_EEPROM_MAGIC) {
|
||||
if (ah->ah_flags & AH_NO_EEP_SWAP) {
|
||||
ath_info(common,
|
||||
"Ignoring endianness difference in EEPROM magic bytes.\n");
|
||||
-
|
||||
- *swap_needed = false;
|
||||
} else {
|
||||
*swap_needed = true;
|
||||
}
|
||||
- } else {
|
||||
+ } else if (magic != AR5416_EEPROM_MAGIC) {
|
||||
+ if (ath9k_hw_use_flash(ah))
|
||||
+ return 0;
|
||||
+
|
||||
ath_err(common,
|
||||
"Invalid EEPROM Magic (0x%04x).\n", magic);
|
||||
return -EINVAL;
|
||||
@@ -1,55 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Fri, 22 Jan 2016 01:05:56 +0100
|
||||
Subject: [PATCH] ath9k: do not limit the number of DFS interfaces to 1
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -751,14 +751,6 @@ static const struct ieee80211_iface_comb
|
||||
|
||||
#endif /* CPTCFG_ATH9K_CHANNEL_CONTEXT */
|
||||
|
||||
-static const struct ieee80211_iface_limit if_dfs_limits[] = {
|
||||
- { .max = 1, .types = BIT(NL80211_IFTYPE_AP) |
|
||||
-#ifdef CPTCFG_MAC80211_MESH
|
||||
- BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
-#endif
|
||||
- BIT(NL80211_IFTYPE_ADHOC) },
|
||||
-};
|
||||
-
|
||||
static const struct ieee80211_iface_combination if_comb[] = {
|
||||
{
|
||||
.limits = if_limits,
|
||||
@@ -766,6 +758,11 @@ static const struct ieee80211_iface_comb
|
||||
.max_interfaces = 2048,
|
||||
.num_different_channels = 1,
|
||||
.beacon_int_infra_match = true,
|
||||
+#ifdef CPTCFG_ATH9K_DFS_CERTIFIED
|
||||
+ .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
+ BIT(NL80211_CHAN_WIDTH_20) |
|
||||
+ BIT(NL80211_CHAN_WIDTH_40),
|
||||
+#endif
|
||||
},
|
||||
{
|
||||
.limits = wds_limits,
|
||||
@@ -774,18 +771,6 @@ static const struct ieee80211_iface_comb
|
||||
.num_different_channels = 1,
|
||||
.beacon_int_infra_match = true,
|
||||
},
|
||||
-#ifdef CPTCFG_ATH9K_DFS_CERTIFIED
|
||||
- {
|
||||
- .limits = if_dfs_limits,
|
||||
- .n_limits = ARRAY_SIZE(if_dfs_limits),
|
||||
- .max_interfaces = 1,
|
||||
- .num_different_channels = 1,
|
||||
- .beacon_int_infra_match = true,
|
||||
- .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
- BIT(NL80211_CHAN_WIDTH_20) |
|
||||
- BIT(NL80211_CHAN_WIDTH_40),
|
||||
- }
|
||||
-#endif
|
||||
};
|
||||
|
||||
#ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
|
||||
@@ -1,27 +0,0 @@
|
||||
From: Michal Kazior <michal.kazior@tieto.com>
|
||||
Date: Thu, 21 Jan 2016 14:23:07 +0100
|
||||
Subject: [PATCH] mac80211: fix txq queue related crashes
|
||||
|
||||
The driver can access the queue simultanously
|
||||
while mac80211 tears down the interface. Without
|
||||
spinlock protection this could lead to corrupting
|
||||
sk_buff_head and subsequently to an invalid
|
||||
pointer dereference.
|
||||
|
||||
Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation")
|
||||
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -977,7 +977,10 @@ static void ieee80211_do_stop(struct iee
|
||||
if (sdata->vif.txq) {
|
||||
struct txq_info *txqi = to_txq_info(sdata->vif.txq);
|
||||
|
||||
+ spin_lock_bh(&txqi->queue.lock);
|
||||
ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
|
||||
+ spin_unlock_bh(&txqi->queue.lock);
|
||||
+
|
||||
atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
From: Michal Kazior <michal.kazior@tieto.com>
|
||||
Date: Mon, 25 Jan 2016 14:43:24 +0100
|
||||
Subject: [PATCH] mac80211: fix unnecessary frame drops in mesh fwding
|
||||
|
||||
The ieee80211_queue_stopped() expects hw queue
|
||||
number but it was given raw WMM AC number instead.
|
||||
|
||||
This could cause frame drops and problems with
|
||||
traffic in some cases - most notably if driver
|
||||
doesn't map AC numbers to queue numbers 1:1 and
|
||||
uses ieee80211_stop_queues() and
|
||||
ieee80211_wake_queue() only without ever calling
|
||||
ieee80211_wake_queues().
|
||||
|
||||
On ath10k it was possible to hit this problem in
|
||||
the following case:
|
||||
|
||||
1. wlan0 uses queue 0
|
||||
(ath10k maps queues per vif)
|
||||
2. offchannel uses queue 15
|
||||
3. queues 1-14 are unused
|
||||
4. ieee80211_stop_queues()
|
||||
5. ieee80211_wake_queue(q=0)
|
||||
6. ieee80211_wake_queue(q=15)
|
||||
(other queues are not woken up because both
|
||||
driver and mac80211 know other queues are
|
||||
unused)
|
||||
7. ieee80211_rx_h_mesh_fwding()
|
||||
8. ieee80211_select_queue_80211() returns 2
|
||||
9. ieee80211_queue_stopped(q=2) returns true
|
||||
10. frame is dropped (oops!)
|
||||
|
||||
Fixes: d3c1597b8d1b ("mac80211: fix forwarded mesh frame queue mapping")
|
||||
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -2235,7 +2235,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
|
||||
struct ieee80211_local *local = rx->local;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
- u16 q, hdrlen;
|
||||
+ u16 ac, q, hdrlen;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
@@ -2304,7 +2304,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
|
||||
ether_addr_equal(sdata->vif.addr, hdr->addr3))
|
||||
return RX_CONTINUE;
|
||||
|
||||
- q = ieee80211_select_queue_80211(sdata, skb, hdr);
|
||||
+ ac = ieee80211_select_queue_80211(sdata, skb, hdr);
|
||||
+ q = sdata->vif.hw_queue[ac];
|
||||
if (ieee80211_queue_stopped(&local->hw, q)) {
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
|
||||
return RX_DROP_MONITOR;
|
||||
@@ -1,103 +0,0 @@
|
||||
From: Sachin Kulkarni <Sachin.Kulkarni@imgtec.com>
|
||||
Date: Tue, 12 Jan 2016 14:30:19 +0530
|
||||
Subject: [PATCH] mac80211: Requeue work after scan complete for all VIF
|
||||
types.
|
||||
|
||||
During a sw scan ieee80211_iface_work ignores work items for all vifs.
|
||||
However after the scan complete work is requeued only for STA, ADHOC
|
||||
and MESH iftypes.
|
||||
|
||||
This occasionally results in event processing getting delayed/not
|
||||
processed for iftype AP when it coexists with a STA. This can result
|
||||
in data halt and eventually disconnection on the AP interface.
|
||||
|
||||
Signed-off-by: Sachin Kulkarni <Sachin.Kulkarni@imgtec.com>
|
||||
Cc: linux-wireless@vger.kernel.org
|
||||
Cc: johannes@sipsolutions.net
|
||||
---
|
||||
|
||||
--- a/net/mac80211/ibss.c
|
||||
+++ b/net/mac80211/ibss.c
|
||||
@@ -1731,7 +1731,6 @@ void ieee80211_ibss_notify_scan_complete
|
||||
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
||||
continue;
|
||||
sdata->u.ibss.last_scan_completed = jiffies;
|
||||
- ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
--- a/net/mac80211/mesh.c
|
||||
+++ b/net/mac80211/mesh.c
|
||||
@@ -1369,17 +1369,6 @@ out:
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
|
||||
-{
|
||||
- struct ieee80211_sub_if_data *sdata;
|
||||
-
|
||||
- rcu_read_lock();
|
||||
- list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
||||
- if (ieee80211_vif_is_mesh(&sdata->vif) &&
|
||||
- ieee80211_sdata_running(sdata))
|
||||
- ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
- rcu_read_unlock();
|
||||
-}
|
||||
|
||||
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
--- a/net/mac80211/mesh.h
|
||||
+++ b/net/mac80211/mesh.h
|
||||
@@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp
|
||||
return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP;
|
||||
}
|
||||
|
||||
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
|
||||
-
|
||||
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
|
||||
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211s_stop(void);
|
||||
#else
|
||||
-static inline void
|
||||
-ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
|
||||
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
|
||||
{ return false; }
|
||||
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
|
||||
--- a/net/mac80211/mlme.c
|
||||
+++ b/net/mac80211/mlme.c
|
||||
@@ -3978,8 +3978,6 @@ static void ieee80211_restart_sta_timer(
|
||||
if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->u.mgd.monitor_work);
|
||||
- /* and do all the other regular work too */
|
||||
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/net/mac80211/scan.c
|
||||
+++ b/net/mac80211/scan.c
|
||||
@@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(s
|
||||
bool was_scanning = local->scanning;
|
||||
struct cfg80211_scan_request *scan_req;
|
||||
struct ieee80211_sub_if_data *scan_sdata;
|
||||
+ struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
@@ -373,7 +374,15 @@ static void __ieee80211_scan_completed(s
|
||||
|
||||
ieee80211_mlme_notify_scan_completed(local);
|
||||
ieee80211_ibss_notify_scan_completed(local);
|
||||
- ieee80211_mesh_notify_scan_completed(local);
|
||||
+
|
||||
+ /* Requeue all the work that might have been ignored while
|
||||
+ * the scan was in progress
|
||||
+ */
|
||||
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
+ if (ieee80211_sdata_running(sdata))
|
||||
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
||||
+ }
|
||||
+
|
||||
if (was_scanning)
|
||||
ieee80211_start_next_roc(local);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
From: Sara Sharon <sara.sharon@intel.com>
|
||||
Date: Mon, 25 Jan 2016 15:46:35 +0200
|
||||
Subject: [PATCH] mac80211: fix ibss scan parameters
|
||||
|
||||
When joining IBSS a full scan should be initiated in order to search
|
||||
for existing cell, unless the fixed_channel parameter was set.
|
||||
A default channel to create the IBSS on if no cell was found is
|
||||
provided as well.
|
||||
However - a scan is initiated only on the default channel provided
|
||||
regardless of whether ifibss->fixed_channel is set or not, with the
|
||||
obvious result of the cell not joining existing IBSS cell that is
|
||||
on another channel.
|
||||
|
||||
Fixes: 76bed0f43b27 ("mac80211: IBSS fix scan request")
|
||||
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
|
||||
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/ibss.c
|
||||
+++ b/net/mac80211/ibss.c
|
||||
@@ -7,6 +7,7 @@
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
+ * Copyright(c) 2016 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -1483,14 +1484,21 @@ static void ieee80211_sta_find_ibss(stru
|
||||
|
||||
sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
|
||||
|
||||
- num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
|
||||
- &ifibss->chandef,
|
||||
- channels,
|
||||
- ARRAY_SIZE(channels));
|
||||
scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
|
||||
- ieee80211_request_ibss_scan(sdata, ifibss->ssid,
|
||||
- ifibss->ssid_len, channels, num,
|
||||
- scan_width);
|
||||
+
|
||||
+ if (ifibss->fixed_channel) {
|
||||
+ num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
|
||||
+ &ifibss->chandef,
|
||||
+ channels,
|
||||
+ ARRAY_SIZE(channels));
|
||||
+ ieee80211_request_ibss_scan(sdata, ifibss->ssid,
|
||||
+ ifibss->ssid_len, channels,
|
||||
+ num, scan_width);
|
||||
+ } else {
|
||||
+ ieee80211_request_ibss_scan(sdata, ifibss->ssid,
|
||||
+ ifibss->ssid_len, NULL,
|
||||
+ 0, scan_width);
|
||||
+ }
|
||||
} else {
|
||||
int interval = IEEE80211_SCAN_INTERVAL;
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
From: Chris Bainbridge <chris.bainbridge@gmail.com>
|
||||
Date: Wed, 27 Jan 2016 15:46:18 +0000
|
||||
Subject: [PATCH] net/mac80211/agg-rx.c: fix use of uninitialised values
|
||||
|
||||
Use kzalloc instead of kmalloc for struct tid_ampdu_rx. Fixes:
|
||||
|
||||
[ 7.976605] UBSAN: Undefined behaviour in net/mac80211/rx.c:932:29
|
||||
[ 7.976608] load of value 2 is not a valid value for type '_Bool'
|
||||
[ 7.976611] CPU: 3 PID: 1134 Comm: kworker/u16:7 Not tainted 4.5.0-rc1+ #265
|
||||
[ 7.976613] Hardware name: Apple Inc. MacBookPro10,2/Mac-AFD8A9D944EA4843, BIOS MBP102.88Z.0106.B0A.1509130955 09/13/2015
|
||||
[ 7.976616] Workqueue: phy0 rt2x00usb_work_rxdone
|
||||
[ 7.976619] 0000000000000004 ffff880254a7ba50 ffffffff8181d866 0000000000000007
|
||||
[ 7.976622] ffff880254a7ba78 ffff880254a7ba68 ffffffff8188422d ffffffff8379b500
|
||||
[ 7.976626] ffff880254a7bab8 ffffffff81884747 0000000000000202 0000000348620032
|
||||
[ 7.976629] Call Trace:
|
||||
[ 7.976633] [<ffffffff8181d866>] dump_stack+0x45/0x5f
|
||||
[ 7.976637] [<ffffffff8188422d>] ubsan_epilogue+0xd/0x40
|
||||
[ 7.976642] [<ffffffff81884747>] __ubsan_handle_load_invalid_value+0x67/0x70
|
||||
[ 7.976646] [<ffffffff82227b4d>] ieee80211_sta_reorder_release.isra.16+0x5ed/0x730
|
||||
[ 7.976650] [<ffffffff8222ca14>] ieee80211_prepare_and_rx_handle+0xd04/0x1c00
|
||||
[ 7.976654] [<ffffffff81cb27ce>] ? usb_hcd_map_urb_for_dma+0x65e/0x960
|
||||
[ 7.976659] [<ffffffff8222db03>] __ieee80211_rx_handle_packet+0x1f3/0x750
|
||||
[ 7.976663] [<ffffffff8222e4a7>] ieee80211_rx_napi+0x447/0x990
|
||||
[ 7.976667] [<ffffffff81c5fb85>] rt2x00lib_rxdone+0x305/0xbd0
|
||||
[ 7.976670] [<ffffffff811ac23f>] ? dequeue_task_fair+0x64f/0x1de0
|
||||
[ 7.976674] [<ffffffff811a1516>] ? sched_clock_cpu+0xe6/0x150
|
||||
[ 7.976678] [<ffffffff81c6c45c>] rt2x00usb_work_rxdone+0x7c/0x140
|
||||
[ 7.976682] [<ffffffff8117aef6>] process_one_work+0x226/0x860
|
||||
[ 7.976686] [<ffffffff8117b58c>] worker_thread+0x5c/0x680
|
||||
[ 7.976690] [<ffffffff8117b530>] ? process_one_work+0x860/0x860
|
||||
[ 7.976693] [<ffffffff81184f86>] kthread+0xf6/0x150
|
||||
[ 7.976697] [<ffffffff81184e90>] ? kthread_worker_fn+0x310/0x310
|
||||
[ 7.976700] [<ffffffff822a94df>] ret_from_fork+0x3f/0x70
|
||||
[ 7.976703] [<ffffffff81184e90>] ? kthread_worker_fn+0x310/0x310
|
||||
|
||||
Link: https://lkml.org/lkml/2016/1/26/230
|
||||
Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/agg-rx.c
|
||||
+++ b/net/mac80211/agg-rx.c
|
||||
@@ -327,7 +327,7 @@ void __ieee80211_start_rx_ba_session(str
|
||||
}
|
||||
|
||||
/* prepare A-MPDU MLME for Rx aggregation */
|
||||
- tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
|
||||
+ tid_agg_rx = kzalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
|
||||
if (!tid_agg_rx)
|
||||
goto end;
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
From: Konstantin Khlebnikov <koct9i@gmail.com>
|
||||
Date: Fri, 29 Jan 2016 11:35:12 +0300
|
||||
Subject: [PATCH] mac80211: minstrel_ht: fix out-of-bound in
|
||||
minstrel_ht_set_best_prob_rate
|
||||
|
||||
Patch fixes this splat
|
||||
|
||||
BUG: KASAN: slab-out-of-bounds in minstrel_ht_update_stats.isra.7+0x6e1/0x9e0
|
||||
[mac80211] at addr ffff8800cee640f4 Read of size 4 by task swapper/3/0
|
||||
|
||||
Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com>
|
||||
Link: http://lkml.kernel.org/r/CALYGNiNyJhSaVnE35qS6UCGaSb2Dx1_i5HcRavuOX14oTz2P+w@mail.gmail.com
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -414,15 +414,16 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
(max_tp_group != MINSTREL_CCK_GROUP))
|
||||
return;
|
||||
|
||||
+ max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
|
||||
+ max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
||||
+ max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
|
||||
+
|
||||
if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
|
||||
cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx,
|
||||
mrs->prob_ewma);
|
||||
if (cur_tp_avg > tmp_tp_avg)
|
||||
mi->max_prob_rate = index;
|
||||
|
||||
- max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
|
||||
- max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
||||
- max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
|
||||
max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group,
|
||||
max_gpr_idx,
|
||||
max_gpr_prob);
|
||||
@@ -431,7 +432,7 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
} else {
|
||||
if (mrs->prob_ewma > tmp_prob)
|
||||
mi->max_prob_rate = index;
|
||||
- if (mrs->prob_ewma > mg->rates[mg->max_group_prob_rate].prob_ewma)
|
||||
+ if (mrs->prob_ewma > max_gpr_prob)
|
||||
mg->max_group_prob_rate = index;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Tue, 2 Feb 2016 14:39:08 +0100
|
||||
Subject: [PATCH] mac80211: move A-MSDU skb_linearize call to
|
||||
ieee80211_amsdu_to_8023s
|
||||
|
||||
Prepararation for zero-copy A-MSDU support with page fragment SKBs
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -2203,9 +2203,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
|
||||
skb->dev = dev;
|
||||
__skb_queue_head_init(&frame_list);
|
||||
|
||||
- if (skb_linearize(skb))
|
||||
- return RX_DROP_UNUSABLE;
|
||||
-
|
||||
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
|
||||
rx->sdata->vif.type,
|
||||
rx->local->hw.extra_tx_headroom, true);
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -657,6 +657,9 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
int remaining, err;
|
||||
u8 dst[ETH_ALEN], src[ETH_ALEN];
|
||||
|
||||
+ if (skb_linearize(skb))
|
||||
+ goto out;
|
||||
+
|
||||
if (has_80211_header) {
|
||||
err = ieee80211_data_to_8023(skb, addr, iftype);
|
||||
if (err)
|
||||
@@ -1,186 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Tue, 2 Feb 2016 14:39:09 +0100
|
||||
Subject: [PATCH] cfg80211: add function for 802.3 conversion with separate
|
||||
output buffer
|
||||
|
||||
Use skb_copy_bits in preparation for allowing fragmented skbs
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -393,9 +393,9 @@ unsigned int ieee80211_get_hdrlen_from_s
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
|
||||
|
||||
-unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
|
||||
+static unsigned int __ieee80211_get_mesh_hdrlen(u8 flags)
|
||||
{
|
||||
- int ae = meshhdr->flags & MESH_FLAGS_AE;
|
||||
+ int ae = flags & MESH_FLAGS_AE;
|
||||
/* 802.11-2012, 8.2.4.7.3 */
|
||||
switch (ae) {
|
||||
default:
|
||||
@@ -407,21 +407,31 @@ unsigned int ieee80211_get_mesh_hdrlen(s
|
||||
return 18;
|
||||
}
|
||||
}
|
||||
+
|
||||
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
|
||||
+{
|
||||
+ return __ieee80211_get_mesh_hdrlen(meshhdr->flags);
|
||||
+}
|
||||
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
|
||||
|
||||
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
|
||||
- enum nl80211_iftype iftype)
|
||||
+static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
|
||||
+ const u8 *addr, enum nl80211_iftype iftype)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
- u16 hdrlen, ethertype;
|
||||
- u8 *payload;
|
||||
- u8 dst[ETH_ALEN];
|
||||
- u8 src[ETH_ALEN] __aligned(2);
|
||||
+ struct {
|
||||
+ u8 hdr[ETH_ALEN] __aligned(2);
|
||||
+ __be16 proto;
|
||||
+ } payload;
|
||||
+ struct ethhdr tmp;
|
||||
+ u16 hdrlen;
|
||||
+ u8 mesh_flags = 0;
|
||||
|
||||
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
|
||||
return -1;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
+ if (skb->len < hdrlen + 8)
|
||||
+ return -1;
|
||||
|
||||
/* convert IEEE 802.11 header + possible LLC headers into Ethernet
|
||||
* header
|
||||
@@ -432,8 +442,11 @@ int ieee80211_data_to_8023(struct sk_buf
|
||||
* 1 0 BSSID SA DA n/a
|
||||
* 1 1 RA TA DA SA
|
||||
*/
|
||||
- memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
|
||||
- memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
|
||||
+ memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
|
||||
+ memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
|
||||
+
|
||||
+ if (iftype == NL80211_IFTYPE_MESH_POINT)
|
||||
+ skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
|
||||
|
||||
switch (hdr->frame_control &
|
||||
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
|
||||
@@ -450,44 +463,31 @@ int ieee80211_data_to_8023(struct sk_buf
|
||||
iftype != NL80211_IFTYPE_STATION))
|
||||
return -1;
|
||||
if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
||||
- struct ieee80211s_hdr *meshdr =
|
||||
- (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
||||
- /* make sure meshdr->flags is on the linear part */
|
||||
- if (!pskb_may_pull(skb, hdrlen + 1))
|
||||
- return -1;
|
||||
- if (meshdr->flags & MESH_FLAGS_AE_A4)
|
||||
+ if (mesh_flags & MESH_FLAGS_AE_A4)
|
||||
return -1;
|
||||
- if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
|
||||
+ if (mesh_flags & MESH_FLAGS_AE_A5_A6) {
|
||||
skb_copy_bits(skb, hdrlen +
|
||||
offsetof(struct ieee80211s_hdr, eaddr1),
|
||||
- dst, ETH_ALEN);
|
||||
- skb_copy_bits(skb, hdrlen +
|
||||
- offsetof(struct ieee80211s_hdr, eaddr2),
|
||||
- src, ETH_ALEN);
|
||||
+ tmp.h_dest, 2 * ETH_ALEN);
|
||||
}
|
||||
- hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
|
||||
+ hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
|
||||
}
|
||||
break;
|
||||
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
|
||||
if ((iftype != NL80211_IFTYPE_STATION &&
|
||||
iftype != NL80211_IFTYPE_P2P_CLIENT &&
|
||||
iftype != NL80211_IFTYPE_MESH_POINT) ||
|
||||
- (is_multicast_ether_addr(dst) &&
|
||||
- ether_addr_equal(src, addr)))
|
||||
+ (is_multicast_ether_addr(tmp.h_dest) &&
|
||||
+ ether_addr_equal(tmp.h_source, addr)))
|
||||
return -1;
|
||||
if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
||||
- struct ieee80211s_hdr *meshdr =
|
||||
- (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
||||
- /* make sure meshdr->flags is on the linear part */
|
||||
- if (!pskb_may_pull(skb, hdrlen + 1))
|
||||
- return -1;
|
||||
- if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
|
||||
+ if (mesh_flags & MESH_FLAGS_AE_A5_A6)
|
||||
return -1;
|
||||
- if (meshdr->flags & MESH_FLAGS_AE_A4)
|
||||
+ if (mesh_flags & MESH_FLAGS_AE_A4)
|
||||
skb_copy_bits(skb, hdrlen +
|
||||
offsetof(struct ieee80211s_hdr, eaddr1),
|
||||
- src, ETH_ALEN);
|
||||
- hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
|
||||
+ tmp.h_source, ETH_ALEN);
|
||||
+ hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
|
||||
}
|
||||
break;
|
||||
case cpu_to_le16(0):
|
||||
@@ -498,33 +498,33 @@ int ieee80211_data_to_8023(struct sk_buf
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!pskb_may_pull(skb, hdrlen + 8))
|
||||
- return -1;
|
||||
-
|
||||
- payload = skb->data + hdrlen;
|
||||
- ethertype = (payload[6] << 8) | payload[7];
|
||||
+ skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
|
||||
+ tmp.h_proto = payload.proto;
|
||||
|
||||
- if (likely((ether_addr_equal(payload, rfc1042_header) &&
|
||||
- ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
|
||||
- ether_addr_equal(payload, bridge_tunnel_header))) {
|
||||
+ if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
|
||||
+ tmp.h_proto != htons(ETH_P_AARP) &&
|
||||
+ tmp.h_proto != htons(ETH_P_IPX)) ||
|
||||
+ ether_addr_equal(payload.hdr, bridge_tunnel_header)))
|
||||
/* remove RFC1042 or Bridge-Tunnel encapsulation and
|
||||
* replace EtherType */
|
||||
- skb_pull(skb, hdrlen + 6);
|
||||
- memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
|
||||
- memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
|
||||
- } else {
|
||||
- struct ethhdr *ehdr;
|
||||
- __be16 len;
|
||||
+ hdrlen += ETH_ALEN + 2;
|
||||
+ else
|
||||
+ tmp.h_proto = htons(skb->len);
|
||||
|
||||
- skb_pull(skb, hdrlen);
|
||||
- len = htons(skb->len);
|
||||
+ pskb_pull(skb, hdrlen);
|
||||
+
|
||||
+ if (!ehdr)
|
||||
ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
|
||||
- memcpy(ehdr->h_dest, dst, ETH_ALEN);
|
||||
- memcpy(ehdr->h_source, src, ETH_ALEN);
|
||||
- ehdr->h_proto = len;
|
||||
- }
|
||||
+ memcpy(ehdr, &tmp, sizeof(tmp));
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
|
||||
+ enum nl80211_iftype iftype)
|
||||
+{
|
||||
+ return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
|
||||
+}
|
||||
EXPORT_SYMBOL(ieee80211_data_to_8023);
|
||||
|
||||
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
|
||||
@@ -1,159 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Tue, 2 Feb 2016 14:39:10 +0100
|
||||
Subject: [PATCH] cfg80211: add support for non-linear skbs in
|
||||
ieee80211_amsdu_to_8023s
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -644,73 +644,75 @@ int ieee80211_data_from_8023(struct sk_b
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_data_from_8023);
|
||||
|
||||
+static struct sk_buff *
|
||||
+__ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
|
||||
+ int offset, int len)
|
||||
+{
|
||||
+ struct sk_buff *frame;
|
||||
+
|
||||
+ if (skb->len - offset < len)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /*
|
||||
+ * Allocate and reserve two bytes more for payload
|
||||
+ * alignment since sizeof(struct ethhdr) is 14.
|
||||
+ */
|
||||
+ frame = dev_alloc_skb(hlen + sizeof(struct ethhdr) + 2 + len);
|
||||
+
|
||||
+ skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
|
||||
+ skb_copy_bits(skb, offset, skb_put(frame, len), len);
|
||||
+
|
||||
+ return frame;
|
||||
+}
|
||||
|
||||
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
|
||||
const u8 *addr, enum nl80211_iftype iftype,
|
||||
const unsigned int extra_headroom,
|
||||
bool has_80211_header)
|
||||
{
|
||||
+ unsigned int hlen = ALIGN(extra_headroom, 4);
|
||||
struct sk_buff *frame = NULL;
|
||||
u16 ethertype;
|
||||
u8 *payload;
|
||||
- const struct ethhdr *eth;
|
||||
- int remaining, err;
|
||||
- u8 dst[ETH_ALEN], src[ETH_ALEN];
|
||||
-
|
||||
- if (skb_linearize(skb))
|
||||
- goto out;
|
||||
+ int offset = 0, remaining, err;
|
||||
+ struct ethhdr eth;
|
||||
+ bool reuse_skb = true;
|
||||
+ bool last = false;
|
||||
|
||||
if (has_80211_header) {
|
||||
- err = ieee80211_data_to_8023(skb, addr, iftype);
|
||||
+ err = __ieee80211_data_to_8023(skb, ð, addr, iftype);
|
||||
if (err)
|
||||
goto out;
|
||||
-
|
||||
- /* skip the wrapping header */
|
||||
- eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
|
||||
- if (!eth)
|
||||
- goto out;
|
||||
- } else {
|
||||
- eth = (struct ethhdr *) skb->data;
|
||||
}
|
||||
|
||||
- while (skb != frame) {
|
||||
+ while (!last) {
|
||||
+ unsigned int subframe_len;
|
||||
+ int len;
|
||||
u8 padding;
|
||||
- __be16 len = eth->h_proto;
|
||||
- unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len);
|
||||
-
|
||||
- remaining = skb->len;
|
||||
- memcpy(dst, eth->h_dest, ETH_ALEN);
|
||||
- memcpy(src, eth->h_source, ETH_ALEN);
|
||||
|
||||
+ skb_copy_bits(skb, offset, ð, sizeof(eth));
|
||||
+ len = ntohs(eth.h_proto);
|
||||
+ subframe_len = sizeof(struct ethhdr) + len;
|
||||
padding = (4 - subframe_len) & 0x3;
|
||||
+
|
||||
/* the last MSDU has no padding */
|
||||
+ remaining = skb->len - offset;
|
||||
if (subframe_len > remaining)
|
||||
goto purge;
|
||||
|
||||
- skb_pull(skb, sizeof(struct ethhdr));
|
||||
+ offset += sizeof(struct ethhdr);
|
||||
/* reuse skb for the last subframe */
|
||||
- if (remaining <= subframe_len + padding)
|
||||
+ last = remaining <= subframe_len + padding;
|
||||
+ if (!skb_is_nonlinear(skb) && last) {
|
||||
+ skb_pull(skb, offset);
|
||||
frame = skb;
|
||||
- else {
|
||||
- unsigned int hlen = ALIGN(extra_headroom, 4);
|
||||
- /*
|
||||
- * Allocate and reserve two bytes more for payload
|
||||
- * alignment since sizeof(struct ethhdr) is 14.
|
||||
- */
|
||||
- frame = dev_alloc_skb(hlen + subframe_len + 2);
|
||||
+ reuse_skb = true;
|
||||
+ } else {
|
||||
+ frame = __ieee80211_amsdu_copy(skb, hlen, offset, len);
|
||||
if (!frame)
|
||||
goto purge;
|
||||
|
||||
- skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
|
||||
- memcpy(skb_put(frame, ntohs(len)), skb->data,
|
||||
- ntohs(len));
|
||||
-
|
||||
- eth = (struct ethhdr *)skb_pull(skb, ntohs(len) +
|
||||
- padding);
|
||||
- if (!eth) {
|
||||
- dev_kfree_skb(frame);
|
||||
- goto purge;
|
||||
- }
|
||||
+ offset += len + padding;
|
||||
}
|
||||
|
||||
skb_reset_network_header(frame);
|
||||
@@ -719,24 +721,20 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
|
||||
payload = frame->data;
|
||||
ethertype = (payload[6] << 8) | payload[7];
|
||||
-
|
||||
if (likely((ether_addr_equal(payload, rfc1042_header) &&
|
||||
ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
|
||||
ether_addr_equal(payload, bridge_tunnel_header))) {
|
||||
- /* remove RFC1042 or Bridge-Tunnel
|
||||
- * encapsulation and replace EtherType */
|
||||
- skb_pull(frame, 6);
|
||||
- memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
|
||||
- memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
|
||||
- } else {
|
||||
- memcpy(skb_push(frame, sizeof(__be16)), &len,
|
||||
- sizeof(__be16));
|
||||
- memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
|
||||
- memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
|
||||
+ eth.h_proto = htons(ethertype);
|
||||
+ skb_pull(frame, ETH_ALEN + 2);
|
||||
}
|
||||
+
|
||||
+ memcpy(skb_push(frame, sizeof(eth)), ð, sizeof(eth));
|
||||
__skb_queue_tail(list, frame);
|
||||
}
|
||||
|
||||
+ if (!reuse_skb)
|
||||
+ dev_kfree_skb(skb);
|
||||
+
|
||||
return;
|
||||
|
||||
purge:
|
||||
@@ -1,155 +0,0 @@
|
||||
From: Sven Eckelmann <sven@narfation.org>
|
||||
Date: Tue, 26 Jan 2016 17:11:13 +0100
|
||||
Subject: [PATCH] mac80211: Parse legacy and HT rate in injected frames
|
||||
|
||||
Drivers/devices without their own rate control algorithm can get the
|
||||
information what rates they should use from either the radiotap header of
|
||||
injected frames or from the rate control algorithm. But the parsing of the
|
||||
legacy rate information from the radiotap header was removed in commit
|
||||
e6a9854b05c1 ("mac80211/drivers: rewrite the rate control API").
|
||||
|
||||
The removal of this feature heavily reduced the usefulness of frame
|
||||
injection when wanting to simulate specific transmission behavior. Having
|
||||
rate parsing together with MCS rates and retry support allows a fine
|
||||
grained selection of the tx behavior of injected frames for these kind of
|
||||
tests.
|
||||
|
||||
Signed-off-by: Sven Eckelmann <sven@narfation.org>
|
||||
Cc: Simon Wunderlich <sw@simonwunderlich.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -708,12 +708,14 @@ enum mac80211_tx_info_flags {
|
||||
* protocol frame (e.g. EAP)
|
||||
* @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
|
||||
* frame (PS-Poll or uAPSD).
|
||||
+ * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
|
||||
*
|
||||
* These flags are used in tx_info->control.flags.
|
||||
*/
|
||||
enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0),
|
||||
IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
|
||||
+ IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
|
||||
};
|
||||
|
||||
/*
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -710,6 +710,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
|
||||
|
||||
info->control.short_preamble = txrc.short_preamble;
|
||||
|
||||
+ /* don't ask rate control when rate already injected via radiotap */
|
||||
+ if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)
|
||||
+ return TX_CONTINUE;
|
||||
+
|
||||
if (tx->sta)
|
||||
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
|
||||
|
||||
@@ -1665,15 +1669,24 @@ void ieee80211_xmit(struct ieee80211_sub
|
||||
ieee80211_tx(sdata, sta, skb, false);
|
||||
}
|
||||
|
||||
-static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
|
||||
+static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
|
||||
+ struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_radiotap_iterator iterator;
|
||||
struct ieee80211_radiotap_header *rthdr =
|
||||
(struct ieee80211_radiotap_header *) skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
+ struct ieee80211_supported_band *sband =
|
||||
+ local->hw.wiphy->bands[info->band];
|
||||
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
|
||||
NULL);
|
||||
u16 txflags;
|
||||
+ u16 rate = 0;
|
||||
+ bool rate_found = false;
|
||||
+ u8 rate_retries = 0;
|
||||
+ u16 rate_flags = 0;
|
||||
+ u8 mcs_known, mcs_flags;
|
||||
+ int i;
|
||||
|
||||
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
IEEE80211_TX_CTL_DONTFRAG;
|
||||
@@ -1724,6 +1737,35 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
break;
|
||||
|
||||
+ case IEEE80211_RADIOTAP_RATE:
|
||||
+ rate = *iterator.this_arg;
|
||||
+ rate_flags = 0;
|
||||
+ rate_found = true;
|
||||
+ break;
|
||||
+
|
||||
+ case IEEE80211_RADIOTAP_DATA_RETRIES:
|
||||
+ rate_retries = *iterator.this_arg;
|
||||
+ break;
|
||||
+
|
||||
+ case IEEE80211_RADIOTAP_MCS:
|
||||
+ mcs_known = iterator.this_arg[0];
|
||||
+ mcs_flags = iterator.this_arg[1];
|
||||
+ if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS))
|
||||
+ break;
|
||||
+
|
||||
+ rate_found = true;
|
||||
+ rate = iterator.this_arg[2];
|
||||
+ rate_flags = IEEE80211_TX_RC_MCS;
|
||||
+
|
||||
+ if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI &&
|
||||
+ mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
|
||||
+ rate_flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||
+
|
||||
+ if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
|
||||
+ mcs_flags & IEEE80211_RADIOTAP_MCS_BW_40)
|
||||
+ rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
+ break;
|
||||
+
|
||||
/*
|
||||
* Please update the file
|
||||
* Documentation/networking/mac80211-injection.txt
|
||||
@@ -1738,6 +1780,32 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
|
||||
return false;
|
||||
|
||||
+ if (rate_found) {
|
||||
+ info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
|
||||
+
|
||||
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
+ info->control.rates[i].idx = -1;
|
||||
+ info->control.rates[i].flags = 0;
|
||||
+ info->control.rates[i].count = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (rate_flags & IEEE80211_TX_RC_MCS) {
|
||||
+ info->control.rates[0].idx = rate;
|
||||
+ } else {
|
||||
+ for (i = 0; i < sband->n_bitrates; i++) {
|
||||
+ if (rate * 5 != sband->bitrates[i].bitrate)
|
||||
+ continue;
|
||||
+
|
||||
+ info->control.rates[0].idx = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ info->control.rates[0].flags = rate_flags;
|
||||
+ info->control.rates[0].count = min_t(u8, rate_retries + 1,
|
||||
+ local->hw.max_rate_tries);
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* remove the radiotap header
|
||||
* iterator->_max_length was sanity-checked against
|
||||
@@ -1819,7 +1887,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
|
||||
IEEE80211_TX_CTL_INJECTED;
|
||||
|
||||
/* process and remove the injection radiotap header */
|
||||
- if (!ieee80211_parse_tx_radiotap(skb))
|
||||
+ if (!ieee80211_parse_tx_radiotap(local, skb))
|
||||
goto fail;
|
||||
|
||||
rcu_read_lock();
|
||||
@@ -1,317 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Fri, 5 Feb 2016 01:38:51 +0100
|
||||
Subject: [PATCH] mac80211: add A-MSDU tx support
|
||||
|
||||
Requires software tx queueing support. frag_list support (for zero-copy)
|
||||
is optional.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -709,6 +709,7 @@ enum mac80211_tx_info_flags {
|
||||
* @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
|
||||
* frame (PS-Poll or uAPSD).
|
||||
* @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
|
||||
+ * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
|
||||
*
|
||||
* These flags are used in tx_info->control.flags.
|
||||
*/
|
||||
@@ -716,6 +717,7 @@ enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0),
|
||||
IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
|
||||
IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
|
||||
+ IEEE80211_TX_CTRL_AMSDU = BIT(3),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1728,6 +1730,7 @@ struct ieee80211_sta_rates {
|
||||
* size is min(max_amsdu_len, 7935) bytes.
|
||||
* Both additional HT limits must be enforced by the low level driver.
|
||||
* This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2).
|
||||
+ * @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
|
||||
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
|
||||
*/
|
||||
struct ieee80211_sta {
|
||||
@@ -1748,6 +1751,7 @@ struct ieee80211_sta {
|
||||
bool mfp;
|
||||
u8 max_amsdu_subframes;
|
||||
u16 max_amsdu_len;
|
||||
+ u16 max_rc_amsdu_len;
|
||||
|
||||
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
|
||||
|
||||
@@ -1961,6 +1965,15 @@ struct ieee80211_txq {
|
||||
* order and does not need to manage its own reorder buffer or BA session
|
||||
* timeout.
|
||||
*
|
||||
+ * @IEEE80211_HW_TX_AMSDU: Hardware (or driver) supports software aggregated
|
||||
+ * A-MSDU frames. Requires software tx queueing and fast-xmit support.
|
||||
+ * When not using minstrel/minstrel_ht rate control, the driver should
|
||||
+ * limit the maximum A-MSDU size based on the current tx rate by setting
|
||||
+ * max_rc_amsdu_len in struct ieee80211_sta.
|
||||
+ *
|
||||
+ * @IEEE80211_HW_TX_FRAG_LIST: Hardware (or driver) supports sending frag_list
|
||||
+ * skbs, needed for zero-copy software A-MSDU.
|
||||
+ *
|
||||
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
|
||||
*/
|
||||
enum ieee80211_hw_flags {
|
||||
@@ -1998,6 +2011,8 @@ enum ieee80211_hw_flags {
|
||||
IEEE80211_HW_BEACON_TX_STATUS,
|
||||
IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR,
|
||||
IEEE80211_HW_SUPPORTS_REORDERING_BUFFER,
|
||||
+ IEEE80211_HW_TX_AMSDU,
|
||||
+ IEEE80211_HW_TX_FRAG_LIST,
|
||||
|
||||
/* keep last, obviously */
|
||||
NUM_IEEE80211_HW_FLAGS
|
||||
@@ -2070,6 +2085,9 @@ enum ieee80211_hw_flags {
|
||||
* size is smaller (an example is LinkSys WRT120N with FW v1.0.07
|
||||
* build 002 Jun 18 2012).
|
||||
*
|
||||
+ * @max_tx_fragments: maximum number of tx buffers per (A)-MSDU, sum
|
||||
+ * of 1 + skb_shinfo(skb)->nr_frags for each skb in the frag_list.
|
||||
+ *
|
||||
* @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX
|
||||
* (if %IEEE80211_HW_QUEUE_CONTROL is set)
|
||||
*
|
||||
@@ -2124,6 +2142,7 @@ struct ieee80211_hw {
|
||||
u8 max_rate_tries;
|
||||
u8 max_rx_aggregation_subframes;
|
||||
u8 max_tx_aggregation_subframes;
|
||||
+ u8 max_tx_fragments;
|
||||
u8 offchannel_tx_hw_queue;
|
||||
u8 radiotap_mcs_details;
|
||||
u16 radiotap_vht_details;
|
||||
--- a/net/mac80211/agg-tx.c
|
||||
+++ b/net/mac80211/agg-tx.c
|
||||
@@ -935,6 +935,7 @@ void ieee80211_process_addba_resp(struct
|
||||
size_t len)
|
||||
{
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
+ struct ieee80211_txq *txq;
|
||||
u16 capab, tid;
|
||||
u8 buf_size;
|
||||
bool amsdu;
|
||||
@@ -945,6 +946,10 @@ void ieee80211_process_addba_resp(struct
|
||||
buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
|
||||
buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
|
||||
|
||||
+ txq = sta->sta.txq[tid];
|
||||
+ if (!amsdu && txq)
|
||||
+ set_bit(IEEE80211_TXQ_NO_AMSDU, &to_txq_info(txq)->flags);
|
||||
+
|
||||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
|
||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||
--- a/net/mac80211/debugfs.c
|
||||
+++ b/net/mac80211/debugfs.c
|
||||
@@ -127,6 +127,8 @@ static const char *hw_flag_names[NUM_IEE
|
||||
FLAG(BEACON_TX_STATUS),
|
||||
FLAG(NEEDS_UNIQUE_STA_ADDR),
|
||||
FLAG(SUPPORTS_REORDERING_BUFFER),
|
||||
+ FLAG(TX_AMSDU),
|
||||
+ FLAG(TX_FRAG_LIST),
|
||||
|
||||
/* keep last for the build bug below */
|
||||
(void *)0x1
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -799,6 +799,7 @@ struct mac80211_qos_map {
|
||||
enum txq_info_flags {
|
||||
IEEE80211_TXQ_STOP,
|
||||
IEEE80211_TXQ_AMPDU,
|
||||
+ IEEE80211_TXQ_NO_AMSDU,
|
||||
};
|
||||
|
||||
struct txq_info {
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1318,6 +1318,10 @@ struct sk_buff *ieee80211_tx_dequeue(str
|
||||
out:
|
||||
spin_unlock_bh(&txqi->queue.lock);
|
||||
|
||||
+ if (skb && skb_has_frag_list(skb) &&
|
||||
+ !ieee80211_hw_check(&local->hw, TX_FRAG_LIST))
|
||||
+ skb_linearize(skb);
|
||||
+
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_tx_dequeue);
|
||||
@@ -2757,6 +2761,163 @@ void ieee80211_clear_fast_xmit(struct st
|
||||
kfree_rcu(fast_tx, rcu_head);
|
||||
}
|
||||
|
||||
+static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local,
|
||||
+ struct sk_buff *skb, int headroom,
|
||||
+ int *subframe_len)
|
||||
+{
|
||||
+ int amsdu_len = *subframe_len + sizeof(struct ethhdr);
|
||||
+ int padding = (4 - amsdu_len) & 3;
|
||||
+
|
||||
+ if (skb_headroom(skb) < headroom || skb_tailroom(skb) < padding) {
|
||||
+ I802_DEBUG_INC(local->tx_expand_skb_head);
|
||||
+
|
||||
+ if (pskb_expand_head(skb, headroom, padding, GFP_ATOMIC)) {
|
||||
+ wiphy_debug(local->hw.wiphy,
|
||||
+ "failed to reallocate TX buffer\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (padding) {
|
||||
+ *subframe_len += padding;
|
||||
+ memset(skb_put(skb, padding), 0, padding);
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_fast_tx *fast_tx,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
+ struct ieee80211_hdr *hdr;
|
||||
+ struct ethhdr amsdu_hdr;
|
||||
+ int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
|
||||
+ int subframe_len = skb->len - hdr_len;
|
||||
+ void *data;
|
||||
+ u8 *qc;
|
||||
+
|
||||
+ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
|
||||
+ return false;
|
||||
+
|
||||
+ if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
|
||||
+ return true;
|
||||
+
|
||||
+ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(amsdu_hdr),
|
||||
+ &subframe_len))
|
||||
+ return false;
|
||||
+
|
||||
+ amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
|
||||
+ memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
|
||||
+ memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
|
||||
+
|
||||
+ data = skb_push(skb, sizeof(amsdu_hdr));
|
||||
+ memmove(data, data + sizeof(amsdu_hdr), hdr_len);
|
||||
+ memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
|
||||
+
|
||||
+ hdr = data;
|
||||
+ qc = ieee80211_get_qos_ctl(hdr);
|
||||
+ *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
+
|
||||
+ info->control.flags |= IEEE80211_TX_CTRL_AMSDU;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sta_info *sta,
|
||||
+ struct ieee80211_fast_tx *fast_tx,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
+ struct ieee80211_txq *txq = sta->sta.txq[tid];
|
||||
+ struct txq_info *txqi;
|
||||
+ struct sk_buff **frag_tail, *head;
|
||||
+ int subframe_len = skb->len - ETH_ALEN;
|
||||
+ u8 max_subframes = sta->sta.max_amsdu_subframes;
|
||||
+ int max_frags = local->hw.max_tx_fragments;
|
||||
+ int max_amsdu_len = sta->sta.max_amsdu_len;
|
||||
+ __be16 len;
|
||||
+ void *data;
|
||||
+ bool ret = false;
|
||||
+ int n = 1, nfrags;
|
||||
+
|
||||
+ if (!ieee80211_hw_check(&local->hw, TX_AMSDU))
|
||||
+ return false;
|
||||
+
|
||||
+ if (!txq)
|
||||
+ return false;
|
||||
+
|
||||
+ txqi = to_txq_info(txq);
|
||||
+ if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags))
|
||||
+ return false;
|
||||
+
|
||||
+ if (sta->sta.max_rc_amsdu_len)
|
||||
+ max_amsdu_len = min_t(int, max_amsdu_len,
|
||||
+ sta->sta.max_rc_amsdu_len);
|
||||
+
|
||||
+ spin_lock_bh(&txqi->queue.lock);
|
||||
+
|
||||
+ head = skb_peek_tail(&txqi->queue);
|
||||
+ if (!head)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (skb->len + head->len > max_amsdu_len)
|
||||
+ goto out;
|
||||
+
|
||||
+ /*
|
||||
+ * HT A-MPDU limits maximum MPDU size to 4095 bytes. Since aggregation
|
||||
+ * sessions are started/stopped without txq flush, use the limit here
|
||||
+ * to avoid having to de-aggregate later.
|
||||
+ */
|
||||
+ if (skb->len + head->len > 4095 &&
|
||||
+ !sta->sta.vht_cap.vht_supported)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
|
||||
+ goto out;
|
||||
+
|
||||
+ nfrags = 1 + skb_shinfo(skb)->nr_frags;
|
||||
+ nfrags += 1 + skb_shinfo(head)->nr_frags;
|
||||
+ frag_tail = &skb_shinfo(head)->frag_list;
|
||||
+ while (*frag_tail) {
|
||||
+ nfrags += 1 + skb_shinfo(*frag_tail)->nr_frags;
|
||||
+ frag_tail = &(*frag_tail)->next;
|
||||
+ n++;
|
||||
+ }
|
||||
+
|
||||
+ if (max_subframes && n > max_subframes)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (max_frags && nfrags > max_frags)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + 2,
|
||||
+ &subframe_len))
|
||||
+ return false;
|
||||
+
|
||||
+ ret = true;
|
||||
+ data = skb_push(skb, ETH_ALEN + 2);
|
||||
+ memmove(data, data + ETH_ALEN + 2, 2 * ETH_ALEN);
|
||||
+
|
||||
+ data += 2 * ETH_ALEN;
|
||||
+ len = cpu_to_be16(subframe_len);
|
||||
+ memcpy(data, &len, 2);
|
||||
+ memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header));
|
||||
+
|
||||
+ head->len += skb->len;
|
||||
+ head->data_len += skb->len;
|
||||
+ *frag_tail = skb;
|
||||
+
|
||||
+out:
|
||||
+ spin_unlock_bh(&txqi->queue.lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
|
||||
struct net_device *dev, struct sta_info *sta,
|
||||
struct ieee80211_fast_tx *fast_tx,
|
||||
@@ -2811,6 +2972,10 @@ static bool ieee80211_xmit_fast(struct i
|
||||
|
||||
ieee80211_tx_stats(dev, skb->len + extra_head);
|
||||
|
||||
+ if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
|
||||
+ ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
|
||||
+ return true;
|
||||
+
|
||||
/* will not be crypto-handled beyond what we do here, so use false
|
||||
* as the may-encrypt argument for the resize to not account for
|
||||
* more room than we already have in 'extra_head'
|
||||
@@ -1,64 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Wed, 20 Jan 2016 16:46:04 +0100
|
||||
Subject: [PATCH] brcmfmac: fix setting primary channel for 80 MHz width
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
First of all it changes the way we calculate primary channel offset. If
|
||||
we use e.g. 80 MHz channel with primary frequency 5180 MHz (which means
|
||||
center frequency is 5210 MHz) it makes sense to calculate primary offset
|
||||
as -30 MHz.
|
||||
Then it fixes values we compare primary_offset with. We were comparing
|
||||
offset in MHz against -2 or 2 which was resulting in picking a wrong
|
||||
primary channel.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -247,7 +247,7 @@ static u16 chandef_to_chanspec(struct br
|
||||
brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",
|
||||
ch->chan->center_freq, ch->center_freq1, ch->width);
|
||||
ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);
|
||||
- primary_offset = ch->center_freq1 - ch->chan->center_freq;
|
||||
+ primary_offset = ch->chan->center_freq - ch->center_freq1;
|
||||
switch (ch->width) {
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
@@ -256,24 +256,21 @@ static u16 chandef_to_chanspec(struct br
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
ch_inf.bw = BRCMU_CHAN_BW_40;
|
||||
- if (primary_offset < 0)
|
||||
+ if (primary_offset > 0)
|
||||
ch_inf.sb = BRCMU_CHAN_SB_U;
|
||||
else
|
||||
ch_inf.sb = BRCMU_CHAN_SB_L;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
ch_inf.bw = BRCMU_CHAN_BW_80;
|
||||
- if (primary_offset < 0) {
|
||||
- if (primary_offset < -CH_10MHZ_APART)
|
||||
- ch_inf.sb = BRCMU_CHAN_SB_UU;
|
||||
- else
|
||||
- ch_inf.sb = BRCMU_CHAN_SB_UL;
|
||||
- } else {
|
||||
- if (primary_offset > CH_10MHZ_APART)
|
||||
- ch_inf.sb = BRCMU_CHAN_SB_LL;
|
||||
- else
|
||||
- ch_inf.sb = BRCMU_CHAN_SB_LU;
|
||||
- }
|
||||
+ if (primary_offset == -30)
|
||||
+ ch_inf.sb = BRCMU_CHAN_SB_LL;
|
||||
+ else if (primary_offset == -10)
|
||||
+ ch_inf.sb = BRCMU_CHAN_SB_LU;
|
||||
+ else if (primary_offset == 10)
|
||||
+ ch_inf.sb = BRCMU_CHAN_SB_UL;
|
||||
+ else
|
||||
+ ch_inf.sb = BRCMU_CHAN_SB_UU;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
@@ -1,51 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 26 Jan 2016 17:57:01 +0100
|
||||
Subject: [PATCH] brcmfmac: analyze descriptors of current component only
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
So far we were looking for address descriptors without a check for
|
||||
crossing current component border. In case of dealing with unsupported
|
||||
descriptor or descriptor missing at all the code would incorrectly get
|
||||
data from another component.
|
||||
|
||||
Consider this binary-described component from BCM4366 EROM:
|
||||
4bf83b01 TAG==CI CID==0x83b
|
||||
20080201 TAG==CI PORTS==0+1 WRAPPERS==0+1
|
||||
18400035 TAG==ADDR SZ_SZD TYPE_SLAVE
|
||||
00050000
|
||||
18107085 TAG==ADDR SZ_4K TYPE_SWRAP
|
||||
|
||||
Driver was assigning invalid base address to this core:
|
||||
brcmfmac: [6 ] core 0x83b:32 base 0x18109000 wrap 0x18107000
|
||||
which came from totally different component defined in EROM:
|
||||
43b36701 TAG==CI CID==0x367
|
||||
00000201 TAG==CI PORTS==0+1 WRAPPERS==0+0
|
||||
18109005 TAG==ADDR SZ_4K TYPE_SLAVE
|
||||
|
||||
This change will also allow us to support components without wrapper
|
||||
address in the future.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
@@ -803,7 +803,14 @@ static int brcmf_chip_dmp_get_regaddr(st
|
||||
*eromaddr -= 4;
|
||||
return -EFAULT;
|
||||
}
|
||||
- } while (desc != DMP_DESC_ADDRESS);
|
||||
+ } while (desc != DMP_DESC_ADDRESS &&
|
||||
+ desc != DMP_DESC_COMPONENT);
|
||||
+
|
||||
+ /* stop if we crossed current component border */
|
||||
+ if (desc == DMP_DESC_COMPONENT) {
|
||||
+ *eromaddr -= 4;
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
/* skip upper 32-bit address descriptor */
|
||||
if (val & DMP_DESC_ADDRSIZE_GT32)
|
||||
@@ -1,28 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 26 Jan 2016 17:57:02 +0100
|
||||
Subject: [PATCH] brcmfmac: allow storing PMU core without wrapper address
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Separated PMU core can be found in new devices and should be used for
|
||||
accessing PMU registers (which were routed through ChipCommon so far).
|
||||
This core is one of exceptions that doesn't have or need wrapper address
|
||||
to be still safely accessible.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
@@ -883,7 +883,8 @@ int brcmf_chip_dmp_erom_scan(struct brcm
|
||||
rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
|
||||
|
||||
/* need core with ports */
|
||||
- if (nmw + nsw == 0)
|
||||
+ if (nmw + nsw == 0 &&
|
||||
+ id != BCMA_CORE_PMU)
|
||||
continue;
|
||||
|
||||
/* try to obtain register address info */
|
||||
@@ -1,43 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 26 Jan 2016 17:57:03 +0100
|
||||
Subject: [PATCH] brcmfmac: read extended capabilities of ChipCommon core
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is an extra bitfield with info about some present hardware.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
@@ -1025,6 +1025,9 @@ static int brcmf_chip_setup(struct brcmf
|
||||
/* get chipcommon capabilites */
|
||||
pub->cc_caps = chip->ops->read32(chip->ctx,
|
||||
CORE_CC_REG(base, capabilities));
|
||||
+ pub->cc_caps_ext = chip->ops->read32(chip->ctx,
|
||||
+ CORE_CC_REG(base,
|
||||
+ capabilities_ext));
|
||||
|
||||
/* get pmu caps & rev */
|
||||
if (pub->cc_caps & CC_CAP_PMU) {
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
|
||||
@@ -27,6 +27,7 @@
|
||||
* @chip: chip identifier.
|
||||
* @chiprev: chip revision.
|
||||
* @cc_caps: chipcommon core capabilities.
|
||||
+ * @cc_caps_ext: chipcommon core extended capabilities.
|
||||
* @pmucaps: PMU capabilities.
|
||||
* @pmurev: PMU revision.
|
||||
* @rambase: RAM base address (only applicable for ARM CR4 chips).
|
||||
@@ -38,6 +39,7 @@ struct brcmf_chip {
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
u32 cc_caps;
|
||||
+ u32 cc_caps_ext;
|
||||
u32 pmucaps;
|
||||
u32 pmurev;
|
||||
u32 rambase;
|
||||
@@ -1,148 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 26 Jan 2016 17:57:04 +0100
|
||||
Subject: [PATCH] brcmfmac: access PMU registers using standalone PMU core if
|
||||
available
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On recent Broadcom chipsets PMU is present as separated core and it
|
||||
can't be accessed using ChipCommon anymore as it fails with e.g.:
|
||||
[ 18.198412] Unhandled fault: imprecise external abort (0x1406) at 0xb6da200f
|
||||
|
||||
Add a new helper function that will return a proper core that should be
|
||||
used for accessing PMU registers.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
|
||||
@@ -1014,6 +1014,7 @@ static int brcmf_chip_setup(struct brcmf
|
||||
{
|
||||
struct brcmf_chip *pub;
|
||||
struct brcmf_core_priv *cc;
|
||||
+ struct brcmf_core *pmu;
|
||||
u32 base;
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
@@ -1030,9 +1031,10 @@ static int brcmf_chip_setup(struct brcmf
|
||||
capabilities_ext));
|
||||
|
||||
/* get pmu caps & rev */
|
||||
+ pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */
|
||||
if (pub->cc_caps & CC_CAP_PMU) {
|
||||
val = chip->ops->read32(chip->ctx,
|
||||
- CORE_CC_REG(base, pmucapabilities));
|
||||
+ CORE_CC_REG(pmu->base, pmucapabilities));
|
||||
pub->pmurev = val & PCAP_REV_MASK;
|
||||
pub->pmucaps = val;
|
||||
}
|
||||
@@ -1131,6 +1133,23 @@ struct brcmf_core *brcmf_chip_get_chipco
|
||||
return &cc->pub;
|
||||
}
|
||||
|
||||
+struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub)
|
||||
+{
|
||||
+ struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub);
|
||||
+ struct brcmf_core *pmu;
|
||||
+
|
||||
+ /* See if there is separated PMU core available */
|
||||
+ if (cc->rev >= 35 &&
|
||||
+ pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
|
||||
+ pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU);
|
||||
+ if (pmu)
|
||||
+ return pmu;
|
||||
+ }
|
||||
+
|
||||
+ /* Fallback to ChipCommon core for older hardware */
|
||||
+ return cc;
|
||||
+}
|
||||
+
|
||||
bool brcmf_chip_iscoreup(struct brcmf_core *pub)
|
||||
{
|
||||
struct brcmf_core_priv *core;
|
||||
@@ -1301,6 +1320,7 @@ bool brcmf_chip_sr_capable(struct brcmf_
|
||||
{
|
||||
u32 base, addr, reg, pmu_cc3_mask = ~0;
|
||||
struct brcmf_chip_priv *chip;
|
||||
+ struct brcmf_core *pmu = brcmf_chip_get_pmu(pub);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
@@ -1320,9 +1340,9 @@ bool brcmf_chip_sr_capable(struct brcmf_
|
||||
case BRCM_CC_4335_CHIP_ID:
|
||||
case BRCM_CC_4339_CHIP_ID:
|
||||
/* read PMU chipcontrol register 3 */
|
||||
- addr = CORE_CC_REG(base, chipcontrol_addr);
|
||||
+ addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
|
||||
chip->ops->write32(chip->ctx, addr, 3);
|
||||
- addr = CORE_CC_REG(base, chipcontrol_data);
|
||||
+ addr = CORE_CC_REG(pmu->base, chipcontrol_data);
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
return (reg & pmu_cc3_mask) != 0;
|
||||
case BRCM_CC_43430_CHIP_ID:
|
||||
@@ -1330,12 +1350,12 @@ bool brcmf_chip_sr_capable(struct brcmf_
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
return reg != 0;
|
||||
default:
|
||||
- addr = CORE_CC_REG(base, pmucapabilities_ext);
|
||||
+ addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
|
||||
return false;
|
||||
|
||||
- addr = CORE_CC_REG(base, retention_ctl);
|
||||
+ addr = CORE_CC_REG(pmu->base, retention_ctl);
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
|
||||
PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
|
||||
@@ -85,6 +85,7 @@ struct brcmf_chip *brcmf_chip_attach(voi
|
||||
void brcmf_chip_detach(struct brcmf_chip *chip);
|
||||
struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
|
||||
struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
|
||||
+struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub);
|
||||
bool brcmf_chip_iscoreup(struct brcmf_core *core);
|
||||
void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
|
||||
void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -3615,7 +3615,6 @@ brcmf_sdio_drivestrengthinit(struct brcm
|
||||
const struct sdiod_drive_str *str_tab = NULL;
|
||||
u32 str_mask;
|
||||
u32 str_shift;
|
||||
- u32 base;
|
||||
u32 i;
|
||||
u32 drivestrength_sel = 0;
|
||||
u32 cc_data_temp;
|
||||
@@ -3658,14 +3657,15 @@ brcmf_sdio_drivestrengthinit(struct brcm
|
||||
}
|
||||
|
||||
if (str_tab != NULL) {
|
||||
+ struct brcmf_core *pmu = brcmf_chip_get_pmu(ci);
|
||||
+
|
||||
for (i = 0; str_tab[i].strength != 0; i++) {
|
||||
if (drivestrength >= str_tab[i].strength) {
|
||||
drivestrength_sel = str_tab[i].sel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
- base = brcmf_chip_get_chipcommon(ci)->base;
|
||||
- addr = CORE_CC_REG(base, chipcontrol_addr);
|
||||
+ addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
|
||||
brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
|
||||
cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
|
||||
cc_data_temp &= ~str_mask;
|
||||
@@ -3835,8 +3835,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
|
||||
goto fail;
|
||||
|
||||
/* set PMUControl so a backplane reset does PMU state reload */
|
||||
- reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base,
|
||||
- pmucontrol);
|
||||
+ reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
|
||||
reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
|
||||
if (err)
|
||||
goto fail;
|
||||
@@ -1,38 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 26 Jan 2016 17:57:05 +0100
|
||||
Subject: [PATCH] brcmfmac: add support for 14e4:4365 PCI ID with BCM4366
|
||||
chipset
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On Broadcom ARM routers BCM4366 cards are available with 14e4:4365 ID.
|
||||
Unfortunately this ID was already used by Broadcom for cards with
|
||||
BCM43142, a totally different chipset requiring SoftMAC driver. To avoid
|
||||
a conflict between brcmfmac and bcma use more specific ID entry with
|
||||
subvendor and subdevice specified.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
@@ -1951,6 +1951,9 @@ static const struct dev_pm_ops brcmf_pci
|
||||
|
||||
#define BRCMF_PCIE_DEVICE(dev_id) { BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
|
||||
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
|
||||
+#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev) { \
|
||||
+ BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
|
||||
+ subvend, subdev, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
|
||||
|
||||
static struct pci_device_id brcmf_pcie_devid_table[] = {
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID),
|
||||
@@ -1966,6 +1969,7 @@ static struct pci_device_id brcmf_pcie_d
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID),
|
||||
+ BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
|
||||
@@ -1,32 +0,0 @@
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Sun, 31 Jan 2016 12:14:34 +0100
|
||||
Subject: [PATCH] brcmfmac: treat NULL character in NVRAM as separator
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Platform NVRAM (stored on a flash partition) has entries separated by a
|
||||
NULL (\0) char. Our parsing code switches from VALUE state to IDLE
|
||||
whenever it meets a NULL (\0). When that happens our IDLE handler should
|
||||
simply consume it and analyze whatever is placed ahead.
|
||||
|
||||
This fixes harmless warnings spamming debugging output:
|
||||
[ 155.165624] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=20: ignoring invalid character
|
||||
[ 155.180806] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=44: ignoring invalid character
|
||||
[ 155.195971] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=63: ignoring invalid character
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
@@ -93,7 +93,7 @@ static enum nvram_parser_state brcmf_nvr
|
||||
c = nvp->data[nvp->pos];
|
||||
if (c == '\n')
|
||||
return COMMENT;
|
||||
- if (is_whitespace(c))
|
||||
+ if (is_whitespace(c) || c == '\0')
|
||||
goto proceed;
|
||||
if (c == '#')
|
||||
return COMMENT;
|
||||
@@ -1,41 +0,0 @@
|
||||
From: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
|
||||
Date: Mon, 25 Jan 2016 11:47:29 +0100
|
||||
Subject: [PATCH] brcmfmac: sdio: Increase the default timeouts a bit
|
||||
|
||||
On a Radxa Rock2 board with a Ampak AP6335 (Broadcom 4339 core) it seems
|
||||
the card responds very quickly most of the time, unfortunately during
|
||||
initialisation it sometimes seems to take just a bit over 2 seconds to
|
||||
respond.
|
||||
|
||||
This results intialization failing with message like:
|
||||
brcmf_c_preinit_dcmds: Retreiving cur_etheraddr failed, -52
|
||||
brcmf_bus_start: failed: -52
|
||||
brcmf_sdio_firmware_callback: dongle is not responding
|
||||
|
||||
Increasing the timeout to allow for a bit more headroom allows the
|
||||
card to initialize reliably.
|
||||
|
||||
A quick search online after diagnosing/fixing this showed that Google
|
||||
has a similar patch in their ChromeOS tree, so this doesn't seem
|
||||
specific to the board I'm using.
|
||||
|
||||
Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
|
||||
Reviewed-by: Julian Calaby <julian.calaby@gmail.com>
|
||||
Acked-by: Arend van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Douglas Anderson <dianders@chromium.org>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -45,8 +45,8 @@
|
||||
#include "chip.h"
|
||||
#include "firmware.h"
|
||||
|
||||
-#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2000)
|
||||
-#define CTL_DONE_TIMEOUT msecs_to_jiffies(2000)
|
||||
+#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500)
|
||||
+#define CTL_DONE_TIMEOUT msecs_to_jiffies(2500)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
From: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
Date: Fri, 5 Feb 2016 09:45:50 +0800
|
||||
Subject: [PATCH] ath9k: make NF load complete quickly and reliably
|
||||
|
||||
Make NF load complete quickly and reliably. NF load execution
|
||||
is delayed by HW to end of frame if frame Rx or Tx is ongoing.
|
||||
Increasing timeout to max frame duration. If NF cal is ongoing
|
||||
before NF load, stop it before load, and restart it afterwards.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/calib.c
|
||||
@@ -241,6 +241,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
|
||||
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||
+ u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL);
|
||||
|
||||
if (ah->caldata)
|
||||
h = ah->caldata->nfCalHist;
|
||||
@@ -264,6 +265,16 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
|
||||
}
|
||||
|
||||
/*
|
||||
+ * stop NF cal if ongoing to ensure NF load completes immediately
|
||||
+ * (or after end rx/tx frame if ongoing)
|
||||
+ */
|
||||
+ if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
|
||||
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
+ REG_RMW_BUFFER_FLUSH(ah);
|
||||
+ ENABLE_REG_RMW_BUFFER(ah);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* Load software filtered NF value into baseband internal minCCApwr
|
||||
* variable.
|
||||
*/
|
||||
@@ -276,18 +287,33 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
|
||||
|
||||
/*
|
||||
* Wait for load to complete, should be fast, a few 10s of us.
|
||||
- * The max delay was changed from an original 250us to 10000us
|
||||
- * since 250us often results in NF load timeout and causes deaf
|
||||
- * condition during stress testing 12/12/2009
|
||||
+ * The max delay was changed from an original 250us to 22.2 msec.
|
||||
+ * This would increase timeout to the longest possible frame
|
||||
+ * (11n max length 22.1 msec)
|
||||
*/
|
||||
- for (j = 0; j < 10000; j++) {
|
||||
+ for (j = 0; j < 22200; j++) {
|
||||
if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
|
||||
- AR_PHY_AGC_CONTROL_NF) == 0)
|
||||
+ AR_PHY_AGC_CONTROL_NF) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Restart NF so it can continue.
|
||||
+ */
|
||||
+ if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
|
||||
+ ENABLE_REG_RMW_BUFFER(ah);
|
||||
+ if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF)
|
||||
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
|
||||
+ if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF)
|
||||
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
+ REG_RMW_BUFFER_FLUSH(ah);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* We timed out waiting for the noisefloor to load, probably due to an
|
||||
* in-progress rx. Simply return here and allow the load plenty of time
|
||||
* to complete before the next calibration interval. We need to avoid
|
||||
@@ -296,7 +322,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
|
||||
* here, the baseband nf cal will just be capped by our present
|
||||
* noisefloor until the next calibration timer.
|
||||
*/
|
||||
- if (j == 10000) {
|
||||
+ if (j == 22200) {
|
||||
ath_dbg(common, ANY,
|
||||
"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL));
|
||||
@@ -1,54 +0,0 @@
|
||||
From: Henning Rogge <hrogge@gmail.com>
|
||||
Date: Wed, 3 Feb 2016 13:58:36 +0100
|
||||
Subject: [PATCH] mac80211: Remove MPP table entries with MPath
|
||||
|
||||
Make the mesh_path_del() function remove all mpp table entries
|
||||
that are proxied by the removed mesh path.
|
||||
|
||||
Acked-by: Bob Copeland <me@bobcopeland.com>
|
||||
Signed-off-by: Henning Rogge <henning.rogge@fkie.fraunhofer.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/mesh_pathtbl.c
|
||||
+++ b/net/mac80211/mesh_pathtbl.c
|
||||
@@ -835,6 +835,29 @@ void mesh_path_flush_by_nexthop(struct s
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
+static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
|
||||
+ const u8 *proxy)
|
||||
+{
|
||||
+ struct mesh_table *tbl;
|
||||
+ struct mesh_path *mpp;
|
||||
+ struct mpath_node *node;
|
||||
+ int i;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ read_lock_bh(&pathtbl_resize_lock);
|
||||
+ tbl = resize_dereference_mpp_paths();
|
||||
+ for_each_mesh_entry(tbl, node, i) {
|
||||
+ mpp = node->mpath;
|
||||
+ if (ether_addr_equal(mpp->mpp, proxy)) {
|
||||
+ spin_lock(&tbl->hashwlock[i]);
|
||||
+ __mesh_path_del(tbl, node);
|
||||
+ spin_unlock(&tbl->hashwlock[i]);
|
||||
+ }
|
||||
+ }
|
||||
+ read_unlock_bh(&pathtbl_resize_lock);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
static void table_flush_by_iface(struct mesh_table *tbl,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
@@ -892,6 +915,9 @@ int mesh_path_del(struct ieee80211_sub_i
|
||||
int hash_idx;
|
||||
int err = 0;
|
||||
|
||||
+ /* flush relevant mpp entries first */
|
||||
+ mpp_flush_by_proxy(sdata, addr);
|
||||
+
|
||||
read_lock_bh(&pathtbl_resize_lock);
|
||||
tbl = resize_dereference_mesh_paths();
|
||||
hash_idx = mesh_table_hash(addr, sdata, tbl);
|
||||
@@ -1,104 +0,0 @@
|
||||
From: Henning Rogge <hrogge@gmail.com>
|
||||
Date: Wed, 3 Feb 2016 13:58:37 +0100
|
||||
Subject: [PATCH] mac80211: let unused MPP table entries timeout
|
||||
|
||||
Remember the last time when a mpp table entry is used for
|
||||
rx or tx and remove them after MESH_PATH_EXPIRE time.
|
||||
|
||||
Acked-by: Bob Copeland <me@bobcopeland.com>
|
||||
Signed-off-by: Henning Rogge <henning.rogge@fkie.fraunhofer.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/mesh_pathtbl.c
|
||||
+++ b/net/mac80211/mesh_pathtbl.c
|
||||
@@ -942,6 +942,46 @@ enddel:
|
||||
}
|
||||
|
||||
/**
|
||||
+ * mpp_path_del - delete a mesh proxy path from the table
|
||||
+ *
|
||||
+ * @addr: addr address (ETH_ALEN length)
|
||||
+ * @sdata: local subif
|
||||
+ *
|
||||
+ * Returns: 0 if successful
|
||||
+ */
|
||||
+static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
|
||||
+{
|
||||
+ struct mesh_table *tbl;
|
||||
+ struct mesh_path *mpath;
|
||||
+ struct mpath_node *node;
|
||||
+ struct hlist_head *bucket;
|
||||
+ int hash_idx;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ read_lock_bh(&pathtbl_resize_lock);
|
||||
+ tbl = resize_dereference_mpp_paths();
|
||||
+ hash_idx = mesh_table_hash(addr, sdata, tbl);
|
||||
+ bucket = &tbl->hash_buckets[hash_idx];
|
||||
+
|
||||
+ spin_lock(&tbl->hashwlock[hash_idx]);
|
||||
+ hlist_for_each_entry(node, bucket, list) {
|
||||
+ mpath = node->mpath;
|
||||
+ if (mpath->sdata == sdata &&
|
||||
+ ether_addr_equal(addr, mpath->dst)) {
|
||||
+ __mesh_path_del(tbl, node);
|
||||
+ goto enddel;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = -ENXIO;
|
||||
+enddel:
|
||||
+ mesh_paths_generation++;
|
||||
+ spin_unlock(&tbl->hashwlock[hash_idx]);
|
||||
+ read_unlock_bh(&pathtbl_resize_lock);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* mesh_path_tx_pending - sends pending frames in a mesh path queue
|
||||
*
|
||||
* @mpath: mesh path to activate
|
||||
@@ -1157,6 +1197,17 @@ void mesh_path_expire(struct ieee80211_s
|
||||
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
|
||||
mesh_path_del(mpath->sdata, mpath->dst);
|
||||
}
|
||||
+
|
||||
+ tbl = rcu_dereference(mpp_paths);
|
||||
+ for_each_mesh_entry(tbl, node, i) {
|
||||
+ if (node->mpath->sdata != sdata)
|
||||
+ continue;
|
||||
+ mpath = node->mpath;
|
||||
+ if ((!(mpath->flags & MESH_PATH_FIXED)) &&
|
||||
+ time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
|
||||
+ mpp_path_del(mpath->sdata, mpath->dst);
|
||||
+ }
|
||||
+
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -2291,6 +2291,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
|
||||
spin_lock_bh(&mppath->state_lock);
|
||||
if (!ether_addr_equal(mppath->mpp, mpp_addr))
|
||||
memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
|
||||
+ mppath->exp_time = jiffies;
|
||||
spin_unlock_bh(&mppath->state_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -2171,8 +2171,11 @@ static struct sk_buff *ieee80211_build_h
|
||||
mpp_lookup = true;
|
||||
}
|
||||
|
||||
- if (mpp_lookup)
|
||||
+ if (mpp_lookup) {
|
||||
mppath = mpp_path_lookup(sdata, skb->data);
|
||||
+ if (mppath)
|
||||
+ mppath->exp_time = jiffies;
|
||||
+ }
|
||||
|
||||
if (mppath && mpath)
|
||||
mesh_path_del(mpath->sdata, mpath->dst);
|
||||
@@ -1,143 +0,0 @@
|
||||
From: Henning Rogge <hrogge@gmail.com>
|
||||
Date: Wed, 3 Feb 2016 13:58:38 +0100
|
||||
Subject: [PATCH] mac80211: Unify mesh and mpp path removal function
|
||||
|
||||
mpp_path_del() and mesh_path_del() are mostly the same function.
|
||||
Move common code into a new static function.
|
||||
|
||||
Acked-by: Bob Copeland <me@bobcopeland.com>
|
||||
Signed-off-by: Henning Rogge <henning.rogge@fkie.fraunhofer.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/mesh_pathtbl.c
|
||||
+++ b/net/mac80211/mesh_pathtbl.c
|
||||
@@ -55,16 +55,21 @@ int mpp_paths_generation;
|
||||
static DEFINE_RWLOCK(pathtbl_resize_lock);
|
||||
|
||||
|
||||
+static inline struct mesh_table *resize_dereference_paths(
|
||||
+ struct mesh_table __rcu *table)
|
||||
+{
|
||||
+ return rcu_dereference_protected(table,
|
||||
+ lockdep_is_held(&pathtbl_resize_lock));
|
||||
+}
|
||||
+
|
||||
static inline struct mesh_table *resize_dereference_mesh_paths(void)
|
||||
{
|
||||
- return rcu_dereference_protected(mesh_paths,
|
||||
- lockdep_is_held(&pathtbl_resize_lock));
|
||||
+ return resize_dereference_paths(mesh_paths);
|
||||
}
|
||||
|
||||
static inline struct mesh_table *resize_dereference_mpp_paths(void)
|
||||
{
|
||||
- return rcu_dereference_protected(mpp_paths,
|
||||
- lockdep_is_held(&pathtbl_resize_lock));
|
||||
+ return resize_dereference_paths(mpp_paths);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -899,14 +904,17 @@ void mesh_path_flush_by_iface(struct iee
|
||||
}
|
||||
|
||||
/**
|
||||
- * mesh_path_del - delete a mesh path from the table
|
||||
+ * table_path_del - delete a path from the mesh or mpp table
|
||||
*
|
||||
- * @addr: dst address (ETH_ALEN length)
|
||||
+ * @tbl: mesh or mpp path table
|
||||
* @sdata: local subif
|
||||
+ * @addr: dst address (ETH_ALEN length)
|
||||
*
|
||||
* Returns: 0 if successful
|
||||
*/
|
||||
-int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
|
||||
+static int table_path_del(struct mesh_table __rcu *rcu_tbl,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ const u8 *addr)
|
||||
{
|
||||
struct mesh_table *tbl;
|
||||
struct mesh_path *mpath;
|
||||
@@ -915,11 +923,7 @@ int mesh_path_del(struct ieee80211_sub_i
|
||||
int hash_idx;
|
||||
int err = 0;
|
||||
|
||||
- /* flush relevant mpp entries first */
|
||||
- mpp_flush_by_proxy(sdata, addr);
|
||||
-
|
||||
- read_lock_bh(&pathtbl_resize_lock);
|
||||
- tbl = resize_dereference_mesh_paths();
|
||||
+ tbl = resize_dereference_paths(rcu_tbl);
|
||||
hash_idx = mesh_table_hash(addr, sdata, tbl);
|
||||
bucket = &tbl->hash_buckets[hash_idx];
|
||||
|
||||
@@ -935,9 +939,30 @@ int mesh_path_del(struct ieee80211_sub_i
|
||||
|
||||
err = -ENXIO;
|
||||
enddel:
|
||||
- mesh_paths_generation++;
|
||||
spin_unlock(&tbl->hashwlock[hash_idx]);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * mesh_path_del - delete a mesh path from the table
|
||||
+ *
|
||||
+ * @addr: dst address (ETH_ALEN length)
|
||||
+ * @sdata: local subif
|
||||
+ *
|
||||
+ * Returns: 0 if successful
|
||||
+ */
|
||||
+int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
|
||||
+{
|
||||
+ int err = 0;
|
||||
+
|
||||
+ /* flush relevant mpp entries first */
|
||||
+ mpp_flush_by_proxy(sdata, addr);
|
||||
+
|
||||
+ read_lock_bh(&pathtbl_resize_lock);
|
||||
+ err = table_path_del(mesh_paths, sdata, addr);
|
||||
+ mesh_paths_generation++;
|
||||
read_unlock_bh(&pathtbl_resize_lock);
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -951,33 +976,13 @@ enddel:
|
||||
*/
|
||||
static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
|
||||
{
|
||||
- struct mesh_table *tbl;
|
||||
- struct mesh_path *mpath;
|
||||
- struct mpath_node *node;
|
||||
- struct hlist_head *bucket;
|
||||
- int hash_idx;
|
||||
int err = 0;
|
||||
|
||||
read_lock_bh(&pathtbl_resize_lock);
|
||||
- tbl = resize_dereference_mpp_paths();
|
||||
- hash_idx = mesh_table_hash(addr, sdata, tbl);
|
||||
- bucket = &tbl->hash_buckets[hash_idx];
|
||||
-
|
||||
- spin_lock(&tbl->hashwlock[hash_idx]);
|
||||
- hlist_for_each_entry(node, bucket, list) {
|
||||
- mpath = node->mpath;
|
||||
- if (mpath->sdata == sdata &&
|
||||
- ether_addr_equal(addr, mpath->dst)) {
|
||||
- __mesh_path_del(tbl, node);
|
||||
- goto enddel;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- err = -ENXIO;
|
||||
-enddel:
|
||||
- mesh_paths_generation++;
|
||||
- spin_unlock(&tbl->hashwlock[hash_idx]);
|
||||
+ err = table_path_del(mpp_paths, sdata, addr);
|
||||
+ mpp_paths_generation++;
|
||||
read_unlock_bh(&pathtbl_resize_lock);
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
From: Sven Eckelmann <sven.eckelmann@open-mesh.com>
|
||||
Date: Tue, 2 Feb 2016 08:12:26 +0100
|
||||
Subject: [PATCH] mac80211: minstrel: Change expected throughput unit back to
|
||||
Kbps
|
||||
|
||||
The change from cur_tp to the function
|
||||
minstrel_get_tp_avg/minstrel_ht_get_tp_avg changed the unit used for the
|
||||
current throughput. For example in minstrel_ht the correct
|
||||
conversion between them would be:
|
||||
|
||||
mrs->cur_tp / 10 == minstrel_ht_get_tp_avg(..).
|
||||
|
||||
This factor 10 must also be included in the calculation of
|
||||
minstrel_get_expected_throughput and minstrel_ht_get_expected_throughput to
|
||||
return values with the unit [Kbps] instead of [10Kbps]. Otherwise routing
|
||||
algorithms like B.A.T.M.A.N. V will make incorrect decision based on these
|
||||
values. Its kernel based implementation expects expected_throughput always
|
||||
to have the unit [Kbps] and not sometimes [10Kbps] and sometimes [Kbps].
|
||||
|
||||
The same requirement has iw or olsrdv2's nl80211 based statistics module
|
||||
which retrieve the same data via NL80211_STA_INFO_TX_BITRATE.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 6a27b2c40b48 ("mac80211: restructure per-rate throughput calculation into function")
|
||||
Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.c
|
||||
+++ b/net/mac80211/rc80211_minstrel.c
|
||||
@@ -711,7 +711,7 @@ static u32 minstrel_get_expected_through
|
||||
* computing cur_tp
|
||||
*/
|
||||
tmp_mrs = &mi->r[idx].stats;
|
||||
- tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma);
|
||||
+ tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10;
|
||||
tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
|
||||
|
||||
return tmp_cur_tp;
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -1335,7 +1335,8 @@ static u32 minstrel_ht_get_expected_thro
|
||||
prob = mi->groups[i].rates[j].prob_ewma;
|
||||
|
||||
/* convert tp_avg from pkt per second in kbps */
|
||||
- tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * AVG_PKT_SIZE * 8 / 1024;
|
||||
+ tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10;
|
||||
+ tp_avg = tp_avg * AVG_PKT_SIZE * 8 / 1024;
|
||||
|
||||
return tp_avg;
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Sun, 7 Feb 2016 18:08:24 +0100
|
||||
Subject: [PATCH] brcmfmac: Increase nr of supported flowrings.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
New generation devices have firmware which has more than 256 flowrings.
|
||||
E.g. following debugging message comes from 14e4:4365 BCM4366:
|
||||
[ 194.606245] brcmfmac: brcmf_pcie_init_ringbuffers Nr of flowrings is 264
|
||||
|
||||
At various code places (related to flowrings) we were using u8 which
|
||||
could lead to storing wrong number or infinite loops when indexing with
|
||||
this type. This issue was quite easy to spot in brcmf_flowring_detach
|
||||
where it led to infinite loop e.g. on failed initialization.
|
||||
|
||||
This patch switches code to proper types and increases the maximum
|
||||
number of supported flowrings to 512.
|
||||
|
||||
Originally this change was sent in September 2015, but back it was
|
||||
causing a regression on BCM43602 resulting in:
|
||||
Unable to handle kernel NULL pointer dereference at virtual address ...
|
||||
|
||||
The reason for this regression was missing update (s/u8/u16) of struct
|
||||
brcmf_flowring_ring. This problem was handled in 9f64df9 ("brcmfmac: Fix
|
||||
bug in flowring management."). Starting with that it's safe to apply
|
||||
this original patch as it doesn't cause a regression anymore.
|
||||
|
||||
This patch fixes an infinite loop on BCM4366 which is supported since
|
||||
4.4 so it makes sense to apply it to stable 4.4+.
|
||||
|
||||
Cc: <stable@vger.kernel.org> # 4.4+
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
|
||||
@@ -32,7 +32,7 @@
|
||||
#define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256)
|
||||
#define BRCMF_FLOWRING_INVALID_IFIDX 0xff
|
||||
|
||||
-#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16)
|
||||
+#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] * 2 + fifo + ifidx * 16)
|
||||
#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
|
||||
|
||||
static const u8 brcmf_flowring_prio2fifo[] = {
|
||||
@@ -68,7 +68,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
|
||||
u8 prio, u8 ifidx)
|
||||
{
|
||||
struct brcmf_flowring_hash *hash;
|
||||
- u8 hash_idx;
|
||||
+ u16 hash_idx;
|
||||
u32 i;
|
||||
bool found;
|
||||
bool sta;
|
||||
@@ -88,6 +88,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
|
||||
}
|
||||
hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
|
||||
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
||||
+ hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
|
||||
found = false;
|
||||
hash = flow->hash;
|
||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||
@@ -98,6 +99,7 @@ u32 brcmf_flowring_lookup(struct brcmf_f
|
||||
break;
|
||||
}
|
||||
hash_idx++;
|
||||
+ hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
|
||||
}
|
||||
if (found)
|
||||
return hash[hash_idx].flowid;
|
||||
@@ -111,7 +113,7 @@ u32 brcmf_flowring_create(struct brcmf_f
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
struct brcmf_flowring_hash *hash;
|
||||
- u8 hash_idx;
|
||||
+ u16 hash_idx;
|
||||
u32 i;
|
||||
bool found;
|
||||
u8 fifo;
|
||||
@@ -131,6 +133,7 @@ u32 brcmf_flowring_create(struct brcmf_f
|
||||
}
|
||||
hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
|
||||
BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
|
||||
+ hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
|
||||
found = false;
|
||||
hash = flow->hash;
|
||||
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
|
||||
@@ -140,6 +143,7 @@ u32 brcmf_flowring_create(struct brcmf_f
|
||||
break;
|
||||
}
|
||||
hash_idx++;
|
||||
+ hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
|
||||
}
|
||||
if (found) {
|
||||
for (i = 0; i < flow->nrofrings; i++) {
|
||||
@@ -169,7 +173,7 @@ u32 brcmf_flowring_create(struct brcmf_f
|
||||
}
|
||||
|
||||
|
||||
-u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid)
|
||||
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
@@ -179,7 +183,7 @@ u8 brcmf_flowring_tid(struct brcmf_flowr
|
||||
}
|
||||
|
||||
|
||||
-static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
|
||||
+static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,
|
||||
bool blocked)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
@@ -228,10 +232,10 @@ static void brcmf_flowring_block(struct
|
||||
}
|
||||
|
||||
|
||||
-void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
|
||||
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
- u8 hash_idx;
|
||||
+ u16 hash_idx;
|
||||
struct sk_buff *skb;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
@@ -253,7 +257,7 @@ void brcmf_flowring_delete(struct brcmf_
|
||||
}
|
||||
|
||||
|
||||
-u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
@@ -279,7 +283,7 @@ u32 brcmf_flowring_enqueue(struct brcmf_
|
||||
}
|
||||
|
||||
|
||||
-struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid)
|
||||
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
struct sk_buff *skb;
|
||||
@@ -300,7 +304,7 @@ struct sk_buff *brcmf_flowring_dequeue(s
|
||||
}
|
||||
|
||||
|
||||
-void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
|
||||
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
@@ -311,7 +315,7 @@ void brcmf_flowring_reinsert(struct brcm
|
||||
}
|
||||
|
||||
|
||||
-u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid)
|
||||
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
@@ -326,7 +330,7 @@ u32 brcmf_flowring_qlen(struct brcmf_flo
|
||||
}
|
||||
|
||||
|
||||
-void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid)
|
||||
+void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
@@ -340,10 +344,10 @@ void brcmf_flowring_open(struct brcmf_fl
|
||||
}
|
||||
|
||||
|
||||
-u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid)
|
||||
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
- u8 hash_idx;
|
||||
+ u16 hash_idx;
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
hash_idx = ring->hash_id;
|
||||
@@ -384,7 +388,7 @@ void brcmf_flowring_detach(struct brcmf_
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_flowring_tdls_entry *search;
|
||||
struct brcmf_flowring_tdls_entry *remove;
|
||||
- u8 flowid;
|
||||
+ u16 flowid;
|
||||
|
||||
for (flowid = 0; flowid < flow->nrofrings; flowid++) {
|
||||
if (flow->rings[flowid])
|
||||
@@ -408,7 +412,7 @@ void brcmf_flowring_configure_addr_mode(
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
u32 i;
|
||||
- u8 flowid;
|
||||
+ u16 flowid;
|
||||
|
||||
if (flow->addr_mode[ifidx] != addr_mode) {
|
||||
for (i = 0; i < ARRAY_SIZE(flow->hash); i++) {
|
||||
@@ -434,7 +438,7 @@ void brcmf_flowring_delete_peer(struct b
|
||||
struct brcmf_flowring_tdls_entry *prev;
|
||||
struct brcmf_flowring_tdls_entry *search;
|
||||
u32 i;
|
||||
- u8 flowid;
|
||||
+ u16 flowid;
|
||||
bool sta;
|
||||
|
||||
sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
|
||||
@@ -16,7 +16,7 @@
|
||||
#define BRCMFMAC_FLOWRING_H
|
||||
|
||||
|
||||
-#define BRCMF_FLOWRING_HASHSIZE 256
|
||||
+#define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */
|
||||
#define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ struct brcmf_flowring_hash {
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 fifo;
|
||||
u8 ifidx;
|
||||
- u8 flowid;
|
||||
+ u16 flowid;
|
||||
};
|
||||
|
||||
enum ring_status {
|
||||
@@ -61,16 +61,16 @@ u32 brcmf_flowring_lookup(struct brcmf_f
|
||||
u8 prio, u8 ifidx);
|
||||
u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||
u8 prio, u8 ifidx);
|
||||
-void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
|
||||
-void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
|
||||
-u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
|
||||
-u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid);
|
||||
+void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid);
|
||||
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid);
|
||||
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
|
||||
struct sk_buff *skb);
|
||||
-struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
|
||||
-void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
|
||||
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid);
|
||||
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
|
||||
struct sk_buff *skb);
|
||||
-u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid);
|
||||
-u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid);
|
||||
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid);
|
||||
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid);
|
||||
struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings);
|
||||
void brcmf_flowring_detach(struct brcmf_flowring *flow);
|
||||
void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -677,7 +677,7 @@ static u32 brcmf_msgbuf_flowring_create(
|
||||
}
|
||||
|
||||
|
||||
-static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
|
||||
+static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
|
||||
{
|
||||
struct brcmf_flowring *flow = msgbuf->flow;
|
||||
struct brcmf_commonring *commonring;
|
||||
@@ -1310,7 +1310,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct
|
||||
}
|
||||
|
||||
|
||||
-void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid)
|
||||
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
|
||||
{
|
||||
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
|
||||
struct msgbuf_tx_flowring_delete_req *delete;
|
||||
@@ -1415,6 +1415,13 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
u32 count;
|
||||
|
||||
if_msgbuf = drvr->bus_if->msgbuf;
|
||||
+
|
||||
+ if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
|
||||
+ brcmf_err("driver not configured for this many flowrings %d\n",
|
||||
+ if_msgbuf->nrof_flowrings);
|
||||
+ if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
|
||||
+ }
|
||||
+
|
||||
msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL);
|
||||
if (!msgbuf)
|
||||
goto fail;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
|
||||
int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
|
||||
-void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid);
|
||||
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid);
|
||||
int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
|
||||
#else
|
||||
@@ -1,22 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Mon, 8 Feb 2016 14:24:36 +0100
|
||||
Subject: [PATCH] cfg80211: fix faulty variable initialization in
|
||||
ieee80211_amsdu_to_8023s
|
||||
|
||||
reuse_skb is set to true if the code decides to use the last segment.
|
||||
Fixes a memory leak
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -676,7 +676,7 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
u8 *payload;
|
||||
int offset = 0, remaining, err;
|
||||
struct ethhdr eth;
|
||||
- bool reuse_skb = true;
|
||||
+ bool reuse_skb = false;
|
||||
bool last = false;
|
||||
|
||||
if (has_80211_header) {
|
||||
@@ -1,132 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Mon, 8 Feb 2016 14:33:19 +0100
|
||||
Subject: [PATCH] cfg80211: reuse existing page fragments in A-MSDU rx
|
||||
|
||||
This massively reduces data copying and thus improves rx performance
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -644,23 +644,93 @@ int ieee80211_data_from_8023(struct sk_b
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_data_from_8023);
|
||||
|
||||
+static void
|
||||
+__frame_add_frag(struct sk_buff *skb, struct page *page,
|
||||
+ void *ptr, int len, int size)
|
||||
+{
|
||||
+ struct skb_shared_info *sh = skb_shinfo(skb);
|
||||
+ int page_offset;
|
||||
+
|
||||
+ atomic_inc(&page->_count);
|
||||
+ page_offset = ptr - page_address(page);
|
||||
+ skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+__ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame,
|
||||
+ int offset, int len)
|
||||
+{
|
||||
+ struct skb_shared_info *sh = skb_shinfo(skb);
|
||||
+ const skb_frag_t *frag = &sh->frags[-1];
|
||||
+ struct page *frag_page;
|
||||
+ void *frag_ptr;
|
||||
+ int frag_len, frag_size;
|
||||
+ int head_size = skb->len - skb->data_len;
|
||||
+ int cur_len;
|
||||
+
|
||||
+ frag_page = virt_to_head_page(skb->head);
|
||||
+ frag_ptr = skb->data;
|
||||
+ frag_size = head_size;
|
||||
+
|
||||
+ while (offset >= frag_size) {
|
||||
+ offset -= frag_size;
|
||||
+ frag++;
|
||||
+ frag_page = skb_frag_page(frag);
|
||||
+ frag_ptr = skb_frag_address(frag);
|
||||
+ frag_size = skb_frag_size(frag);
|
||||
+ }
|
||||
+
|
||||
+ frag_ptr += offset;
|
||||
+ frag_len = frag_size - offset;
|
||||
+
|
||||
+ cur_len = min(len, frag_len);
|
||||
+
|
||||
+ __frame_add_frag(frame, frag_page, frag_ptr, cur_len, frag_size);
|
||||
+ len -= cur_len;
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ frag++;
|
||||
+ frag_len = skb_frag_size(frag);
|
||||
+ cur_len = min(len, frag_len);
|
||||
+ __frame_add_frag(frame, skb_frag_page(frag),
|
||||
+ skb_frag_address(frag), cur_len, frag_len);
|
||||
+ len -= cur_len;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static struct sk_buff *
|
||||
__ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
|
||||
- int offset, int len)
|
||||
+ int offset, int len, bool reuse_frag)
|
||||
{
|
||||
struct sk_buff *frame;
|
||||
+ int cur_len = len;
|
||||
|
||||
if (skb->len - offset < len)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
+ * When reusing framents, copy some data to the head to simplify
|
||||
+ * ethernet header handling and speed up protocol header processing
|
||||
+ * in the stack later.
|
||||
+ */
|
||||
+ if (reuse_frag)
|
||||
+ cur_len = min_t(int, len, 32);
|
||||
+
|
||||
+ /*
|
||||
* Allocate and reserve two bytes more for payload
|
||||
* alignment since sizeof(struct ethhdr) is 14.
|
||||
*/
|
||||
- frame = dev_alloc_skb(hlen + sizeof(struct ethhdr) + 2 + len);
|
||||
+ frame = dev_alloc_skb(hlen + sizeof(struct ethhdr) + 2 + cur_len);
|
||||
|
||||
skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
|
||||
- skb_copy_bits(skb, offset, skb_put(frame, len), len);
|
||||
+ skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len);
|
||||
+
|
||||
+ len -= cur_len;
|
||||
+ if (!len)
|
||||
+ return frame;
|
||||
+
|
||||
+ offset += cur_len;
|
||||
+ __ieee80211_amsdu_copy_frag(skb, frame, offset, len);
|
||||
|
||||
return frame;
|
||||
}
|
||||
@@ -676,6 +746,7 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
u8 *payload;
|
||||
int offset = 0, remaining, err;
|
||||
struct ethhdr eth;
|
||||
+ bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
|
||||
bool reuse_skb = false;
|
||||
bool last = false;
|
||||
|
||||
@@ -703,12 +774,13 @@ void ieee80211_amsdu_to_8023s(struct sk_
|
||||
offset += sizeof(struct ethhdr);
|
||||
/* reuse skb for the last subframe */
|
||||
last = remaining <= subframe_len + padding;
|
||||
- if (!skb_is_nonlinear(skb) && last) {
|
||||
+ if (!skb_is_nonlinear(skb) && !reuse_frag && last) {
|
||||
skb_pull(skb, offset);
|
||||
frame = skb;
|
||||
reuse_skb = true;
|
||||
} else {
|
||||
- frame = __ieee80211_amsdu_copy(skb, hlen, offset, len);
|
||||
+ frame = __ieee80211_amsdu_copy(skb, hlen, offset, len,
|
||||
+ reuse_frag);
|
||||
if (!frame)
|
||||
goto purge;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
Date: Wed, 10 Feb 2016 16:08:17 +0100
|
||||
Subject: [PATCH] mac80211: fix wiphy supported_band access
|
||||
|
||||
Fix wiphy supported_band access in tx radiotap parsing. In particular,
|
||||
info->band is always set to 0 (IEEE80211_BAND_2GHZ) since it has not
|
||||
assigned yet. This cause a kernel crash on 5GHz only devices.
|
||||
Move ieee80211_parse_tx_radiotap() after info->band assignment
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1890,10 +1890,6 @@ netdev_tx_t ieee80211_monitor_start_xmit
|
||||
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_CTL_INJECTED;
|
||||
|
||||
- /* process and remove the injection radiotap header */
|
||||
- if (!ieee80211_parse_tx_radiotap(local, skb))
|
||||
- goto fail;
|
||||
-
|
||||
rcu_read_lock();
|
||||
|
||||
/*
|
||||
@@ -1955,6 +1951,10 @@ netdev_tx_t ieee80211_monitor_start_xmit
|
||||
goto fail_rcu;
|
||||
|
||||
info->band = chandef->chan->band;
|
||||
+ /* process and remove the injection radiotap header */
|
||||
+ if (!ieee80211_parse_tx_radiotap(local, skb))
|
||||
+ goto fail_rcu;
|
||||
+
|
||||
ieee80211_xmit(sdata, NULL, skb);
|
||||
rcu_read_unlock();
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 18 Feb 2016 19:30:05 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: set A-MSDU tx limits based on selected
|
||||
max_prob_rate
|
||||
|
||||
Prevents excessive A-MSDU aggregation at low data rates or bad
|
||||
conditions.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -883,6 +883,39 @@ minstrel_ht_set_rate(struct minstrel_pri
|
||||
ratetbl->rate[offset].flags = flags;
|
||||
}
|
||||
|
||||
+static int
|
||||
+minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi)
|
||||
+{
|
||||
+ int group = mi->max_prob_rate / MCS_GROUP_RATES;
|
||||
+ const struct mcs_group *g = &minstrel_mcs_groups[group];
|
||||
+ int rate = mi->max_prob_rate % MCS_GROUP_RATES;
|
||||
+
|
||||
+ /* Disable A-MSDU if max_prob_rate is bad */
|
||||
+ if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
|
||||
+ return 1;
|
||||
+
|
||||
+ /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
|
||||
+ if (g->duration[rate] > MCS_DURATION(1, 0, 52))
|
||||
+ return 500;
|
||||
+
|
||||
+ /*
|
||||
+ * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
|
||||
+ * data packet size
|
||||
+ */
|
||||
+ if (g->duration[rate] > MCS_DURATION(1, 0, 104))
|
||||
+ return 1500;
|
||||
+
|
||||
+ /*
|
||||
+ * If the rate is slower than single-stream MCS7, limit A-MSDU to twice
|
||||
+ * the usual data packet size
|
||||
+ */
|
||||
+ if (g->duration[rate] > MCS_DURATION(1, 0, 260))
|
||||
+ return 3000;
|
||||
+
|
||||
+ /* unlimited */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
|
||||
{
|
||||
@@ -907,6 +940,7 @@ minstrel_ht_update_rates(struct minstrel
|
||||
minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
|
||||
}
|
||||
|
||||
+ mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi);
|
||||
rates->rate[i].idx = -1;
|
||||
rate_control_set_rates(mp->hw, mi->sta, rates);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 18 Feb 2016 19:45:33 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: set default tx aggregation timeout to
|
||||
0
|
||||
|
||||
The value 5000 was put here with the addition of the timeout field to
|
||||
ieee80211_start_tx_ba_session. It was originally added in mac80211 to
|
||||
save resources for drivers like iwlwifi, which only supports a limited
|
||||
number of concurrent aggregation sessions.
|
||||
|
||||
Since iwlwifi does not use minstrel_ht and other drivers don't need
|
||||
this, 0 is a better default - especially since there have been
|
||||
recent reports of aggregation setup related issues reproduced with
|
||||
ath9k. This should improve stability without causing any adverse
|
||||
effects.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -692,7 +692,7 @@ minstrel_aggr_check(struct ieee80211_sta
|
||||
if (likely(sta->ampdu_mlme.tid_tx[tid]))
|
||||
return;
|
||||
|
||||
- ieee80211_start_tx_ba_session(pubsta, tid, 5000);
|
||||
+ ieee80211_start_tx_ba_session(pubsta, tid, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1,26 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Wed, 24 Feb 2016 12:03:13 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: fix a logic error in RTS/CTS handling
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RTS/CTS needs to be enabled if the rate is a fallback rate *or* if it's
|
||||
a dual-stream rate and the sta is in dynamic SMPS mode.
|
||||
|
||||
Fixes: a3ebb4e1b763 ("mac80211: minstrel_ht: handle peers in dynamic SMPS")
|
||||
Reported-by: Matías Richart <mrichart@fing.edu.uy>
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -872,7 +872,7 @@ minstrel_ht_set_rate(struct minstrel_pri
|
||||
* - if station is in dynamic SMPS (and streams > 1)
|
||||
* - for fallback rates, to increase chances of getting through
|
||||
*/
|
||||
- if (offset > 0 &&
|
||||
+ if (offset > 0 ||
|
||||
(mi->sta->smps_mode == IEEE80211_SMPS_DYNAMIC &&
|
||||
group->streams > 1)) {
|
||||
ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
|
||||
@@ -1,35 +0,0 @@
|
||||
From: Jouni Malinen <jouni@qca.qualcomm.com>
|
||||
Date: Tue, 1 Mar 2016 00:29:00 +0200
|
||||
Subject: [PATCH] mac80211: Fix Public Action frame RX in AP mode
|
||||
|
||||
Public Action frames use special rules for how the BSSID field (Address
|
||||
3) is set. A wildcard BSSID is used in cases where the transmitter and
|
||||
recipient are not members of the same BSS. As such, we need to accept
|
||||
Public Action frames with wildcard BSSID.
|
||||
|
||||
Commit db8e17324553 ("mac80211: ignore frames between TDLS peers when
|
||||
operating as AP") added a rule that drops Action frames to TDLS-peers
|
||||
based on an Action frame having different DA (Address 1) and BSSID
|
||||
(Address 3) values. This is not correct since it misses the possibility
|
||||
of BSSID being a wildcard BSSID in which case the Address 1 would not
|
||||
necessarily match.
|
||||
|
||||
Fix this by allowing mac80211 to accept wildcard BSSID in an Action
|
||||
frame when in AP mode.
|
||||
|
||||
Fixes: db8e17324553 ("mac80211: ignore frames between TDLS peers when operating as AP")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -3374,6 +3374,7 @@ static bool ieee80211_accept_frame(struc
|
||||
return false;
|
||||
/* ignore action frames to TDLS-peers */
|
||||
if (ieee80211_is_action(hdr->frame_control) &&
|
||||
+ !is_broadcast_ether_addr(bssid) &&
|
||||
!ether_addr_equal(bssid, hdr->addr1))
|
||||
return false;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
Date: Fri, 19 Feb 2016 11:43:04 +0100
|
||||
Subject: [PATCH] cfg80211: add radiotap VHT info to rtap_namespace_sizes
|
||||
|
||||
Add IEEE80211_RADIOTAP_VHT entry to rtap_namespace_sizes array in order to
|
||||
define alignment and size of VHT info in tx radiotap
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/radiotap.c
|
||||
+++ b/net/wireless/radiotap.c
|
||||
@@ -43,6 +43,7 @@ static const struct radiotap_align_size
|
||||
[IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
|
||||
[IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
|
||||
[IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, },
|
||||
+ [IEEE80211_RADIOTAP_VHT] = { .align = 2, .size = 12, },
|
||||
/*
|
||||
* add more here as they are defined in radiotap.h
|
||||
*/
|
||||
@@ -1,36 +0,0 @@
|
||||
From: Sven Eckelmann <sven@narfation.org>
|
||||
Date: Wed, 24 Feb 2016 16:25:49 +0100
|
||||
Subject: [PATCH] mac80211: fix parsing of 40Mhz in injected radiotap
|
||||
header
|
||||
|
||||
The MCS bandwidth part of the radiotap header is 2 bits wide. The full 2
|
||||
bit have to compared against IEEE80211_RADIOTAP_MCS_BW_40 and not only if
|
||||
the first bit is set. Otherwise IEEE80211_RADIOTAP_MCS_BW_40 can be
|
||||
confused with IEEE80211_RADIOTAP_MCS_BW_20U.
|
||||
|
||||
Fixes: 5ec3aed9ba4c ("mac80211: Parse legacy and HT rate in injected frames")
|
||||
Signed-off-by: Sven Eckelmann <sven@narfation.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1689,7 +1689,7 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
bool rate_found = false;
|
||||
u8 rate_retries = 0;
|
||||
u16 rate_flags = 0;
|
||||
- u8 mcs_known, mcs_flags;
|
||||
+ u8 mcs_known, mcs_flags, mcs_bw;
|
||||
int i;
|
||||
|
||||
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
@@ -1765,8 +1765,9 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
|
||||
rate_flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||
|
||||
+ mcs_bw = mcs_flags & IEEE80211_RADIOTAP_MCS_BW_MASK;
|
||||
if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
|
||||
- mcs_flags & IEEE80211_RADIOTAP_MCS_BW_40)
|
||||
+ mcs_bw == IEEE80211_RADIOTAP_MCS_BW_40)
|
||||
rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
break;
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
Date: Tue, 23 Feb 2016 15:43:35 +0100
|
||||
Subject: [PATCH] mac80211: parse VHT info in injected frames
|
||||
|
||||
Add VHT radiotap parsing support to ieee80211_parse_tx_radiotap().
|
||||
That capability has been tested using a d-link dir-860l rev b1 running
|
||||
OpenWrt trunk and mt76 driver
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1690,6 +1690,8 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
u8 rate_retries = 0;
|
||||
u16 rate_flags = 0;
|
||||
u8 mcs_known, mcs_flags, mcs_bw;
|
||||
+ u16 vht_known;
|
||||
+ u8 vht_mcs = 0, vht_nss = 0;
|
||||
int i;
|
||||
|
||||
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
@@ -1771,6 +1773,32 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
break;
|
||||
|
||||
+ case IEEE80211_RADIOTAP_VHT:
|
||||
+ vht_known = get_unaligned_le16(iterator.this_arg);
|
||||
+ rate_found = true;
|
||||
+
|
||||
+ rate_flags = IEEE80211_TX_RC_VHT_MCS;
|
||||
+ if ((vht_known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) &&
|
||||
+ (iterator.this_arg[2] &
|
||||
+ IEEE80211_RADIOTAP_VHT_FLAG_SGI))
|
||||
+ rate_flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||
+ if (vht_known &
|
||||
+ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) {
|
||||
+ if (iterator.this_arg[3] == 1)
|
||||
+ rate_flags |=
|
||||
+ IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
+ else if (iterator.this_arg[3] == 4)
|
||||
+ rate_flags |=
|
||||
+ IEEE80211_TX_RC_80_MHZ_WIDTH;
|
||||
+ else if (iterator.this_arg[3] == 11)
|
||||
+ rate_flags |=
|
||||
+ IEEE80211_TX_RC_160_MHZ_WIDTH;
|
||||
+ }
|
||||
+
|
||||
+ vht_mcs = iterator.this_arg[4] >> 4;
|
||||
+ vht_nss = iterator.this_arg[4] & 0xF;
|
||||
+ break;
|
||||
+
|
||||
/*
|
||||
* Please update the file
|
||||
* Documentation/networking/mac80211-injection.txt
|
||||
@@ -1796,6 +1824,9 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
|
||||
if (rate_flags & IEEE80211_TX_RC_MCS) {
|
||||
info->control.rates[0].idx = rate;
|
||||
+ } else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
|
||||
+ ieee80211_rate_set_vht(info->control.rates, vht_mcs,
|
||||
+ vht_nss);
|
||||
} else {
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (rate * 5 != sband->bitrates[i].bitrate)
|
||||
@@ -1,23 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Wed, 2 Mar 2016 15:51:40 +0100
|
||||
Subject: [PATCH] mac80211: do not pass injected frames without a valid rate to
|
||||
the driver
|
||||
|
||||
Fall back to rate control if the requested bitrate was not found.
|
||||
|
||||
Fixes: dfdfc2beb0dd ("mac80211: Parse legacy and HT rate in injected frames")
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1837,6 +1837,9 @@ static bool ieee80211_parse_tx_radiotap(
|
||||
}
|
||||
}
|
||||
|
||||
+ if (info->control.rates[0].idx < 0)
|
||||
+ info->control.flags &= ~IEEE80211_TX_CTRL_RATE_INJECT;
|
||||
+
|
||||
info->control.rates[0].flags = rate_flags;
|
||||
info->control.rates[0].count = min_t(u8, rate_retries + 1,
|
||||
local->hw.max_rate_tries);
|
||||
@@ -1,77 +0,0 @@
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 3 Mar 2016 23:20:06 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: improve sample rate skip logic
|
||||
|
||||
There were a few issues that were slowing down the process of finding
|
||||
the optimal rate, especially on devices with multi-rate retry
|
||||
limitations:
|
||||
|
||||
When max_tp_rate[0] was slower than max_tp_rate[1], the code did not
|
||||
sample max_tp_rate[1], which would often allow it to switch places with
|
||||
max_tp_rate[0] (e.g. if only the first sampling attempts were bad, but the
|
||||
rate is otherwise good).
|
||||
|
||||
Also, sample attempts of rates between max_tp_rate[0] and [1] were being
|
||||
ignored in this case, because the code only checked if the rate was
|
||||
slower than [1].
|
||||
|
||||
Fix this by checking against the fastest / second fastest max_tp_rate
|
||||
instead of assuming a specific order between the two.
|
||||
|
||||
In my tests this patch significantly reduces the time until minstrel_ht
|
||||
finds the optimal rate right after assoc
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -958,6 +958,7 @@ minstrel_get_sample_rate(struct minstrel
|
||||
struct minstrel_rate_stats *mrs;
|
||||
struct minstrel_mcs_group_data *mg;
|
||||
unsigned int sample_dur, sample_group, cur_max_tp_streams;
|
||||
+ int tp_rate1, tp_rate2;
|
||||
int sample_idx = 0;
|
||||
|
||||
if (mi->sample_wait > 0) {
|
||||
@@ -979,14 +980,22 @@ minstrel_get_sample_rate(struct minstrel
|
||||
mrs = &mg->rates[sample_idx];
|
||||
sample_idx += sample_group * MCS_GROUP_RATES;
|
||||
|
||||
+ /* Set tp_rate1, tp_rate2 to the highest / second highest max_tp_rate */
|
||||
+ if (minstrel_get_duration(mi->max_tp_rate[0]) >
|
||||
+ minstrel_get_duration(mi->max_tp_rate[1])) {
|
||||
+ tp_rate1 = mi->max_tp_rate[1];
|
||||
+ tp_rate2 = mi->max_tp_rate[0];
|
||||
+ } else {
|
||||
+ tp_rate1 = mi->max_tp_rate[0];
|
||||
+ tp_rate2 = mi->max_tp_rate[1];
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Sampling might add some overhead (RTS, no aggregation)
|
||||
- * to the frame. Hence, don't use sampling for the currently
|
||||
- * used rates.
|
||||
+ * to the frame. Hence, don't use sampling for the highest currently
|
||||
+ * used highest throughput or probability rate.
|
||||
*/
|
||||
- if (sample_idx == mi->max_tp_rate[0] ||
|
||||
- sample_idx == mi->max_tp_rate[1] ||
|
||||
- sample_idx == mi->max_prob_rate)
|
||||
+ if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@@ -1001,10 +1010,10 @@ minstrel_get_sample_rate(struct minstrel
|
||||
* if the link is working perfectly.
|
||||
*/
|
||||
|
||||
- cur_max_tp_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
|
||||
+ cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
|
||||
MCS_GROUP_RATES].streams;
|
||||
sample_dur = minstrel_get_duration(sample_idx);
|
||||
- if (sample_dur >= minstrel_get_duration(mi->max_tp_rate[1]) &&
|
||||
+ if (sample_dur >= minstrel_get_duration(tp_rate2) &&
|
||||
(cur_max_tp_streams - 1 <
|
||||
minstrel_mcs_groups[sample_group].streams ||
|
||||
sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
|
||||
@@ -1,73 +0,0 @@
|
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Wed, 17 Feb 2016 11:26:57 +0100
|
||||
Subject: [PATCH] brcmfmac: use device memsize config from fw if defined
|
||||
|
||||
Newer type pcie devices have memory which get shared between fw and
|
||||
hw. The division of this memory is done firmware compile time. As a
|
||||
result the ramsize as used by driver needs to be adjusted for this.
|
||||
This is done by reading the memory size from the firmware.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
@@ -207,6 +207,10 @@ static struct brcmf_firmware_mapping brc
|
||||
#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4
|
||||
#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3
|
||||
|
||||
+/* Magic number at a magic location to find RAM size */
|
||||
+#define BRCMF_RAMSIZE_MAGIC 0x534d4152 /* SMAR */
|
||||
+#define BRCMF_RAMSIZE_OFFSET 0x6c
|
||||
+
|
||||
|
||||
struct brcmf_pcie_console {
|
||||
u32 base_addr;
|
||||
@@ -1412,6 +1416,28 @@ static const struct brcmf_bus_ops brcmf_
|
||||
};
|
||||
|
||||
|
||||
+static void
|
||||
+brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,
|
||||
+ u32 data_len)
|
||||
+{
|
||||
+ __le32 *field;
|
||||
+ u32 newsize;
|
||||
+
|
||||
+ if (data_len < BRCMF_RAMSIZE_OFFSET + 8)
|
||||
+ return;
|
||||
+
|
||||
+ field = (__le32 *)&data[BRCMF_RAMSIZE_OFFSET];
|
||||
+ if (le32_to_cpup(field) != BRCMF_RAMSIZE_MAGIC)
|
||||
+ return;
|
||||
+ field++;
|
||||
+ newsize = le32_to_cpup(field);
|
||||
+
|
||||
+ brcmf_dbg(PCIE, "Found ramsize info in FW, adjusting to 0x%x\n",
|
||||
+ newsize);
|
||||
+ devinfo->ci->ramsize = newsize;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int
|
||||
brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
|
||||
u32 sharedram_addr)
|
||||
@@ -1694,6 +1720,13 @@ static void brcmf_pcie_setup(struct devi
|
||||
|
||||
brcmf_pcie_attach(devinfo);
|
||||
|
||||
+ /* Some of the firmwares have the size of the memory of the device
|
||||
+ * defined inside the firmware. This is because part of the memory in
|
||||
+ * the device is shared and the devision is determined by FW. Parse
|
||||
+ * the firmware and adjust the chip memory size now.
|
||||
+ */
|
||||
+ brcmf_pcie_adjust_ramsize(devinfo, (u8 *)fw->data, fw->size);
|
||||
+
|
||||
ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);
|
||||
if (ret)
|
||||
goto fail;
|
||||
@@ -1,58 +0,0 @@
|
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Wed, 17 Feb 2016 11:26:58 +0100
|
||||
Subject: [PATCH] brcmfmac: use bar1 window size as provided by pci subsystem
|
||||
|
||||
The PCIE bar1 window size is specified by chip. Currently the
|
||||
ioremap of bar1 was using a define which always matched the size
|
||||
of bar1, but newer chips can have a different bar1 sizes. With
|
||||
this patch the ioremap will be called with the by chip provided
|
||||
window size.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
@@ -72,7 +72,6 @@ static struct brcmf_firmware_mapping brc
|
||||
|
||||
#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */
|
||||
|
||||
-#define BRCMF_PCIE_TCM_MAP_SIZE (4096 * 1024)
|
||||
#define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024)
|
||||
|
||||
/* backplane addres space accessed by BAR0 */
|
||||
@@ -252,7 +251,6 @@ struct brcmf_pciedev_info {
|
||||
char nvram_name[BRCMF_FW_NAME_LEN];
|
||||
void __iomem *regs;
|
||||
void __iomem *tcm;
|
||||
- u32 tcm_size;
|
||||
u32 ram_base;
|
||||
u32 ram_size;
|
||||
struct brcmf_chip *ci;
|
||||
@@ -1592,8 +1590,7 @@ static int brcmf_pcie_get_resource(struc
|
||||
}
|
||||
|
||||
devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);
|
||||
- devinfo->tcm = ioremap_nocache(bar1_addr, BRCMF_PCIE_TCM_MAP_SIZE);
|
||||
- devinfo->tcm_size = BRCMF_PCIE_TCM_MAP_SIZE;
|
||||
+ devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size);
|
||||
|
||||
if (!devinfo->regs || !devinfo->tcm) {
|
||||
brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs,
|
||||
@@ -1602,8 +1599,9 @@ static int brcmf_pcie_get_resource(struc
|
||||
}
|
||||
brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",
|
||||
devinfo->regs, (unsigned long long)bar0_addr);
|
||||
- brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx\n",
|
||||
- devinfo->tcm, (unsigned long long)bar1_addr);
|
||||
+ brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx size 0x%x\n",
|
||||
+ devinfo->tcm, (unsigned long long)bar1_addr,
|
||||
+ (unsigned int)bar1_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Wed, 17 Feb 2016 11:26:59 +0100
|
||||
Subject: [PATCH] brcmfmac: add support for the PCIE 4366c0 chip
|
||||
|
||||
A newer version of the 4366 PCIE chip has been released. Add
|
||||
support for this version of the chip.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
@@ -53,6 +53,7 @@ BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-p
|
||||
BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt");
|
||||
BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt");
|
||||
BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt");
|
||||
+BRCMF_FW_NVRAM_DEF(4366C, "brcmfmac4366c-pcie.bin", "brcmfmac4366c-pcie.txt");
|
||||
BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt");
|
||||
|
||||
static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
@@ -66,7 +67,8 @@ static struct brcmf_firmware_mapping brc
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B),
|
||||
- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFFF, 4366B),
|
||||
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
|
||||
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Wed, 17 Feb 2016 11:27:01 +0100
|
||||
Subject: [PATCH] brcmfmac: increase timeout for tx eapol
|
||||
|
||||
When keys get set and updated this has to happen after eapol got
|
||||
transmitted (without key or old key) before the key can be updated.
|
||||
To make sure the order of sending eapol and configuring key is done
|
||||
correctly a timeout for tx of eapol is applied. This timeout is set
|
||||
to 50 msec, which is not always enough. Especially in AP mode and
|
||||
key updates the timeout may need to be much longer because client(s)
|
||||
can be in powersave. Increase the timeout from 50 to 950 msec.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -40,7 +40,7 @@ MODULE_AUTHOR("Broadcom Corporation");
|
||||
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
-#define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(50)
|
||||
+#define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
|
||||
|
||||
/* AMPDU rx reordering definitions */
|
||||
#define BRCMF_RXREORDER_FLOWID_OFFSET 0
|
||||
@@ -1,114 +0,0 @@
|
||||
From: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:23 +0200
|
||||
Subject: [PATCH] brcmfmac: insert default boardrev in nvram data if
|
||||
missing
|
||||
|
||||
Some nvram files/stores come without the boardrev information,
|
||||
but firmware requires this to be set. When not found in nvram then
|
||||
add a default boardrev string to the nvram data.
|
||||
|
||||
Reported-by: Rafal Milecki <zajec5@gmail.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <franky.lin@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
|
||||
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||
+#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
|
||||
|
||||
enum nvram_parser_state {
|
||||
IDLE,
|
||||
@@ -51,6 +52,7 @@ enum nvram_parser_state {
|
||||
* @entry: start position of key,value entry.
|
||||
* @multi_dev_v1: detect pcie multi device v1 (compressed).
|
||||
* @multi_dev_v2: detect pcie multi device v2.
|
||||
+ * @boardrev_found: nvram contains boardrev information.
|
||||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
@@ -63,6 +65,7 @@ struct nvram_parser {
|
||||
u32 entry;
|
||||
bool multi_dev_v1;
|
||||
bool multi_dev_v2;
|
||||
+ bool boardrev_found;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,6 +128,8 @@ static enum nvram_parser_state brcmf_nvr
|
||||
nvp->multi_dev_v1 = true;
|
||||
if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
|
||||
nvp->multi_dev_v2 = true;
|
||||
+ if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
|
||||
+ nvp->boardrev_found = true;
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
nvp->line, nvp->column);
|
||||
@@ -284,6 +289,8 @@ static void brcmf_fw_strip_multi_v1(stru
|
||||
while (i < nvp->nvram_len) {
|
||||
if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
|
||||
i += 2;
|
||||
+ if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
|
||||
+ nvp->boardrev_found = true;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
@@ -335,6 +342,8 @@ static void brcmf_fw_strip_multi_v2(stru
|
||||
while (i < nvp->nvram_len - len) {
|
||||
if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
|
||||
i += len;
|
||||
+ if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
|
||||
+ nvp->boardrev_found = true;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
@@ -356,6 +365,18 @@ fail:
|
||||
nvp->nvram_len = 0;
|
||||
}
|
||||
|
||||
+static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
|
||||
+{
|
||||
+ if (nvp->boardrev_found)
|
||||
+ return;
|
||||
+
|
||||
+ memcpy(&nvp->nvram[nvp->nvram_len], &BRCMF_FW_DEFAULT_BOARDREV,
|
||||
+ strlen(BRCMF_FW_DEFAULT_BOARDREV));
|
||||
+ nvp->nvram_len += strlen(BRCMF_FW_DEFAULT_BOARDREV);
|
||||
+ nvp->nvram[nvp->nvram_len] = '\0';
|
||||
+ nvp->nvram_len++;
|
||||
+}
|
||||
+
|
||||
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
|
||||
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
|
||||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
@@ -377,16 +398,21 @@ static void *brcmf_fw_nvram_strip(const
|
||||
if (nvp.state == END)
|
||||
break;
|
||||
}
|
||||
- if (nvp.multi_dev_v1)
|
||||
+ if (nvp.multi_dev_v1) {
|
||||
+ nvp.boardrev_found = false;
|
||||
brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
|
||||
- else if (nvp.multi_dev_v2)
|
||||
+ } else if (nvp.multi_dev_v2) {
|
||||
+ nvp.boardrev_found = false;
|
||||
brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
|
||||
+ }
|
||||
|
||||
if (nvp.nvram_len == 0) {
|
||||
kfree(nvp.nvram);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ brcmf_fw_add_defaults(&nvp);
|
||||
+
|
||||
pad = nvp.nvram_len;
|
||||
*new_length = roundup(nvp.nvram_len + 1, 4);
|
||||
while (pad != *new_length) {
|
||||
@@ -1,30 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/Makefile
|
||||
+++ b/drivers/net/wireless/ath/Makefile
|
||||
@@ -13,10 +13,10 @@ ath-objs := main.o \
|
||||
regd.o \
|
||||
hw.o \
|
||||
key.o \
|
||||
+ debug.o \
|
||||
dfs_pattern_detector.o \
|
||||
dfs_pri_detector.o
|
||||
|
||||
-ath-$(CPTCFG_ATH_DEBUG) += debug.o
|
||||
ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
--- a/drivers/net/wireless/ath/ath.h
|
||||
+++ b/drivers/net/wireless/ath/ath.h
|
||||
@@ -318,13 +318,6 @@ void _ath_dbg(struct ath_common *common,
|
||||
#endif /* CPTCFG_ATH_DEBUG */
|
||||
|
||||
/** Returns string describing opmode, or NULL if unknown mode. */
|
||||
-#ifdef CPTCFG_ATH_DEBUG
|
||||
const char *ath_opmode_to_string(enum nl80211_iftype opmode);
|
||||
-#else
|
||||
-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
|
||||
-{
|
||||
- return "UNKNOWN";
|
||||
-}
|
||||
-#endif
|
||||
|
||||
#endif /* ATH_H */
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -45,7 +45,7 @@ int ath9k_modparam_nohwcrypt;
|
||||
module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
|
||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
|
||||
|
||||
-int ath9k_led_blink;
|
||||
+int ath9k_led_blink = 1;
|
||||
module_param_named(blink, ath9k_led_blink, int, 0444);
|
||||
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/regd.c
|
||||
+++ b/drivers/net/wireless/ath/regd.c
|
||||
@@ -341,6 +341,10 @@ ath_reg_apply_beaconing_flags(struct wip
|
||||
struct ieee80211_channel *ch;
|
||||
unsigned int i;
|
||||
|
||||
+#ifdef CPTCFG_ATH_USER_REGD
|
||||
+ return;
|
||||
+#endif
|
||||
+
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!wiphy->bands[band])
|
||||
continue;
|
||||
@@ -374,6 +378,10 @@ ath_reg_apply_ir_flags(struct wiphy *wip
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
+#ifdef CPTCFG_ATH_USER_REGD
|
||||
+ return;
|
||||
+#endif
|
||||
+
|
||||
sband = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
if (!sband)
|
||||
return;
|
||||
@@ -402,6 +410,10 @@ static void ath_reg_apply_radar_flags(st
|
||||
struct ieee80211_channel *ch;
|
||||
unsigned int i;
|
||||
|
||||
+#ifdef CPTCFG_ATH_USER_REGD
|
||||
+ return;
|
||||
+#endif
|
||||
+
|
||||
if (!wiphy->bands[IEEE80211_BAND_5GHZ])
|
||||
return;
|
||||
|
||||
@@ -633,6 +645,11 @@ ath_regd_init_wiphy(struct ath_regulator
|
||||
const struct ieee80211_regdomain *regd;
|
||||
|
||||
wiphy->reg_notifier = reg_notifier;
|
||||
+
|
||||
+#ifdef CPTCFG_ATH_USER_REGD
|
||||
+ return 0;
|
||||
+#endif
|
||||
+
|
||||
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
|
||||
REGULATORY_CUSTOM_REG;
|
||||
|
||||
--- a/drivers/net/wireless/ath/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/Kconfig
|
||||
@@ -23,6 +23,9 @@ config WLAN_VENDOR_ATH
|
||||
|
||||
if WLAN_VENDOR_ATH
|
||||
|
||||
+config ATH_USER_REGD
|
||||
+ bool "Do not enforce EEPROM regulatory restrictions"
|
||||
+
|
||||
config ATH_DEBUG
|
||||
bool "Atheros wireless debugging"
|
||||
---help---
|
||||
--- a/.local-symbols
|
||||
+++ b/.local-symbols
|
||||
@@ -125,6 +125,7 @@ ADM8211=
|
||||
ATH_COMMON=
|
||||
WLAN_VENDOR_ATH=
|
||||
ATH_DEBUG=
|
||||
+ATH_USER_REGD=
|
||||
ATH_TRACEPOINTS=
|
||||
ATH_REG_DYNAMIC_USER_REG_HINTS=
|
||||
ATH_REG_DYNAMIC_USER_CERT_TESTING=
|
||||
@@ -1,84 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/regd.c
|
||||
+++ b/drivers/net/wireless/ath/regd.c
|
||||
@@ -43,7 +43,8 @@ static int __ath_regd_init(struct ath_re
|
||||
NL80211_RRF_NO_OFDM)
|
||||
|
||||
/* We allow IBSS on these on a case by case basis by regulatory domain */
|
||||
-#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
|
||||
+#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
|
||||
+ REG_RULE(5260-10, 5350+10, 80, 0, 30,\
|
||||
NL80211_RRF_NO_IR)
|
||||
#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
|
||||
NL80211_RRF_NO_IR)
|
||||
@@ -61,57 +62,56 @@ static int __ath_regd_init(struct ath_re
|
||||
#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
|
||||
ATH9K_5GHZ_5725_5850
|
||||
|
||||
+#define REGD_RULES(...) \
|
||||
+ .reg_rules = { __VA_ARGS__ }, \
|
||||
+ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ }))
|
||||
+
|
||||
/* Can be used for:
|
||||
* 0x60, 0x61, 0x62 */
|
||||
static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
|
||||
- .n_reg_rules = 5,
|
||||
.alpha2 = "99",
|
||||
- .reg_rules = {
|
||||
+ REGD_RULES(
|
||||
ATH9K_2GHZ_ALL,
|
||||
ATH9K_5GHZ_ALL,
|
||||
- }
|
||||
+ )
|
||||
};
|
||||
|
||||
/* Can be used by 0x63 and 0x65 */
|
||||
static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
|
||||
- .n_reg_rules = 4,
|
||||
.alpha2 = "99",
|
||||
- .reg_rules = {
|
||||
+ REGD_RULES(
|
||||
ATH9K_2GHZ_CH01_11,
|
||||
ATH9K_2GHZ_CH12_13,
|
||||
ATH9K_5GHZ_NO_MIDBAND,
|
||||
- }
|
||||
+ )
|
||||
};
|
||||
|
||||
/* Can be used by 0x64 only */
|
||||
static const struct ieee80211_regdomain ath_world_regdom_64 = {
|
||||
- .n_reg_rules = 3,
|
||||
.alpha2 = "99",
|
||||
- .reg_rules = {
|
||||
+ REGD_RULES(
|
||||
ATH9K_2GHZ_CH01_11,
|
||||
ATH9K_5GHZ_NO_MIDBAND,
|
||||
- }
|
||||
+ )
|
||||
};
|
||||
|
||||
/* Can be used by 0x66 and 0x69 */
|
||||
static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
|
||||
- .n_reg_rules = 3,
|
||||
.alpha2 = "99",
|
||||
- .reg_rules = {
|
||||
+ REGD_RULES(
|
||||
ATH9K_2GHZ_CH01_11,
|
||||
ATH9K_5GHZ_ALL,
|
||||
- }
|
||||
+ )
|
||||
};
|
||||
|
||||
/* Can be used by 0x67, 0x68, 0x6A and 0x6C */
|
||||
static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
|
||||
- .n_reg_rules = 4,
|
||||
.alpha2 = "99",
|
||||
- .reg_rules = {
|
||||
+ REGD_RULES(
|
||||
ATH9K_2GHZ_CH01_11,
|
||||
ATH9K_2GHZ_CH12_13,
|
||||
ATH9K_5GHZ_ALL,
|
||||
- }
|
||||
+ )
|
||||
};
|
||||
|
||||
static bool dynamic_country_user_possible(struct ath_regulatory *reg)
|
||||
@@ -1,19 +0,0 @@
|
||||
--- a/net/wireless/reg.c
|
||||
+++ b/net/wireless/reg.c
|
||||
@@ -2411,6 +2411,8 @@ void regulatory_hint_country_ie(struct w
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request = NULL, *lr;
|
||||
|
||||
+ return;
|
||||
+
|
||||
/* IE len must be evenly divisible by 2 */
|
||||
if (country_ie_len & 0x01)
|
||||
return;
|
||||
@@ -2617,6 +2619,7 @@ static void restore_regulatory_settings(
|
||||
|
||||
void regulatory_hint_disconnect(void)
|
||||
{
|
||||
+ return;
|
||||
pr_debug("All devices are disconnected, going to restore regulatory settings\n");
|
||||
restore_regulatory_settings(false);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/regd_common.h
|
||||
+++ b/drivers/net/wireless/ath/regd_common.h
|
||||
@@ -32,6 +32,7 @@ enum EnumRd {
|
||||
FCC2_WORLD = 0x21,
|
||||
FCC2_ETSIC = 0x22,
|
||||
FCC6_WORLD = 0x23,
|
||||
+ FCC3_FCCA_2 = 0x2A,
|
||||
FRANCE_RES = 0x31,
|
||||
FCC3_FCCA = 0x3A,
|
||||
FCC3_WORLD = 0x3B,
|
||||
@@ -167,6 +168,7 @@ static struct reg_dmn_pair_mapping regDo
|
||||
{FCC2_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{FCC2_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
{FCC3_FCCA, CTL_FCC, CTL_FCC},
|
||||
+ {FCC3_FCCA_2, CTL_FCC, CTL_FCC},
|
||||
{FCC3_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{FCC4_FCCA, CTL_FCC, CTL_FCC},
|
||||
{FCC5_FCCA, CTL_FCC, CTL_FCC},
|
||||
@@ -463,6 +465,7 @@ static struct country_code_to_enum_rd al
|
||||
{CTRY_UAE, NULL1_WORLD, "AE"},
|
||||
{CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
|
||||
{CTRY_UNITED_STATES, FCC3_FCCA, "US"},
|
||||
+ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"},
|
||||
/* This "PS" is for US public safety actually... to support this we
|
||||
* would need to assign new special alpha2 to CRDA db as with the world
|
||||
* regdomain and use another alpha2 */
|
||||
@@ -1,47 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/regd.c
|
||||
+++ b/drivers/net/wireless/ath/regd.c
|
||||
@@ -114,10 +114,22 @@ static const struct ieee80211_regdomain
|
||||
)
|
||||
};
|
||||
|
||||
+static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
|
||||
+{
|
||||
+ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
|
||||
+}
|
||||
+
|
||||
+static bool is_default_regd(struct ath_regulatory *reg)
|
||||
+{
|
||||
+ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT;
|
||||
+}
|
||||
+
|
||||
static bool dynamic_country_user_possible(struct ath_regulatory *reg)
|
||||
{
|
||||
if (config_enabled(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
|
||||
return true;
|
||||
+ if (is_default_regd(reg))
|
||||
+ return true;
|
||||
|
||||
switch (reg->country_code) {
|
||||
case CTRY_UNITED_STATES:
|
||||
@@ -202,11 +214,6 @@ static inline bool is_wwr_sku(u16 regd)
|
||||
(regd == WORLD));
|
||||
}
|
||||
|
||||
-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
|
||||
-{
|
||||
- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
|
||||
-}
|
||||
-
|
||||
bool ath_is_world_regd(struct ath_regulatory *reg)
|
||||
{
|
||||
return is_wwr_sku(ath_regd_get_eepromRD(reg));
|
||||
@@ -650,6 +657,9 @@ ath_regd_init_wiphy(struct ath_regulator
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
+ if (is_default_regd(reg))
|
||||
+ return 0;
|
||||
+
|
||||
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
|
||||
REGULATORY_CUSTOM_REG;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -722,6 +722,7 @@ static const struct ieee80211_iface_limi
|
||||
BIT(NL80211_IFTYPE_AP) },
|
||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||
+ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit wds_limits[] = {
|
||||
@@ -1,46 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw
|
||||
goto end;
|
||||
}
|
||||
|
||||
- /* Don't allow other interfaces if one ad-hoc is configured.
|
||||
- * TODO: Fix the problems with ad-hoc and multiple other interfaces.
|
||||
- * We would need to operate the HW in ad-hoc mode to allow TSF updates
|
||||
- * for the IBSS, but this breaks with additional AP or STA interfaces
|
||||
- * at the moment. */
|
||||
- if (ah->num_adhoc_vifs ||
|
||||
- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
|
||||
+ /* Don't allow more than one ad-hoc interface */
|
||||
+ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
|
||||
ret = -ELNRNG;
|
||||
goto end;
|
||||
--- a/drivers/net/wireless/ath/ath5k/base.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/base.c
|
||||
@@ -1965,7 +1965,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
|
||||
}
|
||||
|
||||
if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
|
||||
- ah->num_mesh_vifs > 1) ||
|
||||
+ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
|
||||
ah->opmode == NL80211_IFTYPE_MESH_POINT) {
|
||||
u64 tsf = ath5k_hw_get_tsf64(ah);
|
||||
u32 tsftu = TSF_TO_TU(tsf);
|
||||
@@ -2051,7 +2051,7 @@ ath5k_beacon_update_timers(struct ath5k_
|
||||
|
||||
intval = ah->bintval & AR5K_BEACON_PERIOD;
|
||||
if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
|
||||
- + ah->num_mesh_vifs > 1) {
|
||||
+ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
|
||||
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
|
||||
if (intval < 15)
|
||||
ATH5K_WARN(ah, "intval %u is too low, min 15\n",
|
||||
@@ -2518,6 +2518,7 @@ static const struct ieee80211_iface_limi
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
#endif
|
||||
BIT(NL80211_IFTYPE_AP) },
|
||||
+ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination if_comb = {
|
||||
@@ -1,18 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath5k/reset.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/reset.c
|
||||
@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
|
||||
tsf_lo = 0;
|
||||
mode = 0;
|
||||
|
||||
+#if 0
|
||||
/*
|
||||
* Sanity check for fast flag
|
||||
* Fast channel change only available
|
||||
@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
|
||||
*/
|
||||
if (fast && (ah->ah_radio != AR5K_RF2413) &&
|
||||
(ah->ah_radio != AR5K_RF5413))
|
||||
+#endif
|
||||
fast = false;
|
||||
|
||||
/* Disable sleep clock operation
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user