2 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sys/dev/netif/acx/acx111.c,v 1.13 2008/02/06 08:21:22 sephe Exp $
37 #include <sys/param.h>
39 #include <sys/endian.h>
41 #include <sys/socket.h>
42 #include <sys/sysctl.h>
45 #include <net/if_arp.h>
46 #include <net/if_media.h>
48 #include <netproto/802_11/ieee80211_var.h>
49 #include <netproto/802_11/ieee80211_radiotap.h>
50 #include <netproto/802_11/wlan_ratectl/amrr/ieee80211_amrr_param.h>
51 #include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
53 #include <bus/pci/pcireg.h>
57 #include <dev/netif/acx/if_acxreg.h>
58 #include <dev/netif/acx/if_acxvar.h>
59 #include <dev/netif/acx/acxcmd.h>
61 #define ACX111_CONF_MEM 0x0003
62 #define ACX111_CONF_MEMINFO 0x0005
63 #define ACX111_CONF_RT0_NRETRY 0x0006
65 #define ACX111_INTR_ENABLE (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
67 * XXX do we really care about fowlling interrupts?
69 * ACXRV_INTR_IV_ICV_FAILURE | ACXRV_INTR_INFO |
70 * ACXRV_INTR_SCAN_FINI | ACXRV_INTR_FCS_THRESHOLD
73 #define ACX111_INTR_DISABLE (uint16_t)~(ACXRV_INTR_CMD_FINI)
75 #define ACX111_RATE_2 0x0001
76 #define ACX111_RATE_4 0x0002
77 #define ACX111_RATE_11 0x0004
78 #define ACX111_RATE_12 0x0008
79 #define ACX111_RATE_18 0x0010
80 #define ACX111_RATE_22 0x0020
81 #define ACX111_RATE_24 0x0040
82 #define ACX111_RATE_36 0x0080
83 #define ACX111_RATE_44 0x0100
84 #define ACX111_RATE_48 0x0200
85 #define ACX111_RATE_72 0x0400
86 #define ACX111_RATE_96 0x0800
87 #define ACX111_RATE_108 0x1000
88 #define ACX111_RATE(rate) [rate] = ACX111_RATE_##rate
90 #define ACX111_RSSI_CORR 5
91 #define ACX111_TXPOWER 15
92 #define ACX111_GPIO_POWER_LED 0x0040
93 #define ACX111_EE_EADDR_OFS 0x21
95 #define ACX111_FW_TXDESC_SIZE (sizeof(struct acx_fw_txdesc) + 4)
97 #if ACX111_TXPOWER <= 12
98 #define ACX111_TXPOWER_VAL 1
100 #define ACX111_TXPOWER_VAL 2
103 #define ACX111_ONOE_RATEIDX_MAX 4
104 #define ACX111_AMRR_RATEIDX_MAX 4
108 * Following structs' fields are little endian
111 struct acx111_bss_join
{
112 uint16_t basic_rates
;
116 struct acx111_conf_mem
{
117 struct acx_conf confcom
;
119 uint16_t sta_max
; /* max num of sta, ACX111_STA_MAX */
120 uint16_t memblk_size
; /* mem block size */
121 uint8_t rx_memblk_perc
; /* percent of RX mem block, unit: 5% */
122 uint8_t fw_rxring_num
; /* num of RX ring */
123 uint8_t fw_txring_num
; /* num of TX ring */
124 uint8_t opt
; /* see ACX111_MEMOPT_ */
125 uint8_t xfer_perc
; /* frag/xfer proportion, unit: 5% */
129 uint8_t fw_rxdesc_num
; /* num of fw rx desc */
130 uint8_t fw_rxring_reserved1
;
131 uint8_t fw_rxring_type
; /* see ACX111_RXRING_TYPE_ */
132 uint8_t fw_rxring_prio
; /* see ACX111_RXRING_PRIO_ */
134 uint32_t h_rxring_paddr
; /* host rx desc start phyaddr */
136 uint8_t fw_txdesc_num
; /* num of fw tx desc */
137 uint8_t fw_txring_reserved1
;
138 uint8_t fw_txring_reserved2
;
139 uint8_t fw_txring_attr
; /* see ACX111_TXRING_ATTR_ */
143 * ACX111 does support limited multi-rate retry, following rules apply to
144 * at least firmware rev1.2.x.x:
145 * 1) Rate field in firmware descriptor is a bitmask, which indicates
146 * set of rates to be used to send the packet.
147 * 2) "acx111_conf_rt0_nretry" configures the number of retries for
149 * 3) Except for the last rate and 1st rate, rest of the rates in the
150 * rate set are tried only once.
151 * 4) Last rate will be tried until "short retry limit" + "long retry limit"
155 * a) 54Mbit/s, 48Mbit/s and 1Mbit/s are in the rate set.
156 * b) Number of retries for the 1st rate (i.e. 54Mbit/s) is set to 3.
157 * c) Short retry limit is set to 7
159 * For the above configuration:
160 * A) 4 tries will be spent at 54Mbit/s.
161 * B) 1 try will be spent at 48Mbit/s, if A) fails.
162 * C) 3 tries will be spent at 1Mbit/s, if A) and B) fail.
164 struct acx111_conf_rt0_nretry
{
165 struct acx_conf confcom
;
166 uint8_t rt0_nretry
; /* number of retry for 1st rate */
169 #define ACX111_STA_MAX 32
170 #define ACX111_RX_MEMBLK_PERCENT 10 /* 50% */
171 #define ACX111_XFER_PERCENT 15 /* 75% */
172 #define ACX111_RXRING_TYPE_DEFAULT 7
173 #define ACX111_RXRING_PRIO_DEFAULT 0
174 #define ACX111_TXRING_ATTR_DEFAULT 0
175 #define ACX111_MEMOPT_DEFAULT 0
177 struct acx111_conf_meminfo
{
178 struct acx_conf confcom
;
179 uint32_t tx_memblk_addr
; /* start addr of tx mem blocks */
180 uint32_t rx_memblk_addr
; /* start addr of rx mem blocks */
181 uint32_t fw_rxring_start
; /* start phyaddr of fw rx ring */
183 uint32_t fw_txring_start
; /* start phyaddr of fw tx ring */
184 uint8_t fw_txring_attr
; /* XXX see ACX111_TXRING_ATTR_ */
189 struct acx111_conf_txpower
{
190 struct acx_conf confcom
;
194 struct acx111_conf_option
{
195 struct acx_conf confcom
;
197 uint32_t dataflow
; /* see ACX111_DF_ */
200 #define ACX111_DF_NO_RXDECRYPT 0x00000080
201 #define ACX111_DF_NO_TXENCRYPT 0x00000001
203 struct acx111_wepkey
{
204 uint8_t mac_addr
[IEEE80211_ADDR_LEN
];
205 uint16_t action
; /* see ACX111_WEPKEY_ACT_ */
208 uint8_t key_type
; /* see ACX111_WEPKEY_TYPE_ */
209 uint8_t index
; /* XXX ?? */
212 #define ACX111_WEPKEY_LEN 32
213 uint8_t key
[ACX111_WEPKEY_LEN
];
216 #define ACX111_WEPKEY_ACT_ADD 1
217 #define ACX111_WEPKEY_TYPE_DEFAULT 0
219 #define ACX111_CONF_FUNC(sg, name) _ACX_CONF_FUNC(sg, name, 111)
220 #define ACX_CONF_mem ACX111_CONF_MEM
221 #define ACX_CONF_meminfo ACX111_CONF_MEMINFO
222 #define ACX_CONF_rt0_nretry ACX111_CONF_RT0_NRETRY
223 #define ACX_CONF_txpower ACX_CONF_TXPOWER
224 #define ACX_CONF_option ACX_CONF_OPTION
225 ACX111_CONF_FUNC(set
, mem
);
226 ACX111_CONF_FUNC(get
, meminfo
);
227 ACX111_CONF_FUNC(set
, txpower
);
228 ACX111_CONF_FUNC(get
, option
);
229 ACX111_CONF_FUNC(set
, option
);
230 ACX111_CONF_FUNC(set
, rt0_nretry
);
232 static const uint16_t acx111_reg
[ACXREG_MAX
] = {
233 ACXREG(SOFT_RESET
, 0x0000),
235 ACXREG(FWMEM_ADDR
, 0x0014),
236 ACXREG(FWMEM_DATA
, 0x0018),
237 ACXREG(FWMEM_CTRL
, 0x001c),
238 ACXREG(FWMEM_START
, 0x0020),
240 ACXREG(EVENT_MASK
, 0x0034),
242 ACXREG(INTR_TRIG
, 0x00b4),
243 ACXREG(INTR_MASK
, 0x00d4),
244 ACXREG(INTR_STATUS
, 0x00f0),
245 ACXREG(INTR_STATUS_CLR
, 0x00e4),
246 ACXREG(INTR_ACK
, 0x00e8),
248 ACXREG(HINTR_TRIG
, 0x00ec),
249 ACXREG(RADIO_ENABLE
, 0x01d0),
251 ACXREG(EEPROM_INIT
, 0x0100),
252 ACXREG(EEPROM_CTRL
, 0x0338),
253 ACXREG(EEPROM_ADDR
, 0x033c),
254 ACXREG(EEPROM_DATA
, 0x0340),
255 ACXREG(EEPROM_CONF
, 0x0344),
256 ACXREG(EEPROM_INFO
, 0x0390),
258 ACXREG(PHY_ADDR
, 0x0350),
259 ACXREG(PHY_DATA
, 0x0354),
260 ACXREG(PHY_CTRL
, 0x0358),
262 ACXREG(GPIO_OUT_ENABLE
, 0x0374),
263 ACXREG(GPIO_OUT
, 0x037c),
265 ACXREG(CMD_REG_OFFSET
, 0x0388),
266 ACXREG(INFO_REG_OFFSET
, 0x038c),
268 ACXREG(RESET_SENSE
, 0x0104),
269 ACXREG(ECPU_CTRL
, 0x0108)
272 static const uint16_t acx111_rate_map
[109] = {
289 acx111_onoe_tries
[IEEE80211_RATEIDX_MAX
] = { 4, 1, 1, 3, 0 };
292 acx111_amrr_tries
[IEEE80211_RATEIDX_MAX
] = { 4, 1, 1, 3, 0 };
294 static int acx111_init(struct acx_softc
*);
295 static int acx111_init_memory(struct acx_softc
*);
296 static void acx111_init_fw_txring(struct acx_softc
*, uint32_t);
298 static int acx111_write_config(struct acx_softc
*, struct acx_config
*);
300 static void acx111_set_bss_join_param(struct acx_softc
*, void *, int);
302 static void *acx111_ratectl_attach(struct ieee80211com
*, u_int
);
304 static uint8_t _acx111_set_fw_txdesc_rate(struct acx_softc
*,
306 struct ieee80211_node
*, int, int);
307 static uint8_t acx111_set_fw_txdesc_rate_onoe(struct acx_softc
*,
309 struct ieee80211_node
*, int);
310 static uint8_t acx111_set_fw_txdesc_rate_amrr(struct acx_softc
*,
312 struct ieee80211_node
*, int);
314 static void _acx111_tx_complete(struct acx_softc
*, struct acx_txbuf
*,
315 int, int, const int[]);
316 static void acx111_tx_complete_onoe(struct acx_softc
*, struct acx_txbuf
*,
318 static void acx111_tx_complete_amrr(struct acx_softc
*, struct acx_txbuf
*,
321 #define ACX111_CHK_RATE(ifp, rate, rate_idx) \
322 acx111_check_rate(ifp, rate, rate_idx, __func__)
325 acx111_check_rate(struct ifnet
*ifp
, u_int rate
, int rate_idx
,
328 #define N(arr) (sizeof(arr) / sizeof(arr[0]))
329 if (rate
>= N(acx111_rate_map
)) {
330 if_printf(ifp
, "%s rate out of range %u (idx %d)\n",
331 fname
, rate
, rate_idx
);
336 if (acx111_rate_map
[rate
] == 0) {
337 if_printf(ifp
, "%s invalid rate %u (idx %d)\n",
338 fname
, rate
, rate_idx
);
345 acx111_set_param(device_t dev
)
347 struct acx_softc
*sc
= device_get_softc(dev
);
348 struct ieee80211com
*ic
= &sc
->sc_ic
;
349 struct acx_firmware
*fw
= &sc
->sc_firmware
;
351 sc
->chip_mem1_rid
= PCIR_BAR(0);
352 sc
->chip_mem2_rid
= PCIR_BAR(1);
353 sc
->chip_ioreg
= acx111_reg
;
354 sc
->chip_intr_enable
= ACX111_INTR_ENABLE
;
355 sc
->chip_intr_disable
= ACX111_INTR_DISABLE
;
356 sc
->chip_gpio_pled
= ACX111_GPIO_POWER_LED
;
357 sc
->chip_ee_eaddr_ofs
= ACX111_EE_EADDR_OFS
;
358 sc
->chip_rssi_corr
= ACX111_RSSI_CORR
;
360 sc
->chip_phymode
= IEEE80211_MODE_11G
;
361 sc
->chip_chan_flags
= IEEE80211_CHAN_CCK
|
362 IEEE80211_CHAN_OFDM
|
366 ic
->ic_caps
= IEEE80211_C_WPA
/* | IEEE80211_C_SHSLOT */;
367 ic
->ic_phytype
= IEEE80211_T_OFDM
;
368 ic
->ic_sup_rates
[IEEE80211_MODE_11B
] = acx_rates_11b
;
369 ic
->ic_sup_rates
[IEEE80211_MODE_11G
] = acx_rates_11g
;
371 IEEE80211_ONOE_PARAM_SETUP(&sc
->sc_onoe_param
);
372 IEEE80211_AMRR_PARAM_SETUP(&sc
->sc_amrr_param
);
374 ic
->ic_ratectl
.rc_st_ratectl_cap
= IEEE80211_RATECTL_CAP_ONOE
|
375 IEEE80211_RATECTL_CAP_AMRR
;
376 ic
->ic_ratectl
.rc_st_ratectl
= IEEE80211_RATECTL_AMRR
;
377 ic
->ic_ratectl
.rc_st_attach
= acx111_ratectl_attach
;
379 sc
->chip_init
= acx111_init
;
380 sc
->chip_write_config
= acx111_write_config
;
381 sc
->chip_set_bss_join_param
= acx111_set_bss_join_param
;
383 fw
->combined_radio_fw
= 1;
388 acx111_init(struct acx_softc
*sc
)
392 * Order of initialization:
395 * Above order is critical to get a correct memory map
398 if (acx_init_tmplt_ordered(sc
) != 0) {
399 if_printf(&sc
->sc_ic
.ic_if
, "%s can't initialize templates\n",
404 if (acx111_init_memory(sc
) != 0) {
405 if_printf(&sc
->sc_ic
.ic_if
, "%s can't initialize hw memory\n",
413 acx111_init_memory(struct acx_softc
*sc
)
415 struct acx111_conf_mem mem
;
416 struct acx111_conf_meminfo mem_info
;
418 /* Set memory configuration */
419 bzero(&mem
, sizeof(mem
));
421 mem
.sta_max
= htole16(ACX111_STA_MAX
);
422 mem
.memblk_size
= htole16(ACX_MEMBLOCK_SIZE
);
423 mem
.rx_memblk_perc
= ACX111_RX_MEMBLK_PERCENT
;
424 mem
.opt
= ACX111_MEMOPT_DEFAULT
;
425 mem
.xfer_perc
= ACX111_XFER_PERCENT
;
427 mem
.fw_rxring_num
= 1;
428 mem
.fw_rxring_type
= ACX111_RXRING_TYPE_DEFAULT
;
429 mem
.fw_rxring_prio
= ACX111_RXRING_PRIO_DEFAULT
;
430 mem
.fw_rxdesc_num
= ACX_RX_DESC_CNT
;
431 mem
.h_rxring_paddr
= htole32(sc
->sc_ring_data
.rx_ring_paddr
);
433 mem
.fw_txring_num
= 1;
434 mem
.fw_txring_attr
= ACX111_TXRING_ATTR_DEFAULT
;
435 mem
.fw_txdesc_num
= ACX_TX_DESC_CNT
;
437 if (acx111_set_mem_conf(sc
, &mem
) != 0) {
438 if_printf(&sc
->sc_ic
.ic_if
, "can't set mem\n");
442 /* Get memory configuration */
443 if (acx111_get_meminfo_conf(sc
, &mem_info
) != 0) {
444 if_printf(&sc
->sc_ic
.ic_if
, "can't get meminfo\n");
448 /* Setup firmware TX descriptor ring */
449 acx111_init_fw_txring(sc
, le32toh(mem_info
.fw_txring_start
));
452 * There is no need to setup firmware RX descriptor ring,
453 * it is automaticly setup by hardware.
460 acx111_init_fw_txring(struct acx_softc
*sc
, uint32_t fw_txdesc_start
)
462 struct acx_txbuf
*tx_buf
;
466 tx_buf
= sc
->sc_buf_data
.tx_buf
;
467 desc_paddr
= sc
->sc_ring_data
.tx_ring_paddr
;
469 for (i
= 0; i
< ACX_TX_DESC_CNT
; ++i
) {
470 tx_buf
[i
].tb_fwdesc_ofs
= fw_txdesc_start
+
471 (i
* ACX111_FW_TXDESC_SIZE
);
474 * Except for the following fields, rest of the fields
475 * are setup by hardware.
477 FW_TXDESC_SETFIELD_4(sc
, &tx_buf
[i
], f_tx_host_desc
,
479 FW_TXDESC_SETFIELD_1(sc
, &tx_buf
[i
], f_tx_ctrl
,
482 desc_paddr
+= (2 * sizeof(struct acx_host_desc
));
487 acx111_write_config(struct acx_softc
*sc
, struct acx_config
*conf
)
489 struct acx111_conf_txpower tx_power
;
490 struct acx111_conf_option opt
;
491 struct acx111_conf_rt0_nretry rt0_nretry
;
495 tx_power
.txpower
= ACX111_TXPOWER_VAL
;
496 if (acx111_set_txpower_conf(sc
, &tx_power
) != 0) {
497 if_printf(&sc
->sc_ic
.ic_if
, "%s can't set TX power\n",
503 * Turn off hardware WEP
505 if (acx111_get_option_conf(sc
, &opt
) != 0) {
506 if_printf(&sc
->sc_ic
.ic_if
, "%s can't get option\n", __func__
);
510 dataflow
= le32toh(opt
.dataflow
) |
511 ACX111_DF_NO_TXENCRYPT
|
512 ACX111_DF_NO_RXDECRYPT
;
513 opt
.dataflow
= htole32(dataflow
);
515 if (acx111_set_option_conf(sc
, &opt
) != 0) {
516 if_printf(&sc
->sc_ic
.ic_if
, "%s can't set option\n", __func__
);
521 * Set number of retries for 0th rate
523 rt0_nretry
.rt0_nretry
= sc
->chip_rate_fallback
;
524 if (acx111_set_rt0_nretry_conf(sc
, &rt0_nretry
) != 0) {
525 if_printf(&sc
->sc_ic
.ic_if
, "%s can't set rate0 nretry\n",
533 _acx111_set_fw_txdesc_rate(struct acx_softc
*sc
, struct acx_txbuf
*tx_buf
,
534 struct ieee80211_node
*ni
, int data_len
,
537 struct ifnet
*ifp
= &sc
->sc_ic
.ic_if
;
541 KKASSERT(rateidx_max
<= IEEE80211_RATEIDX_MAX
);
544 rate
= ACX111_RATE_2
; /* 1Mbit/s */
546 tx_buf
->tb_rateidx_len
= 1;
547 tx_buf
->tb_rateidx
[0] = 0;
549 struct ieee80211_rateset
*rs
= &ni
->ni_rates
;
550 int *rateidx
= tx_buf
->tb_rateidx
;
553 n
= ieee80211_ratectl_findrate(ni
, data_len
, rateidx
,
557 for (i
= 0; i
< n
; ++i
) {
558 u_int map_idx
= IEEE80211_RS_RATE(rs
, rateidx
[i
]);
560 if (ACX111_CHK_RATE(ifp
, map_idx
, rateidx
[i
]) < 0)
566 rate
|= acx111_rate_map
[map_idx
];
569 if_printf(ifp
, "WARNING no rate, set to 1Mbit/s\n");
570 rate
= ACX111_RATE_2
;
572 tx_buf
->tb_rateidx_len
= 1;
573 tx_buf
->tb_rateidx
[0] = 0;
575 tx_buf
->tb_rateidx_len
= n
;
578 FW_TXDESC_SETFIELD_2(sc
, tx_buf
, u
.r2
.rate111
, rate
);
584 acx111_set_fw_txdesc_rate_onoe(struct acx_softc
*sc
, struct acx_txbuf
*tx_buf
,
585 struct ieee80211_node
*ni
, int data_len
)
587 return _acx111_set_fw_txdesc_rate(sc
, tx_buf
, ni
, data_len
,
588 ACX111_ONOE_RATEIDX_MAX
);
592 acx111_set_fw_txdesc_rate_amrr(struct acx_softc
*sc
, struct acx_txbuf
*tx_buf
,
593 struct ieee80211_node
*ni
, int data_len
)
595 return _acx111_set_fw_txdesc_rate(sc
, tx_buf
, ni
, data_len
,
596 ACX111_AMRR_RATEIDX_MAX
);
600 acx111_set_bss_join_param(struct acx_softc
*sc
, void *param
, int dtim_intvl
)
602 struct acx111_bss_join
*bj
= param
;
603 const struct ieee80211_rateset
*rs
= &sc
->sc_ic
.ic_bss
->ni_rates
;
604 struct ifnet
*ifp
= &sc
->sc_ic
.ic_if
;
605 uint16_t basic_rates
= 0;
608 for (i
= 0; i
< rs
->rs_nrates
; ++i
) {
609 if (rs
->rs_rates
[i
] & IEEE80211_RATE_BASIC
) {
610 u_int map_idx
= IEEE80211_RS_RATE(rs
, i
);
612 if (ACX111_CHK_RATE(ifp
, map_idx
, i
) < 0)
615 basic_rates
|= acx111_rate_map
[map_idx
];
618 DPRINTF((ifp
, "basic rates: 0x%04x\n", basic_rates
));
620 bj
->basic_rates
= htole16(basic_rates
);
621 bj
->dtim_intvl
= dtim_intvl
;
625 acx111_ratectl_attach(struct ieee80211com
*ic
, u_int rc
)
627 struct ifnet
*ifp
= &ic
->ic_if
;
628 struct acx_softc
*sc
= ifp
->if_softc
;
634 case IEEE80211_RATECTL_ONOE
:
635 tries
= acx111_onoe_tries
;
636 sc
->chip_set_fw_txdesc_rate
= acx111_set_fw_txdesc_rate_onoe
;
637 sc
->chip_tx_complete
= acx111_tx_complete_onoe
;
638 ret
= &sc
->sc_onoe_param
;
641 case IEEE80211_RATECTL_AMRR
:
642 tries
= acx111_amrr_tries
;
643 sc
->chip_set_fw_txdesc_rate
= acx111_set_fw_txdesc_rate_amrr
;
644 sc
->chip_tx_complete
= acx111_tx_complete_amrr
;
645 ret
= &sc
->sc_amrr_param
;
648 case IEEE80211_RATECTL_NONE
:
649 /* This could only happen during detaching */
653 panic("unknown rate control algo %u\n", rc
);
657 sc
->chip_rate_fallback
= tries
[0] - 1;
659 sc
->chip_short_retry_limit
= 0;
660 for (i
= 0; i
< IEEE80211_RATEIDX_MAX
; ++i
)
661 sc
->chip_short_retry_limit
+= tries
[i
];
662 sc
->chip_short_retry_limit
--;
664 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_UP
)) ==
665 (IFF_RUNNING
| IFF_UP
)) {
666 struct acx_conf_nretry_short sretry
;
667 struct acx111_conf_rt0_nretry rt0_nretry
;
670 * Set number of short retries
672 sretry
.nretry
= sc
->chip_short_retry_limit
;
673 if (acx_set_nretry_short_conf(sc
, &sretry
) != 0) {
674 if_printf(ifp
, "%s can't set short retry limit\n",
677 DPRINTF((ifp
, "%s set sretry %d\n", __func__
,
678 sc
->chip_short_retry_limit
));
681 * Set number of retries for 0th rate
683 rt0_nretry
.rt0_nretry
= sc
->chip_rate_fallback
;
684 if (acx111_set_rt0_nretry_conf(sc
, &rt0_nretry
) != 0) {
685 if_printf(ifp
, "%s can't set rate0 nretry\n",
688 DPRINTF((ifp
, "%s set rate 0 nretry %d\n", __func__
,
689 sc
->chip_rate_fallback
));
695 _acx111_tx_complete(struct acx_softc
*sc
, struct acx_txbuf
*tx_buf
,
696 int frame_len
, int is_fail
, const int tries_arr
[])
698 struct ieee80211_ratectl_res rc_res
[IEEE80211_RATEIDX_MAX
];
699 int rts_retries
, data_retries
, n
, tries
, prev_tries
;
701 KKASSERT(tx_buf
->tb_rateidx_len
<= IEEE80211_RATEIDX_MAX
);
703 rts_retries
= FW_TXDESC_GETFIELD_1(sc
, tx_buf
, f_tx_rts_nretry
);
704 data_retries
= FW_TXDESC_GETFIELD_1(sc
, tx_buf
, f_tx_data_nretry
);
707 DPRINTF((&sc
->sc_ic
.ic_if
, "d%d r%d rateidx_len %d\n",
708 data_retries
, rts_retries
, tx_buf
->tb_rateidx_len
));
711 prev_tries
= tries
= 0;
712 for (n
= 0; n
< tx_buf
->tb_rateidx_len
; ++n
) {
713 rc_res
[n
].rc_res_tries
= tries_arr
[n
];
714 rc_res
[n
].rc_res_rateidx
= tx_buf
->tb_rateidx
[n
];
716 if (data_retries
+ 1 <= tries
)
719 tries
+= tries_arr
[n
];
724 if (!is_fail
&& data_retries
+ 1 <= tries
) {
725 rc_res
[n
- 1].rc_res_tries
= data_retries
+ 1 - prev_tries
;
727 DPRINTF((&sc
->sc_ic
.ic_if
, "n %d, last tries%d\n",
728 n
, rc_res
[n
- 1].rc_res_tries
));
731 ieee80211_ratectl_tx_complete(tx_buf
->tb_node
, frame_len
, rc_res
, n
,
732 data_retries
, rts_retries
, is_fail
);
736 acx111_tx_complete_onoe(struct acx_softc
*sc
, struct acx_txbuf
*tx_buf
,
737 int frame_len
, int is_fail
)
739 _acx111_tx_complete(sc
, tx_buf
, frame_len
, is_fail
,
744 acx111_tx_complete_amrr(struct acx_softc
*sc
, struct acx_txbuf
*tx_buf
,
745 int frame_len
, int is_fail
)
747 _acx111_tx_complete(sc
, tx_buf
, frame_len
, is_fail
,