Commit 9ee1ba47 authored by Ron Rindjunsky's avatar Ron Rindjunsky Committed by David S. Miller
Browse files

iwlwifi: 802.11n add support to 8K A-MSDU Rx frames



This patch give the iwlwifi the ability to support A-MSDU up to 8K

Please notice - in order to work in 8K A-MSDU ucode support is needed,
version 4.44.1.19 (soon to be published). 4K A-MSDU works in current ucode
version as well.

Signed-off-by: default avatarRon Rindjunsky <ron.rindjunsky@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 270243a5
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -646,9 +646,6 @@ struct iwl3945_eeprom {
#define RX_FREE_BUFFERS 64
#define RX_LOW_WATERMARK 8

/* Size of one Rx buffer in host DRAM */
#define IWL_RX_BUF_SIZE 3000

/* Sizes and addresses for instruction and data memory (SRAM) in
 * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
#define RTC_INST_LOWER_BOUND			(0x000000)
+2 −1
Original line number Diff line number Diff line
@@ -2229,7 +2229,8 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
	}

	priv->hw_setting.ac_queue_count = AC_NUM;
	priv->hw_setting.rx_buffer_size = IWL_RX_BUF_SIZE;
	priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
	priv->hw_setting.max_pkt_size = 2342;
	priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
	priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
	priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
+29 −2
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ enum iwl3945_antenna {
 * else RTS for data/management frames where MPDU is larger
 *   than RTS value.
 */
#define IWL_RX_BUF_SIZE           3000U
#define DEFAULT_RTS_THRESHOLD     2347U
#define MIN_RTS_THRESHOLD         0U
#define MAX_RTS_THRESHOLD         2347U
@@ -452,6 +453,30 @@ union iwl3945_ht_rate_supp {
	};
};

#ifdef CONFIG_IWL3945_HT
#define CFG_HT_RX_AMPDU_FACTOR_DEF  (0x3)
#define CFG_HT_MPDU_DENSITY_2USEC   (0x5)
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC

struct sta_ht_info {
	u8 is_ht;
	u16 rx_mimo_ps_mode;
	u16 tx_mimo_ps_mode;
	u16 control_channel;
	u8 max_amsdu_size;
	u8 ampdu_factor;
	u8 mpdu_density;
	u8 operating_mode;
	u8 supported_chan_width;
	u8 extension_chan_offset;
	u8 is_green_field;
	u8 sgf;
	u8 supp_rates[16];
	u8 tx_chan_width;
	u8 chan_width_cap;
};
#endif				/*CONFIG_IWL3945_HT */

#ifdef CONFIG_IWL3945_QOS

union iwl3945_qos_capabity {
@@ -535,7 +560,8 @@ struct iwl3945_ibss_seq {
 * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
 * @tx_cmd_len: Size of Tx command (but not including frame itself)
 * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
 * @rx_buffer_size:
 * @rx_buf_size:
 * @max_pkt_size:
 * @max_rxq_log: Log-base-2 of max_rxq_size
 * @max_stations:
 * @bcast_sta_id:
@@ -547,7 +573,8 @@ struct iwl3945_driver_hw_info {
	u16 ac_queue_count;
	u16 tx_cmd_len;
	u16 max_rxq_size;
	u32 rx_buffer_size;
	u32 rx_buf_size;
	u32 max_pkt_size;
	u16 max_rxq_log;
	u8  max_stations;
	u8  bcast_sta_id;
+8 −3
Original line number Diff line number Diff line
@@ -609,7 +609,8 @@ struct iwl4965_eeprom {
#define RX_LOW_WATERMARK 8

/* Size of one Rx buffer in host DRAM */
#define IWL_RX_BUF_SIZE (4 * 1024)
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
#define IWL_RX_BUF_SIZE_8K (8 * 1024)

/* Sizes and addresses for instruction and data memory (SRAM) in
 * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
@@ -1457,13 +1458,17 @@ enum {
#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MASK  (0xC0000000) /* bits 30-31 */

#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT	(20)
#define FH_RCSR_RX_CONFIG_RB_SIZE_BITSHIFT	(16)
#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_BITSHIFT	(4)
#define RX_RB_TIMEOUT	(0x10)

#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        (0x80000000)

#define IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K    (0x00010000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K   (0x00020000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K   (0x00030000)

#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL       (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL     (0x00001000)
+17 −3
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *r
{
	int rc;
	unsigned long flags;
	unsigned int rb_size;

	spin_lock_irqsave(&priv->lock, flags);
	rc = iwl4965_grab_nic_access(priv);
@@ -234,6 +235,11 @@ static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *r
		return rc;
	}

	if (iwl4965_param_amsdu_size_8K)
		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
	else
		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;

	/* Stop Rx DMA */
	iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);

@@ -253,7 +259,7 @@ static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *r
	iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
			     FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
			     FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
			     IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
			     rb_size |
			     /*0x10 << 4 | */
			     (RX_QUEUE_SIZE_LOG <<
			      FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
@@ -1771,7 +1777,11 @@ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
	priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
	priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
	priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;

	if (iwl4965_param_amsdu_size_8K)
		priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K;
	else
		priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K;
	priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256;
	priv->hw_setting.max_stations = IWL4965_STATION_COUNT;
	priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID;
	return 0;
@@ -3619,7 +3629,7 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
		rx_start->byte_count = amsdu->byte_count;
		rx_end = (__le32 *) (((u8 *) hdr) + len);
	}
	if (len > IWL_RX_BUF_SIZE || len < 16) {
	if (len > priv->hw_setting.max_pkt_size || len < 16) {
		IWL_WARNING("byte count out of range [16,4K]"
			       " : %d\n", len);
		return;
@@ -3785,6 +3795,10 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
	ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
	ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
			     (IWL_MIMO_PS_NONE << 2));
	if (iwl4965_param_amsdu_size_8K) {
		printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n");
		ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
	}

	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
Loading