예제 #1
0
a_uint32_t ar5416NumTxPending(struct ath_hal *ah, a_uint32_t q)
{
        a_uint32_t npend;

        HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
        HALASSERT(AH5416(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);

        npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
        if (npend == 0) {
                /*
                 * Pending frame count (PFC) can momentarily go to zero
                 * while TXE remains asserted.  In other words a PFC of
                 * zero is not sufficient to say that the queue has stopped.
                 */
                if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q))
                        npend = 1;
        }
#ifdef DEBUG
        if (npend && (AH5416(ah)->ah_txq[q].tqi_type == HAL_TX_QUEUE_CAB)) {
                if (OS_REG_READ(ah, AR_Q_RDYTIMESHDN) & (1 << q)) {
                        isrPrintf("RTSD on CAB queue\n");
                        /* Clear the ReadyTime shutdown status bits */
                        OS_REG_WRITE(ah, AR_Q_RDYTIMESHDN, 1 << q);
                }
        }
#endif
        return npend;
}
예제 #2
0
HAL_INT_TYPE
ar5212GetInterrupts(WLAN_DEV_INFO *pDev, HAL_INT_TYPE *pUnmaskedValue, A_UINT32 *pDescQueueBitMask)
{
    A_UINT32        isr, isrS2 = 0, maskedIsr;
    HAL_INT_TYPE    ints = 0, maskedInts = 0;

    *pDescQueueBitMask = 0;
    isr = readPlatformReg(pDev, MAC_ISR);
    
    if (isr == 0xffffffff) {
        return HAL_INT_NOCARD;
    }

    maskedIsr = isr & pDev->MaskReg;
    ASSERT(maskedIsr);

    /* Mask out non-common interrupts.  These will be added in below. */
    maskedInts = maskedIsr & HAL_INT_COMMON;

   if (
#ifdef PCI_INTERFACE
        (maskedIsr & MAC_ISR_HIUERR) ||
#endif
        (maskedIsr & MAC_ISR_BCNMISC))
    {
        isrS2 = readPlatformReg(pDev, MAC_ISR_S2);
    }
#ifdef PCI_INTERFACE
    if (maskedIsr & MAC_ISR_HIUERR) {
        if (isrS2 & MAC_ISR_S2_MCABT) {
            isrPrintf("hwGetInterrupts: Bus Master Cycle Abort Error!\n");
        }
        if (isrS2 & MAC_ISR_S2_SSERR) {
            isrPrintf("hwGetInterrupts: Bus Signalled System Error!\n");
        }
        if (isrS2 & MAC_ISR_S2_DPERR) {
            isrPrintf("hwGetInterrupts: Bus Parity Error!\n");
        }
        maskedInts |= HAL_INT_FATAL;
    }
#endif

    if (maskedIsr & (MAC_ISR_RXOK | MAC_ISR_RXERR)) {
        maskedInts |= HAL_INT_RX;
    }
    if (maskedIsr & (MAC_ISR_TXOK | MAC_ISR_TXERR)) {
        maskedInts |= HAL_INT_TX;
    }

    if (maskedIsr & MAC_ISR_TXDESC) {
        maskedInts |= HAL_INT_TXDESC;
    }

    if ((maskedIsr & MAC_ISR_BCNMISC) && (isrS2 & MAC_ISR_S2_DTIM)) {
        maskedInts |= HAL_INT_DTIM;
    }
    if (maskedIsr & MAC_ISR_RXCHIRP) {
        maskedInts |= HAL_INT_RXCHIRP;
    }
    /*
     * Receive Overuns happen quite frequently in Venice/Hainan based MAC 
     * when compression and fastframes are enabled as reported in 
     * bug 9208. Since the bug report also concludes that RXORN is 
     * not fatal anymore, software now uses it as information and 
     * carries on with its normal operation without doing a chip reset 
     */  
#if 0
    /* Receive overrun is usually non-fatal on Oahu/Spirit.
     *
     * BUT early silicon had a bug which causes the rx to fail and the chip
     * must be reset.
     *
     * AND even AR531X v3.1 and AR5211 v4.2 silicon seems to have a problem
     * with RXORN which hangs the receive path and requires a chip reset
     * to proceed (see bug 3996). So for now, we force a hardware reset in
     * all cases.
     */
    if (isr & MAC_ISR_RXORN) {
        isrPrintf("hwGetInterrupts: Receive FIFO Overrun Error!\n");
        maskedInts |= HAL_INT_FATAL;
    }
#endif
    /*
     * Now we take care of the unmasked interrupts.  We need to return certain
     * unmasked interrupts or we'll "lose" them after reading the ISR register.
     */
    ints = isr & HAL_INT_COMMON;

    if (isr & (MAC_ISR_RXOK | MAC_ISR_RXERR)) {
        ints |= HAL_INT_RX;
    }

    if (isr & (MAC_ISR_TXOK | MAC_ISR_TXERR)) {
        ints |= HAL_INT_TX;
    }

    if (isr & MAC_ISR_TXDESC) {
        ints |= HAL_INT_TXDESC;
        *pDescQueueBitMask = A_REG_RD_FIELD(pDev, MAC_ISR_S0, QCU_TXDESC);

        /*
         * Disable the interrupt caused by the queue by writing ones
         * to the secondary ISR.  This avoids the race condition
         * mentioned below.
         */
        A_REG_WR_FIELD(pDev, MAC_ISR_S0, QCU_TXDESC, *pDescQueueBitMask);

        /*
         * This avoids a race condition where a new TXDESC interrupt
         * could come in between reading the ISR and clearing the interrupt
         * via the primary ISR.  We therefore clear the interrupt via
         * the secondary, which avoids this race.
         */
        isr = isr & ~MAC_ISR_TXDESC;
    }
    /*
     * Clear the interrupts we've read by writing back ones in these locations
     * to the primary ISR, TXDESC excepted (see above).
     */
    writePlatformReg(pDev, MAC_ISR, isr);
    /* Flush the write to the Register */
    (void)readPlatformReg(pDev, MAC_ISR); 

#if AR_PB32
    sysPciIntrAck();
#endif

    /* Return the unmasked value. */
    *pUnmaskedValue = ints;

    /* Return the masked value. */
    return maskedInts;
}