diff options
Diffstat (limited to 'drivers/staging/vt6655/device_main.c')
-rw-r--r-- | drivers/staging/vt6655/device_main.c | 231 |
1 files changed, 101 insertions, 130 deletions
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 458bc34..ed040fb 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -32,7 +32,6 @@ * device_free_info - device structure resource free function * device_get_pci_info - get allocated pci io/mem resource * device_print_info - print out resource - * device_intr - interrupt handle function * device_rx_srv - rx service function * device_alloc_rx_buf - rx buffer pre-allocated function * device_free_tx_buf - free tx buffer function @@ -148,16 +147,6 @@ static void vt6655_init_info(struct pci_dev *pcid, static void device_free_info(struct vnt_private *pDevice); static bool device_get_pci_info(struct vnt_private *, struct pci_dev *pcid); static void device_print_info(struct vnt_private *pDevice); -static irqreturn_t device_intr(int irq, void *dev_instance); - -#ifdef CONFIG_PM -static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); -static struct notifier_block device_notifier = { - .notifier_call = device_notify_reboot, - .next = NULL, - .priority = 0, -}; -#endif static void device_init_rd0_ring(struct vnt_private *pDevice); static void device_init_rd1_ring(struct vnt_private *pDevice); @@ -807,6 +796,10 @@ static int device_rx_srv(struct vnt_private *pDevice, unsigned int uIdx) pRD = pRD->next) { if (works++ > 15) break; + + if (!pRD->pRDInfo->skb) + break; + if (vnt_receive_frame(pDevice, pRD)) { if (!device_alloc_rx_buf(pDevice, pRD)) { dev_err(&pDevice->pcid->dev, @@ -1053,129 +1046,135 @@ static void vnt_check_bb_vga(struct vnt_private *priv) } } -static irqreturn_t device_intr(int irq, void *dev_instance) +static void vnt_interrupt_process(struct vnt_private *priv) { - struct vnt_private *pDevice = dev_instance; + struct ieee80211_low_level_stats *low_stats = &priv->low_stats; int max_count = 0; - unsigned long dwMIBCounter = 0; - unsigned char byOrgPageSel = 0; - int handled = 0; + u32 mib_counter; + u32 isr; unsigned long flags; - MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); + MACvReadISR(priv->PortOffset, &isr); - if (pDevice->dwIsr == 0) - return IRQ_RETVAL(handled); + if (isr == 0) + return; - if (pDevice->dwIsr == 0xffffffff) { - pr_debug("dwIsr = 0xffff\n"); - return IRQ_RETVAL(handled); + if (isr == 0xffffffff) { + pr_debug("isr = 0xffff\n"); + return; } - handled = 1; - MACvIntDisable(pDevice->PortOffset); + MACvIntDisable(priv->PortOffset); - spin_lock_irqsave(&pDevice->lock, flags); + spin_lock_irqsave(&priv->lock, flags); - /* Make sure current page is 0 */ - VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel); - if (byOrgPageSel == 1) - MACvSelectPage0(pDevice->PortOffset); - else - byOrgPageSel = 0; + /* Read low level stats */ + MACvReadMIBCounter(priv->PortOffset, &mib_counter); + + low_stats->dot11RTSSuccessCount += mib_counter & 0xff; + low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff; + low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff; + low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff; - MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter); /* * TBD.... * Must do this after doing rx/tx, cause ISR bit is slow * than RD/TD write back * update ISR counter */ - STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic, dwMIBCounter); - while (pDevice->dwIsr != 0) { - STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); - MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); + while (isr && priv->vif) { + MACvWriteISR(priv->PortOffset, isr); - if (pDevice->dwIsr & ISR_FETALERR) { + if (isr & ISR_FETALERR) { pr_debug(" ISR_FETALERR\n"); - VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0); - VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI); - device_error(pDevice, pDevice->dwIsr); + VNSvOutPortB(priv->PortOffset + MAC_REG_SOFTPWRCTL, 0); + VNSvOutPortW(priv->PortOffset + + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI); + device_error(priv, isr); } - if (pDevice->dwIsr & ISR_TBTT) { - if (pDevice->vif && - pDevice->op_mode != NL80211_IFTYPE_ADHOC) - vnt_check_bb_vga(pDevice); + if (isr & ISR_TBTT) { + if (priv->op_mode != NL80211_IFTYPE_ADHOC) + vnt_check_bb_vga(priv); - pDevice->bBeaconSent = false; - if (pDevice->bEnablePSMode) - PSbIsNextTBTTWakeUp((void *)pDevice); + priv->bBeaconSent = false; + if (priv->bEnablePSMode) + PSbIsNextTBTTWakeUp((void *)priv); - if ((pDevice->op_mode == NL80211_IFTYPE_AP || - pDevice->op_mode == NL80211_IFTYPE_ADHOC) && - pDevice->vif->bss_conf.enable_beacon) { - MACvOneShotTimer1MicroSec(pDevice->PortOffset, - (pDevice->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10); + if ((priv->op_mode == NL80211_IFTYPE_AP || + priv->op_mode == NL80211_IFTYPE_ADHOC) && + priv->vif->bss_conf.enable_beacon) { + MACvOneShotTimer1MicroSec(priv->PortOffset, + (priv->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10); } /* TODO: adhoc PS mode */ } - if (pDevice->dwIsr & ISR_BNTX) { - if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) { - pDevice->bIsBeaconBufReadySet = false; - pDevice->cbBeaconBufReadySetCnt = 0; + if (isr & ISR_BNTX) { + if (priv->op_mode == NL80211_IFTYPE_ADHOC) { + priv->bIsBeaconBufReadySet = false; + priv->cbBeaconBufReadySetCnt = 0; } - pDevice->bBeaconSent = true; + priv->bBeaconSent = true; } - if (pDevice->dwIsr & ISR_RXDMA0) - max_count += device_rx_srv(pDevice, TYPE_RXDMA0); + if (isr & ISR_RXDMA0) + max_count += device_rx_srv(priv, TYPE_RXDMA0); - if (pDevice->dwIsr & ISR_RXDMA1) - max_count += device_rx_srv(pDevice, TYPE_RXDMA1); + if (isr & ISR_RXDMA1) + max_count += device_rx_srv(priv, TYPE_RXDMA1); - if (pDevice->dwIsr & ISR_TXDMA0) - max_count += device_tx_srv(pDevice, TYPE_TXDMA0); + if (isr & ISR_TXDMA0) + max_count += device_tx_srv(priv, TYPE_TXDMA0); - if (pDevice->dwIsr & ISR_AC0DMA) - max_count += device_tx_srv(pDevice, TYPE_AC0DMA); + if (isr & ISR_AC0DMA) + max_count += device_tx_srv(priv, TYPE_AC0DMA); - if (pDevice->dwIsr & ISR_SOFTTIMER1) { - if (pDevice->vif) { - if (pDevice->vif->bss_conf.enable_beacon) - vnt_beacon_make(pDevice, pDevice->vif); - } + if (isr & ISR_SOFTTIMER1) { + if (priv->vif->bss_conf.enable_beacon) + vnt_beacon_make(priv, priv->vif); } /* If both buffers available wake the queue */ - if (pDevice->vif) { - if (AVAIL_TD(pDevice, TYPE_TXDMA0) && - AVAIL_TD(pDevice, TYPE_AC0DMA) && - ieee80211_queue_stopped(pDevice->hw, 0)) - ieee80211_wake_queues(pDevice->hw); - } + if (AVAIL_TD(priv, TYPE_TXDMA0) && + AVAIL_TD(priv, TYPE_AC0DMA) && + ieee80211_queue_stopped(priv->hw, 0)) + ieee80211_wake_queues(priv->hw); - MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); + MACvReadISR(priv->PortOffset, &isr); - MACvReceive0(pDevice->PortOffset); - MACvReceive1(pDevice->PortOffset); + MACvReceive0(priv->PortOffset); + MACvReceive1(priv->PortOffset); - if (max_count > pDevice->sOpts.int_works) + if (max_count > priv->sOpts.int_works) break; } - if (byOrgPageSel == 1) - MACvSelectPage1(pDevice->PortOffset); + spin_unlock_irqrestore(&priv->lock, flags); - spin_unlock_irqrestore(&pDevice->lock, flags); + MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE); +} + +static void vnt_interrupt_work(struct work_struct *work) +{ + struct vnt_private *priv = + container_of(work, struct vnt_private, interrupt_work); + + if (priv->vif) + vnt_interrupt_process(priv); +} - MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); +static irqreturn_t vnt_interrupt(int irq, void *arg) +{ + struct vnt_private *priv = arg; - return IRQ_RETVAL(handled); + if (priv->vif) + schedule_work(&priv->interrupt_work); + + return IRQ_HANDLED; } static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) @@ -1267,7 +1266,7 @@ static int vnt_start(struct ieee80211_hw *hw) if (!device_init_rings(priv)) return -ENOMEM; - ret = request_irq(priv->pcid->irq, &device_intr, + ret = request_irq(priv->pcid->irq, &vnt_interrupt, IRQF_SHARED, "vt6655", priv); if (ret) { dev_dbg(&priv->pcid->dev, "failed to start irq\n"); @@ -1296,6 +1295,8 @@ static void vnt_stop(struct ieee80211_hw *hw) ieee80211_stop_queues(hw); + cancel_work_sync(&priv->interrupt_work); + MACbShutdown(priv->PortOffset); MACbSoftwareReset(priv->PortOffset); CARDbRadioPowerOff(priv); @@ -1600,6 +1601,16 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return 0; } +static int vnt_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct vnt_private *priv = hw->priv; + + memcpy(stats, &priv->low_stats, sizeof(*stats)); + + return 0; +} + static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct vnt_private *priv = hw->priv; @@ -1637,6 +1648,7 @@ static const struct ieee80211_ops vnt_mac_ops = { .prepare_multicast = vnt_prepare_multicast, .configure_filter = vnt_configure, .set_key = vnt_set_key, + .get_stats = vnt_get_stats, .get_tsf = vnt_get_tsf, .set_tsf = vnt_set_tsf, .reset_tsf = vnt_reset_tsf, @@ -1762,6 +1774,8 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) return -ENODEV; } + INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); + /* do reset */ if (!MACbSoftwareReset(priv->PortOffset)) { dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); @@ -1855,47 +1869,4 @@ static struct pci_driver device_driver = { #endif }; -static int __init vt6655_init_module(void) -{ - int ret; - - ret = pci_register_driver(&device_driver); -#ifdef CONFIG_PM - if (ret >= 0) - register_reboot_notifier(&device_notifier); -#endif - - return ret; -} - -static void __exit vt6655_cleanup_module(void) -{ -#ifdef CONFIG_PM - unregister_reboot_notifier(&device_notifier); -#endif - pci_unregister_driver(&device_driver); -} - -module_init(vt6655_init_module); -module_exit(vt6655_cleanup_module); - -#ifdef CONFIG_PM -static int -device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -{ - struct pci_dev *pdev = NULL; - - switch (event) { - case SYS_DOWN: - case SYS_HALT: - case SYS_POWER_OFF: - for_each_pci_dev(pdev) { - if (pci_dev_driver(pdev) == &device_driver) { - if (pci_get_drvdata(pdev)) - vt6655_suspend(pdev, PMSG_HIBERNATE); - } - } - } - return NOTIFY_DONE; -} -#endif +module_pci_driver(device_driver); |