Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 333c0dbf authored by John W. Linville's avatar John W. Linville
Browse files
parents 115f9450 95dac04f
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -11,7 +11,6 @@ config WL12XX
	depends on WL12XX_MENU && GENERIC_HARDIRQS
	depends on WL12XX_MENU && GENERIC_HARDIRQS
	depends on INET
	depends on INET
	select FW_LOADER
	select FW_LOADER
	select CRC7
	---help---
	---help---
	  This module adds support for wireless adapters based on TI wl1271 and
	  This module adds support for wireless adapters based on TI wl1271 and
	  TI wl1273 chipsets. This module does *not* include support for wl1251.
	  TI wl1273 chipsets. This module does *not* include support for wl1251.
@@ -33,6 +32,7 @@ config WL12XX_HT
config WL12XX_SPI
config WL12XX_SPI
	tristate "TI wl12xx SPI support"
	tristate "TI wl12xx SPI support"
	depends on WL12XX && SPI_MASTER
	depends on WL12XX && SPI_MASTER
	select CRC7
	---help---
	---help---
	  This module adds support for the SPI interface of adapters using
	  This module adds support for the SPI interface of adapters using
	  TI wl12xx chipsets.  Select this if your platform is using
	  TI wl12xx chipsets.  Select this if your platform is using
+48 −1
Original line number Original line Diff line number Diff line
@@ -25,7 +25,6 @@


#include <linux/module.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/slab.h>


@@ -1068,6 +1067,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
	mem_conf->tx_free_req = mem->min_req_tx_blocks;
	mem_conf->tx_free_req = mem->min_req_tx_blocks;
	mem_conf->rx_free_req = mem->min_req_rx_blocks;
	mem_conf->rx_free_req = mem->min_req_rx_blocks;
	mem_conf->tx_min = mem->tx_min;
	mem_conf->tx_min = mem->tx_min;
	mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;


	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
				   sizeof(*mem_conf));
				   sizeof(*mem_conf));
@@ -1577,6 +1577,53 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
	return ret;
	return ret;
}
}


int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
{
	struct wl1271_acx_ps_rx_streaming *rx_streaming;
	u32 conf_queues, enable_queues;
	int i, ret = 0;

	wl1271_debug(DEBUG_ACX, "acx ps rx streaming");

	rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL);
	if (!rx_streaming) {
		ret = -ENOMEM;
		goto out;
	}

	conf_queues = wl->conf.rx_streaming.queues;
	if (enable)
		enable_queues = conf_queues;
	else
		enable_queues = 0;

	for (i = 0; i < 8; i++) {
		/*
		 * Skip non-changed queues, to avoid redundant acxs.
		 * this check assumes conf.rx_streaming.queues can't
		 * be changed while rx_streaming is enabled.
		 */
		if (!(conf_queues & BIT(i)))
			continue;

		rx_streaming->tid = i;
		rx_streaming->enable = enable_queues & BIT(i);
		rx_streaming->period = wl->conf.rx_streaming.interval;
		rx_streaming->timeout = wl->conf.rx_streaming.interval;

		ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,
					   rx_streaming,
					   sizeof(*rx_streaming));
		if (ret < 0) {
			wl1271_warning("acx ps rx streaming failed: %d", ret);
			goto out;
		}
	}
out:
	kfree(rx_streaming);
	return ret;
}

int wl1271_acx_max_tx_retry(struct wl1271 *wl)
int wl1271_acx_max_tx_retry(struct wl1271 *wl)
{
{
	struct wl1271_acx_max_tx_retry *acx = NULL;
	struct wl1271_acx_max_tx_retry *acx = NULL;
+16 −0
Original line number Original line Diff line number Diff line
@@ -828,6 +828,8 @@ struct wl1271_acx_sta_config_memory {
	u8 tx_free_req;
	u8 tx_free_req;
	u8 rx_free_req;
	u8 rx_free_req;
	u8 tx_min;
	u8 tx_min;
	u8 fwlog_blocks;
	u8 padding[3];
} __packed;
} __packed;


struct wl1271_acx_mem_map {
struct wl1271_acx_mem_map {
@@ -1153,6 +1155,19 @@ struct wl1271_acx_fw_tsf_information {
	u8 padding[3];
	u8 padding[3];
} __packed;
} __packed;


struct wl1271_acx_ps_rx_streaming {
	struct acx_header header;

	u8 tid;
	u8 enable;

	/* interval between triggers (10-100 msec) */
	u8 period;

	/* timeout before first trigger (0-200 msec) */
	u8 timeout;
} __packed;

struct wl1271_acx_max_tx_retry {
struct wl1271_acx_max_tx_retry {
	struct acx_header header;
	struct acx_header header;


@@ -1384,6 +1399,7 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
				       bool enable);
				       bool enable);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
int wl1271_acx_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
+33 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,33 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
}


static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
{
	unsigned int quirks = 0;
	unsigned int *fw_ver = wl->chip.fw_ver;

	/* Only for wl127x */
	if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
	    /* Check STA version */
	    (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
	     /* Check AP version */
	     ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
		quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;

	/* Only new station firmwares support routing fw logs to the host */
	if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
	    (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;

	/* This feature is not yet supported for AP mode */
	if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;

	return quirks;
}

static void wl1271_parse_fw_ver(struct wl1271 *wl)
static void wl1271_parse_fw_ver(struct wl1271 *wl)
{
{
	int ret;
	int ret;
@@ -116,6 +143,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)
		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
		return;
		return;
	}
	}

	/* Check if any quirks are needed with older fw versions */
	wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
}
}


static void wl1271_boot_fw_version(struct wl1271 *wl)
static void wl1271_boot_fw_version(struct wl1271 *wl)
@@ -749,6 +779,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
		clk |= (wl->ref_clock << 1) << 4;
		clk |= (wl->ref_clock << 1) << 4;
	}
	}


	if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
		clk |= SCRATCH_ENABLE_LPD;

	wl1271_write32(wl, DRPW_SCRATCH_START, clk);
	wl1271_write32(wl, DRPW_SCRATCH_START, clk);


	wl1271_set_partition(wl, &part_table[PART_WORK]);
	wl1271_set_partition(wl, &part_table[PART_WORK]);
+91 −3
Original line number Original line Diff line number Diff line
@@ -23,7 +23,6 @@


#include <linux/module.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
#include <linux/ieee80211.h>
@@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,


fail:
fail:
	WARN_ON(1);
	WARN_ON(1);
	ieee80211_queue_work(wl->hw, &wl->recovery_work);
	wl12xx_queue_recovery_work(wl);
	return ret;
	return ret;
}
}


@@ -135,6 +134,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
	/* Override the REF CLK from the NVS with the one from platform data */
	/* Override the REF CLK from the NVS with the one from platform data */
	gen_parms->general_params.ref_clock = wl->ref_clock;
	gen_parms->general_params.ref_clock = wl->ref_clock;


	/* LPD mode enable (bits 6-7) in WL1271 AP mode only */
	if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
		gen_parms->general_params.general_settings |=
			GENERAL_SETTINGS_DRPW_LPD;

	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
	if (ret < 0) {
	if (ret < 0) {
		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
@@ -352,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)


	ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
	ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
	if (ret != 0) {
	if (ret != 0) {
		ieee80211_queue_work(wl->hw, &wl->recovery_work);
		wl12xx_queue_recovery_work(wl);
		return ret;
		return ret;
	}
	}


@@ -1223,3 +1227,87 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
out:
out:
	return ret;
	return ret;
}
}

int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
{
	struct wl12xx_cmd_config_fwlog *cmd;
	int ret = 0;

	wl1271_debug(DEBUG_CMD, "cmd config firmware logger");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd) {
		ret = -ENOMEM;
		goto out;
	}

	cmd->logger_mode = wl->conf.fwlog.mode;
	cmd->log_severity = wl->conf.fwlog.severity;
	cmd->timestamp = wl->conf.fwlog.timestamp;
	cmd->output = wl->conf.fwlog.output;
	cmd->threshold = wl->conf.fwlog.threshold;

	ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0);
	if (ret < 0) {
		wl1271_error("failed to send config firmware logger command");
		goto out_free;
	}

out_free:
	kfree(cmd);

out:
	return ret;
}

int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
{
	struct wl12xx_cmd_start_fwlog *cmd;
	int ret = 0;

	wl1271_debug(DEBUG_CMD, "cmd start firmware logger");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd) {
		ret = -ENOMEM;
		goto out;
	}

	ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0);
	if (ret < 0) {
		wl1271_error("failed to send start firmware logger command");
		goto out_free;
	}

out_free:
	kfree(cmd);

out:
	return ret;
}

int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
{
	struct wl12xx_cmd_stop_fwlog *cmd;
	int ret = 0;

	wl1271_debug(DEBUG_CMD, "cmd stop firmware logger");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd) {
		ret = -ENOMEM;
		goto out;
	}

	ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0);
	if (ret < 0) {
		wl1271_error("failed to send stop firmware logger command");
		goto out_free;
	}

out_free:
	kfree(cmd);

out:
	return ret;
}
Loading