Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 2/2] rsi: Device initialization sequence is changed
From: Prameela Rani Garnepudi @ 2016-10-21 10:10 UTC (permalink / raw)
  To: linux-wireless
  Cc: kvalo, johannes.berg, hofrat, xypron.glpk, prameela.garnepudi,
	Prameela Rani Garnepudi

BT Co-ex support has been added in the firmware and hence BT, COEX queues are
introducted. To support the latest firmware queues, packet processing,
and initialization sequence is modified in the Host.

Common device configuration parameters (tx command frame) need to be send after
common card ready indication from the firmware. This frame contains information
about the driver mode, coex mode, protocols to support etc. Once it is sent,
then second level card ready indication comes for each protocol (WLAN, BT etc).

Currently host supports only WLAN mode. New command frames are added as part
of these changes.

Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
---
 drivers/net/wireless/rsi/rsi_91x_main.c     |  14 +-
 drivers/net/wireless/rsi/rsi_91x_mgmt.c     | 281 ++++++++++++++++++++++++----
 drivers/net/wireless/rsi/rsi_91x_sdio_ops.c |  39 +++-
 drivers/net/wireless/rsi/rsi_91x_usb.c      |  97 ++++++----
 drivers/net/wireless/rsi/rsi_main.h         |  49 ++++-
 drivers/net/wireless/rsi/rsi_mgmt.h         | 195 ++++++++++++++++---
 drivers/net/wireless/rsi/rsi_usb.h          |   1 +
 7 files changed, 559 insertions(+), 117 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 8810862..ad725a4 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -121,11 +121,23 @@ int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len)
 		actual_length = *(u16 *)&frame_desc[0];
 		offset = *(u16 *)&frame_desc[2];
 
+		if ((actual_length < (4 + FRAME_DESC_SZ)) || (offset < 4)) {
+			rsi_dbg(ERR_ZONE,
+				"%s: actual_length (%d) is less than 20 or"
+				" offset(%d) is less than 4\n",
+				__func__, actual_length, offset);
+			break;
+		}
 		queueno = rsi_get_queueno(frame_desc, offset);
 		length = rsi_get_length(frame_desc, offset);
-		extended_desc = rsi_get_extended_desc(frame_desc, offset);
+		if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q)
+			extended_desc = rsi_get_extended_desc(frame_desc,
+							      offset);
 
 		switch (queueno) {
+		case RSI_COEX_Q:
+			rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+			break;
 		case RSI_WIFI_DATA_Q:
 			skb = rsi_prepare_skb(common,
 					      (frame_desc + offset),
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 7aec45a..1bffd7d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -18,6 +18,16 @@
 #include "rsi_mgmt.h"
 #include "rsi_common.h"
 
+struct rsi_config_vals dev_config_vals[] = {
+	{
+		.lp_ps_handshake = 0,
+		.ulp_ps_handshake = 0,
+		.sleep_config_params = 0,
+		.ext_pa_or_bt_coex_en = 0,
+	},
+};
+
+/* Bootup Parameters for 20MHz */
 static struct bootup_params boot_params_20 = {
 	.magic_number = cpu_to_le16(0x5aa5),
 	.crystal_good_time = 0x0,
@@ -199,6 +209,39 @@ static struct bootup_params boot_params_40 = {
 	.dcdc_operation_mode = 0x0,
 	.soc_reset_wait_cnt = 0x0
 };
+#define UNUSED_GPIO	1
+#define USED_GPIO	0
+struct rsi_ulp_gpio_vals unused_ulp_gpio_bitmap = {
+	.motion_sensor_gpio_ulp_wakeup = UNUSED_GPIO,
+	.sleep_ind_from_device = UNUSED_GPIO,
+	.ulp_gpio_2 = UNUSED_GPIO,
+	.push_button_ulp_wakeup = UNUSED_GPIO,
+};
+
+struct rsi_soc_gpio_vals unused_soc_gpio_bitmap = {
+	.pspi_csn_0		= USED_GPIO,	//GPIO_0
+	.pspi_csn_1		= USED_GPIO,	//GPIO_1
+	.host_wakeup_intr	= UNUSED_GPIO,	//GPIO_2
+	.pspi_data_0		= USED_GPIO,	//GPIO_3
+	.pspi_data_1		= USED_GPIO,	//GPIO_4
+	.pspi_data_2		= USED_GPIO,	//GPIO_5
+	.pspi_data_3		= USED_GPIO,	//GPIO_6
+	.i2c_scl		= USED_GPIO,	//GPIO_7
+	.i2c_sda		= USED_GPIO,	//GPIO_8
+	.uart1_rx		= UNUSED_GPIO,	//GPIO_9
+	.uart1_tx		= UNUSED_GPIO,	//GPIO_10
+	.uart1_rts_i2s_clk	= UNUSED_GPIO,	//GPIO_11
+	.uart1_cts_i2s_ws	= UNUSED_GPIO,	//GPIO_12
+	.dbg_uart_rx_i2s_din	= UNUSED_GPIO,	//GPIO_13
+	.dbg_uart_tx_i2s_dout	= UNUSED_GPIO,	//GPIO_14
+	.lp_wakeup_boot_bypass	= UNUSED_GPIO,	//GPIO_15
+	.led_0			= USED_GPIO,	//GPIO_16
+	.btcoex_wlan_active_ext_pa_ant_sel_A = UNUSED_GPIO, //GPIO_17
+	.btcoex_bt_priority_ext_pa_ant_sel_B = UNUSED_GPIO, //GPIO_18
+	.btcoex_bt_active_ext_pa_on_off = UNUSED_GPIO, //GPIO_19
+	.rf_reset		= USED_GPIO, //GPIO_20
+	.sleep_ind_from_device	= UNUSED_GPIO,
+};
 
 static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};
 
@@ -218,6 +261,26 @@ static void rsi_set_default_parameters(struct rsi_common *common)
 	common->fsm_state = FSM_CARD_NOT_READY;
 	common->iface_down = true;
 	common->endpoint = EP_2GHZ_20MHZ;
+	common->driver_mode = 1; /* End-to-End Mode */
+#ifdef CONFIG_RSI_COEX
+	common->coex_mode = 4;
+#else
+	common->coex_mode = 1; /*Default coex mode is WIFI alone */
+#endif
+	common->oper_mode = 1;
+	common->ta_aggr = 0;
+	common->skip_fw_load = 0; /* Default disable skipping fw loading */
+	common->lp_ps_handshake_mode = 0; /* Default No HandShake mode*/
+	common->ulp_ps_handshake_mode = 2; /* Default PKT HandShake mode*/
+	common->rf_power_val = 0; /* Default 1.9V */
+	common->device_gpio_type = TA_GPIO; /* Default TA GPIO */
+	common->country_code = 840; /* Default US */
+	common->wlan_rf_power_mode = 0;
+	common->bt_rf_power_mode = 0;
+	common->obm_ant_sel_val = 2;
+	common->antenna_diversity = 0;
+	common->tx_power = RSI_TXPOWER_MAX;
+
 }
 
 /**
@@ -301,10 +364,11 @@ static int rsi_load_radio_caps(struct rsi_common *common)
 	radio_caps = (struct rsi_radio_caps *)skb->data;
 
 	radio_caps->desc_word[1] = cpu_to_le16(RADIO_CAPABILITIES);
-	radio_caps->desc_word[4] = cpu_to_le16(RSI_RF_TYPE << 8);
+	radio_caps->desc_word[4] = cpu_to_le16(common->channel);
+	radio_caps->desc_word[4] |= cpu_to_le16(RSI_RF_TYPE << 8);
 
+	radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ);
 	if (common->channel_width == BW_40MHZ) {
-		radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ);
 		radio_caps->desc_word[7] |= cpu_to_le16(RSI_ENABLE_40MHZ);
 
 		if (common->fsm_state == FSM_MAC_INIT_DONE) {
@@ -345,7 +409,7 @@ static int rsi_load_radio_caps(struct rsi_common *common)
 		radio_caps->qos_params[ii].txop_q = 0;
 	}
 
-	for (ii = 0; ii < MAX_HW_QUEUES - 4; ii++) {
+	for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {
 		radio_caps->qos_params[ii].cont_win_min_q =
 			cpu_to_le16(common->edca_params[ii].cw_min);
 		radio_caps->qos_params[ii].cont_win_max_q =
@@ -356,6 +420,10 @@ static int rsi_load_radio_caps(struct rsi_common *common)
 			cpu_to_le16(common->edca_params[ii].txop);
 	}
 
+	radio_caps->qos_params[BROADCAST_HW_Q].txop_q = 0xffff;
+	radio_caps->qos_params[MGMT_HW_Q].txop_q = 0;
+	radio_caps->qos_params[BEACON_HW_Q].txop_q = 0xffff;
+
 	memcpy(&common->rate_pwr[0], &gc[0], 40);
 	for (ii = 0; ii < 20; ii++)
 		radio_caps->gcpd_per_rate[inx++] =
@@ -469,7 +537,7 @@ static int rsi_hal_send_sta_notify_frame(struct rsi_common *common,
 	memset(skb->data, 0, sizeof(struct rsi_peer_notify));
 	peer_notify = (struct rsi_peer_notify *)skb->data;
 
-	peer_notify->command = cpu_to_le16(opmode << 1);
+	peer_notify->command = 0;
 
 	switch (notify_event) {
 	case STA_CONNECTED:
@@ -499,7 +567,6 @@ static int rsi_hal_send_sta_notify_frame(struct rsi_common *common,
 
 	if (!status && qos_enable) {
 		rsi_set_contention_vals(common);
-		status = rsi_load_radio_caps(common);
 	}
 	return status;
 }
@@ -595,6 +662,7 @@ static int rsi_program_bb_rf(struct rsi_common *common)
 	mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
 	mgmt_frame->desc_word[1] = cpu_to_le16(BBP_PROG_IN_TA);
 	mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint);
+	mgmt_frame->desc_word[3] = cpu_to_le16(common->rf_pwr_mode);
 
 	if (common->rf_reset) {
 		mgmt_frame->desc_word[7] =  cpu_to_le16(RF_RESET_ENABLE);
@@ -752,6 +820,53 @@ int rsi_hal_load_key(struct rsi_common *common,
 	return rsi_send_internal_mgmt_frame(common, skb);
 }
 
+/**
+ * rsi_send_common_dev_params() - This function send the common device
+ *				configuration parameters to device.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_send_common_dev_params(struct rsi_common *common)
+{
+	struct sk_buff *skb = NULL;
+	u32 *soc_gpio, len;
+	u16 *frame, *ulp_gpio, *desc;
+
+	len = 0x20;
+
+	skb = dev_alloc_skb(len + FRAME_DESC_SZ);
+	if (!skb)
+		return -ENOMEM;
+	memset(skb->data, 0, len + FRAME_DESC_SZ);
+
+	desc = (u16 *)&skb->data[0];
+	frame = (u16 *)&skb->data[FRAME_DESC_SZ];
+
+	desc[0] = cpu_to_le16(len | (RSI_COEX_Q << 12));
+	desc[1] = cpu_to_le16(COMMON_DEV_CONFIG);
+
+	frame[0] = (u16)common->lp_ps_handshake_mode;
+	frame[0] |= (u16)common->ulp_ps_handshake_mode << 8;
+
+	ulp_gpio = (u16 *)&unused_ulp_gpio_bitmap;
+	soc_gpio = (u32 *)&unused_soc_gpio_bitmap;
+
+	frame[1] |= (*ulp_gpio) << 8;
+	*(u32 *)&frame[2] = *soc_gpio;
+	frame[4] |= ((u16)common->oper_mode << 8);
+	frame[5] |= ((u16)common->wlan_rf_power_mode);
+	frame[5] |= ((u16)common->bt_rf_power_mode << 8);
+	frame[6] |= ((u16)common->driver_mode << 8);
+	frame[7] = 3; //((u16 )d_assets->region_code);
+	frame[7] |= ((u16)common->obm_ant_sel_val << 8);
+
+	skb_put(skb, len + FRAME_DESC_SZ);
+
+	return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+
 /*
  * rsi_load_bootup_params() - This function send bootup params to the firmware.
  * @common: Pointer to the driver private structure.
@@ -1140,6 +1255,7 @@ void rsi_inform_bss_status(struct rsi_common *common,
 			   u16 aid)
 {
 	if (status) {
+		common->hw_data_qs_blocked = true;
 		rsi_hal_send_sta_notify_frame(common,
 					      RSI_IFTYPE_STATION,
 					      STA_CONNECTED,
@@ -1148,13 +1264,17 @@ void rsi_inform_bss_status(struct rsi_common *common,
 					      aid);
 		if (common->min_rate == 0xffff)
 			rsi_send_auto_rate_request(common);
+		if (!rsi_send_block_unblock_frame(common, false))
+			common->hw_data_qs_blocked = false;
 	} else {
+		common->hw_data_qs_blocked = true;
 		rsi_hal_send_sta_notify_frame(common,
 					      RSI_IFTYPE_STATION,
 					      STA_DISCONNECTED,
 					      bssid,
 					      qos_enable,
 					      aid);
+		rsi_send_block_unblock_frame(common, true);
 	}
 }
 
@@ -1168,6 +1288,7 @@ void rsi_inform_bss_status(struct rsi_common *common,
 static int rsi_eeprom_read(struct rsi_common *common)
 {
 	struct rsi_mac_frame *mgmt_frame;
+	struct rsi_hw *adapter = common->priv;
 	struct sk_buff *skb;
 
 	rsi_dbg(MGMT_TX_ZONE, "%s: Sending EEPROM read req frame\n", __func__);
@@ -1183,15 +1304,16 @@ static int rsi_eeprom_read(struct rsi_common *common)
 	mgmt_frame = (struct rsi_mac_frame *)skb->data;
 
 	/* FrameType */
-	mgmt_frame->desc_word[1] = cpu_to_le16(EEPROM_READ_TYPE);
+	mgmt_frame->desc_word[1] = cpu_to_le16(EEPROM_READ);
 	mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
 	/* Number of bytes to read */
-	mgmt_frame->desc_word[3] = cpu_to_le16(ETH_ALEN +
-					       WLAN_MAC_MAGIC_WORD_LEN +
-					       WLAN_HOST_MODE_LEN +
-					       WLAN_FW_VERSION_LEN);
+	mgmt_frame->desc_word[3] = cpu_to_le16(adapter->eeprom.length << 4);
+	mgmt_frame->desc_word[2] |= cpu_to_le16(3 << 8);
+
 	/* Address to read */
-	mgmt_frame->desc_word[4] = cpu_to_le16(WLAN_MAC_EEPROM_ADDR);
+	mgmt_frame->desc_word[4] = cpu_to_le16(adapter->eeprom.offset);
+	mgmt_frame->desc_word[5] = cpu_to_le16(adapter->eeprom.offset >> 16);
+	mgmt_frame->desc_word[6] = cpu_to_le16(0); //delay = 0
 
 	skb_put(skb, FRAME_DESC_SZ);
 
@@ -1225,13 +1347,16 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
 
 	mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
 	mgmt_frame->desc_word[1] = cpu_to_le16(BLOCK_HW_QUEUE);
+	mgmt_frame->desc_word[3] = cpu_to_le16(0x1);
 
 	if (block_event) {
 		rsi_dbg(INFO_ZONE, "blocking the data qs\n");
 		mgmt_frame->desc_word[4] = cpu_to_le16(0xf);
+		mgmt_frame->desc_word[4] |= cpu_to_le16(0xf << 4);
 	} else {
 		rsi_dbg(INFO_ZONE, "unblocking the data qs\n");
 		mgmt_frame->desc_word[5] = cpu_to_le16(0xf);
+		mgmt_frame->desc_word[5] |= cpu_to_le16(0xf << 4);
 	}
 
 	skb_put(skb, FRAME_DESC_SZ);
@@ -1262,7 +1387,7 @@ int rsi_flash_read(struct rsi_hw *adapter)
 	cmd_frame = (struct rsi_mac_frame *)skb->data;
 
 	/* FrameType */
-	cmd_frame->desc_word[1] = cpu_to_le16(EEPROM_READ_TYPE);
+	cmd_frame->desc_word[1] = cpu_to_le16(EEPROM_READ);
 
 	/* Format of length and offset differs for
 	 * autoflashing and swbl flashing
@@ -1300,13 +1425,36 @@ int rsi_flash_read(struct rsi_hw *adapter)
 static int rsi_handle_ta_confirm_type(struct rsi_common *common,
 				      u8 *msg)
 {
+	struct rsi_hw *adapter = common->priv;
 	u8 sub_type = (msg[15] & 0xff);
 
 	switch (sub_type) {
+	case COMMON_DEV_CONFIG:
+		rsi_dbg(FSM_ZONE,
+			"Common Dev Config params confirm received\n");
+		if (common->fsm_state == FSM_COMMON_DEV_PARAMS_SENT) {
+			if (rsi_load_bootup_params(common)) {
+				common->fsm_state = FSM_CARD_NOT_READY;
+				goto out;
+			} else {
+				common->fsm_state = FSM_BOOT_PARAMS_SENT;
+			}
+		} else {
+			rsi_dbg(INFO_ZONE,
+				"%s: Received common dev config params cfm in %d state\n",
+				 __func__, common->fsm_state);
+			return 0;
+		}
+		break;
+
 	case BOOTUP_PARAMS_REQUEST:
 		rsi_dbg(FSM_ZONE, "%s: Boot up params confirm received\n",
 			__func__);
 		if (common->fsm_state == FSM_BOOT_PARAMS_SENT) {
+			adapter->eeprom.length = (IEEE80211_ADDR_LEN +
+						  WLAN_MAC_MAGIC_WORD_LEN +
+						  WLAN_HOST_MODE_LEN);
+			adapter->eeprom.offset = WLAN_MAC_EEPROM_ADDR;
 			if (rsi_eeprom_read(common)) {
 				common->fsm_state = FSM_CARD_NOT_READY;
 				goto out;
@@ -1321,18 +1469,59 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
 		}
 		break;
 
-	case EEPROM_READ_TYPE:
+	case EEPROM_READ:
+		rsi_dbg(FSM_ZONE, "EEPROM READ confirm received\n");
 		if (common->fsm_state == FSM_EEPROM_READ_MAC_ADDR) {
+			u32 msg_len = ((u16 *)msg)[0] & 0xfff;
+
+			if (msg_len <= 0) {
+				rsi_dbg(FSM_ZONE,
+					"%s: [EEPROM_READ] Invalid len %d\n",
+					__func__, msg_len);
+				goto out;
+			}
 			if (msg[16] == MAGIC_WORD) {
 				u8 offset = (FRAME_DESC_SZ + WLAN_HOST_MODE_LEN
 					     + WLAN_MAC_MAGIC_WORD_LEN);
 				memcpy(common->mac_addr,
 				       &msg[offset],
 				       ETH_ALEN);
-				memcpy(&common->fw_ver,
-				       &msg[offset + ETH_ALEN],
-				       sizeof(struct version_info));
+				adapter->eeprom.length =
+					((WLAN_MAC_MAGIC_WORD_LEN + 3) & (~3));
+				adapter->eeprom.offset =
+					WLAN_EEPROM_RFTYPE_ADDR;
+				if (rsi_eeprom_read(common)) {
+					rsi_dbg(ERR_ZONE,
+						"%s: Failed reading RF band\n",
+						__func__);
+					common->fsm_state = FSM_CARD_NOT_READY;
+				} else {
+					common->fsm_state =
+						FSM_EEPROM_READ_RF_TYPE;
+				}
+			} else {
+				common->fsm_state = FSM_CARD_NOT_READY;
+				break;
+			}
+		} else if (common->fsm_state == FSM_EEPROM_READ_RF_TYPE) {
+			u32 msg_len = ((u16 *)msg)[0] & 0xfff;
 
+			if (msg_len <= 0) {
+				rsi_dbg(FSM_ZONE,
+					"%s:[EEPROM_READ_CFM] Invalid len %d\n",
+					__func__, msg_len);
+				goto out;
+			}
+			if (msg[16] == MAGIC_WORD) {
+				if ((msg[17] & 0x3) == 0x3) {
+					rsi_dbg(INIT_ZONE,
+						"Dual band supported\n");
+					common->band = NL80211_BAND_5GHZ;
+				} else if ((msg[17] & 0x3) == 0x1) {
+					rsi_dbg(INIT_ZONE,
+						"Only 2.4Ghz band supported\n");
+					common->band = NL80211_BAND_2GHZ;
+				}
 			} else {
 				common->fsm_state = FSM_CARD_NOT_READY;
 				break;
@@ -1415,6 +1604,40 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
 }
 
 /**
+ * rsi_handle_card_ready() - This function handles the card ready
+ *			 indication from firmware.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_handle_card_ready(struct rsi_common *common)
+{
+	switch (common->fsm_state) {
+	case FSM_CARD_NOT_READY:
+		rsi_set_default_parameters(common);
+		if (rsi_send_common_dev_params(common) < 0)
+			return -EINVAL;
+		common->fsm_state = FSM_COMMON_DEV_PARAMS_SENT;
+		break;
+	case FSM_COMMON_DEV_PARAMS_SENT:
+		rsi_dbg(FSM_ZONE, "Card ready indication from wlan.\n");
+		if (rsi_load_bootup_params(common)) {
+			common->fsm_state = FSM_CARD_NOT_READY;
+			return -EINVAL;
+		}
+		common->fsm_state = FSM_BOOT_PARAMS_SENT;
+		break;
+	default:
+		rsi_dbg(ERR_ZONE,
+			"%s: card ready indication in invalid state %d.\n",
+			__func__, common->fsm_state);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
  * rsi_mgmt_pkt_recv() - This function processes the management packets
  *			 recieved from the hardware.
  * @common: Pointer to the driver private structure.
@@ -1426,34 +1649,26 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
 {
 	s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff);
 	u16 msg_type = (msg[2]);
-	int ret;
 
 	rsi_dbg(FSM_ZONE, "%s: Msg Len: %d, Msg Type: %4x\n",
 		__func__, msg_len, msg_type);
 
-	if (msg_type == TA_CONFIRM_TYPE) {
+	switch (msg_type) {
+	case TA_CONFIRM_TYPE:
 		return rsi_handle_ta_confirm_type(common, msg);
-	} else if (msg_type == CARD_READY_IND) {
-		rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n",
-			__func__);
-		if (common->fsm_state == FSM_CARD_NOT_READY) {
-			rsi_set_default_parameters(common);
 
-			ret = rsi_load_bootup_params(common);
-			if (ret)
-				return ret;
-			else
-				common->fsm_state = FSM_BOOT_PARAMS_SENT;
-		} else {
-			return -EINVAL;
-		}
-	} else if (msg_type == TX_STATUS_IND) {
+	case CARD_READY_IND:
+		return rsi_handle_card_ready(common);
+
+	case TX_STATUS_IND:
 		if (msg[15] == PROBEREQ_CONFIRM) {
 			common->mgmt_q_block = false;
 			rsi_dbg(FSM_ZONE, "%s: Probe confirm received\n",
 				__func__);
 		}
-	} else {
+		break;
+
+	default:
 		return rsi_mgmt_pkt_to_core(common, msg, msg_len, msg_type);
 	}
 	return 0;
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index c54a534..ad399b5 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -74,17 +74,36 @@ static int rsi_process_pkt(struct rsi_common *common)
 	u8 num_blks = 0;
 	u32 rcv_pkt_len = 0;
 	int status = 0;
+	u8 value = 0;
+	u8 protocol = 0, unaggr_pkt = 0;
+
+#define COEX_PKT 0
+#define WLAN_PKT 3
+#define ZIGB_PKT 1
+#define BT_PKT   2
+	num_blks = ((adapter->interrupt_status & 1) |
+			((adapter->interrupt_status >> 4) << 1));
+
+	if (!num_blks) {
+		status = rsi_sdio_read_register(adapter,
+						SDIO_RX_NUM_BLOCKS_REG,
+						&value);
+		if (status) {
+			rsi_dbg(ERR_ZONE,
+				"%s: Failed to read pkt length from the card:\n",
+				__func__);
+			return status;
+		}
 
-	status = rsi_sdio_read_register(adapter,
-					SDIO_RX_NUM_BLOCKS_REG,
-					&num_blks);
-
-	if (status) {
-		rsi_dbg(ERR_ZONE,
-			"%s: Failed to read pkt length from the card:\n",
-			__func__);
-		return status;
+		protocol = value >> 5;
+		num_blks = value & 0x1f;
+	} else {
+		protocol = WLAN_PKT;
 	}
+
+	if (protocol == BT_PKT || protocol == ZIGB_PKT)  //unaggr_pkt FIXME
+		unaggr_pkt = 1;
+
 	rcv_pkt_len = (num_blks * 256);
 
 	common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL);
@@ -233,6 +252,8 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
 			mutex_unlock(&common->tx_rxlock);
 			return;
 		}
+		adapter->interrupt_status = isr_status;
+		isr_status &= 0xE;
 
 		rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",
 			__func__, isr_status, (1 << MSDU_PKT_PENDING),
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 84ca609..63104bb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -41,19 +41,25 @@ static struct rsi_host_intf_ops usb_host_intf_ops = {
  * Return: status: 0 on success, a negative error code on failure.
  */
 static int rsi_usb_card_write(struct rsi_hw *adapter,
-			      void *buf,
+			      u8 *buf,
 			      u16 len,
-			      u8 endpoint)
+			      u32 endpoint)
 {
 	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
-	int status;
-	s32 transfer;
+	int status = 0;
+	u8 *seg = dev->tx_buffer;
+	int transfer = 0;
+	int ep = dev->bulkout_endpoint_addr[endpoint - 1];
+
+	memset(seg, 0, len + 128);
+	memcpy(seg + 128, buf, len);
+	len += 128;
+	transfer = len;
 
 	status = usb_bulk_msg(dev->usbdev,
-			      usb_sndbulkpipe(dev->usbdev,
-			      dev->bulkout_endpoint_addr[endpoint - 1]),
-			      buf,
-			      len,
+			      usb_sndbulkpipe(dev->usbdev, ep),
+			      (void *)seg,
+			      (int)len,
 			      &transfer,
 			      HZ * 5);
 
@@ -61,7 +67,11 @@ static int rsi_usb_card_write(struct rsi_hw *adapter,
 		rsi_dbg(ERR_ZONE,
 			"Card write failed with error code :%10d\n", status);
 		dev->write_fail = 1;
+		goto fail;
 	}
+	rsi_dbg(MGMT_TX_ZONE, "%s: Sent Message successfully\n", __func__);
+
+fail:
 	return status;
 }
 
@@ -76,27 +86,23 @@ static int rsi_usb_card_write(struct rsi_hw *adapter,
  * Return: 0 on success, a negative error code on failure.
  */
 static int rsi_write_multiple(struct rsi_hw *adapter,
-			      u8 endpoint,
+			      u32 addr,
 			      u8 *data,
 			      u32 count)
 {
-	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
-	u8 *seg = dev->tx_buffer;
-
-	if (dev->write_fail)
-		return 0;
+	struct rsi_91x_usbdev *dev =
+		(struct rsi_91x_usbdev *)adapter->rsi_dev;
 
-	if (endpoint == MGMT_EP) {
-		memset(seg, 0, RSI_USB_TX_HEAD_ROOM);
-		memcpy(seg + RSI_USB_TX_HEAD_ROOM, data, count);
-	} else {
-		seg = ((u8 *)data - RSI_USB_TX_HEAD_ROOM);
+	if (!adapter || addr == 0) {
+		rsi_dbg(INFO_ZONE,
+			"%s: Unable to write to card\n", __func__);
+		return -1;
 	}
 
-	return rsi_usb_card_write(adapter,
-				  seg,
-				  count + RSI_USB_TX_HEAD_ROOM,
-				  endpoint);
+	if (dev->write_fail)
+		return -1;
+
+	return rsi_usb_card_write(adapter, data, count, addr);
 }
 
 /**
@@ -259,6 +265,11 @@ static void rsi_rx_done_handler(struct urb *urb)
 	if (urb->status)
 		return;
 
+	if (urb->actual_length <= 0) {
+		rsi_dbg(INFO_ZONE, "%s: Zero length packet\n", __func__);
+		return;
+	}
+
 	rsi_set_event(&dev->rx_thread.event);
 }
 
@@ -386,15 +397,16 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
 			rsi_dbg(ERR_ZONE,
 				"Reg write failed with error code :%d\n",
 				status);
-		} else {
-			count -= transfer;
-			data += transfer;
-			addr += transfer;
+			kfree(buf);
+			return status;
 		}
+		count -= transfer;
+		data += transfer;
+		addr += transfer;
 	}
 
 	kfree(buf);
-	return 0;
+	return status;
 }
 
 /**
@@ -410,10 +422,12 @@ int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
 				u8 *pkt,
 				u32 len)
 {
-	u32 queueno = ((pkt[1] >> 4) & 0xf);
+	u32 queueno = ((pkt[1] >> 4) & 0x7);
 	u8 endpoint;
 
-	endpoint = ((queueno == RSI_WIFI_MGMT_Q) ? MGMT_EP : DATA_EP);
+	endpoint = ((queueno == RSI_WIFI_MGMT_Q || queueno == RSI_COEX_Q ||
+		     queueno == RSI_WIFI_DATA_Q) ?
+		    MGMT_EP : DATA_EP);
 
 	return rsi_write_multiple(adapter,
 				  endpoint,
@@ -500,7 +514,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
 	rsi_kill_thread(&dev->rx_thread);
 	usb_free_urb(dev->rx_usb_urb[0]);
 	kfree(adapter->priv->rx_data_pkt);
-	kfree(dev->tx_buffer);
+	kfree(dev->saved_tx_buffer);
 }
 
 /**
@@ -516,6 +530,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
 	struct rsi_91x_usbdev *rsi_dev;
 	struct rsi_common *common = adapter->priv;
 	int status;
+	u8 dword_align_bytes = 0;
 
 	rsi_dev = kzalloc(sizeof(*rsi_dev), GFP_KERNEL);
 	if (!rsi_dev)
@@ -530,18 +545,29 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
 	adapter->device = &pfunction->dev;
 	usb_set_intfdata(pfunction, adapter);
 
-	common->rx_data_pkt = kmalloc(2048, GFP_KERNEL);
+	common->rx_data_pkt = kmalloc(2000 * 4, GFP_KERNEL | GFP_DMA);
 	if (!common->rx_data_pkt) {
 		rsi_dbg(ERR_ZONE, "%s: Failed to allocate memory\n",
 			__func__);
 		return -ENOMEM;
 	}
+	common->saved_rx_data_pkt = common->rx_data_pkt;
+	dword_align_bytes = (u32)common->rx_data_pkt & 0x3f;
+	if (dword_align_bytes)
+		common->rx_data_pkt = common->rx_data_pkt +
+				      (64 - dword_align_bytes);
 
 	rsi_dev->tx_buffer = kmalloc(2048, GFP_KERNEL);
 	if (!rsi_dev->tx_buffer) {
 		status = -ENOMEM;
 		goto fail_tx;
 	}
+	rsi_dev->saved_tx_buffer = rsi_dev->tx_buffer;
+	dword_align_bytes = (u32)rsi_dev->tx_buffer & 0x3f;
+	if (dword_align_bytes)
+		rsi_dev->tx_buffer = rsi_dev->tx_buffer +
+				     (64 - dword_align_bytes);
+
 	rsi_dev->rx_usb_urb[0] = usb_alloc_urb(0, GFP_KERNEL);
 	if (!rsi_dev->rx_usb_urb[0]) {
 		status = -ENOMEM;
@@ -549,6 +575,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
 	}
 	rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
 	rsi_dev->tx_blk_size = 252;
+	adapter->tx_blk_size = rsi_dev->tx_blk_size;
 
 	/* Initializing function callbacks */
 	adapter->rx_urb_submit = rsi_rx_urb_submit;
@@ -575,9 +602,9 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
 fail_thread:
 	usb_free_urb(rsi_dev->rx_usb_urb[0]);
 fail_rx:
-	kfree(rsi_dev->tx_buffer);
+	kfree(rsi_dev->saved_tx_buffer);
 fail_tx:
-	kfree(common->rx_data_pkt);
+	kfree(common->saved_rx_data_pkt);
 	return status;
 }
 
@@ -595,7 +622,7 @@ static int rsi_probe(struct usb_interface *pfunction,
 {
 	struct rsi_hw *adapter;
 	struct rsi_91x_usbdev *dev;
-	u32 fw_status;
+	u32 fw_status = 0;
 	int status;
 
 	rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 752c429..49e9fdf 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -32,12 +32,14 @@
 #define ISR_ZONE                        BIT(8)  /* For Interrupt Msgs         */
 
 #define FSM_CARD_NOT_READY              0
-#define FSM_BOOT_PARAMS_SENT            1
-#define FSM_EEPROM_READ_MAC_ADDR        2
-#define FSM_RESET_MAC_SENT              3
-#define FSM_RADIO_CAPS_SENT             4
-#define FSM_BB_RF_PROG_SENT             5
-#define FSM_MAC_INIT_DONE               6
+#define FSM_COMMON_DEV_PARAMS_SENT	1
+#define FSM_BOOT_PARAMS_SENT            2
+#define FSM_EEPROM_READ_MAC_ADDR        3
+#define FSM_EEPROM_READ_RF_TYPE		4
+#define FSM_RESET_MAC_SENT              5
+#define FSM_RADIO_CAPS_SENT             6
+#define FSM_BB_RF_PROG_SENT             7
+#define FSM_MAC_INIT_DONE               8
 
 extern u32 rsi_zone_enabled;
 extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
@@ -54,12 +56,23 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
 #define MAC_80211_HDR_FRAME_CONTROL     0
 #define WME_NUM_AC                      4
 #define NUM_SOFT_QUEUES                 5
-#define MAX_HW_QUEUES                   8
+#define MAX_HW_QUEUES                   12
 #define INVALID_QUEUE                   0xff
 #define MAX_CONTINUOUS_VO_PKTS          8
 #define MAX_CONTINUOUS_VI_PKTS          4
+#define MGMT_HW_Q			10 /* Queue No 10 is used for
+					    * MGMT_QUEUE in Device FW,
+					    *  Hence this is Reserved
+					    */
+#define BROADCAST_HW_Q			9
+#define BEACON_HW_Q			11
+#define MAX_NUM_SCAN_BGCHANS		24
 
 /* Queue information */
+#define RSI_COEX_Q			0x0
+#define RSI_ZIGB_Q			0x1
+#define RSI_BT_Q			0x2
+#define RSI_WLAN_Q			0x3
 #define RSI_WIFI_MGMT_Q                 0x4
 #define RSI_WIFI_DATA_Q                 0x5
 #define IEEE80211_MGMT_FRAME            0x00
@@ -190,6 +203,7 @@ struct rsi_common {
 	/* Generic */
 	u8 channel;
 	u8 *rx_data_pkt;
+	u8 *saved_rx_data_pkt;
 	u8 mac_id;
 	u8 radio_id;
 	u16 rate_pwr[20];
@@ -204,8 +218,27 @@ struct rsi_common {
 	struct cqm_info cqm_info;
 
 	bool hw_data_qs_blocked;
-	
+	u8 driver_mode;
 	u8 coex_mode;
+	u8 oper_mode;
+	u8 ta_aggr;
+	u8 skip_fw_load;
+	u8 lp_ps_handshake_mode;
+	u8 ulp_ps_handshake_mode;
+	u8 uapsd_bitmap;
+	u8 rf_power_val;
+	u8 device_gpio_type;
+	u16 country_code;
+	u8 wlan_rf_power_mode;
+	u8 bt_rf_power_mode;
+	u8 obm_ant_sel_val;
+	u8 antenna_diversity;
+	u16 rf_pwr_mode;
+	char antenna_gain[2];
+	u8 host_wakeup_intr_enable;
+	u8 host_wakeup_intr_active_high;
+	int tx_power;
+	u8 ant_in_use;
 };
 
 enum host_intf {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index f8823126..b0bbb5a 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -43,13 +43,32 @@
 #define WLAN_HOST_MODE_LEN              0x04
 #define WLAN_FW_VERSION_LEN             0x08
 #define MAGIC_WORD                      0x5A
+#define WLAN_EEPROM_RFTYPE_ADDR		424
 
 /* Receive Frame Types */
-#define TA_CONFIRM_TYPE                 0x01
-#define RX_DOT11_MGMT                   0x02
-#define TX_STATUS_IND                   0x04
+enum rx_cmd_type {
+	CARD_READY_IND = 0x0,
+	TA_CONFIRM_TYPE = 0x01,
+	RX_DOT11_MGMT = 0x02,
+	RX_DOT11_DATA = 0x03,
+	TX_STATUS_IND = 0x04,
+	PS_NOTIFY_IND = 0x05,
+	SLEEP_NOTIFY_IND = 0x06,
+	DECRYPT_ERROR_IND = 0x07,
+	BEACON_EVENT_IND = 0x08,
+	DEBUG_IND = 0x09,
+	RX_MISC_IND = 0xa,
+	UNCONNECTED_PEER = 0xb,
+	HW_BMISS_EVENT = 0xc,
+	RATE_GC_TABLE_UPDATE = 0xd,
+	RADAR_DETECTED = 0x0e,
+	TSF_SYNC_CONFIRM = 0xc0,
+	ANTENNA_SELECT = 0xf,
+};
+
+#define EAPOL4_CONFIRM			1
 #define PROBEREQ_CONFIRM                2
-#define CARD_READY_IND                  0x00
+#define NULLDATA_CONFIRM		3
 
 #define RSI_DELETE_PEER                 0x0
 #define RSI_ADD_PEER                    0x1
@@ -62,6 +81,7 @@
 #define RF_RESET_ENABLE                 BIT(3)
 #define RATE_INFO_ENABLE                BIT(0)
 #define RSI_BROADCAST_PKT               BIT(9)
+#define RSI_DESC_11G_MODE		BIT(7)
 #define RSI_DESC_REQUIRE_CFM_TO_HOST	BIT(10)
 
 #define UPPER_20_ENABLE                 (0x2 << 12)
@@ -75,7 +95,7 @@
 #define RX_BA_INDICATION                1
 #define RSI_TBL_SZ                      40
 #define MAX_RETRIES                     8
-#define RSI_IFTYPE_STATION		 0
+#define RSI_IFTYPE_STATION		1
 
 #define STD_RATE_MCS7                   0x07
 #define STD_RATE_MCS6                   0x06
@@ -141,6 +161,44 @@
 
 #define RSI_SUPP_FILTERS	(FIF_ALLMULTI | FIF_PROBE_REQ |\
 				 FIF_BCN_PRBRESP_PROMISC)
+
+/* Power save handshake types */
+#define NO_HAND_SHAKE			0
+#define GPIO_HAND_SHAKE			1
+#define PACKET_HAND_SHAKE		2
+#define TA_GPIO				0
+#define ULP_GPIO			1
+#define RF_POWER_3_3			1
+#define RF_POWER_1_9			0
+
+/* Rx filter word definitions */
+#define PROMISCOUS_MODE			BIT(0)
+#define ALLOW_DATA_ASSOC_PEER		BIT(1)
+#define ALLOW_MGMT_ASSOC_PEER		BIT(2)
+#define ALLOW_CTRL_ASSOC_PEER		BIT(3)
+#define DISALLOW_BEACONS		BIT(4)
+#define ALLOW_CONN_PEER_MGMT_WHILE_BUF_FULL BIT(5)
+#define DISALLOW_BROADCAST_DATA		BIT(6)
+
+#define RSI_TXPOWER_MAX			30
+#define RSI_TXPOWER_MIN			-127
+
+#define DEEP_SLEEP			1
+#define CONNECTED_SLEEP			2
+
+#define SLEEP_REQUEST			1
+#define WAKEUP_REQUEST			2
+
+#define RSI_TXPOWER_MAX			30
+#define RSI_TXPOWER_MIN			-127
+
+#define IEEE80211_MARKALL_UAPSD_QUEUES \
+	(IEEE80211_WMM_IE_STA_QOSINFO_AC_VO | \
+	 IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \
+	 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \
+	 IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
+#define IEEE80211_STA_SP_ALL_PKTS	0x00
+
 enum opmode {
 	STA_OPMODE = 1,
 	AP_OPMODE = 2
@@ -160,32 +218,51 @@ enum sta_notify_events {
 
 /* Send Frames Types */
 enum cmd_frame_type {
-	TX_DOT11_MGMT,
-	RESET_MAC_REQ,
-	RADIO_CAPABILITIES,
-	BB_PROG_VALUES_REQUEST,
-	RF_PROG_VALUES_REQUEST,
-	WAKEUP_SLEEP_REQUEST,
-	SCAN_REQUEST,
-	TSF_UPDATE,
-	PEER_NOTIFY,
-	BLOCK_HW_QUEUE,
-	SET_KEY_REQ,
-	AUTO_RATE_IND,
-	BOOTUP_PARAMS_REQUEST,
-	VAP_CAPABILITIES,
-	EEPROM_READ_TYPE ,
-	EEPROM_WRITE,
-	GPIO_PIN_CONFIG ,
-	SET_RX_FILTER,
-	AMPDU_IND,
-	STATS_REQUEST_FRAME,
-	BB_BUF_PROG_VALUES_REQ,
-	BBP_PROG_IN_TA,
-	BG_SCAN_PARAMS,
-	BG_SCAN_PROBE_REQ,
-	CW_MODE_REQ,
-	PER_CMD_PKT
+	TX_DOT11_MGMT = 0,
+	RESET_MAC_REQ, /* 0x1 */
+	RADIO_CAPABILITIES, /* 0x2 */
+	BB_PROG_VALUES_REQUEST, /* 0x3 */
+	RF_PROG_VALUES_REQUEST, /* 0x4 */
+	WAKEUP_SLEEP_REQUEST, /* 0x5 */
+	SCAN_REQUEST, /* 0x6 */
+	TSF_UPDATE, /* 0x7 */
+	PEER_NOTIFY, /* 0x8 */
+	BLOCK_HW_QUEUE, /* 0x9 */
+	SET_KEY_REQ, /* 0xA */
+	AUTO_RATE_IND, /* 0xB */
+	BOOTUP_PARAMS_REQUEST, /* 0xC */
+	VAP_CAPABILITIES, /* 0xD */
+	EEPROM_READ, /* 0xE */
+	EEPROM_WRITE, /* 0xF */
+	GPIO_PIN_CONFIG, /* 0x10 */
+	SET_RX_FILTER, /* 0x11 */
+	AMPDU_IND, /* 0x12 */
+	STATS_REQUEST, /* 0x13 */
+	BB_BUF_PROG_VALUES_REQ, /* 0x14 */
+	BBP_PROG_IN_TA, /* 0x15 */
+	BG_SCAN_PARAMS, /* 0x16 */
+	BG_SCAN_PROBE_REQ, /* 0x17 */
+	CW_MODE_REQ, /* 0x18 */
+	PER_CMD_PKT, /* 0x19 */
+	DEV_SLEEP_REQUEST, /* 0x1A */
+	DEV_WAKEUP_CNF,  /* 0x1B */
+	RF_LOOPBACK_REQ, /* 0x1C */
+	RF_LPBK_M3,  /* 0x1D */
+	RF_RESET_FRAME,  /* 0x1E */
+	LMAC_REG_OPS,  /* 0x1F */
+	ANT_SEL_FRAME, /* 0x20 */
+	CONFIRM, /* 0x21 */
+	WLAN_DE_REGISTER, /* 0x22 */
+	DEBUG_FRAME,  /* 0x23 */
+	HW_BMISS_HANDLE, /* 0x24 */
+	MULTICAST_ENABLE, /* 0x25 */
+	TX_MISC_IND, /* 0x26 */
+	VAP_DYNAMIC_UPDATE, /* 0x27 */
+	COMMON_DEV_CONFIG, /* 0x28 */
+	RADIO_PARAMS_UPDATE, /* 0x29 */
+	RADAR_REQUEST, /* 0x2A */
+	WOWLAN_CONFIG_PARAMS, /* 2B */
+	IAP_CONFIG, /* 0x2C */
 };
 
 struct rsi_mac_frame {
@@ -220,6 +297,7 @@ struct rsi_vap_caps {
 	__le32 default_data_rate;
 	__le16 beacon_interval;
 	__le16 dtim_period;
+	__le16 beacon_miss_threshold;
 } __packed;
 
 struct rsi_set_key {
@@ -262,6 +340,61 @@ struct rsi_radio_caps {
 	__le16 preamble_type;
 } __packed;
 
+struct rsi_ulp_gpio_vals {
+	u8 motion_sensor_gpio_ulp_wakeup : 1;
+	u8 sleep_ind_from_device : 1;
+	u8 ulp_gpio_2 :1;
+	u8 push_button_ulp_wakeup : 1;
+	u8 reserved : 4;
+} __packed;
+
+struct rsi_soc_gpio_vals {
+	u32 pspi_csn_0 : 1;
+	u32 pspi_csn_1 : 1;
+	u32 host_wakeup_intr :1;
+	u32 pspi_data_0 : 1;
+	u32 pspi_data_1 : 1;
+	u32 pspi_data_2 : 1;
+	u32 pspi_data_3 : 1;
+	u32 i2c_scl :1;
+	u32 i2c_sda   :1;
+	u32 uart1_rx :1;
+	u32 uart1_tx  :1;
+	u32 uart1_rts_i2s_clk :1;
+	u32 uart1_cts_i2s_ws :1;
+	u32 dbg_uart_rx_i2s_din :1;
+	u32 dbg_uart_tx_i2s_dout :1;
+	u32 lp_wakeup_boot_bypass :1;
+	u32 led_0 :1;
+	u32 btcoex_wlan_active_ext_pa_ant_sel_A :1;
+	u32 btcoex_bt_priority_ext_pa_ant_sel_B :1;
+	u32 btcoex_bt_active_ext_pa_on_off :1;
+	u32 rf_reset :1;
+	u32 sleep_ind_from_device :1;
+} __packed;
+
+struct rsi_config_vals {
+	u16 desc_word[8];
+	u8 lp_ps_handshake;
+	u8 ulp_ps_handshake;
+	u8 sleep_config_params; /* 0 for no handshake,
+				 * 1 for GPIO based handshake,
+				 * 2 packet handshake
+				 */
+	u8 unused_ulp_gpio;
+	u32 unused_soc_gpio_bitmap;
+	u8 ext_pa_or_bt_coex_en;
+	u8 opermode;
+	u8 wlan_rf_pwr_mode;
+	u8 bt_rf_pwr_mode;
+	u8 zigbee_rf_pwr_mode;
+	u8 driver_mode;
+	u8 region_code;
+	u8 antenna_sel_val;
+#define EXT_PA      1
+#define EXT_BT_COEX 2
+} __packed;
+
 static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
 {
 	return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index d21d40d..b20b99d 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -42,6 +42,7 @@ struct rsi_91x_usbdev {
 	struct usb_interface *pfunction;
 	struct urb *rx_usb_urb[MAX_RX_URBS];
 	u8 *tx_buffer;
+	u8 *saved_tx_buffer;
 	__le16 bulkin_size;
 	u8 bulkin_endpoint_addr;
 	__le16 bulkout_size[MAX_BULK_EP];
-- 
2.4.11

^ permalink raw reply related

* [PATCH] cfg80211: fix beacon interval in interface combination iteration
From: Johannes Berg @ 2016-10-21 10:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We shouldn't abort the iteration with an error when one of the
potential combinations can't accomodate the beacon interval
request, we should just skip that particular combination. Fix
the code to do so.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/util.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index ec17c2800117..78bf53705466 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1676,10 +1676,8 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 
 		if (params->beacon_int_gcd) {
 			if (c->beacon_int_min_gcd &&
-			    params->beacon_int_gcd < c->beacon_int_min_gcd) {
-				kfree(limits);
-				return -EINVAL;
-			}
+			    params->beacon_int_gcd < c->beacon_int_min_gcd)
+				goto cont;
 			if (!c->beacon_int_min_gcd &&
 			    params->beacon_int_different)
 				goto cont;
-- 
2.8.1

^ permalink raw reply related

* [PATCH] cfg80211: don't export cfg80211_iter_combinations()
From: Johannes Berg @ 2016-10-21 10:19 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Nothing uses it outside of cfg80211, and since only
cfg80211_check_combinations() uses it in the same file
it can even be static - do that.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/cfg80211.h | 18 ------------------
 net/wireless/util.c    | 12 ++++++------
 2 files changed, 6 insertions(+), 24 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ec39f891b7a3..db3d020d7349 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5628,24 +5628,6 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
 int cfg80211_check_combinations(struct wiphy *wiphy,
 				struct iface_combination_params *params);
 
-/**
- * cfg80211_iter_combinations - iterate over matching combinations
- *
- * @wiphy: the wiphy
- * @params: the interface combinations parameter
- * @iter: function to call for each matching combination
- * @data: pointer to pass to iter function
- *
- * This function can be called by the driver to check what possible
- * combinations it fits in at a given moment, e.g. for channel switching
- * purposes.
- */
-int cfg80211_iter_combinations(struct wiphy *wiphy,
-			       struct iface_combination_params *params,
-			       void (*iter)(const struct ieee80211_iface_combination *c,
-					    void *data),
-			       void *data);
-
 /*
  * cfg80211_stop_iface - trigger interface disconnection
  *
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 78bf53705466..8a244fb769e6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1601,11 +1601,12 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 	return cfg80211_check_combinations(&rdev->wiphy, &params);
 }
 
-int cfg80211_iter_combinations(struct wiphy *wiphy,
-			       struct iface_combination_params *params,
-			       void (*iter)(const struct ieee80211_iface_combination *c,
-					    void *data),
-			       void *data)
+static int
+cfg80211_iter_combinations(struct wiphy *wiphy,
+			   struct iface_combination_params *params,
+			   void (*iter)(const struct ieee80211_iface_combination *c,
+					void *data),
+			   void *data)
 {
 	const struct ieee80211_regdomain *regdom;
 	enum nl80211_dfs_regions region = 0;
@@ -1694,7 +1695,6 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 
 	return 0;
 }
-EXPORT_SYMBOL(cfg80211_iter_combinations);
 
 static void
 cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
-- 
2.8.1

^ permalink raw reply related

* Re: [PATCH] cfg80211: don't export cfg80211_iter_combinations()
From: Johannes Berg @ 2016-10-21 10:24 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1477045188-13733-1-git-send-email-johannes@sipsolutions.net>

On Fri, 2016-10-21 at 12:19 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> Nothing uses it outside of cfg80211, and since only
> cfg80211_check_combinations() uses it in the same file
> it can even be static - do that.
> 
Err, obviously my git grep foo failed me ... :)

johannes

^ permalink raw reply

* [mac80211-next:master 25/25] net/mac80211/util.c:3411:8: error: implicit declaration of function 'cfg80211_iter_combinations'
From: kbuild test robot @ 2016-10-21 10:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: kbuild-all, linux-wireless

[-- Attachment #1: Type: text/plain, Size: 2178 bytes --]

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
head:   9fd96261756ed32c762d417b2c4dfd1febbbf71c
commit: 9fd96261756ed32c762d417b2c4dfd1febbbf71c [25/25] cfg80211: don't export cfg80211_iter_combinations()
config: x86_64-randconfig-x019-201642 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        git checkout 9fd96261756ed32c762d417b2c4dfd1febbbf71c
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   net/mac80211/util.c: In function 'ieee80211_max_num_channels':
>> net/mac80211/util.c:3411:8: error: implicit declaration of function 'cfg80211_iter_combinations' [-Werror=implicit-function-declaration]
     err = cfg80211_iter_combinations(local->hw.wiphy, &params,
           ^~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/cfg80211_iter_combinations +3411 net/mac80211/util.c

e227300c Purushottam Kushwaha 2016-10-12  3405  			ieee80211_chanctx_radar_detect(local, ctx);
6fa001bc Michal Kazior        2014-04-09  3406  	}
6fa001bc Michal Kazior        2014-04-09  3407  
6fa001bc Michal Kazior        2014-04-09  3408  	list_for_each_entry_rcu(sdata, &local->interfaces, list)
e227300c Purushottam Kushwaha 2016-10-12  3409  		params.iftype_num[sdata->wdev.iftype]++;
6fa001bc Michal Kazior        2014-04-09  3410  
e227300c Purushottam Kushwaha 2016-10-12 @3411  	err = cfg80211_iter_combinations(local->hw.wiphy, &params,
e227300c Purushottam Kushwaha 2016-10-12  3412  					 ieee80211_iter_max_chans,
6fa001bc Michal Kazior        2014-04-09  3413  					 &max_num_different_channels);
6fa001bc Michal Kazior        2014-04-09  3414  	if (err < 0)

:::::: The code at line 3411 was first introduced by commit
:::::: e227300c8395dffaa7614ce7c7666a82180ebc60 cfg80211: pass struct to interface combination check/iter

:::::: TO: Purushottam Kushwaha <pkushwah@qti.qualcomm.com>
:::::: CC: Johannes Berg <johannes.berg@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 24924 bytes --]

^ permalink raw reply

* brcmfmac interface combinations
From: Johannes Berg @ 2016-10-21 11:55 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless

Hi Arend,

I'm looking into the interface combinations stuff, mostly due to the
patches from QCA to add the support for differing beacon intervals.

One thing that I was considering, was to change the API
for cfg80211_check_combinations() to not require the driver to fill in
the # of interfaces of each given type, but just have it pass the new
one, if present, or so.


However, there's a major difference between brcmfmac and mac80211 (the
only "drivers" using this), namely this: mac80211 allows *adding* any
kind of interface, as long as you don't actually try to operate it.
brcmfmac, on the other hand, prevents even adding an interface if it
doesn't fit the combinations.

I'm wondering if this is intentional?

I suspect that we can't change mac80211 at this point, and the brcmfmac
behaviour might be unexpected to some people who are used to working
with mac80211, but I'm not sure you'd want to change it either?

johannes

^ permalink raw reply

* [PATCH 1/4] cfg80211: mesh: track (and thus validate) beacon interval
From: Johannes Berg @ 2016-10-21 12:25 UTC (permalink / raw)
  To: linux-wireless
  Cc: Purushottam Kushwaha, jouni, usdutt, amarnath, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

This is needed for beacon interval validation; if we don't
store it, then new interfaces added won't validate that the
beacon interval is the same as existing ones. Fix this.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/mesh.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index fa2066b56f36..2d8518a37eab 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -183,6 +183,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
 		memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
 		wdev->mesh_id_len = setup->mesh_id_len;
 		wdev->chandef = setup->chandef;
+		wdev->beacon_interval = setup->beacon_interval;
 	}
 
 	return err;
@@ -258,6 +259,7 @@ int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
 	err = rdev_leave_mesh(rdev, dev);
 	if (!err) {
 		wdev->mesh_id_len = 0;
+		wdev->beacon_interval = 0;
 		memset(&wdev->chandef, 0, sizeof(wdev->chandef));
 		rdev_set_qos_map(rdev, dev, NULL);
 	}
-- 
2.8.1

^ permalink raw reply related

* [PATCH 3/4] cfg80211: validate beacon int as part of iface combinations
From: Johannes Berg @ 2016-10-21 12:25 UTC (permalink / raw)
  To: linux-wireless
  Cc: Purushottam Kushwaha, jouni, usdutt, amarnath, Johannes Berg
In-Reply-To: <1477052714-11223-1-git-send-email-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Remove the pointless checking against interface combinations in
the initial basic beacon interval validation, that currently isn't
taking into account radar detection or channels properly. Instead,
just validate the basic range there, and then delay real checking
to the interface combination validation that drivers must do.

This means that drivers wanting to use the beacon_int_min_gcd will
now have to pass the new_beacon_int when validating the AP/mesh
start.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/cfg80211.h | 12 +++-----
 net/wireless/util.c    | 82 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 55 insertions(+), 39 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ec39f891b7a3..d1ffbc3a8e55 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -784,19 +784,15 @@ struct cfg80211_csa_settings {
  * @iftype_num: array with the number of interfaces of each interface
  *	type.  The index is the interface type as specified in &enum
  *	nl80211_iftype.
- * @beacon_int_gcd: a value specifying GCD of all beaconing interfaces,
- *	the GCD of a single value is considered the value itself, so for
- *	a single interface this should be set to that interface's beacon
- *	interval
- * @beacon_int_different: a flag indicating whether or not all beacon
- *	intervals (of beaconing interfaces) are different or not.
+ * @new_beacon_int: set this to the beacon interval of a new interface
+ *	that's not operating yet, if such is to be checked as part of
+ *	the verification
  */
 struct iface_combination_params {
 	int num_different_channels;
 	u8 radar_detect;
 	int iftype_num[NUM_NL80211_IFTYPES];
-	u32 beacon_int_gcd;
-	bool beacon_int_different;
+	u32 new_beacon_int;
 };
 
 /**
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 78bf53705466..40d7a6bf9432 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -13,6 +13,7 @@
 #include <net/dsfield.h>
 #include <linux/if_vlan.h>
 #include <linux/mpls.h>
+#include <linux/gcd.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -1558,47 +1559,52 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
 }
 EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
 
-int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
-				 enum nl80211_iftype iftype, u32 beacon_int)
+static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
+				       u32 *beacon_int_gcd,
+				       bool *beacon_int_different)
 {
 	struct wireless_dev *wdev;
-	struct iface_combination_params params = {
-		.beacon_int_gcd = beacon_int,	/* GCD(n) = n */
-	};
 
-	if (beacon_int < 10 || beacon_int > 10000)
-		return -EINVAL;
+	*beacon_int_gcd = 0;
+	*beacon_int_different = false;
 
-	params.iftype_num[iftype] = 1;
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
 		if (!wdev->beacon_interval)
 			continue;
 
-		params.iftype_num[wdev->iftype]++;
-	}
-
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-		u32 bi_prev = wdev->beacon_interval;
-
-		if (!wdev->beacon_interval)
+		if (!*beacon_int_gcd) {
+			*beacon_int_gcd = wdev->beacon_interval;
 			continue;
+		}
 
-		/* slight optimisation - skip identical BIs */
-		if (wdev->beacon_interval == beacon_int)
+		if (wdev->beacon_interval == *beacon_int_gcd)
 			continue;
 
-		params.beacon_int_different = true;
-
-		/* Get the GCD */
-		while (bi_prev != 0) {
-			u32 tmp_bi = bi_prev;
+		*beacon_int_different = true;
+		*beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
+	}
 
-			bi_prev = params.beacon_int_gcd % bi_prev;
-			params.beacon_int_gcd = tmp_bi;
-		}
+	if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
+		*beacon_int_different = true;
+		*beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
 	}
+}
 
-	return cfg80211_check_combinations(&rdev->wiphy, &params);
+int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
+				 enum nl80211_iftype iftype, u32 beacon_int)
+{
+	/*
+	 * This is just a basic pre-condition check; if interface combinations
+	 * are possible the driver must already be checking those with a call
+	 * to cfg80211_check_combinations(), in which case we'll validate more
+	 * through the cfg80211_calculate_bi_data() call and code in
+	 * cfg80211_iter_combinations().
+	 */
+
+	if (beacon_int < 10 || beacon_int > 10000)
+		return -EINVAL;
+
+	return 0;
 }
 
 int cfg80211_iter_combinations(struct wiphy *wiphy,
@@ -1612,6 +1618,21 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 	int i, j, iftype;
 	int num_interfaces = 0;
 	u32 used_iftypes = 0;
+	u32 beacon_int_gcd;
+	bool beacon_int_different;
+
+	/*
+	 * This is a bit strange, since the iteration used to rely only on
+	 * the data given by the driver, but here it now relies on context,
+	 * in form of the currently operating interfaces.
+	 * This is OK for all current users, and saves us from having to
+	 * push the GCD calculations into all the drivers.
+	 * In the future, this should probably rely more on data that's in
+	 * cfg80211 already - the only thing not would appear to be any new
+	 * interfaces (while being brought up) and channel/radar data.
+	 */
+	cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
+				   &beacon_int_gcd, &beacon_int_different);
 
 	if (params->radar_detect) {
 		rcu_read_lock();
@@ -1674,12 +1695,11 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 		if ((all_iftypes & used_iftypes) != used_iftypes)
 			goto cont;
 
-		if (params->beacon_int_gcd) {
+		if (beacon_int_gcd) {
 			if (c->beacon_int_min_gcd &&
-			    params->beacon_int_gcd < c->beacon_int_min_gcd)
+			    beacon_int_gcd < c->beacon_int_min_gcd)
 				goto cont;
-			if (!c->beacon_int_min_gcd &&
-			    params->beacon_int_different)
+			if (!c->beacon_int_min_gcd && beacon_int_different)
 				goto cont;
 		}
 
-- 
2.8.1

^ permalink raw reply related

* [PATCH 2/4] cfg80211: disallow beacon_int_min_gcd with IBSS
From: Johannes Berg @ 2016-10-21 12:25 UTC (permalink / raw)
  To: linux-wireless
  Cc: Purushottam Kushwaha, jouni, usdutt, amarnath, Johannes Berg
In-Reply-To: <1477052714-11223-1-git-send-email-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

This can't really be supported right now, because the IBSS
interface may change its beacon interval at any time due to
joining another network; thus, there's already "support"
for different beacon intervals here, implicitly.

Until we figure out how we should handle this case (continue
to allow it to arbitrarily join? Join only if compatible?)
disallow advertising that different beacon intervals are
supported if IBSS is allowed.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/core.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/net/wireless/core.c b/net/wireless/core.c
index 725adff6c7d4..158c59ecf90a 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -562,6 +562,21 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
 				    c->limits[j].max > 1))
 				return -EINVAL;
 
+			/*
+			 * This isn't well-defined right now. If you have an
+			 * IBSS interface, then its beacon interval may change
+			 * by joining other networks, and nothing prevents it
+			 * from doing that.
+			 * So technically we probably shouldn't even allow AP
+			 * and IBSS in the same interface, but it seems that
+			 * some drivers support that, possibly only with fixed
+			 * beacon intervals for IBSS.
+			 */
+			if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) &&
+				    c->beacon_int_min_gcd)) {
+				return -EINVAL;
+			}
+
 			cnt += c->limits[j].max;
 			/*
 			 * Don't advertise an unsupported type
-- 
2.8.1

^ permalink raw reply related

* [PATCH 4/4] mac80211: validate new interface's beacon intervals
From: Johannes Berg @ 2016-10-21 12:25 UTC (permalink / raw)
  To: linux-wireless
  Cc: Purushottam Kushwaha, jouni, usdutt, amarnath, Johannes Berg
In-Reply-To: <1477052714-11223-1-git-send-email-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

As part of interface combination checking, verify any new
interface's beacon intervals. In fact, just always add the
beacon interval since that's harmless.

With this patch, mac80211 is prepared for drivers that set
the min_beacon_int_gcd parameter in interface combinations.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c  |  3 ++-
 net/mac80211/util.c | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index eb68add4393c..e91e503bf992 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -864,6 +864,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	}
 	sdata->needed_rx_chains = sdata->local->rx_chains;
 
+	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
+
 	mutex_lock(&local->mtx);
 	err = ieee80211_vif_use_channel(sdata, &params->chandef,
 					IEEE80211_CHANCTX_SHARED);
@@ -894,7 +896,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 					      vlan->vif.type);
 	}
 
-	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
 	sdata->vif.bss_conf.dtim_period = params->dtim_period;
 	sdata->vif.bss_conf.enable_beacon = true;
 	sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7f24bdc68f71..ac59fbd280df 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3326,6 +3326,16 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 	if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
 		return -EINVAL;
 
+	if (sdata->vif.type == NL80211_IFTYPE_AP ||
+	    sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
+		/*
+		 * always passing this is harmless, since it'll be the
+		 * same value that cfg80211 finds if it finds the same
+		 * interface ... and that's always allowed
+		 */
+		params.new_beacon_int = sdata->vif.bss_conf.beacon_int;
+	}
+
 	/* Always allow software iftypes */
 	if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
 		if (radar_detect)
-- 
2.8.1

^ permalink raw reply related

* Re: [PATCH v3] cfg80211: Check radar_detect and num_different_channels with beacon interface combinations.
From: Johannes Berg @ 2016-10-21 12:27 UTC (permalink / raw)
  To: Purushottam Kushwaha; +Cc: linux-wireless, jouni, usdutt, amarnath
In-Reply-To: <1476371730-23027-1-git-send-email-pkushwah@qti.qualcomm.com>

On Thu, 2016-10-13 at 20:45 +0530, Purushottam Kushwaha wrote:
> This commit enhances the current beacon interval validation to also
> consider
> the "radar_detect" and "num_different_channels".
> 
> Move calculation of GCD for all beaconing interfaces to
> "cfg80211_iter_combinations".
> 
> Rename "cfg80211_validate_beacon_int" to
> "cfg80211_validate_beacon_combination"
> as the validation considers other parameters.

So this was better, but I think we're mixing too many things in here.

I'm not convinced, for example, that checking if radar is required is
really the right thing, it might still be enabled even if it's not
required (any more, regulatory may change)?

Not that I don't think that's a worthwhile goal - moving more of the
data/calculation back into cfg80211 - but I don't think it should be
mixed in here.

I've just sent out a few patches that, I think, implement the necessary
validation for just the beacon intervals, without all this extra
baggage. Please take a look and let me know what you think.

johannes

^ permalink raw reply

* Re: sequence diagrams in rst documentation
From: Johannes Berg @ 2016-10-21 12:31 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: linux-wireless, linux-doc
In-Reply-To: <1476863488.5927.10.camel@sipsolutions.net>


> > 	https://pythonhosted.org/sphinxcontrib-aafig/
> > 
> > I've not actually played with it at all, but I like the idea that
> > we'd have readable diagrams in the source docs as well...
> 
> Well, maybe. I agree having it readable in the source docs as well is
> nice, but for sequence diagrams in particular, I don't think
> 
>     +-------+         +-----------+
>     | Hello +-------->+ aafigure! |
>     +-------+         +-----------+
> 
> really beats
> 
>    Hello -> aafigure!


I found another one:

https://pypi.python.org/pypi/sphinxcontrib-plantuml

That one has really nice output and features, but ends up being a
*java* (of all the things) tool that the thing calls out to ...


Perhaps we can have a compromise and embed the raw text when the
tooling isn't all installed, so you can still build useful
documentation, but to get all the "prettiness" you might have to
install more dependencies?

johannes

^ permalink raw reply

* Re: sequence diagrams in rst documentation
From: Jani Nikula @ 2016-10-21 12:56 UTC (permalink / raw)
  To: Johannes Berg, Jonathan Corbet; +Cc: linux-wireless, linux-doc, Markus Heiser
In-Reply-To: <1477053099.4068.42.camel@sipsolutions.net>

On Fri, 21 Oct 2016, Johannes Berg <johannes@sipsolutions.net> wrote:
>> > 	https://pythonhosted.org/sphinxcontrib-aafig/
>> > 
>> > I've not actually played with it at all, but I like the idea that
>> > we'd have readable diagrams in the source docs as well...
>> 
>> Well, maybe. I agree having it readable in the source docs as well is
>> nice, but for sequence diagrams in particular, I don't think
>> 
>>     +-------+         +-----------+
>>     | Hello +-------->+ aafigure! |
>>     +-------+         +-----------+
>> 
>> really beats
>> 
>>    Hello -> aafigure!
>
>
> I found another one:
>
> https://pypi.python.org/pypi/sphinxcontrib-plantuml
>
> That one has really nice output and features, but ends up being a
> *java* (of all the things) tool that the thing calls out to ...
>
>
> Perhaps we can have a compromise and embed the raw text when the
> tooling isn't all installed, so you can still build useful
> documentation, but to get all the "prettiness" you might have to
> install more dependencies?

I had the same conclusion for math:: directives pulling in latex
dependency [1]. Hopefully Markus can help here.

BR,
Jani.


[1] http://lkml.kernel.org/r/877f93qdd2.fsf@intel.com



-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply

* [PATCH 1/2] mac80211: fix some sphinx warnings
From: Jani Nikula @ 2016-10-21 12:57 UTC (permalink / raw)
  To: johannes, linux-wireless; +Cc: linux-doc, Jani Nikula

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 include/net/mac80211.h | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a810dfcb83c2..e2dba93e374f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -811,14 +811,18 @@ enum mac80211_rate_control_flags {
  * in the control information, and it will be filled by the rate
  * control algorithm according to what should be sent. For example,
  * if this array contains, in the format { <idx>, <count> } the
- * information
+ * information::
+ *
  *    { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }
+ *
  * then this means that the frame should be transmitted
  * up to twice at rate 3, up to twice at rate 2, and up to four
  * times at rate 1 if it doesn't get acknowledged. Say it gets
  * acknowledged by the peer after the fifth attempt, the status
- * information should then contain
+ * information should then contain::
+ *
  *   { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...
+ *
  * since it was transmitted twice at rate 3, twice at rate 2
  * and once at rate 1 after which we received an acknowledgement.
  */
@@ -1168,8 +1172,8 @@ enum mac80211_rx_vht_flags {
  * @rate_idx: index of data rate into band's supported rates or MCS index if
  *	HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
  * @vht_nss: number of streams (VHT only)
- * @flag: %RX_FLAG_*
- * @vht_flag: %RX_VHT_FLAG_*
+ * @flag: %RX_FLAG_\*
+ * @vht_flag: %RX_VHT_FLAG_\*
  * @rx_flags: internal RX flags for mac80211
  * @ampdu_reference: A-MPDU reference number, must be a different value for
  *	each A-MPDU but the same for each subframe within one A-MPDU
@@ -1432,7 +1436,7 @@ enum ieee80211_vif_flags {
  * @probe_req_reg: probe requests should be reported to mac80211 for this
  *	interface.
  * @drv_priv: data area for driver use, will always be aligned to
- *	sizeof(void *).
+ *	sizeof(void \*).
  * @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
  */
 struct ieee80211_vif {
@@ -1743,7 +1747,7 @@ struct ieee80211_sta_rates {
  * @wme: indicates whether the STA supports QoS/WME (if local devices does,
  *	otherwise always false)
  * @drv_priv: data area for driver use, will always be aligned to
- *	sizeof(void *), size is determined in hw information.
+ *	sizeof(void \*), size is determined in hw information.
  * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
  *	if wme is supported.
  * @max_sp: max Service Period. Only valid if wme is supported.
@@ -2146,12 +2150,12 @@ enum ieee80211_hw_flags {
  *
  * @radiotap_mcs_details: lists which MCS information can the HW
  *	reports, by default it is set to _MCS, _GI and _BW but doesn't
- *	include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only
+ *	include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_\* values, only
  *	adding _BW is supported today.
  *
  * @radiotap_vht_details: lists which VHT MCS information the HW reports,
  *	the default is _GI | _BANDWIDTH.
- *	Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values.
+ *	Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values.
  *
  * @radiotap_timestamp: Information for the radiotap timestamp field; if the
  *	'units_pos' member is set to a non-negative value it must be set to
@@ -2486,6 +2490,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  * in the software stack cares about, we will, in the future, have mac80211
  * tell the driver which information elements are interesting in the sense
  * that we want to see changes in them. This will include
+ *
  *  - a list of information element IDs
  *  - a list of OUIs for the vendor information element
  *
-- 
2.1.4

^ permalink raw reply related

* [PATCH 2/2] mac80211: use inline kernel-doc for struct ieee80211_hw
From: Jani Nikula @ 2016-10-21 12:57 UTC (permalink / raw)
  To: johannes, linux-wireless; +Cc: linux-doc, Jani Nikula
In-Reply-To: <1477054644-5945-1-git-send-email-jani.nikula@intel.com>

It's easier to manage the kernel-doc for the fields when they
documentation is next to the field.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>

---

The same treatment is sorely needed for struct ieee80211_ops also, but I
don't have the time... this would get rid of the rest of the warnings in
mac80211.h.
---
 include/net/mac80211.h | 280 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 173 insertions(+), 107 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e2dba93e374f..7f659c21ffba 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2078,147 +2078,213 @@ enum ieee80211_hw_flags {
 /**
  * struct ieee80211_hw - hardware information and state
  *
- * This structure contains the configuration and hardware
- * information for an 802.11 PHY.
- *
- * @wiphy: This points to the &struct wiphy allocated for this
- *	802.11 PHY. You must fill in the @perm_addr and @dev
- *	members of this structure using SET_IEEE80211_DEV()
- *	and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
- *	bands (with channels, bitrates) are registered here.
- *
- * @conf: &struct ieee80211_conf, device configuration, don't use.
- *
- * @priv: pointer to private area that was allocated for driver use
- *	along with this structure.
- *
- * @flags: hardware flags, see &enum ieee80211_hw_flags.
- *
- * @extra_tx_headroom: headroom to reserve in each transmit skb
- *	for use by the driver (e.g. for transmit headers.)
- *
- * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
- *	Can be used by drivers to add extra IEs.
- *
- * @max_signal: Maximum value for signal (rssi) in RX information, used
- *	only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
- *
- * @max_listen_interval: max listen interval in units of beacon interval
- *	that HW supports
- *
- * @queues: number of available hardware transmit queues for
- *	data packets. WMM/QoS requires at least four, these
- *	queues need to have configurable access parameters.
- *
- * @rate_control_algorithm: rate control algorithm for this hardware.
- *	If unset (NULL), the default algorithm will be used. Must be
- *	set before calling ieee80211_register_hw().
- *
- * @vif_data_size: size (in bytes) of the drv_priv data area
- *	within &struct ieee80211_vif.
- * @sta_data_size: size (in bytes) of the drv_priv data area
- *	within &struct ieee80211_sta.
- * @chanctx_data_size: size (in bytes) of the drv_priv data area
- *	within &struct ieee80211_chanctx_conf.
- * @txq_data_size: size (in bytes) of the drv_priv data area
- *	within @struct ieee80211_txq.
- *
- * @max_rates: maximum number of alternate rate retry stages the hw
- *	can handle.
- * @max_report_rates: maximum number of alternate rate retry stages
- *	the hw can report back.
- * @max_rate_tries: maximum number of tries for each stage
- *
- * @max_rx_aggregation_subframes: maximum buffer size (number of
- *	sub-frames) to be used for A-MPDU block ack receiver
- *	aggregation.
- *	This is only relevant if the device has restrictions on the
- *	number of subframes, if it relies on mac80211 to do reordering
- *	it shouldn't be set.
- *
- * @max_tx_aggregation_subframes: maximum number of subframes in an
- *	aggregate an HT driver will transmit. Though ADDBA will advertise
- *	a constant value of 64 as some older APs can crash if the window
- *	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)
- *
- * @radiotap_mcs_details: lists which MCS information can the HW
- *	reports, by default it is set to _MCS, _GI and _BW but doesn't
- *	include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_\* values, only
- *	adding _BW is supported today.
- *
- * @radiotap_vht_details: lists which VHT MCS information the HW reports,
- *	the default is _GI | _BANDWIDTH.
- *	Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values.
- *
- * @radiotap_timestamp: Information for the radiotap timestamp field; if the
- *	'units_pos' member is set to a non-negative value it must be set to
- *	a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a
- *	IEEE80211_RADIOTAP_TIMESTAMP_SPOS_* value, and then the timestamp
- *	field will be added and populated from the &struct ieee80211_rx_status
- *	device_timestamp. If the 'accuracy' member is non-negative, it's put
- *	into the accuracy radiotap field and the accuracy known flag is set.
- *
- * @netdev_features: netdev features to be set in each netdev created
- *	from this HW. Note that not all features are usable with mac80211,
- *	other features will be rejected during HW registration.
- *
- * @uapsd_queues: This bitmap is included in (re)association frame to indicate
- *	for each access category if it is uAPSD trigger-enabled and delivery-
- *	enabled. Use IEEE80211_WMM_IE_STA_QOSINFO_AC_* to set this bitmap.
- *	Each bit corresponds to different AC. Value '1' in specific bit means
- *	that corresponding AC is both trigger- and delivery-enabled. '0' means
- *	neither enabled.
- *
- * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
- *	deliver to a WMM STA during any Service Period triggered by the WMM STA.
- *	Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
- *
- * @n_cipher_schemes: a size of an array of cipher schemes definitions.
- * @cipher_schemes: a pointer to an array of cipher scheme definitions
- *	supported by HW.
- * @max_nan_de_entries: maximum number of NAN DE functions supported by the
- *	device.
+ * This structure contains the configuration and hardware information for an
+ * 802.11 PHY.
  */
 struct ieee80211_hw {
+	/**
+	 * @conf: &struct ieee80211_conf, device configuration, don't use.
+	 */
 	struct ieee80211_conf conf;
+
+	/**
+	 * @wiphy: This points to the &struct wiphy allocated for this 802.11
+	 * PHY. You must fill in the @perm_addr and @dev members of this
+	 * structure using SET_IEEE80211_DEV() and
+	 * SET_IEEE80211_PERM_ADDR(). Additionally, all supported bands (with
+	 * channels, bitrates) are registered here.
+	 */
 	struct wiphy *wiphy;
+
+	/**
+	 * @rate_control_algorithm: rate control algorithm for this hardware.
+	 * If unset (NULL), the default algorithm will be used. Must be set
+	 * before calling ieee80211_register_hw().
+	 */
 	const char *rate_control_algorithm;
+
+	/**
+	 * @priv: pointer to private area that was allocated for driver use
+	 * along with this structure.
+	 */
 	void *priv;
+
+	/**
+	 * @flags: hardware flags, see &enum ieee80211_hw_flags.
+	 */
 	unsigned long flags[BITS_TO_LONGS(NUM_IEEE80211_HW_FLAGS)];
+
+	/**
+	 * @extra_tx_headroom: headroom to reserve in each transmit skb for use
+	 * by the driver (e.g. for transmit headers.)
+	 */
 	unsigned int extra_tx_headroom;
+
+	/**
+	 * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
+	 * Can be used by drivers to add extra IEs.
+	 */
 	unsigned int extra_beacon_tailroom;
+
+	/**
+	 * @vif_data_size: size (in bytes) of the drv_priv data area
+	 * within &struct ieee80211_vif.
+	 */
 	int vif_data_size;
+
+	/**
+	 * @sta_data_size: size (in bytes) of the drv_priv data area within
+	 * &struct ieee80211_sta.
+	 */
 	int sta_data_size;
+
+	/**
+	 * @chanctx_data_size: size (in bytes) of the drv_priv data area within
+	 * &struct ieee80211_chanctx_conf.
+	 */
 	int chanctx_data_size;
+
+	/**
+	 * @txq_data_size: size (in bytes) of the drv_priv data area
+	 * within @struct ieee80211_txq.
+	 */
 	int txq_data_size;
+
+	/**
+	 * @queues: number of available hardware transmit queues for data
+	 * packets. WMM/QoS requires at least four, these queues need to have
+	 * configurable access parameters.
+	 */
 	u16 queues;
+
+	/**
+	 * @max_listen_interval: max listen interval in units of beacon interval
+	 * that HW supports
+	 */
 	u16 max_listen_interval;
+
+	/**
+	 * @max_signal: Maximum value for signal (rssi) in RX information, used
+	 * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
+	 */
 	s8 max_signal;
+
+	/**
+	 * @max_rates: maximum number of alternate rate retry stages the hw can
+	 * handle.
+	 */
 	u8 max_rates;
+
+	/**
+	 * @max_report_rates: maximum number of alternate rate retry stages
+	 * the hw can report back.
+	 */
 	u8 max_report_rates;
+
+	/**
+	 * @max_rate_tries: maximum number of tries for each stage
+	 */
 	u8 max_rate_tries;
+
+	/**
+	 * @max_rx_aggregation_subframes: maximum buffer size (number of
+	 * sub-frames) to be used for A-MPDU block ack receiver aggregation.
+	 * This is only relevant if the device has restrictions on the number of
+	 * subframes, if it relies on mac80211 to do reordering it shouldn't be
+	 * set.
+	 */
 	u8 max_rx_aggregation_subframes;
+
+	/**
+	 * @max_tx_aggregation_subframes: maximum number of subframes in an
+	 * aggregate an HT driver will transmit. Though ADDBA will advertise a
+	 * constant value of 64 as some older APs can crash if the window size
+	 * is smaller (an example is LinkSys WRT120N with FW v1.0.07 build 002
+	 * Jun 18 2012).
+	 */
 	u8 max_tx_aggregation_subframes;
+
+	/**
+	 * @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.
+	 */
 	u8 max_tx_fragments;
+
+	/**
+	 * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX (if
+	 * %IEEE80211_HW_QUEUE_CONTROL is set)
+	 */
 	u8 offchannel_tx_hw_queue;
+
+	/**
+	 * @radiotap_mcs_details: lists which MCS information can the HW
+	 * reports, by default it is set to _MCS, _GI and _BW but doesn't
+	 * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_\* values, only adding
+	 * _BW is supported today.
+	 */
 	u8 radiotap_mcs_details;
+
+	/**
+	 * @radiotap_vht_details: lists which VHT MCS information the HW
+	 * reports, the default is _GI | _BANDWIDTH.  Use the
+	 * %IEEE80211_RADIOTAP_VHT_KNOWN_\* values.
+	 */
 	u16 radiotap_vht_details;
+
+	/**
+	 * @radiotap_timestamp: Information for the radiotap timestamp field; if
+	 * the 'units_pos' member is set to a non-negative value it must be set
+	 * to a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a
+	 * IEEE80211_RADIOTAP_TIMESTAMP_SPOS_* value, and then the timestamp
+	 * field will be added and populated from the &struct
+	 * ieee80211_rx_status device_timestamp. If the 'accuracy' member is
+	 * non-negative, it's put into the accuracy radiotap field and the
+	 * accuracy known flag is set.
+	 */
 	struct {
 		int units_pos;
 		s16 accuracy;
 	} radiotap_timestamp;
+
+	/**
+	 * @netdev_features: netdev features to be set in each netdev created
+	 * from this HW. Note that not all features are usable with mac80211,
+	 * other features will be rejected during HW registration.
+	 */
 	netdev_features_t netdev_features;
+
+	/**
+	 * @uapsd_queues: This bitmap is included in (re)association frame to
+	 * indicate for each access category if it is uAPSD trigger-enabled and
+	 * delivery- enabled. Use IEEE80211_WMM_IE_STA_QOSINFO_AC_* to set this
+	 * bitmap.  Each bit corresponds to different AC. Value '1' in specific
+	 * bit means that corresponding AC is both trigger- and
+	 * delivery-enabled. '0' means neither enabled.
+	 */
 	u8 uapsd_queues;
+
+	/**
+	 * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP
+	 * may deliver to a WMM STA during any Service Period triggered by the
+	 * WMM STA. Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
+	 */
 	u8 uapsd_max_sp_len;
+
+	/**
+	 * @n_cipher_schemes: a size of an array of cipher schemes definitions.
+	 */
 	u8 n_cipher_schemes;
+
+	/**
+	 * @cipher_schemes: a pointer to an array of cipher scheme definitions
+	 * supported by HW.
+	 */
 	const struct ieee80211_cipher_scheme *cipher_schemes;
+
+	/**
+	 * @max_nan_de_entries: maximum number of NAN DE functions supported by
+	 * the device.
+	 */
 	u8 max_nan_de_entries;
 };
 
-- 
2.1.4

^ permalink raw reply related

* wl12xx stuck in fw
From: Nicklas Persson @ 2016-10-21 12:57 UTC (permalink / raw)
  To: linux-wireless

Hi, I have been debugging my WLAN driver interface for a while. I have
a Beaglebone equivalent board with the TI wl1271 wireless module. I am
very new to linux drivers and wireless configuration so these couple
of days I have spent have been really interesting and I have much more
knowledge now.

My problem is that when I run "ifconfig wlan0 up" I get the following
message over and over again:

"wlcore: ERROR Tx stuck (in FW) for 5000 ms. Starting recover"

I successfully done a calibration, that does not help. I also tried
with the default .nvs file that is provided.

I have tried with different firmware binaries with no luck. Actually,
I have browsed the source code for wl12xx and wlcore and it seems like
I need to use the 5-series of firmware binaries so I have been using
those for the most time.

I have rebuilt the kernel with a lot of added printk()'s all over the
place but I do not understand at all what is happening. My guess is
that there is something with the watchdog and that the driver thinks
that the firmware/wlan module is not responding.

I am really desperate for some guidance or some pointers. What can I try next?

Thanks,
Regards Nicklas.

^ permalink raw reply

* Re: [PATCH 1/2] mac80211: fix some sphinx warnings
From: Johannes Berg @ 2016-10-21 13:01 UTC (permalink / raw)
  To: Jani Nikula, linux-wireless; +Cc: linux-doc
In-Reply-To: <1477054644-5945-1-git-send-email-jani.nikula@intel.com>

On Fri, 2016-10-21 at 15:57 +0300, Jani Nikula wrote:
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  include/net/mac80211.h | 21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index a810dfcb83c2..e2dba93e374f 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -811,14 +811,18 @@ enum mac80211_rate_control_flags {
>   * in the control information, and it will be filled by the rate
>   * control algorithm according to what should be sent. For example,
>   * if this array contains, in the format { <idx>, <count> } the
> - * information
> + * information::
> 
[...]

interesting, are these not enabled by default?

I guess I'll pick up these patches, even if they probably make things
worse in my tree, since there it's still using docbook. But once we
merge everything it should be good then.

johannes

^ permalink raw reply

* Re: [PATCH 2/2] mac80211: use inline kernel-doc for struct ieee80211_hw
From: Johannes Berg @ 2016-10-21 13:01 UTC (permalink / raw)
  To: Jani Nikula, linux-wireless; +Cc: linux-doc
In-Reply-To: <1477054644-5945-2-git-send-email-jani.nikula@intel.com>

On Fri, 2016-10-21 at 15:57 +0300, Jani Nikula wrote:
> It's easier to manage the kernel-doc for the fields when they
> documentation is next to the field.

Hah, I wasn't even aware this was possible. Thanks!

johannes

^ permalink raw reply

* Re: sequence diagrams in rst documentation
From: Johannes Berg @ 2016-10-21 13:04 UTC (permalink / raw)
  To: Jani Nikula, Jonathan Corbet; +Cc: linux-wireless, linux-doc, Markus Heiser
In-Reply-To: <87k2d1q2qx.fsf@intel.com>

> I had the same conclusion for math:: directives pulling in latex
> dependency [1]. Hopefully Markus can help here.

Yeah, good one.

Maybe it's actually simple? Depending on where sphinx will look for
plugins first, we could just ship the plugins with a no-op
implementation (pass through the text as pre-formatted text), and if it
finds the plugin first in a system-wide path that version would win for
the better rendering?

johannes

^ permalink raw reply

* Re: [PATCH 1/2] mac80211: fix some sphinx warnings
From: Jani Nikula @ 2016-10-21 13:14 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: linux-doc
In-Reply-To: <1477054872.4068.43.camel@sipsolutions.net>

On Fri, 21 Oct 2016, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Fri, 2016-10-21 at 15:57 +0300, Jani Nikula wrote:
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>> ---
>>  include/net/mac80211.h | 21 +++++++++++++--------
>>  1 file changed, 13 insertions(+), 8 deletions(-)
>> 
>> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
>> index a810dfcb83c2..e2dba93e374f 100644
>> --- a/include/net/mac80211.h
>> +++ b/include/net/mac80211.h
>> @@ -811,14 +811,18 @@ enum mac80211_rate_control_flags {
>>   * in the control information, and it will be filled by the rate
>>   * control algorithm according to what should be sent. For example,
>>   * if this array contains, in the format { <idx>, <count> } the
>> - * information
>> + * information::
>> 
> [...]
>
> interesting, are these not enabled by default?

rst wants indented blocks to be separated by blank lines from the
preceding and following blocks. For that you could just add the blank
lines, and it'll work.

I presumed this was nicer as preformatted/monospaced text, and for that
you'll need the "::". Up to you to have that or not.

> I guess I'll pick up these patches, even if they probably make things
> worse in my tree, since there it's still using docbook. But once we
> merge everything it should be good then.

Oh, it's built as reStructuredText in Linus' tree. Again, up to you.

BR,
Jani.


-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply

* Re: [PATCH 1/2] mac80211: fix some sphinx warnings
From: Johannes Berg @ 2016-10-21 13:17 UTC (permalink / raw)
  To: Jani Nikula, linux-wireless; +Cc: linux-doc
In-Reply-To: <87h985q1y6.fsf@intel.com>

On Fri, 2016-10-21 at 16:14 +0300, Jani Nikula wrote:
> On Fri, 21 Oct 2016, Johannes Berg <johannes@sipsolutions.net> wrote:
> > 
> > On Fri, 2016-10-21 at 15:57 +0300, Jani Nikula wrote:
> > > 
> > > Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> > > ---
> > >  include/net/mac80211.h | 21 +++++++++++++--------
> > >  1 file changed, 13 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> > > index a810dfcb83c2..e2dba93e374f 100644
> > > --- a/include/net/mac80211.h
> > > +++ b/include/net/mac80211.h
> > > @@ -811,14 +811,18 @@ enum mac80211_rate_control_flags {
> > >   * in the control information, and it will be filled by the rate
> > >   * control algorithm according to what should be sent. For
> > > example,
> > >   * if this array contains, in the format { <idx>, <count> } the
> > > - * information
> > > + * information::
> > > 
> > [...]
> > 
> > interesting, are these not enabled by default?

> rst wants indented blocks to be separated by blank lines from the
> preceding and following blocks. For that you could just add the blank
> lines, and it'll work.
> 
> I presumed this was nicer as preformatted/monospaced text, and for
> that you'll need the "::". Up to you to have that or not.

Well, I meant the warnings :)

But yeah, this is better as preformatted text. It never came out that
way with docbook either, I think, but now we can fix that.

> > I guess I'll pick up these patches, even if they probably make
> > things
> > worse in my tree, since there it's still using docbook. But once we
> > merge everything it should be good then.
> 
> Oh, it's built as reStructuredText in Linus' tree. Again, up to you.

Right. No worries. I just haven't gotten my own change back from
Linus's tree into mine, but it only means that generating the doc from
mac80211-next or net-next might be weird, which isn't a problem.

johannes

^ permalink raw reply

* Re: [PATCH 2/2] mac80211: use inline kernel-doc for struct ieee80211_hw
From: Jani Nikula @ 2016-10-21 13:18 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: linux-doc
In-Reply-To: <1477054892.4068.44.camel@sipsolutions.net>

On Fri, 21 Oct 2016, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Fri, 2016-10-21 at 15:57 +0300, Jani Nikula wrote:
>> It's easier to manage the kernel-doc for the fields when they
>> documentation is next to the field.
>
> Hah, I wasn't even aware this was possible. Thanks!

It is indeed. And this lets you have multi-paragraph descriptions for
fields which would be impossible in the top level struct kernel-doc,
because you can't have blank lines in the field descriptions there.

Currently you can't have one line inline /** @foo: bar */ descriptions
though, the opening and closing comment markers still need to be on
their own lines. Maybe I'll get around to fixing that one of these
days...

BR,
Jani.


-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply

* Re: [PATCH][RFC] nl80211/mac80211: Rounded RSSI reporting
From: Denis Kenzior @ 2016-10-21 14:20 UTC (permalink / raw)
  To: Johannes Berg, Andrew Zaborowski, linux-wireless
In-Reply-To: <1477038639.4068.28.camel@sipsolutions.net>

Hi Johannes,

On 10/21/2016 03:30 AM, Johannes Berg wrote:
> Hi,
>
>> Userspace tends to display a wifi icon with the rssi shown as a
>> number of "signal bars", usually 4, 5, or 6.
>
> It's actually not clear to me that this is really how it should be.
> There's a point to be made that taking a more holistic "link quality"
> would be a better choice. That's related, but maybe can be a separate
> discussion.
>

Can you elaborate on this 'link quality' idea?

>> and a hysteresis value to be used in the same way as with the
>> NL80211_ATTR_CQM_RSSI_THOLD attribute, or even modify it to allow
>> multiple thresholds to be given but that would need a problematic
>> driver api change.  What would be the best way to do that?
>
> So ... I don't think there's a good way to do this at all.
>
> The problem is that you really want this to be offloaded to the device,
> *especially* if you care about low power usage, because you absolutely
> don't want to be processing each beacon (which is typically what we
> derive the data from today) in the host CPU - you want those to be
> filtered by the device so you don't wake up the host CPU every ~102ms.

Yes, this would be ideal.

>
> Without offloading to the device, your patch is actually fairly much
> pointless, because you've already woken up the host CPU, at which point
> punting to userspace probably isn't all that much more expensive over
> the cost of waking up the CPU in the first place.

Requiring user space application to process every beacon seems like a 
cop-out to me.  Kernel should provide a proper API for this.  That way 
if the hardware / drivers add offloading support for this in the future, 
userspace can be blissfully ignorant.

Not to mention that the cost of waking up the process, sending a netlink 
message, having userspace process the beacon, etc is not insignificant.

>
> Looking at the code, it seems like only a single driver could support
> this in a pseudo-offloaded fashion (iwlmvm), where all the others that
> offload it today would not be able to support this API at all, unless
> they fall back to complete software processing which, as I wrote above,
> will have far worse power consumption consequences.
>
>
> Therefore, adding this API just for mac80211 seems pretty pointless,
> especially since you're targeting this for IoT, where I expect people
> will be using full-MAC chips rather than soft-MAC, with the consequence
> of not even using mac80211-based drivers. Oops.
>

The scope is not limited to IoT devices.  This has to work everywhere. 
So we need a proper solution to report signal strength / signal quality 
without resorting to polling or having userspace process every packet on 
the WiFi device.  Suggestions?

>> The assumption is that you can't simulate the same behavior with just
>> the current NL80211_ATTR_CQM_RSSI_THOLD attribute.
>
> Is that true? Technically, it seems that perhaps if you wanted to have
> a few ranges, you could always pick one that's currently active, and
> program that into the driver/device, with a hysteresis big enough to
> extend to the edges of the next range, or something?
>
> Let's say you're currently sitting at -50dBm, and want your ranges to
> be -100..-80..-60..-40..-20. Then you could program -50dBm with
> hysteresis of 10dBm, and it'd tell you when you move below/above?
>
> This probably won't really work, the hysteresis probably won't be
> honoured precisely enough by all drivers. Or we can just fix the
> drivers, I guess. However, if you're just at the edge of your range,
> e.g. when your current signal strength is -60dBm, you'd still flip-flop
> in and out of that range continuously, although userspace could just
> program a different threshold/hysteresis for those cases as well.
>
> Anyway, not sure this can be made to work, and drivers would play ball.

This sounds really brittle.  Furthermore, we also need a facility to 
know when signal strength is getting low to trigger roaming logic.  This 
would mean sharing CQM facility between roaming & signal strength 
notifications.  As you wrote above, things become quite impractical.

Regards,
-Denis

^ permalink raw reply

* [PATCH 1/2] mwifiex: fix corner case power save issue
From: Amitkumar Karwar @ 2016-10-21 15:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: Cathy Luo, Nishant Sarmukadam, Amitkumar Karwar

We may get SLEEP event from firmware even if TXDone for last Tx packet
is still pending. In this case, we may end up accessing PCIe memory for
handling TXDone after power save handshake is completed. This causes
kernel crash with external abort.

We will delay sending SLEEP confirm to firmware in
this case to resolve the problem.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 5347728..f582f61 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1118,7 +1118,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
 void
 mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
 {
-	if (!adapter->cmd_sent &&
+	if (!adapter->cmd_sent && !adapter->data_sent &&
 	    !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
 		mwifiex_dnld_sleep_confirm_cmd(adapter);
 	else
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/2] mwifiex: ignore calibration data failure
From: Amitkumar Karwar @ 2016-10-21 15:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: Cathy Luo, Nishant Sarmukadam, Amitkumar Karwar
In-Reply-To: <1477062948-8558-1-git-send-email-akarwar@marvell.com>

Firmware may reject calibration data from host for certain OTP
settings. In that case, we should continue initialisation ignoring
the failure.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 2a162c3..638d30a 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2228,19 +2228,13 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
 				adapter->hs_cfg.gpio = data;
 			}
 
-			ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
-						      "marvell,caldata");
-			if (ret)
-				return -1;
+			mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
+						"marvell,caldata");
 		}
 
-		if (adapter->cal_data) {
-			ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
-					       HostCmd_ACT_GEN_SET, 0, NULL,
-					       true);
-			if (ret)
-				return -1;
-		}
+		if (adapter->cal_data)
+			mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA,
+					 HostCmd_ACT_GEN_SET, 0, NULL, true);
 
 		/* Read MAC address from HW */
 		ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
-- 
1.9.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox