aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/vt6655/device_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/vt6655/device_main.c')
-rw-r--r--drivers/staging/vt6655/device_main.c250
1 files changed, 106 insertions, 144 deletions
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 0343ae386f03..ed040fbb7df8 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);
+}
- MACvIntEnable(pDevice->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);
- return IRQ_RETVAL(handled);
+ if (priv->vif)
+ vnt_interrupt_process(priv);
+}
+
+static irqreturn_t vnt_interrupt(int irq, void *arg)
+{
+ struct vnt_private *priv = arg;
+
+ 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);
@@ -1524,21 +1525,12 @@ static void vnt_configure(struct ieee80211_hw *hw,
struct vnt_private *priv = hw->priv;
u8 rx_mode = 0;
- *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_PROMISC_IN_BSS |
- FIF_BCN_PRBRESP_PROMISC;
+ *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
VNSvInPortB(priv->PortOffset + MAC_REG_RCR, &rx_mode);
dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode);
- if (changed_flags & FIF_PROMISC_IN_BSS) {
- /* unconditionally log net taps */
- if (*total_flags & FIF_PROMISC_IN_BSS)
- rx_mode |= RCR_UNICAST;
- else
- rx_mode &= ~RCR_UNICAST;
- }
-
if (changed_flags & FIF_ALLMULTI) {
if (*total_flags & FIF_ALLMULTI) {
unsigned long flags;
@@ -1609,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;
@@ -1646,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,
@@ -1771,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");
@@ -1802,10 +1807,10 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
- priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS |
- IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_TIMING_BEACON_ONLY;
+ ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY);
+ ieee80211_hw_set(priv->hw, SIGNAL_DBM);
+ ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
+ ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
priv->hw->max_signal = 100;
@@ -1864,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);