Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2009 Atheros Communications Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include <linux/export.h>
0018 #include <asm/unaligned.h>
0019 
0020 #include "ath.h"
0021 #include "reg.h"
0022 
0023 #define REG_READ            (common->ops->read)
0024 #define REG_WRITE(_ah, _reg, _val)  (common->ops->write)(_ah, _val, _reg)
0025 
0026 /**
0027  * ath_hw_setbssidmask - filter out bssids we listen
0028  *
0029  * @common: the ath_common struct for the device.
0030  *
0031  * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
0032  * which bits of the interface's MAC address should be looked at when trying
0033  * to decide which packets to ACK. In station mode and AP mode with a single
0034  * BSS every bit matters since we lock to only one BSS. In AP mode with
0035  * multiple BSSes (virtual interfaces) not every bit matters because hw must
0036  * accept frames for all BSSes and so we tweak some bits of our mac address
0037  * in order to have multiple BSSes.
0038  *
0039  * NOTE: This is a simple filter and does *not* filter out all
0040  * relevant frames. Some frames that are not for us might get ACKed from us
0041  * by PCU because they just match the mask.
0042  *
0043  * When handling multiple BSSes you can get the BSSID mask by computing the
0044  * set of  ~ ( MAC XOR BSSID ) for all bssids we handle.
0045  *
0046  * When you do this you are essentially computing the common bits of all your
0047  * BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with
0048  * the MAC address to obtain the relevant bits and compare the result with
0049  * (frame's BSSID & mask) to see if they match.
0050  *
0051  * Simple example: on your card you have two BSSes you have created with
0052  * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
0053  * There is another BSSID-03 but you are not part of it. For simplicity's sake,
0054  * assuming only 4 bits for a mac address and for BSSIDs you can then have:
0055  *
0056  *                  \
0057  * MAC:        0001 |
0058  * BSSID-01:   0100 | --> Belongs to us
0059  * BSSID-02:   1001 |
0060  *                  /
0061  * -------------------
0062  * BSSID-03:   0110  | --> External
0063  * -------------------
0064  *
0065  * Our bssid_mask would then be:
0066  *
0067  *             On loop iteration for BSSID-01:
0068  *             ~(0001 ^ 0100)  -> ~(0101)
0069  *                             ->   1010
0070  *             bssid_mask      =    1010
0071  *
0072  *             On loop iteration for BSSID-02:
0073  *             bssid_mask &= ~(0001   ^   1001)
0074  *             bssid_mask =   (1010)  & ~(0001 ^ 1001)
0075  *             bssid_mask =   (1010)  & ~(1000)
0076  *             bssid_mask =   (1010)  &  (0111)
0077  *             bssid_mask =   0010
0078  *
0079  * A bssid_mask of 0010 means "only pay attention to the second least
0080  * significant bit". This is because its the only bit common
0081  * amongst the MAC and all BSSIDs we support. To findout what the real
0082  * common bit is we can simply "&" the bssid_mask now with any BSSID we have
0083  * or our MAC address (we assume the hardware uses the MAC address).
0084  *
0085  * Now, suppose there's an incoming frame for BSSID-03:
0086  *
0087  * IFRAME-01:  0110
0088  *
0089  * An easy eye-inspeciton of this already should tell you that this frame
0090  * will not pass our check. This is because the bssid_mask tells the
0091  * hardware to only look at the second least significant bit and the
0092  * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
0093  * as 1, which does not match 0.
0094  *
0095  * So with IFRAME-01 we *assume* the hardware will do:
0096  *
0097  *     allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
0098  *  --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
0099  *  --> allow = (0010) == 0000 ? 1 : 0;
0100  *  --> allow = 0
0101  *
0102  *  Lets now test a frame that should work:
0103  *
0104  * IFRAME-02:  0001 (we should allow)
0105  *
0106  *     allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
0107  *  --> allow = (0001 & 0010) ==  (0010 & 0001) ? 1 :0;
0108  *  --> allow = (0000) == (0000)
0109  *  --> allow = 1
0110  *
0111  * Other examples:
0112  *
0113  * IFRAME-03:  0100 --> allowed
0114  * IFRAME-04:  1001 --> allowed
0115  * IFRAME-05:  1101 --> allowed but its not for us!!!
0116  *
0117  */
0118 void ath_hw_setbssidmask(struct ath_common *common)
0119 {
0120     void *ah = common->ah;
0121     u32 id1;
0122 
0123     REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
0124     id1 = REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_SADH_MASK;
0125     id1 |= get_unaligned_le16(common->macaddr + 4);
0126     REG_WRITE(ah, AR_STA_ID1, id1);
0127 
0128     REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
0129     REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
0130 }
0131 EXPORT_SYMBOL(ath_hw_setbssidmask);
0132 
0133 
0134 /**
0135  * ath_hw_cycle_counters_update - common function to update cycle counters
0136  *
0137  * @common: the ath_common struct for the device.
0138  *
0139  * This function is used to update all cycle counters in one place.
0140  * It has to be called while holding common->cc_lock!
0141  */
0142 void ath_hw_cycle_counters_update(struct ath_common *common)
0143 {
0144     u32 cycles, busy, rx, tx;
0145     void *ah = common->ah;
0146 
0147     /* freeze */
0148     REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
0149 
0150     /* read */
0151     cycles = REG_READ(ah, AR_CCCNT);
0152     busy = REG_READ(ah, AR_RCCNT);
0153     rx = REG_READ(ah, AR_RFCNT);
0154     tx = REG_READ(ah, AR_TFCNT);
0155 
0156     /* clear */
0157     REG_WRITE(ah, AR_CCCNT, 0);
0158     REG_WRITE(ah, AR_RFCNT, 0);
0159     REG_WRITE(ah, AR_RCCNT, 0);
0160     REG_WRITE(ah, AR_TFCNT, 0);
0161 
0162     /* unfreeze */
0163     REG_WRITE(ah, AR_MIBC, 0);
0164 
0165     /* update all cycle counters here */
0166     common->cc_ani.cycles += cycles;
0167     common->cc_ani.rx_busy += busy;
0168     common->cc_ani.rx_frame += rx;
0169     common->cc_ani.tx_frame += tx;
0170 
0171     common->cc_survey.cycles += cycles;
0172     common->cc_survey.rx_busy += busy;
0173     common->cc_survey.rx_frame += rx;
0174     common->cc_survey.tx_frame += tx;
0175 }
0176 EXPORT_SYMBOL(ath_hw_cycle_counters_update);
0177 
0178 int32_t ath_hw_get_listen_time(struct ath_common *common)
0179 {
0180     struct ath_cycle_counters *cc = &common->cc_ani;
0181     int32_t listen_time;
0182 
0183     listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
0184               (common->clockrate * 1000);
0185 
0186     memset(cc, 0, sizeof(*cc));
0187 
0188     return listen_time;
0189 }
0190 EXPORT_SYMBOL(ath_hw_get_listen_time);