Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * This file is part of wl1271 * * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. * Copyright (C) 2009 Nokia Corporation * * Contact: Luciano Coelho <luciano.coelho@nokia.com> */ #ifndef __TX_H__ #define __TX_H__ #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 #define TX_HW_ATTR_SAVE_RETRIES BIT(0) #define TX_HW_ATTR_HEADER_PAD BIT(1) #define TX_HW_ATTR_SESSION_COUNTER (BIT(2) | BIT(3) | BIT(4)) #define TX_HW_ATTR_RATE_POLICY (BIT(5) | BIT(6) | BIT(7) | \ BIT(8) | BIT(9)) #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) #define TX_HW_ATTR_HOST_ENCRYPT BIT(14) #define TX_HW_ATTR_EAPOL_FRAME BIT(15) #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 #define TX_HW_ATTR_OFST_HEADER_PAD 1 #define TX_HW_ATTR_OFST_SESSION_COUNTER 2 #define TX_HW_ATTR_OFST_RATE_POLICY 5 #define TX_HW_ATTR_OFST_LAST_WORD_PAD 10 #define TX_HW_ATTR_OFST_TX_CMPLT_REQ 12 #define TX_HW_RESULT_QUEUE_LEN 16 #define TX_HW_RESULT_QUEUE_LEN_MASK 0xf #define WL1271_TX_ALIGN_TO 4 #define WL1271_EXTRA_SPACE_TKIP 4 #define WL1271_EXTRA_SPACE_AES 8 #define WL1271_EXTRA_SPACE_MAX 8 /* Used for management frames and dummy packets */ #define WL1271_TID_MGMT 7 /* stop a ROC for pending authentication reply after this time (ms) */ #define WLCORE_PEND_AUTH_ROC_TIMEOUT 1000 struct wl127x_tx_mem { /* * Number of extra memory blocks to allocate for this packet * in addition to the number of blocks derived from the packet * length. */ u8 extra_blocks; /* * Total number of memory blocks allocated by the host for * this packet. Must be equal or greater than the actual * blocks number allocated by HW. */ u8 total_mem_blocks; } __packed; struct wl128x_tx_mem { /* * Total number of memory blocks allocated by the host for * this packet. */ u8 total_mem_blocks; /* * Number of extra bytes, at the end of the frame. the host * uses this padding to complete each frame to integer number * of SDIO blocks. */ u8 extra_bytes; } __packed; struct wl18xx_tx_mem { /* * Total number of memory blocks allocated by the host for * this packet. */ u8 total_mem_blocks; /* * control bits */ u8 ctrl; } __packed; /* * On wl128x based devices, when TX packets are aggregated, each packet * size must be aligned to the SDIO block size. The maximum block size * is bounded by the type of the padded bytes field that is sent to the * FW. Currently the type is u8, so the maximum block size is 256 bytes. */ #define WL12XX_BUS_BLOCK_SIZE min(512u, \ (1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes)))) struct wl1271_tx_hw_descr { /* Length of packet in words, including descriptor+header+data */ __le16 length; union { struct wl127x_tx_mem wl127x_mem; struct wl128x_tx_mem wl128x_mem; struct wl18xx_tx_mem wl18xx_mem; } __packed; /* Device time (in us) when the packet arrived to the driver */ __le32 start_time; /* * Max delay in TUs until transmission. The last device time the * packet can be transmitted is: start_time + (1024 * life_time) */ __le16 life_time; /* Bitwise fields - see TX_ATTR... definitions above. */ __le16 tx_attr; /* Packet identifier used also in the Tx-Result. */ u8 id; /* The packet TID value (as User-Priority) */ u8 tid; /* host link ID (HLID) */ u8 hlid; union { u8 wl12xx_reserved; /* * bit 0 -> 0 = udp, 1 = tcp * bit 1:7 -> IP header offset */ u8 wl18xx_checksum_data; } __packed; } __packed; enum wl1271_tx_hw_res_status { TX_SUCCESS = 0, TX_HW_ERROR = 1, TX_DISABLED = 2, TX_RETRY_EXCEEDED = 3, TX_TIMEOUT = 4, TX_KEY_NOT_FOUND = 5, TX_PEER_NOT_FOUND = 6, TX_SESSION_MISMATCH = 7, TX_LINK_NOT_VALID = 8, }; struct wl1271_tx_hw_res_descr { /* Packet Identifier - same value used in the Tx descriptor.*/ u8 id; /* The status of the transmission, indicating success or one of several possible reasons for failure. */ u8 status; /* Total air access duration including all retrys and overheads.*/ __le16 medium_usage; /* The time passed from host xfer to Tx-complete.*/ __le32 fw_handling_time; /* Total media delay (from 1st EDCA AIFS counter until TX Complete). */ __le32 medium_delay; /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ u8 tx_security_sequence_number_lsb; /* Retry count - number of transmissions without successful ACK.*/ u8 ack_failures; /* The rate that succeeded getting ACK (Valid only if status=SUCCESS). */ u8 rate_class_index; /* for 4-byte alignment. */ u8 spare; } __packed; struct wl1271_tx_hw_res_if { __le32 tx_result_fw_counter; __le32 tx_result_host_counter; struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; } __packed; enum wlcore_queue_stop_reason { WLCORE_QUEUE_STOP_REASON_WATERMARK, WLCORE_QUEUE_STOP_REASON_FW_RESTART, WLCORE_QUEUE_STOP_REASON_FLUSH, WLCORE_QUEUE_STOP_REASON_SPARE_BLK, /* 18xx specific */ }; static inline int wl1271_tx_get_queue(int queue) { switch (queue) { case 0: return CONF_TX_AC_VO; case 1: return CONF_TX_AC_VI; case 2: return CONF_TX_AC_BE; case 3: return CONF_TX_AC_BK; default: return CONF_TX_AC_BE; } } static inline int wlcore_tx_get_mac80211_queue(struct wl12xx_vif *wlvif, int queue) { int mac_queue = wlvif->hw_queue_base; switch (queue) { case CONF_TX_AC_VO: return mac_queue + 0; case CONF_TX_AC_VI: return mac_queue + 1; case CONF_TX_AC_BE: return mac_queue + 2; case CONF_TX_AC_BK: return mac_queue + 3; default: return mac_queue + 2; } } static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) { int i, count = 0; for (i = 0; i < NUM_TX_QUEUES; i++) count += wl->tx_queue_count[i]; return count; } void wl1271_tx_work(struct work_struct *work); int wlcore_tx_work_locked(struct wl1271 *wl); int wlcore_tx_complete(struct wl1271 *wl); void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); void wl12xx_tx_reset(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl); u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum nl80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, enum nl80211_band rate_band); u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb, struct ieee80211_sta *sta); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length); void wl1271_free_tx_id(struct wl1271 *wl, int id); void wlcore_stop_queue_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, enum wlcore_queue_stop_reason reason); void wlcore_stop_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, enum wlcore_queue_stop_reason reason); void wlcore_wake_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, enum wlcore_queue_stop_reason reason); void wlcore_stop_queues(struct wl1271 *wl, enum wlcore_queue_stop_reason reason); void wlcore_wake_queues(struct wl1271 *wl, enum wlcore_queue_stop_reason reason); bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, enum wlcore_queue_stop_reason reason); bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, enum wlcore_queue_stop_reason reason); bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue); /* from main.c */ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl); #endif |