| /* |
| * Copyright (c) 2007-2008 Atheros Communications Inc. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| /* */ |
| /* Module Name : cagg.h */ |
| /* */ |
| /* Abstract */ |
| /* This module contains A-MPDU aggregation relatived functions. */ |
| /* */ |
| /* NOTES */ |
| /* None */ |
| /* */ |
| /****************************************************************************/ |
| /*Revision History: */ |
| /* Who When What */ |
| /* -------- -------- ----------------------------------------------*/ |
| /* */ |
| /* Honda 12-4-06 created */ |
| /* */ |
| /****************************************************************************/ |
| |
| #ifndef _CAGG_H |
| #define _CAGG_H |
| |
| |
| /* |
| * the aggregation functions flag, 0 if don't do aggregate |
| */ |
| |
| #define ZM_AGG_FPGA_DEBUG 1 |
| #define ZM_AGG_FPGA_REORDERING 1 |
| |
| #ifndef ZM_AGG_TALLY |
| //#define ZM_AGG_TALLY |
| #endif |
| /* |
| * Aggregate control |
| */ |
| |
| |
| #define ZM_AGG_POOL_SIZE 20 |
| #define ZM_BAW_POOL_SIZE 32 |
| #define ZM_AGGQ_SIZE 64 |
| #define ZM_AGGQ_SIZE_MASK (ZM_AGGQ_SIZE-1) |
| #define ZM_AGG_LOW_THRESHOLD 1 |
| #define ZM_AGG_HIGH_THRESHOLD 5 |
| |
| /* |
| * number of access categories (ac) |
| */ |
| #define ZM_AC 4 |
| /* |
| * the timer to clear aggregation queue, unit: 1 tick |
| * if the packet is too old (current time - arrival time) |
| * the packet and the aggregate queue will be cleared |
| */ |
| #define ZM_AGG_CLEAR_TIME 10 |
| /* |
| * delete the queue if idle for ZM_DELETE_TIME |
| * unit: 10ms |
| */ |
| #define ZM_AGG_DELETE_TIME 10000 |
| |
| /* |
| * block ack window size |
| */ |
| #define ZM_AGG_BAW_SIZE 64 |
| #define ZM_AGG_BAW_MASK (ZM_AGG_BAW_SIZE-1) |
| /* |
| * originator ADDBA Resquest receiver |
| * |----------------------------->| |
| * 1| ACK |1 |
| * |<-----------------------------| |
| * 2| ADDBA Response |2 |
| * |<-----------------------------| |
| * 3| ACK |3 |
| * |----------------------------->| |
| * 4 4 |
| */ |
| #define ZM_AGG_ADDBA_REQUEST 1 |
| #define ZM_AGG_ADDBA_REQUEST_ACK 2 |
| #define ZM_AGG_ADDBA_RESPONSE 3 |
| #define ZM_AGG_ADDBA_RESPONSE_ACK 4 |
| |
| #define ZM_AGG_SINGLE_MPDU 00 |
| #define ZM_AGG_FIRST_MPDU 01 |
| #define ZM_AGG_MIDDLE_MPDU 11 |
| #define ZM_AGG_LAST_MPDU 10 |
| /* |
| * end of Aggregate control |
| */ |
| |
| #define TID_TX struct aggQueue* |
| #define TID_BAW struct baw_q* |
| #define BAW wd->baw_enabler |
| #define DESTQ wd->destQ |
| |
| /* |
| * Queue access |
| */ |
| #define zm_agg_qlen(dev, head, tail) ((head - tail) & ZM_AGGQ_SIZE_MASK) |
| #define zm_agg_inQ(tid_tx, pt) ((((pt - tid_tx->aggTail) & ZM_AGGQ_SIZE_MASK) < \ |
| ((tid_tx->aggHead - tid_tx->aggTail) & ZM_AGGQ_SIZE_MASK))? TRUE:FALSE) |
| #define zm_agg_plus(pt) pt = (pt + 1) & ZM_AGGQ_SIZE_MASK |
| #define zm_agg_min(A, B) ((A>B)? B:A) |
| #define zm_agg_GetTime() wd->tick |
| #define TXQL (zfHpGetMaxTxdCount(dev) - zfHpGetFreeTxdCount(dev)) |
| |
| /* don't change AGG_MIN_TXQL easily, this might cause BAW BSOD */ |
| #define AGG_MIN_TXQL 2 |
| /* |
| * consider tcp,udp,ac(1234) |
| */ |
| #define zm_agg_dynamic_threshold(dev, ar) ((ar > 16)? 11: \ |
| (ar > 12)? 8: \ |
| (ar > 8)? 5: \ |
| (ar > 4)? 2:1) |
| #define zm_agg_weight(ac) ((3 == ac)? 4: \ |
| (2 == ac)? 3: \ |
| (0 == ac)? 2:1) |
| /* |
| * the required free queue ratio per ac |
| */ |
| |
| #define zm_agg_ratio(ac) ((3 == ac)? 3: \ |
| (2 == ac)? (zfHpGetMaxTxdCount(dev)*1/4): \ |
| (0 == ac)? (zfHpGetMaxTxdCount(dev)*2/4): \ |
| (zfHpGetMaxTxdCount(dev)*3/4)) |
| |
| //#define zm_agg_ratio(ac) 3 |
| /* |
| * end of Queue access |
| */ |
| |
| #define ZM_AGGMSG_LEV ZM_LV_3 |
| #define zm_msg0_agg(lv, msg) if (ZM_AGGMSG_LEV >= lv) \ |
| {zm_debug_msg0(msg);} |
| #define zm_msg1_agg(lv, msg, val) if (ZM_AGGMSG_LEV >= lv) \ |
| {zm_debug_msg1(msg, val);} |
| #define zm_msg2_agg(lv, msg, val) if (ZM_AGGMSG_LEV >= lv) \ |
| {zm_debug_msg2(msg, val);} |
| |
| #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW |
| struct baw_header_r { |
| u16_t *header; |
| u16_t *mic; |
| u16_t *snap; |
| u16_t headerLen; |
| u16_t micLen; |
| u16_t snapLen; |
| u16_t removeLen; |
| u8_t keyIdx; |
| }; |
| |
| struct baw_header { |
| u16_t header[29];//[(8+30+2+18)/2]; 58 bytes /* ctr+(4+a1+a2+a3+2+a4)+qos+iv */ |
| u16_t headerLen; |
| u16_t mic[4]; //[8/2]; 8 bytes |
| u16_t micLen; |
| u16_t snap[4]; //[8/2]; 8 bytes |
| u16_t snapLen; |
| u16_t removeLen; |
| u8_t keyIdx; |
| }; |
| |
| struct bufInfo { |
| zbuf_t* buf; |
| u8_t baw_retransmit; |
| u32_t timestamp; |
| struct baw_header *baw_header; |
| }; |
| #endif |
| struct aggElement |
| { |
| zbuf_t* buf; |
| u32_t arrivalTime; |
| u8_t baw_retransmit; |
| struct zsAdditionInfo addInfo; |
| //struct baw_header baw_header; |
| }; |
| |
| |
| #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW |
| struct baw_buf |
| { |
| zbuf_t* buf; |
| u16_t baw_seq; |
| u32_t timestamp; |
| u8_t baw_retransmit; |
| struct baw_header baw_header; |
| }; |
| |
| struct baw_q { |
| struct baw_buf frame[ZM_VTXQ_SIZE]; |
| u16_t enabled; |
| u16_t start_seq; |
| u16_t head; |
| u16_t tail; |
| u16_t size; |
| TID_TX tid_tx; |
| |
| //struct baw_header *baw_header; |
| }; |
| |
| struct baw_enabler |
| { |
| struct baw_q tid_baw[ZM_BAW_POOL_SIZE]; |
| u8_t delPoint; |
| void (*core)(zdev_t* dev, u16_t baw_seq, u32_t bitmap, u16_t aggLen); |
| //void (*core); |
| void (*init)(zdev_t* dev); |
| TID_BAW (*getNewQ)(zdev_t* dev, u16_t start_seq, TID_TX tid_tx); |
| TID_BAW (*getQ)(zdev_t* dev, u16_t baw_seq); |
| u16_t (*insert)(zdev_t* dev, zbuf_t* buf, u16_t baw_seq, TID_BAW tid_baw, u8_t baw_retransmit, struct baw_header_r *header_r); |
| struct bufInfo* (*pop)(zdev_t* dev, u16_t index, TID_BAW tid_baw); |
| void (*enable)(zdev_t* dev, TID_BAW tid_baw, u16_t start_seq); |
| void (*disable)(zdev_t* dev, TID_BAW tid_baw); |
| |
| }; |
| #endif |
| struct aggQueue |
| { |
| struct aggElement aggvtxq[ZM_AGGQ_SIZE]; |
| u16_t aggHead; |
| u16_t aggTail; |
| s16_t size; |
| u16_t aggQSTA; |
| u16_t aggQEnabled; |
| u16_t ac; |
| u16_t tid; |
| u16_t aggReady; |
| u16_t clearFlag; |
| u16_t deleteFlag; |
| u32_t lastArrival; |
| u16_t aggFrameSize; |
| u16_t bar_ssn; /* starting sequence number in BAR */ |
| u16_t dst[3]; |
| u16_t complete; /* complete indication pointer */ |
| }; |
| |
| struct aggSta |
| { |
| u16_t count[ZM_AC]; |
| TID_TX tid_tx[8]; |
| u16_t aggFlag[ZM_AC]; |
| }; |
| |
| struct agg_tid_rx |
| { |
| u16_t aid; |
| u16_t ac; |
| u16_t addBaExchangeStatusCode; |
| //struct zsAdditionInfo *addInfo; |
| u16_t seq_start; /* first seq expected next */ |
| u16_t baw_head; /* head of valid block ack window */ |
| u16_t baw_tail; /* tail of valid block ack window */ |
| //u16_t free_count; /* block ack window size */ |
| u8_t sq_exceed_count; |
| u8_t sq_behind_count; |
| struct aggElement frame[ZM_AGG_BAW_SIZE + 1]; /* out-of-order rx frames */ |
| }; |
| |
| struct aggControl |
| { |
| u16_t aggEnabled; |
| u16_t ampduIndication; |
| u16_t addbaIndication; |
| //TID_BAW tid_baw; |
| u32_t timestamp; |
| }; |
| |
| struct aggBaFrameParameter |
| { |
| zbuf_t* buf; |
| u16_t ba_parameter; |
| u8_t dialog; |
| u16_t ba_policy; |
| u16_t tid; |
| u16_t buffer_size; |
| u16_t ba_timeout; |
| u16_t ba_start_seq; |
| u16_t status_code; |
| }; |
| |
| struct aggBarControl |
| { |
| u16_t bar_ack_policy ; |
| u16_t multi_tid ; |
| u16_t compressed_bitmap ; |
| u16_t tid_info ; |
| }; |
| |
| struct aggTally |
| { |
| u32_t got_packets_sum; |
| u32_t got_bytes_sum; |
| u32_t sent_packets_sum; |
| u32_t sent_bytes_sum; |
| u32_t avg_got_packets; |
| u32_t avg_got_bytes; |
| u32_t avg_sent_packets; |
| u32_t avg_sent_bytes; |
| u16_t time; |
| }; |
| |
| |
| struct destQ { |
| struct dest{ |
| u16_t Qtype : 1; /* 0 aggr, 1 vtxq */ |
| TID_TX tid_tx; |
| void* vtxq; |
| |
| struct dest* next; |
| } *dest[4]; |
| struct dest* Head[4]; |
| //s16_t size[4]; |
| u16_t ppri; |
| void (*insert)(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq); |
| void (*delete)(zdev_t* dev, u16_t Qtype, TID_TX tid_tx, void* vtxq); |
| void (*init)(zdev_t* dev); |
| struct dest* (*getNext)(zdev_t* dev, u16_t ac); |
| u16_t (*exist)(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq); |
| //void (*scan)(zdev_t* dev); |
| }; |
| /* |
| * aggregation tx |
| */ |
| void zfAggInit(zdev_t* dev); |
| u16_t zfApFindSta(zdev_t* dev, u16_t* addr); |
| u16_t zfAggGetSta(zdev_t* dev, zbuf_t* buf); |
| TID_TX zfAggTxGetQueue(zdev_t* dev, u16_t aid, u16_t tid); |
| TID_TX zfAggTxNewQueue(zdev_t* dev, u16_t aid, u16_t tid, zbuf_t* buf); |
| u16_t zfAggTxEnqueue(zdev_t* dev, zbuf_t* buf, u16_t aid, TID_TX tid_tx); |
| u16_t zfAggTx(zdev_t* dev, zbuf_t* buf, u16_t tid); |
| u16_t zfAggTxReadyCount(zdev_t* dev, u16_t ac); |
| u16_t zfAggTxPartial(zdev_t* dev, u16_t ac, u16_t readycount); |
| u16_t zfAggTxSend(zdev_t* dev, u32_t freeTxd, TID_TX tid_tx); |
| TID_TX zfAggTxGetReadyQueue(zdev_t* dev, u16_t ac); |
| zbuf_t* zfAggTxGetVtxq(zdev_t* dev, TID_TX tid_tx); |
| u16_t zfAggTxDeleteQueue(zdev_t* dev, u16_t qnum); |
| u16_t zfAggScanAndClear(zdev_t* dev, u32_t time); |
| u16_t zfAggClearQueue(zdev_t* dev); |
| void zfAggTxScheduler(zdev_t* dev, u8_t ScanAndClear); |
| |
| /* tid_tx manipulation */ |
| #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW |
| u16_t zfAggTidTxInsertHead(zdev_t* dev, struct bufInfo* buf_info, TID_TX tid_tx); |
| #endif |
| void zfAggDestInsert(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq); |
| void zfAggDestDelete(zdev_t* dev, u16_t Qtype, TID_TX tid_tx, void* vtxq); |
| void zfAggDestInit(zdev_t* dev); |
| struct dest* zfAggDestGetNext(zdev_t* dev, u16_t ac); |
| u16_t zfAggDestExist(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq); |
| /* |
| * aggregation rx |
| */ |
| struct agg_tid_rx *zfAggRxEnabled(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggRx(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo *addInfo, struct agg_tid_rx *tid_rx); |
| struct agg_tid_rx *zfAggRxGetQueue(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggRxEnqueue(zdev_t* dev, zbuf_t* buf, struct agg_tid_rx *tid_rx, struct zsAdditionInfo *addInfo); |
| u16_t zfAggRxFlush(zdev_t* dev, u16_t seq_no, struct agg_tid_rx *tid_rx); |
| u16_t zfAggRxFreeBuf(zdev_t* dev, u16_t destroy); |
| u16_t zfAggRxClear(zdev_t* dev, u32_t time); |
| void zfAggRecvBAR(zdev_t* dev, zbuf_t* buf); |
| /* |
| * end of aggregation rx |
| */ |
| |
| /* |
| * ADDBA |
| */ |
| u16_t zfAggSendAddbaRequest(zdev_t* dev, u16_t *dst, u16_t ac, u16_t up); |
| u16_t zfAggSetAddbaFrameBody(zdev_t* dev,zbuf_t* buf, u16_t offset, u16_t ac, u16_t up); |
| u16_t zfAggGenAddbaHeader(zdev_t* dev, u16_t* dst, |
| u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt); |
| u16_t zfAggProcessAction(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggBlockAckActionFrame(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggRecvAddbaRequest(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggRecvAddbaResponse(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggRecvDelba(zdev_t* dev, zbuf_t* buf); |
| u16_t zfAggSendAddbaResponse(zdev_t* dev, struct aggBaFrameParameter *bf); |
| u16_t zfAggSetAddbaResponseFrameBody(zdev_t* dev, zbuf_t* buf, |
| struct aggBaFrameParameter *bf, u16_t offset); |
| u16_t zfAggAddbaSetTidRx(zdev_t* dev, zbuf_t* buf, |
| struct aggBaFrameParameter *bf); |
| /* |
| * zfAggTxSendEth |
| */ |
| u16_t zfAggTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u8_t flag, struct aggControl *aggControl, TID_TX tid_tx); |
| |
| /* |
| * statistics functions |
| */ |
| u16_t zfAggTallyReset(zdev_t* dev); |
| |
| u16_t zfAggPrintTally(zdev_t* dev); |
| |
| /* |
| * BAR |
| */ |
| void zfAggInvokeBar(zdev_t* dev, TID_TX tid_tx); |
| u16_t zfAggSendBar(zdev_t* dev, TID_TX tid_tx, struct aggBarControl *aggBarControl); |
| u16_t zfAggSetBarBody(zdev_t* dev, zbuf_t* buf, u16_t offset, TID_TX tid_tx, struct aggBarControl *aggBarControl); |
| u16_t zfAggGenBarHeader(zdev_t* dev, u16_t* dst, |
| u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt); |
| |
| #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW |
| /* BAW BA retransmission */ |
| void zfBawCore(zdev_t* dev, u16_t baw_seq, u32_t bitmap, u16_t aggLen); |
| void zfBawInit(zdev_t* dev); |
| TID_BAW zfBawGetNewQ(zdev_t* dev, u16_t start_seq, TID_TX tid_tx); |
| u16_t zfBawInsert(zdev_t* dev, zbuf_t* buf, u16_t baw_seq, TID_BAW tid_baw, u8_t baw_retransmit, struct baw_header_r *header_r); |
| struct bufInfo* zfBawPop(zdev_t* dev, u16_t index, TID_BAW tid_baw); |
| void zfBawEnable(zdev_t* dev, TID_BAW tid_baw, u16_t start_seq); |
| void zfBawDisable(zdev_t* dev, TID_BAW tid_baw); |
| TID_BAW zfBawGetQ(zdev_t* dev, u16_t baw_seq); |
| void zfAggTxRetransmit(zdev_t* dev, struct bufInfo *buf_info, struct aggControl *aggControl, TID_TX tid_tx); |
| #endif |
| /* extern functions */ |
| extern zbuf_t* zfGetVtxq(zdev_t* dev, u8_t ac); |
| |
| #endif /* #ifndef _CAGG_H */ |
| |