Loading Documentation/rfkill.txt +16 −4 Original line number Diff line number Diff line Loading @@ -390,9 +390,10 @@ rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft rfkill input line is active. Only if none of the rfkill input lines are active, will it return RFKILL_STATE_UNBLOCKED. If it doesn't implement the get_state() hook, it must make sure that its calls to rfkill_force_state() are enough to keep the status always up-to-date, and it must do a rfkill_force_state() on resume from sleep. Since the device has a hardware rfkill line, it IS subject to state changes external to rfkill. Therefore, the driver must make sure that it calls rfkill_force_state() to keep the status always up-to-date, and it must do a rfkill_force_state() on resume from sleep. Every time the driver gets a notification from the card that one of its rfkill lines changed state (polling might be needed on badly designed cards that don't Loading Loading @@ -422,13 +423,24 @@ of the hardware is unknown), or read-write (where the hardware can be queried about its current state). The rfkill class will call the get_state hook of a device every time it needs to know the *real* current state of the hardware. This can happen often. to know the *real* current state of the hardware. This can happen often, but it does not do any polling, so it is not enough on hardware that is subject to state changes outside of the rfkill subsystem. Therefore, calling rfkill_force_state() when a state change happens is mandatory when the device has a hardware rfkill line, or when something else like the firmware could cause its state to be changed without going through the rfkill class. Some hardware provides events when its status changes. In these cases, it is best for the driver to not provide a get_state hook, and instead register the rfkill class *already* with the correct status, and keep it updated using rfkill_force_state() when it gets an event from the hardware. rfkill_force_state() must be used on the device resume handlers to update the rfkill status, should there be any chance of the device status changing during the sleep. There is no provision for a statically-allocated rfkill struct. You must use rfkill_allocate() to allocate one. Loading drivers/net/ps3_gelic_wireless.c +6 −6 Original line number Diff line number Diff line Loading @@ -1024,7 +1024,7 @@ static int gelic_wl_set_encode(struct net_device *netdev, struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; __u16 flags; unsigned int irqflag; unsigned long irqflag; int key_index, index_specified; int ret = 0; Loading Loading @@ -1097,7 +1097,7 @@ static int gelic_wl_get_encode(struct net_device *netdev, { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; unsigned int irqflag; unsigned long irqflag; unsigned int key_index, index_specified; int ret = 0; Loading Loading @@ -1215,7 +1215,7 @@ static int gelic_wl_set_encodeext(struct net_device *netdev, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; __u16 alg; __u16 flags; unsigned int irqflag; unsigned long irqflag; int key_index; int ret = 0; Loading Loading @@ -1303,7 +1303,7 @@ static int gelic_wl_get_encodeext(struct net_device *netdev, struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; unsigned int irqflag; unsigned long irqflag; int key_index; int ret = 0; int max_key_len; Loading Loading @@ -1426,7 +1426,7 @@ static int gelic_wl_priv_set_psk(struct net_device *net_dev, { struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); unsigned int len; unsigned int irqflag; unsigned long irqflag; int ret = 0; pr_debug("%s:<- len=%d\n", __func__, data->data.length); Loading Loading @@ -1467,7 +1467,7 @@ static int gelic_wl_priv_get_psk(struct net_device *net_dev, { struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); char *p; unsigned int irqflag; unsigned long irqflag; unsigned int i; pr_debug("%s:<-\n", __func__); Loading drivers/net/wireless/ath5k/base.c +63 −36 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ #include <linux/version.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/hardirq.h> #include <linux/if.h> #include <linux/io.h> #include <linux/netdevice.h> #include <linux/cache.h> #include <linux/pci.h> Loading Loading @@ -471,9 +473,6 @@ ath5k_pci_probe(struct pci_dev *pdev, /* Set private data */ pci_set_drvdata(pdev, hw); /* Enable msi for devices that support it */ pci_enable_msi(pdev); /* Setup interrupt handler */ ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (ret) { Loading Loading @@ -551,7 +550,6 @@ ath5k_pci_probe(struct pci_dev *pdev, err_irq: free_irq(pdev->irq, sc); err_free: pci_disable_msi(pdev); ieee80211_free_hw(hw); err_map: pci_iounmap(pdev, mem); Loading @@ -573,7 +571,6 @@ ath5k_pci_remove(struct pci_dev *pdev) ath5k_detach(pdev, hw); ath5k_hw_detach(sc->ah); free_irq(pdev->irq, sc); pci_disable_msi(pdev); pci_iounmap(pdev, sc->iobase); pci_release_region(pdev, 0); pci_disable_device(pdev); Loading @@ -590,6 +587,9 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath5k_led_off(sc); ath5k_stop_hw(sc); free_irq(pdev->irq, sc); pci_disable_msi(pdev); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); Loading @@ -605,15 +605,12 @@ ath5k_pci_resume(struct pci_dev *pdev) struct ath5k_hw *ah = sc->ah; int i, err; err = pci_set_power_state(pdev, PCI_D0); if (err) return err; pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) return err; pci_restore_state(pdev); /* * Suspend/Resume resets the PCI configuration space, so we have to * re-disable the RETRY_TIMEOUT register (0x41) to keep Loading @@ -621,7 +618,17 @@ ath5k_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, 0x41, 0); ath5k_init(sc); pci_enable_msi(pdev); err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (err) { ATH5K_ERR(sc, "request_irq failed\n"); goto err_msi; } err = ath5k_init(sc); if (err) goto err_irq; ath5k_led_enable(sc); /* Loading @@ -635,6 +642,12 @@ ath5k_pci_resume(struct pci_dev *pdev) ath5k_hw_reset_key(ah, i); return 0; err_irq: free_irq(pdev->irq, sc); err_msi: pci_disable_msi(pdev); pci_disable_device(pdev); return err; } #endif /* CONFIG_PM */ Loading Loading @@ -1224,7 +1237,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) pktlen = skb->len; if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) { if (info->control.hw_key) { keyidx = info->control.hw_key->hw_key_idx; pktlen += info->control.icv_len; } Loading @@ -1249,6 +1262,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) txq->link = &ds->ds_link; ath5k_hw_tx_start(ah, txq->qnum); mmiowb(); spin_unlock_bh(&txq->lock); return 0; Loading Loading @@ -1583,7 +1597,6 @@ ath5k_rx_stop(struct ath5k_softc *sc) ath5k_hw_stop_pcu_recv(ah); /* disable PCU */ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ mdelay(3); /* 3ms is long enough for 1 frame */ ath5k_debug_printrxbuffs(sc, ah); Loading Loading @@ -1682,31 +1695,44 @@ ath5k_tasklet_rx(unsigned long data) struct ath5k_rx_status rs = {}; struct sk_buff *skb; struct ath5k_softc *sc = (void *)data; struct ath5k_buf *bf; struct ath5k_buf *bf, *bf_last; struct ath5k_desc *ds; int ret; int hdrlen; int pad; spin_lock(&sc->rxbuflock); if (list_empty(&sc->rxbuf)) { ATH5K_WARN(sc, "empty rx buf pool\n"); goto unlock; } bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); do { rxs.flag = 0; if (unlikely(list_empty(&sc->rxbuf))) { ATH5K_WARN(sc, "empty rx buf pool\n"); break; } bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); BUG_ON(bf->skb == NULL); skb = bf->skb; ds = bf->desc; /* TODO only one segment */ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, sc->desc_len, PCI_DMA_FROMDEVICE); if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ /* * last buffer must not be freed to ensure proper hardware * function. When the hardware finishes also a packet next to * it, we are sure, it doesn't use it anymore and we can go on. */ if (bf_last == bf) bf->flags |= 1; if (bf->flags) { struct ath5k_buf *bf_next = list_entry(bf->list.next, struct ath5k_buf, list); ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, &rs); if (ret) break; bf->flags &= ~1; /* skip the overwritten one (even status is martian) */ goto next; } ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); if (unlikely(ret == -EINPROGRESS)) Loading Loading @@ -1752,8 +1778,6 @@ ath5k_tasklet_rx(unsigned long data) goto next; } accept: pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, rs.rs_datalen, PCI_DMA_FROMDEVICE); pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, PCI_DMA_FROMDEVICE); bf->skb = NULL; Loading Loading @@ -1816,6 +1840,7 @@ ath5k_tasklet_rx(unsigned long data) next: list_move_tail(&bf->list, &sc->rxbuf); } while (ath5k_rxbuf_setup(sc, bf) == 0); unlock: spin_unlock(&sc->rxbuflock); } Loading @@ -1840,9 +1865,6 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) list_for_each_entry_safe(bf, bf0, &txq->q, list) { ds = bf->desc; /* TODO only one segment */ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, sc->desc_len, PCI_DMA_FROMDEVICE); ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); if (unlikely(ret == -EINPROGRESS)) break; Loading Loading @@ -2015,8 +2037,6 @@ ath5k_beacon_send(struct ath5k_softc *sc) ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len, PCI_DMA_TODEVICE); ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); ath5k_hw_tx_start(ah, sc->bhalq); Loading Loading @@ -2240,6 +2260,7 @@ ath5k_init(struct ath5k_softc *sc) ret = 0; done: mmiowb(); mutex_unlock(&sc->lock); return ret; } Loading Loading @@ -2272,6 +2293,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) if (!test_bit(ATH_STAT_INVALID, sc->status)) { ath5k_led_off(sc); ath5k_hw_set_intr(ah, 0); synchronize_irq(sc->pdev->irq); } ath5k_txq_cleanup(sc); if (!test_bit(ATH_STAT_INVALID, sc->status)) { Loading Loading @@ -2321,9 +2343,13 @@ ath5k_stop_hw(struct ath5k_softc *sc) } } ath5k_txbuf_free(sc, sc->bbuf); mmiowb(); mutex_unlock(&sc->lock); del_timer_sync(&sc->calib_tim); tasklet_kill(&sc->rxtq); tasklet_kill(&sc->txtq); tasklet_kill(&sc->restq); return ret; } Loading Loading @@ -2550,8 +2576,6 @@ ath5k_init_leds(struct ath5k_softc *sc) struct pci_dev *pdev = sc->pdev; char name[ATH5K_LED_MAX_NAME_LEN + 1]; sc->led_on = 0; /* active low */ /* * Auto-enable soft led processing for IBM cards and for * 5211 minipci cards. Loading @@ -2560,11 +2584,13 @@ ath5k_init_leds(struct ath5k_softc *sc) pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = 0; sc->led_on = 0; /* active low */ } /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = 1; sc->led_on = 1; /* active high */ } if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) goto out; Loading Loading @@ -2783,6 +2809,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* XXX: assoc id is set to 0 for now, mac80211 doesn't have * a clean way of letting us retrieve this yet. */ ath5k_hw_set_associd(ah, ah->ah_bssid, 0); mmiowb(); } if (conf->changed & IEEE80211_IFCC_BEACON && Loading Loading @@ -2971,6 +2998,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } unlock: mmiowb(); mutex_unlock(&sc->lock); return ret; } Loading Loading @@ -3032,8 +3060,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ath5k_debug_dump_skb(sc, skb, "BC ", 1); mutex_lock(&sc->lock); if (sc->opmode != IEEE80211_IF_TYPE_IBSS) { ret = -EIO; goto end; Loading @@ -3044,11 +3070,12 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ret = ath5k_beacon_setup(sc, sc->bbuf); if (ret) sc->bbuf->skb = NULL; else else { ath5k_beacon_config(sc); mmiowb(); } end: mutex_unlock(&sc->lock); return ret; } drivers/net/wireless/ath5k/base.h +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ struct ath5k_buf { struct list_head list; unsigned int flags; /* tx descriptor flags */ unsigned int flags; /* rx descriptor flags */ struct ath5k_desc *desc; /* virtual addr of desc */ dma_addr_t daddr; /* physical addr of desc */ struct sk_buff *skb; /* skbuff for buf */ Loading drivers/net/wireless/ath5k/hw.c +4 −0 Original line number Diff line number Diff line Loading @@ -1440,6 +1440,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Stop queue */ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR); } else { /* * Schedule TX disable and wait until queue is empty Loading @@ -1456,6 +1457,8 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Clear register */ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); if (pending) return -EBUSY; } /* TODO: Check for success else return error */ Loading Loading @@ -1716,6 +1719,7 @@ enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask) /* ..re-enable interrupts */ ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); ath5k_hw_reg_read(ah, AR5K_IER); return old_mask; } Loading Loading
Documentation/rfkill.txt +16 −4 Original line number Diff line number Diff line Loading @@ -390,9 +390,10 @@ rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft rfkill input line is active. Only if none of the rfkill input lines are active, will it return RFKILL_STATE_UNBLOCKED. If it doesn't implement the get_state() hook, it must make sure that its calls to rfkill_force_state() are enough to keep the status always up-to-date, and it must do a rfkill_force_state() on resume from sleep. Since the device has a hardware rfkill line, it IS subject to state changes external to rfkill. Therefore, the driver must make sure that it calls rfkill_force_state() to keep the status always up-to-date, and it must do a rfkill_force_state() on resume from sleep. Every time the driver gets a notification from the card that one of its rfkill lines changed state (polling might be needed on badly designed cards that don't Loading Loading @@ -422,13 +423,24 @@ of the hardware is unknown), or read-write (where the hardware can be queried about its current state). The rfkill class will call the get_state hook of a device every time it needs to know the *real* current state of the hardware. This can happen often. to know the *real* current state of the hardware. This can happen often, but it does not do any polling, so it is not enough on hardware that is subject to state changes outside of the rfkill subsystem. Therefore, calling rfkill_force_state() when a state change happens is mandatory when the device has a hardware rfkill line, or when something else like the firmware could cause its state to be changed without going through the rfkill class. Some hardware provides events when its status changes. In these cases, it is best for the driver to not provide a get_state hook, and instead register the rfkill class *already* with the correct status, and keep it updated using rfkill_force_state() when it gets an event from the hardware. rfkill_force_state() must be used on the device resume handlers to update the rfkill status, should there be any chance of the device status changing during the sleep. There is no provision for a statically-allocated rfkill struct. You must use rfkill_allocate() to allocate one. Loading
drivers/net/ps3_gelic_wireless.c +6 −6 Original line number Diff line number Diff line Loading @@ -1024,7 +1024,7 @@ static int gelic_wl_set_encode(struct net_device *netdev, struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; __u16 flags; unsigned int irqflag; unsigned long irqflag; int key_index, index_specified; int ret = 0; Loading Loading @@ -1097,7 +1097,7 @@ static int gelic_wl_get_encode(struct net_device *netdev, { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; unsigned int irqflag; unsigned long irqflag; unsigned int key_index, index_specified; int ret = 0; Loading Loading @@ -1215,7 +1215,7 @@ static int gelic_wl_set_encodeext(struct net_device *netdev, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; __u16 alg; __u16 flags; unsigned int irqflag; unsigned long irqflag; int key_index; int ret = 0; Loading Loading @@ -1303,7 +1303,7 @@ static int gelic_wl_get_encodeext(struct net_device *netdev, struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; unsigned int irqflag; unsigned long irqflag; int key_index; int ret = 0; int max_key_len; Loading Loading @@ -1426,7 +1426,7 @@ static int gelic_wl_priv_set_psk(struct net_device *net_dev, { struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); unsigned int len; unsigned int irqflag; unsigned long irqflag; int ret = 0; pr_debug("%s:<- len=%d\n", __func__, data->data.length); Loading Loading @@ -1467,7 +1467,7 @@ static int gelic_wl_priv_get_psk(struct net_device *net_dev, { struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); char *p; unsigned int irqflag; unsigned long irqflag; unsigned int i; pr_debug("%s:<-\n", __func__); Loading
drivers/net/wireless/ath5k/base.c +63 −36 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ #include <linux/version.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/hardirq.h> #include <linux/if.h> #include <linux/io.h> #include <linux/netdevice.h> #include <linux/cache.h> #include <linux/pci.h> Loading Loading @@ -471,9 +473,6 @@ ath5k_pci_probe(struct pci_dev *pdev, /* Set private data */ pci_set_drvdata(pdev, hw); /* Enable msi for devices that support it */ pci_enable_msi(pdev); /* Setup interrupt handler */ ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (ret) { Loading Loading @@ -551,7 +550,6 @@ ath5k_pci_probe(struct pci_dev *pdev, err_irq: free_irq(pdev->irq, sc); err_free: pci_disable_msi(pdev); ieee80211_free_hw(hw); err_map: pci_iounmap(pdev, mem); Loading @@ -573,7 +571,6 @@ ath5k_pci_remove(struct pci_dev *pdev) ath5k_detach(pdev, hw); ath5k_hw_detach(sc->ah); free_irq(pdev->irq, sc); pci_disable_msi(pdev); pci_iounmap(pdev, sc->iobase); pci_release_region(pdev, 0); pci_disable_device(pdev); Loading @@ -590,6 +587,9 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath5k_led_off(sc); ath5k_stop_hw(sc); free_irq(pdev->irq, sc); pci_disable_msi(pdev); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); Loading @@ -605,15 +605,12 @@ ath5k_pci_resume(struct pci_dev *pdev) struct ath5k_hw *ah = sc->ah; int i, err; err = pci_set_power_state(pdev, PCI_D0); if (err) return err; pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) return err; pci_restore_state(pdev); /* * Suspend/Resume resets the PCI configuration space, so we have to * re-disable the RETRY_TIMEOUT register (0x41) to keep Loading @@ -621,7 +618,17 @@ ath5k_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, 0x41, 0); ath5k_init(sc); pci_enable_msi(pdev); err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (err) { ATH5K_ERR(sc, "request_irq failed\n"); goto err_msi; } err = ath5k_init(sc); if (err) goto err_irq; ath5k_led_enable(sc); /* Loading @@ -635,6 +642,12 @@ ath5k_pci_resume(struct pci_dev *pdev) ath5k_hw_reset_key(ah, i); return 0; err_irq: free_irq(pdev->irq, sc); err_msi: pci_disable_msi(pdev); pci_disable_device(pdev); return err; } #endif /* CONFIG_PM */ Loading Loading @@ -1224,7 +1237,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) pktlen = skb->len; if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) { if (info->control.hw_key) { keyidx = info->control.hw_key->hw_key_idx; pktlen += info->control.icv_len; } Loading @@ -1249,6 +1262,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) txq->link = &ds->ds_link; ath5k_hw_tx_start(ah, txq->qnum); mmiowb(); spin_unlock_bh(&txq->lock); return 0; Loading Loading @@ -1583,7 +1597,6 @@ ath5k_rx_stop(struct ath5k_softc *sc) ath5k_hw_stop_pcu_recv(ah); /* disable PCU */ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ mdelay(3); /* 3ms is long enough for 1 frame */ ath5k_debug_printrxbuffs(sc, ah); Loading Loading @@ -1682,31 +1695,44 @@ ath5k_tasklet_rx(unsigned long data) struct ath5k_rx_status rs = {}; struct sk_buff *skb; struct ath5k_softc *sc = (void *)data; struct ath5k_buf *bf; struct ath5k_buf *bf, *bf_last; struct ath5k_desc *ds; int ret; int hdrlen; int pad; spin_lock(&sc->rxbuflock); if (list_empty(&sc->rxbuf)) { ATH5K_WARN(sc, "empty rx buf pool\n"); goto unlock; } bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); do { rxs.flag = 0; if (unlikely(list_empty(&sc->rxbuf))) { ATH5K_WARN(sc, "empty rx buf pool\n"); break; } bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); BUG_ON(bf->skb == NULL); skb = bf->skb; ds = bf->desc; /* TODO only one segment */ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, sc->desc_len, PCI_DMA_FROMDEVICE); if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ /* * last buffer must not be freed to ensure proper hardware * function. When the hardware finishes also a packet next to * it, we are sure, it doesn't use it anymore and we can go on. */ if (bf_last == bf) bf->flags |= 1; if (bf->flags) { struct ath5k_buf *bf_next = list_entry(bf->list.next, struct ath5k_buf, list); ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, &rs); if (ret) break; bf->flags &= ~1; /* skip the overwritten one (even status is martian) */ goto next; } ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); if (unlikely(ret == -EINPROGRESS)) Loading Loading @@ -1752,8 +1778,6 @@ ath5k_tasklet_rx(unsigned long data) goto next; } accept: pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, rs.rs_datalen, PCI_DMA_FROMDEVICE); pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, PCI_DMA_FROMDEVICE); bf->skb = NULL; Loading Loading @@ -1816,6 +1840,7 @@ ath5k_tasklet_rx(unsigned long data) next: list_move_tail(&bf->list, &sc->rxbuf); } while (ath5k_rxbuf_setup(sc, bf) == 0); unlock: spin_unlock(&sc->rxbuflock); } Loading @@ -1840,9 +1865,6 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) list_for_each_entry_safe(bf, bf0, &txq->q, list) { ds = bf->desc; /* TODO only one segment */ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, sc->desc_len, PCI_DMA_FROMDEVICE); ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); if (unlikely(ret == -EINPROGRESS)) break; Loading Loading @@ -2015,8 +2037,6 @@ ath5k_beacon_send(struct ath5k_softc *sc) ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len, PCI_DMA_TODEVICE); ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); ath5k_hw_tx_start(ah, sc->bhalq); Loading Loading @@ -2240,6 +2260,7 @@ ath5k_init(struct ath5k_softc *sc) ret = 0; done: mmiowb(); mutex_unlock(&sc->lock); return ret; } Loading Loading @@ -2272,6 +2293,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) if (!test_bit(ATH_STAT_INVALID, sc->status)) { ath5k_led_off(sc); ath5k_hw_set_intr(ah, 0); synchronize_irq(sc->pdev->irq); } ath5k_txq_cleanup(sc); if (!test_bit(ATH_STAT_INVALID, sc->status)) { Loading Loading @@ -2321,9 +2343,13 @@ ath5k_stop_hw(struct ath5k_softc *sc) } } ath5k_txbuf_free(sc, sc->bbuf); mmiowb(); mutex_unlock(&sc->lock); del_timer_sync(&sc->calib_tim); tasklet_kill(&sc->rxtq); tasklet_kill(&sc->txtq); tasklet_kill(&sc->restq); return ret; } Loading Loading @@ -2550,8 +2576,6 @@ ath5k_init_leds(struct ath5k_softc *sc) struct pci_dev *pdev = sc->pdev; char name[ATH5K_LED_MAX_NAME_LEN + 1]; sc->led_on = 0; /* active low */ /* * Auto-enable soft led processing for IBM cards and for * 5211 minipci cards. Loading @@ -2560,11 +2584,13 @@ ath5k_init_leds(struct ath5k_softc *sc) pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = 0; sc->led_on = 0; /* active low */ } /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = 1; sc->led_on = 1; /* active high */ } if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) goto out; Loading Loading @@ -2783,6 +2809,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* XXX: assoc id is set to 0 for now, mac80211 doesn't have * a clean way of letting us retrieve this yet. */ ath5k_hw_set_associd(ah, ah->ah_bssid, 0); mmiowb(); } if (conf->changed & IEEE80211_IFCC_BEACON && Loading Loading @@ -2971,6 +2998,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } unlock: mmiowb(); mutex_unlock(&sc->lock); return ret; } Loading Loading @@ -3032,8 +3060,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ath5k_debug_dump_skb(sc, skb, "BC ", 1); mutex_lock(&sc->lock); if (sc->opmode != IEEE80211_IF_TYPE_IBSS) { ret = -EIO; goto end; Loading @@ -3044,11 +3070,12 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ret = ath5k_beacon_setup(sc, sc->bbuf); if (ret) sc->bbuf->skb = NULL; else else { ath5k_beacon_config(sc); mmiowb(); } end: mutex_unlock(&sc->lock); return ret; }
drivers/net/wireless/ath5k/base.h +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ struct ath5k_buf { struct list_head list; unsigned int flags; /* tx descriptor flags */ unsigned int flags; /* rx descriptor flags */ struct ath5k_desc *desc; /* virtual addr of desc */ dma_addr_t daddr; /* physical addr of desc */ struct sk_buff *skb; /* skbuff for buf */ Loading
drivers/net/wireless/ath5k/hw.c +4 −0 Original line number Diff line number Diff line Loading @@ -1440,6 +1440,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Stop queue */ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR); } else { /* * Schedule TX disable and wait until queue is empty Loading @@ -1456,6 +1457,8 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Clear register */ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); if (pending) return -EBUSY; } /* TODO: Check for success else return error */ Loading Loading @@ -1716,6 +1719,7 @@ enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask) /* ..re-enable interrupts */ ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); ath5k_hw_reg_read(ah, AR5K_IER); return old_mask; } Loading