/* * 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 */