From 47c1b496015e41e1068878814596af9a45d4fa84 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 3 Jul 2011 11:22:15 +0300 Subject: iwlagn: move Tx datapath to transport layer Split the Tx datapath in two parts: * the first deals with the Tx cmd composition * the second attaches the skb + Tx cmd to the queues Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a0cca02032e..173fad2ab24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1257,6 +1257,10 @@ struct iwl_trans_ops { int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, const void *data); + struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); + int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx); }; struct iwl_trans { -- cgit v1.2.3-70-g09d2 From 34c1b7ba127d1815b3dd1cb81cc4338ce0e712b7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 4 Jul 2011 08:58:19 +0300 Subject: iwlagn: move the tasklet / irq to the transport layer PCIe doesn't provide any ISR registration API, whereas other buses do. Hence, we need to move the tasklet and irq to the transport layer to allow this flexibility. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 4 +++ drivers/net/wireless/iwlwifi/iwl-agn.c | 39 ++++++++++-------------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +++ drivers/net/wireless/iwlwifi/iwl-trans.c | 29 ++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 7 +++++- 6 files changed, 55 insertions(+), 29 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index f1b40ec1c87..9a2eb1e426b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -49,6 +49,10 @@ void iwl_free_isr_ict(struct iwl_priv *priv) priv->_agn.ict_tbl_vir, priv->_agn.ict_tbl_dma); priv->_agn.ict_tbl_vir = NULL; + memset(&priv->_agn.ict_tbl_dma, 0, + sizeof(priv->_agn.ict_tbl_dma)); + memset(&priv->_agn.aligned_ict_tbl_dma, 0, + sizeof(priv->_agn.aligned_ict_tbl_dma)); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 38a1e4f5882..598f16486aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -625,7 +625,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) } /* tasklet for iwlagn interrupt */ -static void iwl_irq_tasklet(struct iwl_priv *priv) +void iwl_irq_tasklet(struct iwl_priv *priv) { u32 inta = 0; u32 handled = 0; @@ -3227,9 +3227,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) init_timer(&priv->watchdog); priv->watchdog.data = (unsigned long)priv; priv->watchdog.function = iwl_bg_watchdog; - - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); } static void iwl_cancel_deferred_work(struct iwl_priv *priv) @@ -3548,8 +3545,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, priv->bus.ops->set_drv_data(&priv->bus, priv); priv->bus.dev = priv->bus.ops->get_dev(&priv->bus); - iwl_trans_register(&priv->trans); - /* At this point both hw and priv are allocated. */ SET_IEEE80211_DEV(hw, priv->bus.dev); @@ -3558,6 +3553,10 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, priv->cfg = cfg; priv->inta_mask = CSR_INI_SET_MASK; + err = iwl_trans_register(priv); + if (err) + goto out_free_priv; + /* is antenna coupling more than 35dB ? */ priv->bt_ant_couple_ok = (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? @@ -3652,15 +3651,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, /******************** * 7. Setup services ********************/ - iwl_alloc_isr_ict(priv); - - err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED, - DRV_NAME, priv); - if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq); - goto out_uninit_drv; - } - iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); iwl_testmode_init(priv); @@ -3691,19 +3681,18 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, return 0; - out_destroy_workqueue: +out_destroy_workqueue: destroy_workqueue(priv->workqueue); priv->workqueue = NULL; - free_irq(priv->bus.irq, priv); - iwl_free_isr_ict(priv); - out_uninit_drv: iwl_uninit_drv(priv); - out_free_eeprom: +out_free_eeprom: iwl_eeprom_free(priv); - out_free_traffic_mem: +out_free_traffic_mem: iwl_free_traffic_mem(priv); + trans_free(priv); +out_free_priv: ieee80211_free_hw(priv->hw); - out: +out: return err; } @@ -3754,7 +3743,6 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_eeprom_free(priv); - /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); @@ -3765,13 +3753,12 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->workqueue = NULL; iwl_free_traffic_mem(priv); - free_irq(priv->bus.irq, priv); + trans_free(priv); + priv->bus.ops->set_drv_data(&priv->bus, NULL); iwl_uninit_drv(priv); - iwl_free_isr_ict(priv); - dev_kfree_skb(priv->beacon_skb); ieee80211_free_hw(priv->hw); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index aed86c6cd93..70188550a4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -188,6 +188,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); /* rx */ +void iwl_irq_tasklet(struct iwl_priv *priv); void iwlagn_rx_queue_restock(struct iwl_priv *priv); void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); void iwlagn_rx_replenish(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 173fad2ab24..b38b00cebd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1243,6 +1243,8 @@ struct iwl_trans; * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* + * @free: release all the ressource for the transport layer itself such as + * irq, tasklet etc... */ struct iwl_trans_ops { int (*rx_init)(struct iwl_priv *priv); @@ -1261,6 +1263,8 @@ struct iwl_trans_ops { int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); + + void (*free)(struct iwl_priv *priv); }; struct iwl_trans { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index acd2a5feec9..ecdda6d57b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -705,6 +705,12 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return 0; } +static void iwl_trans_free(struct iwl_priv *priv) +{ + free_irq(priv->bus.irq, priv); + iwl_free_isr_ict(priv); +} + static const struct iwl_trans_ops trans_ops = { .rx_init = iwl_trans_rx_init, .rx_stop = iwl_trans_rx_stop, @@ -719,9 +725,28 @@ static const struct iwl_trans_ops trans_ops = { .get_tx_cmd = iwl_trans_get_tx_cmd, .tx = iwl_trans_tx, + + .free = iwl_trans_free, }; -void iwl_trans_register(struct iwl_trans *trans) +int iwl_trans_register(struct iwl_priv *priv) { - trans->ops = &trans_ops; + int err; + + priv->trans.ops = &trans_ops; + + iwl_alloc_isr_ict(priv); + + err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED, + DRV_NAME, priv); + if (err) { + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq); + iwl_free_isr_ict(priv); + return err; + } + + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); + + return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index f10bee8c1f8..f8133ea90af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -115,4 +115,9 @@ static inline int trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return priv->trans.ops->tx(priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } -void iwl_trans_register(struct iwl_trans *trans); +static inline void trans_free(struct iwl_priv *priv) +{ + priv->trans.ops->free(priv); +} + +int iwl_trans_register(struct iwl_priv *priv); -- cgit v1.2.3-70-g09d2 From a27367d25da06c24e0379ad4489542016ff11dbb Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 4 Jul 2011 09:06:44 +0300 Subject: iwlagn: move sync_irq to transport layer Since all the irq / tasklet is now handled in the transport layer, it should give an API to ensure that all the irq / tasklet have finished running. This will allow the upper layer to release all its resources. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 8 -------- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 +++++ drivers/net/wireless/iwlwifi/iwl-trans.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-trans.h | 5 +++++ 6 files changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index eb2be0d3048..b2821900312 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2399,7 +2399,7 @@ void iwlagn_stop_device(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); + trans_sync_irq(priv); /* device going down, Stop using ICT table */ iwl_disable_ict(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 598f16486aa..c91e0104a7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3734,7 +3734,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); + trans_sync_irq(priv); iwl_dealloc_ucode(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 70188550a4f..fe5451eee82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -118,14 +118,6 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->bus.irq); - tasklet_kill(&priv->irq_tasklet); -} - static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { hdr->op_code = cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b38b00cebd2..cb6801c38fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1243,6 +1243,10 @@ struct iwl_trans; * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* + * @sync_irq: the upper layer will typically disable interrupt and call this + * handler. After this handler returns, it is guaranteed that all + * the ISR / tasklet etc... have finished running and the transport + * layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... */ @@ -1264,6 +1268,7 @@ struct iwl_trans_ops { struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); + void (*sync_irq)(struct iwl_priv *priv); void (*free)(struct iwl_priv *priv); }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ecdda6d57b1..ca969028710 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -705,6 +705,13 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return 0; } +static void iwl_trans_sync_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->bus.irq); + tasklet_kill(&priv->irq_tasklet); +} + static void iwl_trans_free(struct iwl_priv *priv) { free_irq(priv->bus.irq, priv); @@ -726,6 +733,7 @@ static const struct iwl_trans_ops trans_ops = { .get_tx_cmd = iwl_trans_get_tx_cmd, .tx = iwl_trans_tx, + .sync_irq = iwl_trans_sync_irq, .free = iwl_trans_free, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index f8133ea90af..886730ecf30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -115,6 +115,11 @@ static inline int trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return priv->trans.ops->tx(priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } +static inline void trans_sync_irq(struct iwl_priv *priv) +{ + priv->trans.ops->sync_irq(priv); +} + static inline void trans_free(struct iwl_priv *priv) { priv->trans.ops->free(priv); -- cgit v1.2.3-70-g09d2 From 47365ab858a7f452e79437d1a44488245e903f37 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 7 Jul 2011 09:25:51 -0700 Subject: iwlagn: add comment to tx and get_tx_cmd in iwl_trans_ops Those comments were missed in a previous commit. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index cb6801c38fd..34625de2e51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1243,6 +1243,8 @@ struct iwl_trans; * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* + * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use + * @tx: send an skb * @sync_irq: the upper layer will typically disable interrupt and call this * handler. After this handler returns, it is guaranteed that all * the ISR / tasklet etc... have finished running and the transport -- cgit v1.2.3-70-g09d2 From ab6cf8e816bad473a1496f2006bea3a3849c2519 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 7 Jul 2011 14:37:26 +0300 Subject: iwlagn: move iwlagn_stop_device to transport layer Since iwlagn_stop_device was the only caller to the rx_stop / tx_stop, these two don't need to be API any more. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 39 ------------------------ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 7 ++--- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 44 ++++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 13 +++----- 8 files changed, 52 insertions(+), 58 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 4156316e108..e06a5c2f835 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2166,42 +2166,3 @@ int iwlagn_start_device(struct iwl_priv *priv) return 0; } -void iwlagn_stop_device(struct iwl_priv *priv) -{ - unsigned long flags; - - /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - - /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - trans_sync_irq(priv); - - /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); - - /* - * If a HW restart happens during firmware loading, - * then the firmware loading might call this function - * and later it might be called again due to the - * restart. So don't process again if the device is - * already dead. - */ - if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { - trans_tx_stop(priv); - trans_rx_stop(priv); - - /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); - udelay(5); - } - - /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv); -} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 06304a681ed..c15a1f7f4ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -707,6 +707,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ - iwlagn_stop_device(priv); + trans_stop_device(priv); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bd85af91c58..3de90c54028 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1782,7 +1782,7 @@ static void __iwl_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - iwlagn_stop_device(priv); + trans_stop_device(priv); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 0c4e14527df..fa32eb99e1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -129,7 +129,6 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) int iwl_prepare_card_hw(struct iwl_priv *priv); int iwlagn_start_device(struct iwl_priv *priv); -void iwlagn_stop_device(struct iwl_priv *priv); /* tx queue */ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 34625de2e51..cf6f4b2e2cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1236,11 +1236,10 @@ struct iwl_trans; * struct iwl_trans_ops - transport specific operations * @rx_init: inits the rx memory, allocate it if needed - * @rx_stop: stop the rx * @rx_free: frees the rx memory * @tx_init:inits the tx memory, allocate if needed - * @tx_stop: stop the tx * @tx_free: frees the tx memory + * @stop_device:stops the whole device (embedded CPU put to reset) * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use @@ -1254,13 +1253,13 @@ struct iwl_trans; */ struct iwl_trans_ops { int (*rx_init)(struct iwl_priv *priv); - int (*rx_stop)(struct iwl_priv *priv); void (*rx_free)(struct iwl_priv *priv); int (*tx_init)(struct iwl_priv *priv); - int (*tx_stop)(struct iwl_priv *priv); void (*tx_free)(struct iwl_priv *priv); + void (*stop_device)(struct iwl_priv *priv); + int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 77ed1c295da..d736a9d0e06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -407,7 +407,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: iwl_testmode_cfg_init_calib(priv); - iwlagn_stop_device(priv); + trans_stop_device(priv); break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 6b7cb73442b..8d455540479 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -611,6 +611,46 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) return 0; } +static void iwl_trans_stop_device(struct iwl_priv *priv) +{ + unsigned long flags; + + /* stop and reset the on-board processor */ + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + + /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + trans_sync_irq(priv); + + /* device going down, Stop using ICT table */ + iwl_disable_ict(priv); + + /* + * If a HW restart happens during firmware loading, + * then the firmware loading might call this function + * and later it might be called again due to the + * restart. So don't process again if the device is + * already dead. + */ + if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { + iwl_trans_tx_stop(priv); + iwl_trans_rx_stop(priv); + + /* Power-down device's busmaster DMA clocks */ + iwl_write_prph(priv, APMG_CLK_DIS_REG, + APMG_CLK_VAL_DMA_CLK_RQT); + udelay(5); + } + + /* Make sure (redundant) we've released our request to stay awake */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + + /* Stop the device, and put it in low power state */ + iwl_apm_stop(priv); +} + static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv, int txq_id) { @@ -779,13 +819,13 @@ static void iwl_trans_free(struct iwl_priv *priv) static const struct iwl_trans_ops trans_ops = { .rx_init = iwl_trans_rx_init, - .rx_stop = iwl_trans_rx_stop, .rx_free = iwl_trans_rx_free, .tx_init = iwl_trans_tx_init, - .tx_stop = iwl_trans_tx_stop, .tx_free = iwl_trans_tx_free, + .stop_device = iwl_trans_stop_device, + .send_cmd = iwl_send_cmd, .send_cmd_pdu = iwl_send_cmd_pdu, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 8293f54e039..55e6c333bfa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -69,11 +69,6 @@ static inline int trans_rx_init(struct iwl_priv *priv) return priv->trans.ops->rx_init(priv); } -static inline int trans_rx_stop(struct iwl_priv *priv) -{ - return priv->trans.ops->rx_stop(priv); -} - static inline void trans_rx_free(struct iwl_priv *priv) { priv->trans.ops->rx_free(priv); @@ -84,14 +79,14 @@ static inline int trans_tx_init(struct iwl_priv *priv) return priv->trans.ops->tx_init(priv); } -static inline int trans_tx_stop(struct iwl_priv *priv) +static inline void trans_tx_free(struct iwl_priv *priv) { - return priv->trans.ops->tx_stop(priv); + priv->trans.ops->tx_free(priv); } -static inline void trans_tx_free(struct iwl_priv *priv) +static inline void trans_stop_device(struct iwl_priv *priv) { - priv->trans.ops->tx_free(priv); + priv->trans.ops->stop_device(priv); } static inline int trans_send_cmd(struct iwl_priv *priv, -- cgit v1.2.3-70-g09d2 From b3c2ce131c7cd8c53b72b0cc04241cde17ce0c1d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 7 Jul 2011 15:50:10 +0300 Subject: iwlagn: add tx start API to transport layer tx start will start the tx queues: basically configure the SCD Remove the IWLAGN prefix to SCD defines on the way. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 51 ++++----- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 136 +----------------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 82 +++++++------- drivers/net/wireless/iwlwifi/iwl-trans.c | 153 ++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-trans.h | 5 + 7 files changed, 222 insertions(+), 210 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 554750d993e..ece3202427f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -166,10 +166,10 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, u32 tbl_dw; u16 scd_q2ratid; - scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; + scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; tbl_dw_addr = priv->scd_base_addr + - IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); @@ -188,9 +188,9 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ iwl_write_prph(priv, - IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); + SCD_QUEUE_STATUS_BITS(txq_id), + (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } void iwlagn_set_wr_ptrs(struct iwl_priv *priv, @@ -198,7 +198,7 @@ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, { iwl_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); } void iwlagn_tx_queue_set_status(struct iwl_priv *priv, @@ -208,11 +208,11 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv, int txq_id = txq->q.id; int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), - (active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) | - IWLAGN_SCD_QUEUE_STTS_REG_MSK); + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), + (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | + (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << SCD_QUEUE_STTS_REG_POS_WSL) | + SCD_QUEUE_STTS_REG_MSK); txq->sched_retry = scd_retry; @@ -271,10 +271,10 @@ void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | ((frame_limit << - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); @@ -317,29 +317,20 @@ static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, iwlagn_tx_queue_stop_scheduler(priv, txq_id); - iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id)); + iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); /* supposes that ssn_idx is valid (!= 0xFFF) */ iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); - iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(priv, txq_id); iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); return 0; } -/* - * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->lock and mac access - */ -void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) -{ - iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); -} - static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, struct ieee80211_tx_info *info, __le16 fc, __le32 *tx_flags) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index c15a1f7f4ff..aebd5c71f9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -41,38 +41,6 @@ #include "iwl-agn-calib.h" #include "iwl-trans.h" -#define IWL_AC_UNSET -1 - -struct queue_to_fifo_ac { - s8 fifo, ac; -}; - -static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, -}; - -static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_BE_IPAN, 2, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, -}; - static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 0, COEX_UNASSOC_IDLE_FLAGS}, @@ -379,111 +347,9 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) static int iwlagn_alive_notify(struct iwl_priv *priv) { - const struct queue_to_fifo_ac *queue_to_fifo; - struct iwl_rxon_context *ctx; - u32 a; - unsigned long flags; - int i, chan; - u32 reg_val; int ret; - spin_lock_irqsave(&priv->lock, flags); - - priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND; - /* reset conext data memory */ - for (; a < priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND; - a += 4) - iwl_write_targ_mem(priv, a, 0); - /* reset tx status memory */ - for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND; - a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + - IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) - iwl_write_targ_mem(priv, a, 0); - - iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR, - priv->scd_bc_tbls.dma >> 10); - - /* Enable DMA channel */ - for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); - - /* Update FH chicken bits */ - reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - - iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, - IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)); - iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); - - /* initiate the queues */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { - iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) + - sizeof(u32), - ((SCD_WIN_SIZE << - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - } - - iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, - IWL_MASK(0, priv->hw_params.max_txq_num)); - - /* Activate all Tx DMA/FIFO channels */ - iwlagn_txq_set_sched(priv, IWL_MASK(0, 7)); - - /* map queues to FIFOs */ - if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) - queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; - else - queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - - iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); - - /* make sure all queue are not stopped */ - memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); - for (i = 0; i < 4; i++) - atomic_set(&priv->queue_stop_count[i], 0); - for_each_context(priv, ctx) - ctx->last_tx_rejected = false; - - /* reset to 0 to enable all the queue first */ - priv->txq_ctx_active_msk = 0; - - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); - - for (i = 0; i < 10; i++) { - int fifo = queue_to_fifo[i].fifo; - int ac = queue_to_fifo[i].ac; - - iwl_txq_ctx_activate(priv, i); - - if (fifo == IWL_TX_FIFO_UNUSED) - continue; - - if (ac != IWL_AC_UNSET) - iwl_set_swq_id(&priv->txq[i], ac, i); - iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Enable L1-Active */ - iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + trans_tx_start(priv); ret = iwlagn_send_wimax_coex(priv); if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index c851fc2fb6b..0e8ccb9c99b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -136,7 +136,6 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, void iwlagn_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); -void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index cf6f4b2e2cd..fddc2362764 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1234,10 +1234,11 @@ struct iwl_trans; /** * struct iwl_trans_ops - transport specific operations - * @rx_init: inits the rx memory, allocate it if needed * @rx_free: frees the rx memory * @tx_init:inits the tx memory, allocate if needed + * @tx_start: starts and configures all the Tx fifo - usually done once the fw + * is alive. * @tx_free: frees the tx memory * @stop_device:stops the whole device (embedded CPU put to reset) * @send_cmd:send a host command @@ -1256,6 +1257,7 @@ struct iwl_trans_ops { void (*rx_free)(struct iwl_priv *priv); int (*tx_init)(struct iwl_priv *priv); + void (*tx_start)(struct iwl_priv *priv); void (*tx_free)(struct iwl_priv *priv); void (*stop_device)(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 1cc0ed1f488..2f267b8aabb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -178,61 +178,61 @@ #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 -#define IWL_SCD_TXFIFO_POS_TID (0) -#define IWL_SCD_TXFIFO_POS_RA (4) -#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) +#define SCD_TXFIFO_POS_TID (0) +#define SCD_TXFIFO_POS_RA (4) +#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) /* agn SCD */ -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF (0) -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL (4) -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) -#define IWLAGN_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) - -#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) -#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) -#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) -#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) -#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) -#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) -#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) -#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) +#define SCD_QUEUE_STTS_REG_POS_TXF (0) +#define SCD_QUEUE_STTS_REG_POS_ACTIVE (3) +#define SCD_QUEUE_STTS_REG_POS_WSL (4) +#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) +#define SCD_QUEUE_STTS_REG_MSK (0x00FF0000) + +#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) +#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) +#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) +#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) +#define SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) +#define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) +#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) +#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) /* Context Data */ -#define IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) -#define IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) +#define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) +#define SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) /* Tx status */ -#define IWLAGN_SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) -#define IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) +#define SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) +#define SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) /* Translation Data */ -#define IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) -#define IWLAGN_SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808) +#define SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) +#define SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808) -#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ - (IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) +#define SCD_CONTEXT_QUEUE_OFFSET(x)\ + (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) -#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) +#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \ + ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) -#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \ +#define SCD_QUEUECHAIN_SEL_ALL(priv) \ (((1<<(priv)->hw_params.max_txq_num) - 1) &\ (~(1<<(priv)->cmd_queue))) -#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00) - -#define IWLAGN_SCD_SRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x0) -#define IWLAGN_SCD_DRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x8) -#define IWLAGN_SCD_AIT (IWLAGN_SCD_BASE + 0x0c) -#define IWLAGN_SCD_TXFACT (IWLAGN_SCD_BASE + 0x10) -#define IWLAGN_SCD_ACTIVE (IWLAGN_SCD_BASE + 0x14) -#define IWLAGN_SCD_QUEUE_WRPTR(x) (IWLAGN_SCD_BASE + 0x18 + (x) * 4) -#define IWLAGN_SCD_QUEUE_RDPTR(x) (IWLAGN_SCD_BASE + 0x68 + (x) * 4) -#define IWLAGN_SCD_QUEUECHAIN_SEL (IWLAGN_SCD_BASE + 0xe8) -#define IWLAGN_SCD_AGGR_SEL (IWLAGN_SCD_BASE + 0x248) -#define IWLAGN_SCD_INTERRUPT_MASK (IWLAGN_SCD_BASE + 0x108) -#define IWLAGN_SCD_QUEUE_STATUS_BITS(x) (IWLAGN_SCD_BASE + 0x10c + (x) * 4) +#define SCD_BASE (PRPH_BASE + 0xa02c00) + +#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0) +#define SCD_DRAM_BASE_ADDR (SCD_BASE + 0x8) +#define SCD_AIT (SCD_BASE + 0x0c) +#define SCD_TXFACT (SCD_BASE + 0x10) +#define SCD_ACTIVE (SCD_BASE + 0x14) +#define SCD_QUEUE_WRPTR(x) (SCD_BASE + 0x18 + (x) * 4) +#define SCD_QUEUE_RDPTR(x) (SCD_BASE + 0x68 + (x) * 4) +#define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) +#define SCD_AGGR_SEL (SCD_BASE + 0x248) +#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) +#define SCD_QUEUE_STATUS_BITS(x) (SCD_BASE + 0x10c + (x) * 4) /*********************** END TX SCHEDULER *************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 8d455540479..7c748f65c86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -547,7 +547,7 @@ static int iwl_trans_tx_init(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 0); + iwl_write_prph(priv, SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); @@ -574,6 +574,154 @@ error: return ret; } +/* + * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask + * must be called under priv->lock and mac access + */ +static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask) +{ + iwl_write_prph(priv, SCD_TXFACT, mask); +} + +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, +}; + +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, +}; +static void iwl_trans_tx_start(struct iwl_priv *priv) +{ + const struct queue_to_fifo_ac *queue_to_fifo; + struct iwl_rxon_context *ctx; + u32 a; + unsigned long flags; + int i, chan; + u32 reg_val; + + spin_lock_irqsave(&priv->lock, flags); + + priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); + a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; + /* reset conext data memory */ + for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; + a += 4) + iwl_write_targ_mem(priv, a, 0); + /* reset tx status memory */ + for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; + a += 4) + iwl_write_targ_mem(priv, a, 0); + for (; a < priv->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + iwl_write_targ_mem(priv, a, 0); + + iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, + priv->scd_bc_tbls.dma >> 10); + + /* Enable DMA channel */ + for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); + + /* Update FH chicken bits */ + reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, + reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); + + iwl_write_prph(priv, SCD_QUEUECHAIN_SEL, + SCD_QUEUECHAIN_SEL_ALL(priv)); + iwl_write_prph(priv, SCD_AGGR_SEL, 0); + + /* initiate the queues */ + for (i = 0; i < priv->hw_params.max_txq_num; i++) { + iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(priv, priv->scd_base_addr + + SCD_CONTEXT_QUEUE_OFFSET(i), 0); + iwl_write_targ_mem(priv, priv->scd_base_addr + + SCD_CONTEXT_QUEUE_OFFSET(i) + + sizeof(u32), + ((SCD_WIN_SIZE << + SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((SCD_FRAME_LIMIT << + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + } + + iwl_write_prph(priv, SCD_INTERRUPT_MASK, + IWL_MASK(0, priv->hw_params.max_txq_num)); + + /* Activate all Tx DMA/FIFO channels */ + iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); + + /* map queues to FIFOs */ + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; + else + queue_to_fifo = iwlagn_default_queue_to_tx_fifo; + + iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); + + /* make sure all queue are not stopped */ + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); + for (i = 0; i < 4; i++) + atomic_set(&priv->queue_stop_count[i], 0); + for_each_context(priv, ctx) + ctx->last_tx_rejected = false; + + /* reset to 0 to enable all the queue first */ + priv->txq_ctx_active_msk = 0; + + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); + + for (i = 0; i < 10; i++) { + int fifo = queue_to_fifo[i].fifo; + int ac = queue_to_fifo[i].ac; + + iwl_txq_ctx_activate(priv, i); + + if (fifo == IWL_TX_FIFO_UNUSED) + continue; + + if (ac != IWL_AC_UNSET) + iwl_set_swq_id(&priv->txq[i], ac, i); + iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Enable L1-Active */ + iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); +} + /** * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ @@ -585,7 +733,7 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) /* Turn off all Tx DMA fifos */ spin_lock_irqsave(&priv->lock, flags); - iwlagn_txq_set_sched(priv, 0); + iwl_trans_txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { @@ -822,6 +970,7 @@ static const struct iwl_trans_ops trans_ops = { .rx_free = iwl_trans_rx_free, .tx_init = iwl_trans_tx_init, + .tx_start = iwl_trans_tx_start, .tx_free = iwl_trans_tx_free, .stop_device = iwl_trans_stop_device, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 55e6c333bfa..16cdb89b02f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -79,6 +79,11 @@ static inline int trans_tx_init(struct iwl_priv *priv) return priv->trans.ops->tx_init(priv); } +static inline void trans_tx_start(struct iwl_priv *priv) +{ + priv->trans.ops->tx_start(priv); +} + static inline void trans_tx_free(struct iwl_priv *priv) { priv->trans.ops->tx_free(priv); -- cgit v1.2.3-70-g09d2 From 56d90f4c8ac186a708e6af290d23857ea901ba05 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 7 Jul 2011 18:20:01 +0300 Subject: iwlagn: add kick_nic API to transport layer kick_nic means to remove the RESET bit from the embedded CPU Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-trans.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-trans.h | 5 +++++ 4 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index aebd5c71f9d..89363007ede 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -494,8 +494,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; } - /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); + trans_kick_nic(priv); /* * Some things may run in the background now, but we diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fddc2362764..d6d6fe92c47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1245,6 +1245,7 @@ struct iwl_trans; * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use * @tx: send an skb + * @kick_nic: remove the RESET from the embedded CPU and let it run * @sync_irq: the upper layer will typically disable interrupt and call this * handler. After this handler returns, it is guaranteed that all * the ISR / tasklet etc... have finished running and the transport @@ -1271,6 +1272,8 @@ struct iwl_trans_ops { struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); + void (*kick_nic)(struct iwl_priv *priv); + void (*sync_irq)(struct iwl_priv *priv); void (*free)(struct iwl_priv *priv); }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 7c748f65c86..639b4692e45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -952,6 +952,12 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return 0; } +static void iwl_trans_kick_nic(struct iwl_priv *priv) +{ + /* Remove all resets to allow NIC to operate */ + iwl_write32(priv, CSR_RESET, 0); +} + static void iwl_trans_sync_irq(struct iwl_priv *priv) { /* wait to make sure we flush pending tasklet*/ @@ -980,6 +986,7 @@ static const struct iwl_trans_ops trans_ops = { .get_tx_cmd = iwl_trans_get_tx_cmd, .tx = iwl_trans_tx, + .kick_nic = iwl_trans_kick_nic, .sync_irq = iwl_trans_sync_irq, .free = iwl_trans_free, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 16cdb89b02f..9a950492ca7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -119,6 +119,11 @@ static inline int trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return priv->trans.ops->tx(priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } +static inline void trans_kick_nic(struct iwl_priv *priv) +{ + priv->trans.ops->kick_nic(priv); +} + static inline void trans_sync_irq(struct iwl_priv *priv) { priv->trans.ops->sync_irq(priv); -- cgit v1.2.3-70-g09d2 From 48d42c426947d8ffba0caa3cf9c58be6903302e0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 10 Jul 2011 10:47:01 +0300 Subject: iwlagn: SCD configuration for AMPDU moves to transport layer All the configurations of the HW for AMPDU are now in the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 225 +--------------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 13 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 8 + drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h | 14 +- drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 224 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-trans.c | 10 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 17 ++ 8 files changed, 274 insertions(+), 239 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index ece3202427f..932425d019d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -96,132 +96,8 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) return -EINVAL; } -/** - * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array - */ -void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt) -{ - struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int write_ptr = txq->q.write_ptr; - int txq_id = txq->q.id; - u8 sec_ctl = 0; - u8 sta_id = 0; - u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; - __le16 bc_ent; - - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - - sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; - - switch (sec_ctl & TX_CMD_SEC_MSK) { - case TX_CMD_SEC_CCM: - len += CCMP_MIC_LEN; - break; - case TX_CMD_SEC_TKIP: - len += TKIP_ICV_LEN; - break; - case TX_CMD_SEC_WEP: - len += WEP_IV_LEN + WEP_ICV_LEN; - break; - } - - bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); - - scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; - - if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; -} - -static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int txq_id = txq->q.id; - int read_ptr = txq->q.read_ptr; - u8 sta_id = 0; - __le16 bc_ent; - - WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != priv->cmd_queue) - sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; - - bc_ent = cpu_to_le16(1 | (sta_id << 12)); - scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - - if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; -} - -static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, - u16 txq_id) -{ - u32 tbl_dw_addr; - u32 tbl_dw; - u16 scd_q2ratid; - - scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; - - tbl_dw_addr = priv->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); - - tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); - - if (txq_id & 0x1) - tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); - else - tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - - iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); - - return 0; -} - -static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) -{ - /* Simply stop the queue, but don't change any configuration; - * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv, - SCD_QUEUE_STATUS_BITS(txq_id), - (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); -} - -void iwlagn_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index) -{ - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); -} - -void iwlagn_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry) -{ - int txq_id = txq->q.id; - int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - - iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), - (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << SCD_QUEUE_STTS_REG_POS_WSL) | - SCD_QUEUE_STTS_REG_MSK); - - txq->sched_retry = scd_retry; - - IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", - active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); -} - -static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid) +static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, + int tid) { if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + @@ -238,99 +114,6 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); } -void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, - struct ieee80211_sta *sta, - int tid, int frame_limit) -{ - int sta_id, tx_fifo, txq_id, ssn_idx; - u16 ra_tid; - unsigned long flags; - struct iwl_tid_data *tid_data; - - sta_id = iwl_sta_id(sta); - if (WARN_ON(sta_id == IWL_INVALID_STATION)) - return; - if (WARN_ON(tid >= MAX_TID_COUNT)) - return; - - spin_lock_irqsave(&priv->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; - ssn_idx = SEQ_TO_SN(tid_data->seq_number); - txq_id = tid_data->agg.txq_id; - tx_fifo = tid_data->agg.tx_fifo; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - ra_tid = BUILD_RAxTID(sta_id, tid); - - spin_lock_irqsave(&priv->lock, flags); - - /* Stop this Tx queue before configuring it */ - iwlagn_tx_queue_stop_scheduler(priv, txq_id); - - /* Map receiver-address / traffic-ID to this queue */ - iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); - - /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); - - /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(priv, priv->scd_base_addr + - SCD_CONTEXT_QUEUE_OFFSET(txq_id) + - sizeof(u32), - ((frame_limit << - SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((frame_limit << - SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - - iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); - - /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) -{ - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || - (IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { - IWL_ERR(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWLAGN_FIRST_AMPDU_QUEUE, - IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues - 1); - return -EINVAL; - } - - iwlagn_tx_queue_stop_scheduler(priv, txq_id); - - iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); - - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); - - iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv, txq_id); - iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - - return 0; -} - static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, struct ieee80211_tx_info *info, __le16 fc, __le32 *tx_flags) @@ -850,7 +633,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); + trans_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -879,7 +662,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo); + trans_txq_agg_disable(priv, txq_id, ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 503c78606bd..9ba5fcd8288 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2461,7 +2461,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size); + trans_txq_agg_setup(priv, iwl_sta_id(sta), tid, buf_size); /* * If the limit is 0, then it wasn't initialised yet, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 57c70b840a5..0a8417a2c29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -127,15 +127,7 @@ int iwl_prepare_card_hw(struct iwl_priv *priv); int iwlagn_start_device(struct iwl_priv *priv); /* tx queue */ -void iwlagn_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index); -void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); - -void iwlagn_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry); +/*TODO: this one should go to transport layer */ void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); @@ -188,9 +180,6 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); -void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, - struct ieee80211_sta *sta, - int tid, int frame_limit); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d6d6fe92c47..b18a9a88d7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1245,6 +1245,9 @@ struct iwl_trans; * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use * @tx: send an skb + * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is + * ready and a successful ADDBA response has been received. + * @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run * @sync_irq: the upper layer will typically disable interrupt and call this * handler. After this handler returns, it is guaranteed that all @@ -1272,6 +1275,11 @@ struct iwl_trans_ops { struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); + void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); + void (*kick_nic)(struct iwl_priv *priv); void (*sync_irq)(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 3015facd775..b79330d8418 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -66,7 +66,17 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, const void *data); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); - +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt); +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index); +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + int tx_fifo_id, int scd_retry); +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); #endif /* __iwl_trans_int_pcie_h__ */ - diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index f3b531b3447..9cecb107628 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -35,9 +35,56 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" +#include "iwl-sta.h" #include "iwl-helpers.h" #include "iwl-trans-int-pcie.h" +/* TODO:this file should _not_ include the external API header file + * (iwl-trans.h). This is needed as a W/A until reclaim functions will move to + * the transport layer */ +#include "iwl-trans.h" + +/** + * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array + */ +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt) +{ + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + int write_ptr = txq->q.write_ptr; + int txq_id = txq->q.id; + u8 sec_ctl = 0; + u8 sta_id = 0; + u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; + __le16 bc_ent; + + WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); + + sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; + + switch (sec_ctl & TX_CMD_SEC_MSK) { + case TX_CMD_SEC_CCM: + len += CCMP_MIC_LEN; + break; + case TX_CMD_SEC_TKIP: + len += TKIP_ICV_LEN; + break; + case TX_CMD_SEC_WEP: + len += WEP_IV_LEN + WEP_ICV_LEN; + break; + } + + bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); + + scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; + + if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; +} + /** * iwl_txq_update_write_ptr - Send new write index to hardware */ @@ -291,6 +338,183 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, return 0; } +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too */ +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + int txq_id = txq->q.id; + int read_ptr = txq->q.read_ptr; + u8 sta_id = 0; + __le16 bc_ent; + + WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); + + if (txq_id != priv->cmd_queue) + sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; + + bc_ent = cpu_to_le16(1 | (sta_id << 12)); + scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; + + if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; +} + +static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, + u16 txq_id) +{ + u32 tbl_dw_addr; + u32 tbl_dw; + u16 scd_q2ratid; + + scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; + + tbl_dw_addr = priv->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); + + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); + + if (txq_id & 0x1) + tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); + else + tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); + + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); + + return 0; +} + +static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) +{ + /* Simply stop the queue, but don't change any configuration; + * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ + iwl_write_prph(priv, + SCD_QUEUE_STATUS_BITS(txq_id), + (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); +} + +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index) +{ + iwl_write_direct32(priv, HBUS_TARG_WRPTR, + (index & 0xff) | (txq_id << 8)); + iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); +} + +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + int tx_fifo_id, int scd_retry) +{ + int txq_id = txq->q.id; + int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; + + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), + (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | + (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << SCD_QUEUE_STTS_REG_POS_WSL) | + SCD_QUEUE_STTS_REG_MSK); + + txq->sched_retry = scd_retry; + + IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", + active ? "Activate" : "Deactivate", + scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); +} + +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit) +{ + int tx_fifo, txq_id, ssn_idx; + u16 ra_tid; + unsigned long flags; + struct iwl_tid_data *tid_data; + + if (WARN_ON(sta_id == IWL_INVALID_STATION)) + return; + if (WARN_ON(tid >= MAX_TID_COUNT)) + return; + + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + ssn_idx = SEQ_TO_SN(tid_data->seq_number); + txq_id = tid_data->agg.txq_id; + tx_fifo = tid_data->agg.tx_fifo; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ra_tid = BUILD_RAxTID(sta_id, tid); + + spin_lock_irqsave(&priv->lock, flags); + + /* Stop this Tx queue before configuring it */ + iwlagn_tx_queue_stop_scheduler(priv, txq_id); + + /* Map receiver-address / traffic-ID to this queue */ + iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); + + /* Set this queue as a chain-building queue */ + iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); + + /* Set up Tx window size and frame limit for this queue */ + iwl_write_targ_mem(priv, priv->scd_base_addr + + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + + sizeof(u32), + ((frame_limit << + SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((frame_limit << + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + + iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + + /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + IWL_ERR(priv, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues - 1); + return -EINVAL; + } + + iwlagn_tx_queue_stop_scheduler(priv, txq_id); + + iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); + + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); + + iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv, txq_id); + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + + return 0; +} + /*************** HOST COMMAND QUEUE FUNCTIONS *****/ /** diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 639b4692e45..bddc12d27d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -686,7 +686,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) else queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); + iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0); /* make sure all queue are not stopped */ memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); @@ -712,7 +712,7 @@ static void iwl_trans_tx_start(struct iwl_priv *priv) if (ac != IWL_AC_UNSET) iwl_set_swq_id(&priv->txq[i], ac, i); - iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); + iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } spin_unlock_irqrestore(&priv->lock, flags); @@ -919,7 +919,7 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Set up entry for this TFD in Tx byte-count array */ if (ampdu) - iwlagn_txq_update_byte_cnt_tbl(priv, txq, + iwl_trans_txq_update_byte_cnt_tbl(priv, txq, le16_to_cpu(tx_cmd->len)); dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen, @@ -986,6 +986,10 @@ static const struct iwl_trans_ops trans_ops = { .get_tx_cmd = iwl_trans_get_tx_cmd, .tx = iwl_trans_tx, + + .txq_agg_disable = iwl_trans_txq_agg_disable, + .txq_agg_setup = iwl_trans_txq_agg_setup, + .kick_nic = iwl_trans_kick_nic, .sync_irq = iwl_trans_sync_irq, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 9a950492ca7..215f4d5f30b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -119,6 +119,18 @@ static inline int trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return priv->trans.ops->tx(priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } +static inline int trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + return priv->trans.ops->txq_agg_disable(priv, txq_id, ssn_idx, tx_fifo); +} + +static inline void trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, + int tid, int frame_limit) +{ + priv->trans.ops->txq_agg_setup(priv, sta_id, tid, frame_limit); +} + static inline void trans_kick_nic(struct iwl_priv *priv) { priv->trans.ops->kick_nic(priv); @@ -135,3 +147,8 @@ static inline void trans_free(struct iwl_priv *priv) } int iwl_trans_register(struct iwl_priv *priv); + +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too */ +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); -- cgit v1.2.3-70-g09d2 From 392f8b789a4c96b39d527ff8ea5ceba20cd79d56 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 10 Jul 2011 15:30:15 +0300 Subject: iwlagn: move more functions from the start flow to the transport layer Basically all the nic_init flow should be in the transport layer. iwl_prepare_card_hw will move to the transport too in a separate patch. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 102 -------------- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 49 ------- drivers/net/wireless/iwlwifi/iwl-agn.h | 5 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 16 +-- drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 12 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 164 +++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 21 ++- 8 files changed, 178 insertions(+), 193 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 339a89ca4d7..6ed0eae4c54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -606,59 +606,6 @@ struct iwl_mod_params iwlagn_mod_params = { /* the rest are 0 by default */ }; -static void iwlagn_set_pwr_vmain(struct iwl_priv *priv) -{ -/* - * (for documentation purposes) - * to set power to V_AUX, do: - - if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - */ - - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); -} - -/*TODO: this function should move to transport layer */ -int iwlagn_hw_nic_init(struct iwl_priv *priv) -{ - unsigned long flags; - - /* nic_init */ - spin_lock_irqsave(&priv->lock, flags); - iwl_apm_init(priv); - - /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - - spin_unlock_irqrestore(&priv->lock, flags); - - iwlagn_set_pwr_vmain(priv); - - priv->cfg->lib->nic_config(priv); - - /* Allocate the RX queue, or reset if it is already allocated */ - trans_rx_init(priv); - - /* Allocate or reset and init all Tx and Command queues */ - if (trans_tx_init(priv)) - return -ENOMEM; - - if (priv->cfg->base_params->shadow_reg_enable) { - /* enable shadow regs in HW */ - iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, - 0x800FFFFF); - } - - set_bit(STATUS_INIT, &priv->status); - - return 0; -} - int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) { int idx = 0; @@ -2092,52 +2039,3 @@ void iwlagn_remove_notification(struct iwl_priv *priv, list_del(&wait_entry->list); spin_unlock_bh(&priv->_agn.notif_wait_lock); } - -int iwlagn_start_device(struct iwl_priv *priv) -{ - int ret; - - priv->ucode_owner = IWL_OWNERSHIP_DRIVER; - - if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_prepare_card_hw(priv)) { - IWL_WARN(priv, "Exit HW not ready\n"); - return -EIO; - } - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - if (iwl_is_rfkill(priv)) { - wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - iwl_enable_interrupts(priv); - return -ERFKILL; - } - - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - - ret = iwlagn_hw_nic_init(priv); - if (ret) { - IWL_ERR(priv, "Unable to init nic\n"); - return ret; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - return 0; -} - diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 667cfb7002d..e4b2f78775f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -478,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwlagn_ucode_type old_type; - ret = iwlagn_start_device(priv); + ret = trans_start_device(priv); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 9ba5fcd8288..d0f6875c64a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1798,55 +1798,6 @@ static void iwl_down(struct iwl_priv *priv) iwl_cancel_deferred_work(priv); } -#define HW_READY_TIMEOUT (50) - -/* Note: returns poll_bit return value, which is >= 0 if success */ -static int iwl_set_hw_ready(struct iwl_priv *priv) -{ - int ret; - - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); - - /* See if we got it */ - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - HW_READY_TIMEOUT); - - IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); - return ret; -} - -/* Note: returns standard 0/-ERROR code */ -int iwl_prepare_card_hw(struct iwl_priv *priv) -{ - int ret; - - IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); - - ret = iwl_set_hw_ready(priv); - if (ret >= 0) - return 0; - - /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PREPARE); - - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, - CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); - - if (ret < 0) - return ret; - - /* HW should be ready by now, check again. */ - ret = iwl_set_hw_ready(priv); - if (ret >= 0) - return 0; - return ret; -} - #define MAX_HW_RESTARTS 5 static int __iwl_up(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 0a8417a2c29..ffb6bd2e02a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -122,12 +122,10 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) hdr->data_valid = 1; } +/* TODO: this one should be API of the transport layer */ int iwl_prepare_card_hw(struct iwl_priv *priv); -int iwlagn_start_device(struct iwl_priv *priv); - /* tx queue */ -/*TODO: this one should go to transport layer */ void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); @@ -158,7 +156,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_send_tx_power(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); -int iwlagn_hw_nic_init(struct iwl_priv *priv); int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b18a9a88d7b..ca154344bed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1234,13 +1234,13 @@ struct iwl_trans; /** * struct iwl_trans_ops - transport specific operations - * @rx_init: inits the rx memory, allocate it if needed - * @rx_free: frees the rx memory - * @tx_init:inits the tx memory, allocate if needed + * @start_device: allocates and inits all the resources for the transport + * layer. * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. - * @tx_free: frees the tx memory * @stop_device:stops the whole device (embedded CPU put to reset) + * @rx_free: frees the rx memory + * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use @@ -1257,14 +1257,12 @@ struct iwl_trans; * irq, tasklet etc... */ struct iwl_trans_ops { - int (*rx_init)(struct iwl_priv *priv); - void (*rx_free)(struct iwl_priv *priv); - int (*tx_init)(struct iwl_priv *priv); + int (*start_device)(struct iwl_priv *priv); + void (*stop_device)(struct iwl_priv *priv); void (*tx_start)(struct iwl_priv *priv); void (*tx_free)(struct iwl_priv *priv); - - void (*stop_device)(struct iwl_priv *priv); + void (*rx_free)(struct iwl_priv *priv); int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 9cecb107628..7dac6ee2325 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -35,15 +35,9 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-sta.h" #include "iwl-helpers.h" #include "iwl-trans-int-pcie.h" -/* TODO:this file should _not_ include the external API header file - * (iwl-trans.h). This is needed as a W/A until reclaim functions will move to - * the transport layer */ -#include "iwl-trans.h" - /** * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ @@ -339,7 +333,11 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, } /*TODO: this functions should NOT be exported from trans module - export it - * until the reclaim flow will be brought to the transport module too */ + * until the reclaim flow will be brought to the transport module too. + * Add a declaration to make sparse happy */ +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); + void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index bddc12d27d0..e9c7de9f8e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -177,7 +177,7 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } -static int iwl_trans_rx_init(struct iwl_priv *priv) +static int iwl_rx_init(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; int i, err; @@ -530,7 +530,7 @@ error: return ret; } -static int iwl_trans_tx_init(struct iwl_priv *priv) +static int iwl_tx_init(struct iwl_priv *priv) { int ret; int txq_id, slots_num; @@ -574,6 +574,156 @@ error: return ret; } +static void iwl_set_pwr_vmain(struct iwl_priv *priv) +{ +/* + * (for documentation purposes) + * to set power to V_AUX, do: + + if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VAUX, + ~APMG_PS_CTRL_MSK_PWR_SRC); + */ + + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); +} + +static int iwl_nic_init(struct iwl_priv *priv) +{ + unsigned long flags; + + /* nic_init */ + spin_lock_irqsave(&priv->lock, flags); + iwl_apm_init(priv); + + /* Set interrupt coalescing calibration timer to default (512 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_set_pwr_vmain(priv); + + priv->cfg->lib->nic_config(priv); + + /* Allocate the RX queue, or reset if it is already allocated */ + iwl_rx_init(priv); + + /* Allocate or reset and init all Tx and Command queues */ + if (iwl_tx_init(priv)) + return -ENOMEM; + + if (priv->cfg->base_params->shadow_reg_enable) { + /* enable shadow regs in HW */ + iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, + 0x800FFFFF); + } + + set_bit(STATUS_INIT, &priv->status); + + return 0; +} + +#define HW_READY_TIMEOUT (50) + +/* Note: returns poll_bit return value, which is >= 0 if success */ +static int iwl_set_hw_ready(struct iwl_priv *priv) +{ + int ret; + + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); + + /* See if we got it */ + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + HW_READY_TIMEOUT); + + IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); + return ret; +} + +/* Note: returns standard 0/-ERROR code */ +int iwl_prepare_card_hw(struct iwl_priv *priv) +{ + int ret; + + IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); + + ret = iwl_set_hw_ready(priv); + if (ret >= 0) + return 0; + + /* If HW is not ready, prepare the conditions to check again */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PREPARE); + + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, + CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); + + if (ret < 0) + return ret; + + /* HW should be ready by now, check again. */ + ret = iwl_set_hw_ready(priv); + if (ret >= 0) + return 0; + return ret; +} + +static int iwl_trans_start_device(struct iwl_priv *priv) +{ + int ret; + + priv->ucode_owner = IWL_OWNERSHIP_DRIVER; + + if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && + iwl_prepare_card_hw(priv)) { + IWL_WARN(priv, "Exit HW not ready\n"); + return -EIO; + } + + /* If platform's RF_KILL switch is NOT set to KILL */ + if (iwl_read32(priv, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); + else + set_bit(STATUS_RF_KILL_HW, &priv->status); + + if (iwl_is_rfkill(priv)) { + wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); + iwl_enable_interrupts(priv); + return -ERFKILL; + } + + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + + ret = iwl_nic_init(priv); + if (ret) { + IWL_ERR(priv, "Unable to init nic\n"); + return ret; + } + + /* make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + + /* clear (again), then enable host interrupts */ + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); + + /* really make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + + return 0; +} + /* * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask * must be called under priv->lock and mac access @@ -972,14 +1122,12 @@ static void iwl_trans_free(struct iwl_priv *priv) } static const struct iwl_trans_ops trans_ops = { - .rx_init = iwl_trans_rx_init, - .rx_free = iwl_trans_rx_free, - - .tx_init = iwl_trans_tx_init, + .start_device = iwl_trans_start_device, + .stop_device = iwl_trans_stop_device, .tx_start = iwl_trans_tx_start, - .tx_free = iwl_trans_tx_free, - .stop_device = iwl_trans_stop_device, + .rx_free = iwl_trans_rx_free, + .tx_free = iwl_trans_tx_free, .send_cmd = iwl_send_cmd, .send_cmd_pdu = iwl_send_cmd_pdu, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 215f4d5f30b..9e801d8963d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -64,19 +64,14 @@ /*This file includes the declaration that are exported from the transport * layer */ -static inline int trans_rx_init(struct iwl_priv *priv) +static inline int trans_start_device(struct iwl_priv *priv) { - return priv->trans.ops->rx_init(priv); + return priv->trans.ops->start_device(priv); } -static inline void trans_rx_free(struct iwl_priv *priv) -{ - priv->trans.ops->rx_free(priv); -} - -static inline int trans_tx_init(struct iwl_priv *priv) +static inline void trans_stop_device(struct iwl_priv *priv) { - return priv->trans.ops->tx_init(priv); + priv->trans.ops->stop_device(priv); } static inline void trans_tx_start(struct iwl_priv *priv) @@ -84,14 +79,14 @@ static inline void trans_tx_start(struct iwl_priv *priv) priv->trans.ops->tx_start(priv); } -static inline void trans_tx_free(struct iwl_priv *priv) +static inline void trans_rx_free(struct iwl_priv *priv) { - priv->trans.ops->tx_free(priv); + priv->trans.ops->rx_free(priv); } -static inline void trans_stop_device(struct iwl_priv *priv) +static inline void trans_tx_free(struct iwl_priv *priv) { - priv->trans.ops->stop_device(priv); + priv->trans.ops->tx_free(priv); } static inline int trans_send_cmd(struct iwl_priv *priv, -- cgit v1.2.3-70-g09d2 From 0286cee0d2b6357e8e30d817bbce8ff166f358b5 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 10 Jul 2011 15:39:57 +0300 Subject: iwlagn: move iwl_prepare_card_hw to the transport layer This function is really related to the transport layer - move it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 --- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-trans.c | 8 +++++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 5 +++++ 5 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d0f6875c64a..703c106aa8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3174,7 +3174,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, hw_rev); - if (iwl_prepare_card_hw(priv)) { + if (trans_prepare_card_hw(priv)) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); goto out_free_traffic_mem; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ffb6bd2e02a..496ab99c424 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -122,9 +122,6 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) hdr->data_valid = 1; } -/* TODO: this one should be API of the transport layer */ -int iwl_prepare_card_hw(struct iwl_priv *priv); - /* tx queue */ void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ca154344bed..9a39836c0cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1236,6 +1236,8 @@ struct iwl_trans; * struct iwl_trans_ops - transport specific operations * @start_device: allocates and inits all the resources for the transport * layer. + * @prepare_card_hw: claim the ownership on the HW. Will be called during + * probe. * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. * @stop_device:stops the whole device (embedded CPU put to reset) @@ -1259,6 +1261,7 @@ struct iwl_trans; struct iwl_trans_ops { int (*start_device)(struct iwl_priv *priv); + int (*prepare_card_hw)(struct iwl_priv *priv); void (*stop_device)(struct iwl_priv *priv); void (*tx_start)(struct iwl_priv *priv); void (*tx_free)(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index e9c7de9f8e0..88ab20abe25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -647,11 +647,11 @@ static int iwl_set_hw_ready(struct iwl_priv *priv) } /* Note: returns standard 0/-ERROR code */ -int iwl_prepare_card_hw(struct iwl_priv *priv) +static int iwl_trans_prepare_card_hw(struct iwl_priv *priv) { int ret; - IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); + IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n"); ret = iwl_set_hw_ready(priv); if (ret >= 0) @@ -682,7 +682,7 @@ static int iwl_trans_start_device(struct iwl_priv *priv) priv->ucode_owner = IWL_OWNERSHIP_DRIVER; if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_prepare_card_hw(priv)) { + iwl_trans_prepare_card_hw(priv)) { IWL_WARN(priv, "Exit HW not ready\n"); return -EIO; } @@ -1123,7 +1123,9 @@ static void iwl_trans_free(struct iwl_priv *priv) static const struct iwl_trans_ops trans_ops = { .start_device = iwl_trans_start_device, + .prepare_card_hw = iwl_trans_prepare_card_hw, .stop_device = iwl_trans_stop_device, + .tx_start = iwl_trans_tx_start, .rx_free = iwl_trans_rx_free, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 9e801d8963d..fca01819f10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -69,6 +69,11 @@ static inline int trans_start_device(struct iwl_priv *priv) return priv->trans.ops->start_device(priv); } +static inline int trans_prepare_card_hw(struct iwl_priv *priv) +{ + return priv->trans.ops->prepare_card_hw(priv); +} + static inline void trans_stop_device(struct iwl_priv *priv) { priv->trans.ops->stop_device(priv); -- cgit v1.2.3-70-g09d2 From 41c50542669cd7aec45ad708f5120ff8fdaa1194 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 11 Jul 2011 08:51:04 +0300 Subject: iwlagn: transport layer receives struct iwl_trans* It still holds a pointer to iwl_priv. But hopefully this will disappear at some point. Also add the multiple inclusion protection to iwl-trans.h that was forgotten. Move iwl-trans structures to iwl-trans.h Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 +- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 16 ++-- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 9 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 16 ++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 29 +++--- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 62 +------------ drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 9 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 133 ++++++++++++++++++++------- 18 files changed, 168 insertions(+), 154 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8c6fbd74b8d..3eeb12ebe6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -315,7 +315,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return trans_send_cmd(priv, &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl5000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index ea48246f8dd..973d1972e8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -253,7 +253,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return trans_send_cmd(priv, &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl6000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 540e66f5515..204f0ece3c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -98,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = trans_send_cmd(priv, &hcmd); + ret = trans_send_cmd(&priv->trans, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", ret, i); @@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - return trans_send_cmd(priv, &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -548,7 +548,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); - return trans_send_cmd(priv, &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) @@ -892,7 +892,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, priv->_agn.phy_calib_chain_noise_gain_cmd); cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; - trans_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, + trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_ASYNC, sizeof(cmd), &cmd); data->radio_write = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 6ed0eae4c54..67b55c5fa0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -519,7 +519,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return trans_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -1061,7 +1061,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (ret) return ret; - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) { clear_bit(STATUS_SCAN_HW, &priv->status); iwlagn_set_pan_params(priv); @@ -1167,7 +1167,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) flush_cmd.fifo_control); flush_cmd.flush_control = cpu_to_le16(flush_control); - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) @@ -1361,12 +1361,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (priv->cfg->bt_params->bt_session_2) { memcpy(&bt_cmd_2000.basic, &basic, sizeof(basic)); - ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); } else { memcpy(&bt_cmd_6000.basic, &basic, sizeof(basic)); - ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); } if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 53e74752d13..581534a5415 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -40,7 +40,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -66,7 +66,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -92,7 +92,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -121,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - ret = trans_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) @@ -180,7 +180,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = trans_send_cmd_pdu(priv, ctx->rxon_assoc_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; } @@ -266,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -388,7 +388,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) cmd.slots[0].width = cpu_to_le16(slot0); cmd.slots[1].width = cpu_to_le16(slot1); - ret = trans_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); @@ -788,7 +788,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, priv->_agn.phy_calib_chain_noise_reset_cmd); - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 001622c0652..67b9c2bacc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -181,7 +181,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd.len[0] = cmd_size; if (not_empty || send_if_empty) - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); else return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 932425d019d..a5295c15d70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -433,7 +433,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } } - tx_cmd = trans_get_tx_cmd(priv, txq_id); + tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id); if (unlikely(!tx_cmd)) goto drop_unlock_sta; @@ -455,7 +455,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); - if (trans_tx(priv, skb, tx_cmd, txq_id, fc, is_agg, ctx)) + if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx)) goto drop_unlock_sta; if (ieee80211_is_data_qos(fc)) { @@ -633,7 +633,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - trans_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); + trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -662,7 +662,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - trans_txq_agg_disable(priv, txq_id, ssn, tx_fifo); + trans_txq_agg_disable(&priv->trans, txq_id, + ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index e4b2f78775f..946d3a16e49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -193,7 +193,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -291,7 +291,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return trans_send_cmd_pdu(priv, + return trans_send_cmd_pdu(&priv->trans, COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -324,7 +324,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, sizeof(iwlagn_bt_prio_tbl)); - if (trans_send_cmd_pdu(priv, + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) IWL_ERR(priv, "failed to send BT prio tbl command\n"); @@ -337,7 +337,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) env_cmd.action = action; env_cmd.type = type; - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) @@ -350,7 +350,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) { int ret; - trans_tx_start(priv); + trans_tx_start(&priv->trans); ret = iwlagn_send_wimax_coex(priv); if (ret) @@ -478,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwlagn_ucode_type old_type; - ret = trans_start_device(priv); + ret = trans_start_device(&priv->trans); if (ret) return ret; @@ -495,7 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; } - trans_kick_nic(priv); + trans_kick_nic(&priv->trans); /* * Some things may run in the background now, but we @@ -573,6 +573,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ - trans_stop_device(priv); + trans_stop_device(&priv->trans); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 703c106aa8d..d3163d8cf6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -206,7 +206,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) cmd.data[1] = priv->beacon_skb->data; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -1568,7 +1568,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) adv_cmd.critical_temperature_exit = cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(adv_cmd), &adv_cmd); if (ret) @@ -1584,7 +1584,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) cmd.critical_temperature_R = cpu_to_le32(priv->hw_params.ct_kill_threshold); - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -1610,7 +1610,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -1622,7 +1622,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) if (IWL_UCODE_API(priv->ucode_ver) > 1) { IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return trans_send_cmd_pdu(priv, + return trans_send_cmd_pdu(&priv->trans, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, sizeof(struct iwl_tx_ant_config_cmd), @@ -1783,7 +1783,7 @@ static void __iwl_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - trans_stop_device(priv); + trans_stop_device(&priv->trans); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -2412,7 +2412,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - trans_txq_agg_setup(priv, iwl_sta_id(sta), tid, buf_size); + trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid, + buf_size); /* * If the limit is 0, then it wasn't initialised yet, @@ -3136,7 +3137,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, priv->cfg = cfg; priv->inta_mask = CSR_INI_SET_MASK; - err = iwl_trans_register(priv); + err = iwl_trans_register(&priv->trans, priv); if (err) goto out_free_priv; @@ -3174,7 +3175,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, hw_rev); - if (trans_prepare_card_hw(priv)) { + if (trans_prepare_card_hw(&priv->trans)) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); goto out_free_traffic_mem; @@ -3272,7 +3273,7 @@ out_free_eeprom: iwl_eeprom_free(priv); out_free_traffic_mem: iwl_free_traffic_mem(priv); - trans_free(priv); + trans_free(&priv->trans); out_free_priv: ieee80211_free_hw(priv->hw); out: @@ -3317,12 +3318,12 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - trans_sync_irq(priv); + trans_sync_irq(&priv->trans); iwl_dealloc_ucode(priv); - trans_rx_free(priv); - trans_tx_free(priv); + trans_rx_free(&priv->trans); + trans_tx_free(&priv->trans); iwl_eeprom_free(priv); @@ -3336,7 +3337,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->workqueue = NULL; iwl_free_traffic_mem(priv); - trans_free(priv); + trans_free(&priv->trans); priv->bus.ops->set_drv_data(&priv->bus, NULL); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index fa3d5bacbde..a2a95bace84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -376,7 +376,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return trans_send_cmd_pdu(priv, ctx->rxon_timing_cmd, + return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); } @@ -1132,7 +1132,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - if (trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); } @@ -1145,12 +1145,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) }; if (flags & CMD_ASYNC) - return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_ASYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); else - return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_SYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9a39836c0cd..a89b40a585c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -47,6 +47,7 @@ #include "iwl-power.h" #include "iwl-agn-rs.h" #include "iwl-agn-tt.h" +#include "iwl-trans.h" #define DRV_NAME "iwlagn" @@ -1230,67 +1231,6 @@ struct iwl_bus { unsigned int irq; }; -struct iwl_trans; - -/** - * struct iwl_trans_ops - transport specific operations - * @start_device: allocates and inits all the resources for the transport - * layer. - * @prepare_card_hw: claim the ownership on the HW. Will be called during - * probe. - * @tx_start: starts and configures all the Tx fifo - usually done once the fw - * is alive. - * @stop_device:stops the whole device (embedded CPU put to reset) - * @rx_free: frees the rx memory - * @tx_free: frees the tx memory - * @send_cmd:send a host command - * @send_cmd_pdu:send a host command: flags can be CMD_* - * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use - * @tx: send an skb - * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is - * ready and a successful ADDBA response has been received. - * @txq_agg_disable: de-configure a Tx queue to send AMPDUs - * @kick_nic: remove the RESET from the embedded CPU and let it run - * @sync_irq: the upper layer will typically disable interrupt and call this - * handler. After this handler returns, it is guaranteed that all - * the ISR / tasklet etc... have finished running and the transport - * layer shall not pass any Rx. - * @free: release all the ressource for the transport layer itself such as - * irq, tasklet etc... - */ -struct iwl_trans_ops { - - int (*start_device)(struct iwl_priv *priv); - int (*prepare_card_hw)(struct iwl_priv *priv); - void (*stop_device)(struct iwl_priv *priv); - void (*tx_start)(struct iwl_priv *priv); - void (*tx_free)(struct iwl_priv *priv); - void (*rx_free)(struct iwl_priv *priv); - - int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - - int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, - const void *data); - struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); - int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, - struct iwl_rxon_context *ctx); - - int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo); - void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, - int frame_limit); - - void (*kick_nic)(struct iwl_priv *priv); - - void (*sync_irq)(struct iwl_priv *priv); - void (*free)(struct iwl_priv *priv); -}; - -struct iwl_trans { - const struct iwl_trans_ops *ops; -}; - /* uCode ownership */ #define IWL_OWNERSHIP_DRIVER 0 #define IWL_OWNERSHIP_TM 1 diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 60e4169f25e..75663c12e99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -112,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } /* Set led pattern command */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 64ff40ae102..7c99f432996 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -335,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return trans_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index f6ebe29eb79..0505b1ac756 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -75,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EIO; - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 65386e575b1..58dba0a49f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -168,7 +168,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, } cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret || (flags & CMD_ASYNC)) return ret; @@ -424,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, cmd.flags |= CMD_WANT_SKB; - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -793,7 +793,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); else ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index d736a9d0e06..d47483561a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -241,7 +241,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -407,7 +407,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: iwl_testmode_cfg_init_calib(priv); - trans_stop_device(priv); + trans_stop_device(&priv->trans); break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 88ab20abe25..edd28f00dab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -526,7 +526,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) return 0; error: - trans_tx_free(priv); + trans_tx_free(&priv->trans); return ret; } @@ -570,7 +570,7 @@ static int iwl_tx_init(struct iwl_priv *priv) error: /*Upon error, free only if we allocated something */ if (alloc) - trans_tx_free(priv); + trans_tx_free(&priv->trans); return ret; } @@ -920,7 +920,7 @@ static void iwl_trans_stop_device(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - trans_sync_irq(priv); + trans_sync_irq(&priv->trans); /* device going down, Stop using ICT table */ iwl_disable_ict(priv); @@ -1146,11 +1146,12 @@ static const struct iwl_trans_ops trans_ops = { .free = iwl_trans_free, }; -int iwl_trans_register(struct iwl_priv *priv) +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) { int err; priv->trans.ops = &trans_ops; + priv->trans.priv = priv; iwl_alloc_isr_ict(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index fca01819f10..7993aa7ae66 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -60,95 +60,166 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +#ifndef __iwl_trans_h__ +#define __iwl_trans_h__ /*This file includes the declaration that are exported from the transport * layer */ -static inline int trans_start_device(struct iwl_priv *priv) +struct iwl_priv; +struct iwl_rxon_context; +struct iwl_host_cmd; + +/** + * struct iwl_trans_ops - transport specific operations + * @start_device: allocates and inits all the resources for the transport + * layer. + * @prepare_card_hw: claim the ownership on the HW. Will be called during + * probe. + * @tx_start: starts and configures all the Tx fifo - usually done once the fw + * is alive. + * @stop_device:stops the whole device (embedded CPU put to reset) + * @rx_free: frees the rx memory + * @tx_free: frees the tx memory + * @send_cmd:send a host command + * @send_cmd_pdu:send a host command: flags can be CMD_* + * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use + * @tx: send an skb + * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is + * ready and a successful ADDBA response has been received. + * @txq_agg_disable: de-configure a Tx queue to send AMPDUs + * @kick_nic: remove the RESET from the embedded CPU and let it run + * @sync_irq: the upper layer will typically disable interrupt and call this + * handler. After this handler returns, it is guaranteed that all + * the ISR / tasklet etc... have finished running and the transport + * layer shall not pass any Rx. + * @free: release all the ressource for the transport layer itself such as + * irq, tasklet etc... + */ +struct iwl_trans_ops { + + int (*start_device)(struct iwl_priv *priv); + int (*prepare_card_hw)(struct iwl_priv *priv); + void (*stop_device)(struct iwl_priv *priv); + void (*tx_start)(struct iwl_priv *priv); + void (*tx_free)(struct iwl_priv *priv); + void (*rx_free)(struct iwl_priv *priv); + + int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); + + int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + const void *data); + struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); + int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx); + + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); + void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); + + void (*kick_nic)(struct iwl_priv *priv); + + void (*sync_irq)(struct iwl_priv *priv); + void (*free)(struct iwl_priv *priv); +}; + +struct iwl_trans { + const struct iwl_trans_ops *ops; + struct iwl_priv *priv; +}; + +static inline int trans_start_device(struct iwl_trans *trans) { - return priv->trans.ops->start_device(priv); + return trans->ops->start_device(trans->priv); } -static inline int trans_prepare_card_hw(struct iwl_priv *priv) +static inline int trans_prepare_card_hw(struct iwl_trans *trans) { - return priv->trans.ops->prepare_card_hw(priv); + return trans->ops->prepare_card_hw(trans->priv); } -static inline void trans_stop_device(struct iwl_priv *priv) +static inline void trans_stop_device(struct iwl_trans *trans) { - priv->trans.ops->stop_device(priv); + trans->ops->stop_device(trans->priv); } -static inline void trans_tx_start(struct iwl_priv *priv) +static inline void trans_tx_start(struct iwl_trans *trans) { - priv->trans.ops->tx_start(priv); + trans->ops->tx_start(trans->priv); } -static inline void trans_rx_free(struct iwl_priv *priv) +static inline void trans_rx_free(struct iwl_trans *trans) { - priv->trans.ops->rx_free(priv); + trans->ops->rx_free(trans->priv); } -static inline void trans_tx_free(struct iwl_priv *priv) +static inline void trans_tx_free(struct iwl_trans *trans) { - priv->trans.ops->tx_free(priv); + trans->ops->tx_free(trans->priv); } -static inline int trans_send_cmd(struct iwl_priv *priv, +static inline int trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - return priv->trans.ops->send_cmd(priv, cmd); + return trans->ops->send_cmd(trans->priv, cmd); } -static inline int trans_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, +static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data) { - return priv->trans.ops->send_cmd_pdu(priv, id, flags, len, data); + return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data); } -static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_priv *priv, +static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans, int txq_id) { - return priv->trans.ops->get_tx_cmd(priv, txq_id); + return trans->ops->get_tx_cmd(trans->priv, txq_id); } -static inline int trans_tx(struct iwl_priv *priv, struct sk_buff *skb, +static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx) { - return priv->trans.ops->tx(priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); + return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } -static inline int trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, +static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { - return priv->trans.ops->txq_agg_disable(priv, txq_id, ssn_idx, tx_fifo); + return trans->ops->txq_agg_disable(trans->priv, txq_id, + ssn_idx, tx_fifo); } -static inline void trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, +static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, int tid, int frame_limit) { - priv->trans.ops->txq_agg_setup(priv, sta_id, tid, frame_limit); + trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit); } -static inline void trans_kick_nic(struct iwl_priv *priv) +static inline void trans_kick_nic(struct iwl_trans *trans) { - priv->trans.ops->kick_nic(priv); + trans->ops->kick_nic(trans->priv); } -static inline void trans_sync_irq(struct iwl_priv *priv) +static inline void trans_sync_irq(struct iwl_trans *trans) { - priv->trans.ops->sync_irq(priv); + trans->ops->sync_irq(trans->priv); } -static inline void trans_free(struct iwl_priv *priv) +static inline void trans_free(struct iwl_trans *trans) { - priv->trans.ops->free(priv); + trans->ops->free(trans->priv); } -int iwl_trans_register(struct iwl_priv *priv); +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv); /*TODO: this functions should NOT be exported from trans module - export it * until the reclaim flow will be brought to the transport module too */ + +struct iwl_tx_queue; void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq); + +#endif /* __iwl_trans_h__ */ -- cgit v1.2.3-70-g09d2 From d593411084a56124aa9d80aafa15db8463b2d8f7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 11 Jul 2011 10:48:51 +0300 Subject: iwlagn: simplify the bus architecture Call iwl_probe with a ready iwl_bus struct. This means that the bus layer assigns the irq, dev and iwl_bus_ops pointers to iwl_bus before giving it to iwl_probe. The device specific struct is allocated together with the common iwl_bus struct by the bus specific layer. The pointer to the aggregate struct is passed to the upper layer that holds a pointer to iwl_bus instead of an embedded iw_bus. The private data given to the PCI subsystem is now iwl_bus and not iwl_priv. Provide bus_* inliners on the way in order to simplify the syntax. Rename iwl-pci.h -> iwl-bus.h since it is bus agnostic and represent the external of the bus layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 31 ++--- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 +- drivers/net/wireless/iwlwifi/iwl-bus.h | 142 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 8 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 41 +------ drivers/net/wireless/iwlwifi/iwl-io.h | 7 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 64 +++++----- drivers/net/wireless/iwlwifi/iwl-pci.h | 69 ----------- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 6 +- drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 10 +- drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 12 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 38 +++--- 15 files changed, 230 insertions(+), 209 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-bus.h delete mode 100644 drivers/net/wireless/iwlwifi/iwl-pci.h (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d3163d8cf6d..aee62d0726a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -55,7 +55,7 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-pci.h" +#include "iwl-bus.h" #include "iwl-trans.h" /****************************************************************************** @@ -580,7 +580,7 @@ static struct attribute_group iwl_attribute_group = { static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc) { if (desc->v_addr) - dma_free_coherent(priv->bus.dev, desc->len, + dma_free_coherent(priv->bus->dev, desc->len, desc->v_addr, desc->p_addr); desc->v_addr = NULL; desc->len = 0; @@ -606,7 +606,7 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, return -EINVAL; } - desc->v_addr = dma_alloc_coherent(priv->bus.dev, len, + desc->v_addr = dma_alloc_coherent(priv->bus->dev, len, &desc->p_addr, GFP_KERNEL); if (!desc->v_addr) return -ENOMEM; @@ -660,7 +660,7 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) priv->firmware_name); return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, - priv->bus.dev, + priv->bus->dev, GFP_KERNEL, priv, iwl_ucode_callback); } @@ -1163,7 +1163,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (err) IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - err = sysfs_create_group(&(priv->bus.dev->kobj), + err = sysfs_create_group(&(priv->bus->dev->kobj), &iwl_attribute_group); if (err) { IWL_ERR(priv, "failed to create sysfs device attributes\n"); @@ -1187,7 +1187,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) iwl_dealloc_ucode(priv); out_unbind: complete(&priv->_agn.firmware_loading_complete); - device_release_driver(priv->bus.dev); + device_release_driver(priv->bus->dev); release_firmware(ucode_raw); } @@ -3102,8 +3102,7 @@ static void iwl_init_context(struct iwl_priv *priv) BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); } -int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, - struct iwl_cfg *cfg) +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) { int err = 0; struct iwl_priv *priv; @@ -3121,17 +3120,12 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, } priv = hw->priv; - - priv->bus.priv = priv; - priv->bus.bus_specific = bus_specific; - priv->bus.ops = bus_ops; - priv->bus.irq = priv->bus.ops->get_irq(&priv->bus); - priv->bus.ops->set_drv_data(&priv->bus, priv); - priv->bus.dev = priv->bus.ops->get_dev(&priv->bus); + priv->bus = bus; + bus_set_drv_data(priv->bus, priv); /* At this point both hw and priv are allocated. */ - SET_IEEE80211_DEV(hw, priv->bus.dev); + SET_IEEE80211_DEV(hw, priv->bus->dev); IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; @@ -3154,7 +3148,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); - /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ @@ -3289,7 +3282,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); iwl_dbgfs_unregister(priv); - sysfs_remove_group(&priv->bus.dev->kobj, + sysfs_remove_group(&priv->bus->dev->kobj, &iwl_attribute_group); /* ieee80211_unregister_hw call wil cause iwl_mac_stop to @@ -3339,7 +3332,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) trans_free(&priv->trans); - priv->bus.ops->set_drv_data(&priv->bus, NULL); + bus_set_drv_data(priv->bus, NULL); iwl_uninit_drv(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 496ab99c424..78dccde88aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -336,8 +336,7 @@ void iwl_testmode_cleanup(struct iwl_priv *priv) } #endif -int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, - struct iwl_cfg *cfg); +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); void __devexit iwl_remove(struct iwl_priv * priv); #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h new file mode 100644 index 00000000000..fef62e6c2c8 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_pci_h__ +#define __iwl_pci_h__ + +struct iwl_bus; + +/** + * struct iwl_bus_ops - bus specific operations + + * @get_pm_support: must returns true if the bus can go to sleep + * @apm_config: will be called during the config of the APM configuration + * @set_drv_data: set the priv pointer to the bus layer + * @get_hw_id: prints the hw_id in the provided buffer + * @write8: write a byte to register at offset ofs + * @write32: write a dword to register at offset ofs + * @wread32: read a dword at register at offset ofs + */ +struct iwl_bus_ops { + bool (*get_pm_support)(struct iwl_bus *bus); + void (*apm_config)(struct iwl_bus *bus); + void (*set_drv_data)(struct iwl_bus *bus, void *drv_data); + void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); + void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); + void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); + u32 (*read32)(struct iwl_bus *bus, u32 ofs); +}; + +struct iwl_bus { + /* Common data to all buses */ + + /*TODO: priv should be void * */ + struct iwl_priv *priv; /* driver's context */ + struct device *dev; + struct iwl_bus_ops *ops; + + unsigned int irq; + + /* pointer to bus specific struct */ + /*Ensure that this pointer will always be aligned to sizeof pointer */ + char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); +}; + +static inline bool bus_get_pm_support(struct iwl_bus *bus) +{ + return bus->ops->get_pm_support(bus); +} + +static inline void bus_apm_config(struct iwl_bus *bus) +{ + bus->ops->apm_config(bus); +} + +static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data) +{ + bus->ops->set_drv_data(bus, drv_data); +} + +static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) +{ + bus->ops->get_hw_id(bus, buf, buf_len); +} + +static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val) +{ + bus->ops->write8(bus, ofs, val); +} + +static inline void bus_write32(struct iwl_bus *bus, u32 ofs, u32 val) +{ + bus->ops->write32(bus, ofs, val); +} + +static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) +{ + return bus->ops->read32(bus, ofs); +} + +int __must_check iwl_pci_register_driver(void); +void iwl_pci_unregister_driver(void); + +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a2a95bace84..3be011137d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -211,7 +211,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) { char buf[32]; - priv->bus.ops->get_hw_id(&priv->bus, buf, sizeof(buf)); + bus_get_hw_id(priv->bus, buf, sizeof(buf)); IWL_INFO(priv, "Incorrectly detected BG card as ABG. " "Please send your %s to maintainer.\n", buf); priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; @@ -1012,7 +1012,7 @@ int iwl_apm_init(struct iwl_priv *priv) iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - priv->bus.ops->apm_config(&priv->bus); + bus_apm_config(priv->bus); /* Configure analog phase-lock-loop before activating to D0A */ if (priv->cfg->base_params->pll_cfg_val) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index eb95d1a3748..4529e2ddbbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -32,10 +32,10 @@ struct iwl_priv; extern u32 iwl_debug_level; -#define IWL_ERR(p, f, a...) dev_err(p->bus.ops->get_dev(&p->bus), f, ## a) -#define IWL_WARN(p, f, a...) dev_warn(p->bus.ops->get_dev(&p->bus), f, ## a) -#define IWL_INFO(p, f, a...) dev_info(p->bus.ops->get_dev(&p->bus), f, ## a) -#define IWL_CRIT(p, f, a...) dev_crit(p->bus.ops->get_dev(&p->bus), f, ## a) +#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) +#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) +#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a) +#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a) #define iwl_print_hex_error(priv, p, len) \ do { \ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a89b40a585c..964be5795c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -47,6 +47,7 @@ #include "iwl-power.h" #include "iwl-agn-rs.h" #include "iwl-agn-tt.h" +#include "iwl-bus.h" #include "iwl-trans.h" #define DRV_NAME "iwlagn" @@ -1193,44 +1194,6 @@ struct iwl_testmode_trace { }; #endif -struct iwl_bus; - -/** - * struct iwl_bus_ops - bus specific operations - - * @get_pm_support: must returns true if the bus can go to sleep - * @apm_config: will be called during the config of the APM configuration - * @set_drv_data: set the priv pointer to the bus layer - * @get_dev: returns the device struct - * @get_irq: returns the irq number - * @get_hw_id: prints the hw_id in the provided buffer - * @write8: write a byte to register at offset ofs - * @write32: write a dword to register at offset ofs - * @wread32: read a dword at register at offset ofs - */ -struct iwl_bus_ops { - bool (*get_pm_support)(struct iwl_bus *bus); - void (*apm_config)(struct iwl_bus *bus); - void (*set_drv_data)(struct iwl_bus *bus, void *priv); - struct device *(*get_dev)(const struct iwl_bus *bus); - unsigned int (*get_irq)(const struct iwl_bus *bus); - void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); - void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); - void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); - u32 (*read32)(struct iwl_bus *bus, u32 ofs); -}; - -struct iwl_bus { - /* pointer to bus specific struct */ - void *bus_specific; - - /* Common data to all buses */ - struct iwl_priv *priv; /* driver's context */ - struct device *dev; - struct iwl_bus_ops *ops; - unsigned int irq; -}; - /* uCode ownership */ #define IWL_OWNERSHIP_DRIVER 0 #define IWL_OWNERSHIP_TM 1 @@ -1302,7 +1265,7 @@ struct iwl_priv { spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; - struct iwl_bus bus; /* bus specific data */ + struct iwl_bus *bus; /* bus specific data */ struct iwl_trans trans; /* microcode/device supports multiple contexts */ diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index c56eae74c3c..19a09310112 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -34,22 +34,23 @@ #include "iwl-dev.h" #include "iwl-debug.h" #include "iwl-devtrace.h" +#include "iwl-bus.h" static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) { trace_iwlwifi_dev_iowrite8(priv, ofs, val); - priv->bus.ops->write8(&priv->bus, ofs, val); + bus_write8(priv->bus, ofs, val); } static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) { trace_iwlwifi_dev_iowrite32(priv, ofs, val); - priv->bus.ops->write32(&priv->bus, ofs, val); + bus_write32(priv->bus, ofs, val); } static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) { - u32 val = priv->bus.ops->read32(&priv->bus, ofs); + u32 val = bus_read32(priv->bus, ofs); trace_iwlwifi_dev_ioread32(priv, ofs, val); return val; } diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 75663c12e99..a67ae56d546 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -203,7 +203,7 @@ void iwl_leds_init(struct iwl_priv *priv) break; } - ret = led_classdev_register(priv->bus.dev, + ret = led_classdev_register(priv->bus->dev, &priv->led); if (ret) { kfree(priv->led.name); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 74911348a2e..66448895f7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -63,11 +63,10 @@ #include #include -#include "iwl-pci.h" +#include "iwl-bus.h" #include "iwl-agn.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-trans.h" /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -132,19 +131,9 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) } } -static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_priv) +static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) { - pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_priv); -} - -static struct device *iwl_pci_get_dev(const struct iwl_bus *bus) -{ - return &(IWL_BUS_GET_PCI_DEV(bus)->dev); -} - -static unsigned int iwl_pci_get_irq(const struct iwl_bus *bus) -{ - return IWL_BUS_GET_PCI_DEV(bus)->irq; + bus->priv = drv_data; } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -176,8 +165,6 @@ static struct iwl_bus_ops pci_ops = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, .set_drv_data = iwl_pci_set_drv_data, - .get_dev = iwl_pci_get_dev, - .get_irq = iwl_pci_get_irq, .get_hw_id = iwl_pci_get_hw_id, .write8 = iwl_pci_write8, .write32 = iwl_pci_write32, @@ -383,18 +370,20 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - struct iwl_pci_bus *bus; + struct iwl_bus *bus; + struct iwl_pci_bus *pci_bus; u16 pci_cmd; int err; - bus = kzalloc(sizeof(*bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL); if (!bus) { pr_err("Couldn't allocate iwl_pci_bus"); err = -ENOMEM; goto out_no_pci; } - bus->pci_dev = pdev; + pci_bus = IWL_BUS_GET_PCI_BUS(bus); + pci_bus->pci_dev = pdev; /* W/A - seems to solve weird behavior. We need to remove this if we * don't want to stay in L1 all the time. This wastes a lot of power */ @@ -429,8 +418,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_pci_disable_device; } - bus->hw_base = pci_iomap(pdev, 0, 0); - if (!bus->hw_base) { + pci_bus->hw_base = pci_iomap(pdev, 0, 0); + if (!pci_bus->hw_base) { pr_err("pci_iomap failed"); err = -ENODEV; goto out_pci_release_regions; @@ -438,7 +427,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pr_info("pci_resource_len = 0x%08llx\n", (unsigned long long) pci_resource_len(pdev, 0)); - pr_info("pci_resource_base = %p\n", bus->hw_base); + pr_info("pci_resource_base = %p\n", pci_bus->hw_base); pr_info("HW Revision ID = 0x%X\n", pdev->revision); @@ -460,7 +449,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); } - err = iwl_probe((void *) bus, &pci_ops, cfg); + pci_set_drvdata(pdev, bus); + + bus->dev = &pdev->dev; + bus->irq = pdev->irq; + bus->ops = &pci_ops; + + err = iwl_probe(bus, cfg); if (err) goto out_disable_msi; return 0; @@ -468,7 +463,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_disable_msi: pci_disable_msi(pdev); out_iounmap: - pci_iounmap(pdev, bus->hw_base); + pci_iounmap(pdev, pci_bus->hw_base); out_pci_release_regions: pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); @@ -479,9 +474,9 @@ out_no_pci: return err; } -static void iwl_pci_down(void *bus) +static void iwl_pci_down(struct iwl_bus *bus) { - struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus; + struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific; pci_disable_msi(pci_bus->pci_dev); pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); @@ -489,17 +484,16 @@ static void iwl_pci_down(void *bus) pci_disable_device(pci_bus->pci_dev); pci_set_drvdata(pci_bus->pci_dev, NULL); - kfree(pci_bus); + kfree(bus); } static void __devexit iwl_pci_remove(struct pci_dev *pdev) { - struct iwl_priv *priv = pci_get_drvdata(pdev); - void *bus_specific = priv->bus.bus_specific; + struct iwl_bus *bus = pci_get_drvdata(pdev); - iwl_remove(priv); + iwl_remove(bus->priv); - iwl_pci_down(bus_specific); + iwl_pci_down(bus); } #ifdef CONFIG_PM @@ -507,15 +501,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = pci_get_drvdata(pdev); - return iwl_suspend(priv); + return iwl_suspend(bus->priv); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = pci_get_drvdata(pdev); /* * We disable the RETRY_TIMEOUT register (0x41) to keep @@ -523,7 +517,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_resume(priv); + return iwl_resume(bus->priv); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h deleted file mode 100644 index 9396c7c8d6a..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-pci.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_pci_h__ -#define __iwl_pci_h__ - -int __must_check iwl_pci_register_driver(void); -void iwl_pci_unregister_driver(void); - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 7c99f432996..de4f33304ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -432,7 +432,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) /* initialize to default */ void iwl_power_initialize(struct iwl_priv *priv) { - priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus); + priv->power_data.bus_pm = bus_get_pm_support(priv->bus); priv->power_data.debug_sleep_level_override = -1; diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index d47483561a8..b11f60de4f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -181,12 +181,10 @@ void iwl_testmode_init(struct iwl_priv *priv) static void iwl_trace_cleanup(struct iwl_priv *priv) { - struct device *dev = priv->bus.dev; - if (priv->testmode_trace.trace_enabled) { if (priv->testmode_trace.cpu_addr && priv->testmode_trace.dma_addr) - dma_free_coherent(dev, + dma_free_coherent(priv->bus->dev, priv->testmode_trace.total_size, priv->testmode_trace.cpu_addr, priv->testmode_trace.dma_addr); @@ -486,7 +484,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) struct iwl_priv *priv = hw->priv; struct sk_buff *skb; int status = 0; - struct device *dev = priv->bus.dev; + struct device *dev = priv->bus->dev; switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index d5b9adfc3cc..74343589f28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -305,7 +305,7 @@ static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) BUG_ON(rxb->page); rxb->page = page; /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(priv->bus.dev, page, 0, + rxb->page_dma = dma_map_page(priv->bus->dev, page, 0, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); /* dma address must be no more than 36 bits */ @@ -404,7 +404,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; - dma_unmap_page(priv->bus.dev, rxb->page_dma, + dma_unmap_page(priv->bus->dev, rxb->page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); @@ -455,7 +455,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) * rx_free list for reuse later. */ spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page, + rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page, 0, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); list_add_tail(&rxb->list, &rxq->rx_free); @@ -704,7 +704,7 @@ void iwl_irq_tasklet(struct iwl_priv *priv) void iwl_free_isr_ict(struct iwl_priv *priv) { if (priv->_agn.ict_tbl_vir) { - dma_free_coherent(priv->bus.dev, + dma_free_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, priv->_agn.ict_tbl_vir, priv->_agn.ict_tbl_dma); @@ -725,7 +725,7 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) /* allocate shrared data table */ priv->_agn.ict_tbl_vir = - dma_alloc_coherent(priv->bus.dev, + dma_alloc_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, &priv->_agn.ict_tbl_dma, GFP_KERNEL); if (!priv->_agn.ict_tbl_vir) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 7dac6ee2325..27f78fed2ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -182,14 +182,14 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, /* Unmap tx_cmd */ if (num_tbs) - dma_unmap_single(priv->bus.dev, + dma_unmap_single(priv->bus->dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(priv->bus.dev, iwl_tfd_tb_get_addr(tfd, i), + dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); } @@ -640,9 +640,9 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) le16_to_cpu(out_cmd->hdr.sequence), cmd_size, q->write_ptr, idx, priv->cmd_queue); - phys_addr = dma_map_single(priv->bus.dev, &out_cmd->hdr, copy_size, + phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) { + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { idx = -ENOMEM; goto out; } @@ -662,9 +662,9 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) continue; if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; - phys_addr = dma_map_single(priv->bus.dev, (void *)cmd->data[i], + phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i], cmd->len[i], DMA_BIDIRECTIONAL); - if (dma_mapping_error(priv->bus.dev, phys_addr)) { + if (dma_mapping_error(priv->bus->dev, phys_addr)) { iwlagn_unmap_tfd(priv, out_meta, &txq->tfds[q->write_ptr], DMA_BIDIRECTIONAL); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index edd28f00dab..582ab1b8e73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -72,7 +72,7 @@ static int iwl_trans_rx_alloc(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; - struct device *dev = priv->bus.dev; + struct device *dev = priv->bus->dev; memset(&priv->rxq, 0, sizeof(priv->rxq)); @@ -118,7 +118,7 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) /* In the reset function, these buffers may have been allocated * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { - dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma, + dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); __iwl_free_pages(priv, rxq->pool[i].page); @@ -233,13 +233,13 @@ static void iwl_trans_rx_free(struct iwl_priv *priv) iwl_trans_rxq_free_rx_bufs(priv); spin_unlock_irqrestore(&rxq->lock, flags); - dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(priv->bus->dev, sizeof(__le32) * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; if (rxq->rb_stts) - dma_free_coherent(priv->bus.dev, + dma_free_coherent(priv->bus->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); else @@ -263,7 +263,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, if (WARN_ON(ptr->addr)) return -EINVAL; - ptr->addr = dma_alloc_coherent(priv->bus.dev, size, + ptr->addr = dma_alloc_coherent(priv->bus->dev, size, &ptr->dma, GFP_KERNEL); if (!ptr->addr) return -ENOMEM; @@ -277,7 +277,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, if (unlikely(!ptr->addr)) return; - dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } @@ -324,7 +324,7 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = dma_alloc_coherent(priv->bus.dev, tfd_sz, &txq->q.dma_addr, + txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL); if (!txq->tfds) { IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); @@ -415,7 +415,7 @@ static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct device *dev = priv->bus.dev; + struct device *dev = priv->bus->dev; int i; if (WARN_ON(!txq)) return; @@ -1016,10 +1016,10 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = dma_map_single(priv->bus.dev, + txcmd_phys = dma_map_single(priv->bus->dev, &dev_cmd->hdr, firstlen, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(priv->bus.dev, txcmd_phys))) + if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys))) return -1; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); @@ -1035,10 +1035,10 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, * if any (802.11 null frames have no payload). */ secondlen = skb->len - hdr_len; if (secondlen > 0) { - phys_addr = dma_map_single(priv->bus.dev, skb->data + hdr_len, + phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len, secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) { - dma_unmap_single(priv->bus.dev, + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { + dma_unmap_single(priv->bus->dev, dma_unmap_addr(out_meta, mapping), dma_unmap_len(out_meta, len), DMA_BIDIRECTIONAL); @@ -1056,7 +1056,7 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, offsetof(struct iwl_tx_cmd, scratch); /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(priv->bus.dev, txcmd_phys, firstlen, + dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); @@ -1072,7 +1072,7 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, iwl_trans_txq_update_byte_cnt_tbl(priv, txq, le16_to_cpu(tx_cmd->len)); - dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen, + dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); trace_iwlwifi_dev_tx(priv, @@ -1111,13 +1111,13 @@ static void iwl_trans_kick_nic(struct iwl_priv *priv) static void iwl_trans_sync_irq(struct iwl_priv *priv) { /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->bus.irq); + synchronize_irq(priv->bus->irq); tasklet_kill(&priv->irq_tasklet); } static void iwl_trans_free(struct iwl_priv *priv) { - free_irq(priv->bus.irq, priv); + free_irq(priv->bus->irq, priv); iwl_free_isr_ict(priv); } @@ -1155,10 +1155,10 @@ int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) iwl_alloc_isr_ict(priv); - err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED, + err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED, DRV_NAME, priv); if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq); + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); iwl_free_isr_ict(priv); return err; } -- cgit v1.2.3-70-g09d2 From c10e2c102ff180998bf91404c2d76ca66ced46a0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 13 Jul 2011 11:13:46 -0700 Subject: iwlagn: testmode fixed rate available for testmode only Move tm_fixed_rate inside CONFIG_IWLWIFI_DEVICE_SVTOOL and only available when the option is enable. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 8 ++++++-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ebcd13bc10d..3789ff4bf53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -354,9 +354,11 @@ static void rs_program_fix_rate(struct iwl_priv *priv, lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL /* testmode has higher priority to overwirte the fixed rate */ if (priv->tm_fixed_rate) lq_sta->dbg_fixed_rate = priv->tm_fixed_rate; +#endif IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); @@ -1080,7 +1082,8 @@ done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); -#ifdef CONFIG_MAC80211_DEBUGFS + +#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL) if ((priv->tm_fixed_rate) && (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) rs_program_fix_rate(priv, lq_sta); @@ -2904,8 +2907,9 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i if (sband->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; - +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL priv->tm_fixed_rate = 0; +#endif #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->dbg_fixed_rate = 0; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a5295c15d70..53bb59ee719 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -217,6 +217,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, if (ieee80211_is_data(fc)) { tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL if (priv->tm_fixed_rate) { /* * rate overwrite by testmode @@ -227,6 +228,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate, sizeof(tx_cmd->rate_n_flags)); } +#endif return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 964be5795c5..72ef50e319d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1535,8 +1535,8 @@ struct iwl_priv { bool led_registered; #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL struct iwl_testmode_trace testmode_trace; -#endif u32 tm_fixed_rate; +#endif }; /*iwl_priv */ -- cgit v1.2.3-70-g09d2 From a920bffb88260aac36bfd05745696dc6aa256627 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Jul 2011 13:27:25 -0700 Subject: iwlagn: remove keyinfo cache iwlagn keeps a copy of key stuff internally but never actually uses it, so remove it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 22 ---------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 8 -------- 2 files changed, 30 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 67b9c2bacc5..395dee1c144 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -234,7 +234,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->hw_key_idx = HW_KEY_DEFAULT; - priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, @@ -272,13 +271,6 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; - - memcpy(priv->stations[sta_id].keyinfo.key, - keyconf->key, keyconf->keylen); - memcpy(&priv->stations[sta_id].sta.key.key[3], keyconf->key, keyconf->keylen); @@ -323,11 +315,6 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, - keyconf->keylen); memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen); @@ -373,9 +360,6 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = 16; - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC) priv->stations[sta_id].sta.key.key_offset = @@ -388,10 +372,6 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, priv->stations[sta_id].sta.key.key_flags = key_flags; - - /* This copy is acutally not needed: we get the key with each TX */ - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -477,8 +457,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, &priv->ucode_key_table)) IWL_ERR(priv, "index %d not used in uCode key table.\n", priv->stations[sta_id].sta.key.key_offset); - memset(&priv->stations[sta_id].keyinfo, 0, - sizeof(struct iwl_hw_key)); memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl_keyinfo)); priv->stations[sta_id].sta.key.key_flags = diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 72ef50e319d..da9048856a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -397,13 +397,6 @@ struct iwl_tid_data { struct iwl_ht_agg agg; }; -struct iwl_hw_key { - u32 cipher; - int keylen; - u8 keyidx; - u8 key[32]; -}; - union iwl_ht_rate_supp { u16 rates; struct { @@ -456,7 +449,6 @@ struct iwl_station_entry { struct iwl_addsta_cmd sta; struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used, ctxid; - struct iwl_hw_key keyinfo; struct iwl_link_quality_cmd *lq; }; -- cgit v1.2.3-70-g09d2 From 898ed67be047d0762cc7592f67bf1313dff53ca9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 13 Jul 2011 08:38:57 -0700 Subject: iwlagn: remove un-necessary "_agn" After driver split, extra _agn in priv structure is no needed, remove it. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 98 +++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 10 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 90 ++++++++++---------- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 72 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-dev.h | 98 +++++++++++----------- drivers/net/wireless/iwlwifi/iwl-rx.c | 26 +++--- drivers/net/wireless/iwlwifi/iwl-scan.c | 6 +- drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 100 +++++++++++------------ 10 files changed, 254 insertions(+), 256 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 204f0ece3c2..72d6297602b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -889,7 +889,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, - priv->_agn.phy_calib_chain_noise_gain_cmd); + priv->phy_calib_chain_noise_gain_cmd); cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 67b55c5fa0d..e77f91380a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -53,73 +53,73 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) switch (status) { case TX_STATUS_POSTPONE_DELAY: - priv->_agn.reply_tx_stats.pp_delay++; + priv->reply_tx_stats.pp_delay++; break; case TX_STATUS_POSTPONE_FEW_BYTES: - priv->_agn.reply_tx_stats.pp_few_bytes++; + priv->reply_tx_stats.pp_few_bytes++; break; case TX_STATUS_POSTPONE_BT_PRIO: - priv->_agn.reply_tx_stats.pp_bt_prio++; + priv->reply_tx_stats.pp_bt_prio++; break; case TX_STATUS_POSTPONE_QUIET_PERIOD: - priv->_agn.reply_tx_stats.pp_quiet_period++; + priv->reply_tx_stats.pp_quiet_period++; break; case TX_STATUS_POSTPONE_CALC_TTAK: - priv->_agn.reply_tx_stats.pp_calc_ttak++; + priv->reply_tx_stats.pp_calc_ttak++; break; case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: - priv->_agn.reply_tx_stats.int_crossed_retry++; + priv->reply_tx_stats.int_crossed_retry++; break; case TX_STATUS_FAIL_SHORT_LIMIT: - priv->_agn.reply_tx_stats.short_limit++; + priv->reply_tx_stats.short_limit++; break; case TX_STATUS_FAIL_LONG_LIMIT: - priv->_agn.reply_tx_stats.long_limit++; + priv->reply_tx_stats.long_limit++; break; case TX_STATUS_FAIL_FIFO_UNDERRUN: - priv->_agn.reply_tx_stats.fifo_underrun++; + priv->reply_tx_stats.fifo_underrun++; break; case TX_STATUS_FAIL_DRAIN_FLOW: - priv->_agn.reply_tx_stats.drain_flow++; + priv->reply_tx_stats.drain_flow++; break; case TX_STATUS_FAIL_RFKILL_FLUSH: - priv->_agn.reply_tx_stats.rfkill_flush++; + priv->reply_tx_stats.rfkill_flush++; break; case TX_STATUS_FAIL_LIFE_EXPIRE: - priv->_agn.reply_tx_stats.life_expire++; + priv->reply_tx_stats.life_expire++; break; case TX_STATUS_FAIL_DEST_PS: - priv->_agn.reply_tx_stats.dest_ps++; + priv->reply_tx_stats.dest_ps++; break; case TX_STATUS_FAIL_HOST_ABORTED: - priv->_agn.reply_tx_stats.host_abort++; + priv->reply_tx_stats.host_abort++; break; case TX_STATUS_FAIL_BT_RETRY: - priv->_agn.reply_tx_stats.bt_retry++; + priv->reply_tx_stats.bt_retry++; break; case TX_STATUS_FAIL_STA_INVALID: - priv->_agn.reply_tx_stats.sta_invalid++; + priv->reply_tx_stats.sta_invalid++; break; case TX_STATUS_FAIL_FRAG_DROPPED: - priv->_agn.reply_tx_stats.frag_drop++; + priv->reply_tx_stats.frag_drop++; break; case TX_STATUS_FAIL_TID_DISABLE: - priv->_agn.reply_tx_stats.tid_disable++; + priv->reply_tx_stats.tid_disable++; break; case TX_STATUS_FAIL_FIFO_FLUSHED: - priv->_agn.reply_tx_stats.fifo_flush++; + priv->reply_tx_stats.fifo_flush++; break; case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: - priv->_agn.reply_tx_stats.insuff_cf_poll++; + priv->reply_tx_stats.insuff_cf_poll++; break; case TX_STATUS_FAIL_PASSIVE_NO_RX: - priv->_agn.reply_tx_stats.fail_hw_drop++; + priv->reply_tx_stats.fail_hw_drop++; break; case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: - priv->_agn.reply_tx_stats.sta_color_mismatch++; + priv->reply_tx_stats.sta_color_mismatch++; break; default: - priv->_agn.reply_tx_stats.unknown++; + priv->reply_tx_stats.unknown++; break; } } @@ -130,43 +130,43 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) switch (status) { case AGG_TX_STATE_UNDERRUN_MSK: - priv->_agn.reply_agg_tx_stats.underrun++; + priv->reply_agg_tx_stats.underrun++; break; case AGG_TX_STATE_BT_PRIO_MSK: - priv->_agn.reply_agg_tx_stats.bt_prio++; + priv->reply_agg_tx_stats.bt_prio++; break; case AGG_TX_STATE_FEW_BYTES_MSK: - priv->_agn.reply_agg_tx_stats.few_bytes++; + priv->reply_agg_tx_stats.few_bytes++; break; case AGG_TX_STATE_ABORT_MSK: - priv->_agn.reply_agg_tx_stats.abort++; + priv->reply_agg_tx_stats.abort++; break; case AGG_TX_STATE_LAST_SENT_TTL_MSK: - priv->_agn.reply_agg_tx_stats.last_sent_ttl++; + priv->reply_agg_tx_stats.last_sent_ttl++; break; case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: - priv->_agn.reply_agg_tx_stats.last_sent_try++; + priv->reply_agg_tx_stats.last_sent_try++; break; case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: - priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++; + priv->reply_agg_tx_stats.last_sent_bt_kill++; break; case AGG_TX_STATE_SCD_QUERY_MSK: - priv->_agn.reply_agg_tx_stats.scd_query++; + priv->reply_agg_tx_stats.scd_query++; break; case AGG_TX_STATE_TEST_BAD_CRC32_MSK: - priv->_agn.reply_agg_tx_stats.bad_crc32++; + priv->reply_agg_tx_stats.bad_crc32++; break; case AGG_TX_STATE_RESPONSE_MSK: - priv->_agn.reply_agg_tx_stats.response++; + priv->reply_agg_tx_stats.response++; break; case AGG_TX_STATE_DUMP_TX_MSK: - priv->_agn.reply_agg_tx_stats.dump_tx++; + priv->reply_agg_tx_stats.dump_tx++; break; case AGG_TX_STATE_DELAY_TX_MSK: - priv->_agn.reply_agg_tx_stats.delay_tx++; + priv->reply_agg_tx_stats.delay_tx++; break; default: - priv->_agn.reply_agg_tx_stats.unknown++; + priv->reply_agg_tx_stats.unknown++; break; } } @@ -749,7 +749,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen) { - struct sk_buff *skb = priv->_agn.offchan_tx_skb; + struct sk_buff *skb = priv->offchan_tx_skb; if (skb->len < maxlen) maxlen = skb->len; @@ -835,7 +835,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) } else if (priv->scan_type == IWL_SCAN_OFFCH_TX) { scan->suspend_time = 0; scan->max_out_time = - cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout); + cpu_to_le32(1024 * priv->offchan_tx_timeout); } switch (priv->scan_type) { @@ -1023,9 +1023,9 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan_ch = (void *)&scan->data[cmd_len]; scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; scan_ch->channel = - cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value); + cpu_to_le16(priv->offchan_tx_chan->hw_value); scan_ch->active_dwell = - cpu_to_le16(priv->_agn.offchan_tx_timeout); + cpu_to_le16(priv->offchan_tx_timeout); scan_ch->passive_dwell = 0; /* Set txpower levels to defaults */ @@ -1035,7 +1035,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) * power level: * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; */ - if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ) + if (priv->offchan_tx_chan->band == IEEE80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); @@ -2004,9 +2004,9 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv, wait_entry->triggered = false; wait_entry->aborted = false; - spin_lock_bh(&priv->_agn.notif_wait_lock); - list_add(&wait_entry->list, &priv->_agn.notif_waits); - spin_unlock_bh(&priv->_agn.notif_wait_lock); + spin_lock_bh(&priv->notif_wait_lock); + list_add(&wait_entry->list, &priv->notif_waits); + spin_unlock_bh(&priv->notif_wait_lock); } int iwlagn_wait_notification(struct iwl_priv *priv, @@ -2015,13 +2015,13 @@ int iwlagn_wait_notification(struct iwl_priv *priv, { int ret; - ret = wait_event_timeout(priv->_agn.notif_waitq, + ret = wait_event_timeout(priv->notif_waitq, wait_entry->triggered || wait_entry->aborted, timeout); - spin_lock_bh(&priv->_agn.notif_wait_lock); + spin_lock_bh(&priv->notif_wait_lock); list_del(&wait_entry->list); - spin_unlock_bh(&priv->_agn.notif_wait_lock); + spin_unlock_bh(&priv->notif_wait_lock); if (wait_entry->aborted) return -EIO; @@ -2035,7 +2035,7 @@ int iwlagn_wait_notification(struct iwl_priv *priv, void iwlagn_remove_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry) { - spin_lock_bh(&priv->_agn.notif_wait_lock); + spin_lock_bh(&priv->notif_wait_lock); list_del(&wait_entry->list); - spin_unlock_bh(&priv->_agn.notif_wait_lock); + spin_unlock_bh(&priv->notif_wait_lock); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 581534a5415..71487487d60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -337,9 +337,9 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) cmd.slots[0].type = 0; /* BSS */ cmd.slots[1].type = 1; /* PAN */ - if (priv->_agn.hw_roc_channel) { + if (priv->hw_roc_channel) { /* both contexts must be used for this to happen */ - slot1 = priv->_agn.hw_roc_duration; + slot1 = priv->hw_roc_duration; slot0 = IWL_MIN_SLOT_TIME; } else if (ctx_bss->vif && ctx_pan->vif) { int bcnint = ctx_pan->vif->bss_conf.beacon_int; @@ -438,8 +438,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) /* always get timestamp with Rx frame */ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; - if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) { - struct ieee80211_channel *chan = priv->_agn.hw_roc_channel; + if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->hw_roc_channel) { + struct ieee80211_channel *chan = priv->hw_roc_channel; iwl_set_rxon_channel(priv, chan, ctx); iwl_set_flags_for_band(priv, ctx, chan->band, NULL); @@ -787,7 +787,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, - priv->_agn.phy_calib_chain_noise_reset_cmd); + priv->phy_calib_chain_noise_reset_cmd); ret = trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8afdeca2946..6df244387b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1103,20 +1103,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * for each event, which is of mode 1 (including timestamp) for all * new microcodes that include this information. */ - priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; + priv->init_evtlog_ptr = pieces.init_evtlog_ptr; if (pieces.init_evtlog_size) - priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; + priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; else - priv->_agn.init_evtlog_size = + priv->init_evtlog_size = priv->cfg->base_params->max_event_log_size; - priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; - priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; + priv->init_errlog_ptr = pieces.init_errlog_ptr; + priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr; if (pieces.inst_evtlog_size) - priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; + priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; else - priv->_agn.inst_evtlog_size = + priv->inst_evtlog_size = priv->cfg->base_params->max_event_log_size; - priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; + priv->inst_errlog_ptr = pieces.inst_errlog_ptr; priv->new_scan_threshold_behaviour = !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); @@ -1142,9 +1142,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) ucode_capa.standard_phy_calibration_size = IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; - priv->_agn.phy_calib_chain_noise_reset_cmd = + priv->phy_calib_chain_noise_reset_cmd = ucode_capa.standard_phy_calibration_size; - priv->_agn.phy_calib_chain_noise_gain_cmd = + priv->phy_calib_chain_noise_gain_cmd = ucode_capa.standard_phy_calibration_size + 1; /************************************************** @@ -1169,7 +1169,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); - complete(&priv->_agn.firmware_loading_complete); + complete(&priv->firmware_loading_complete); return; try_again: @@ -1183,7 +1183,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_ERR(priv, "failed to allocate pci memory\n"); iwl_dealloc_ucode(priv); out_unbind: - complete(&priv->_agn.firmware_loading_complete); + complete(&priv->firmware_loading_complete); device_release_driver(priv->bus->dev); release_firmware(ucode_raw); } @@ -1265,10 +1265,10 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) base = priv->device_pointers.error_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { if (!base) - base = priv->_agn.init_errlog_ptr; + base = priv->init_errlog_ptr; } else { if (!base) - base = priv->_agn.inst_errlog_ptr; + base = priv->inst_errlog_ptr; } if (!iwlagn_hw_valid_rtc_data_addr(base)) { @@ -1341,10 +1341,10 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, base = priv->device_pointers.log_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { if (!base) - base = priv->_agn.init_evtlog_ptr; + base = priv->init_evtlog_ptr; } else { if (!base) - base = priv->_agn.inst_evtlog_ptr; + base = priv->inst_evtlog_ptr; } if (mode == 0) @@ -1453,13 +1453,13 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, base = priv->device_pointers.log_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { - logsize = priv->_agn.init_evtlog_size; + logsize = priv->init_evtlog_size; if (!base) - base = priv->_agn.init_evtlog_ptr; + base = priv->init_evtlog_ptr; } else { - logsize = priv->_agn.inst_evtlog_size; + logsize = priv->inst_evtlog_size; if (!base) - base = priv->_agn.inst_evtlog_ptr; + base = priv->inst_evtlog_ptr; } if (!iwlagn_hw_valid_rtc_data_addr(base)) { @@ -1964,7 +1964,7 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb, /* TODO: queue up if scanning? */ if (test_bit(STATUS_SCANNING, &priv->status) || - priv->_agn.offchan_tx_skb) { + priv->offchan_tx_skb) { ret = -EBUSY; goto out; } @@ -1978,14 +1978,14 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb, goto out; } - priv->_agn.offchan_tx_skb = skb; - priv->_agn.offchan_tx_timeout = wait; - priv->_agn.offchan_tx_chan = chan; + priv->offchan_tx_skb = skb; + priv->offchan_tx_timeout = wait; + priv->offchan_tx_chan = chan; ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif, IWL_SCAN_OFFCH_TX, chan->band); if (ret) - priv->_agn.offchan_tx_skb = NULL; + priv->offchan_tx_skb = NULL; out: mutex_unlock(&priv->mutex); free: @@ -2002,12 +2002,12 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); - if (!priv->_agn.offchan_tx_skb) { + if (!priv->offchan_tx_skb) { ret = -EINVAL; goto unlock; } - priv->_agn.offchan_tx_skb = NULL; + priv->offchan_tx_skb = NULL; ret = iwl_scan_cancel_timeout(priv, 200); if (ret) @@ -2380,18 +2380,18 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "start Tx\n"); ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); if (ret == 0) { - priv->_agn.agg_tids_count++; - IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", - priv->_agn.agg_tids_count); + priv->agg_tids_count++; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); } break; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); - if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { - priv->_agn.agg_tids_count--; - IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", - priv->_agn.agg_tids_count); + if ((ret == 0) && (priv->agg_tids_count > 0)) { + priv->agg_tids_count--; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ret = 0; @@ -2698,7 +2698,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv) iwl_set_rxon_channel(priv, chan, ctx); iwl_set_flags_for_band(priv, ctx, chan->band, NULL); - priv->_agn.hw_roc_channel = NULL; + priv->hw_roc_channel = NULL; iwlagn_commit_rxon(priv, ctx); @@ -2708,7 +2708,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv) static void iwlagn_bg_roc_done(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, - _agn.hw_roc_work.work); + hw_roc_work.work); mutex_lock(&priv->mutex); ieee80211_remain_on_channel_expired(priv->hw); @@ -2740,11 +2740,11 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, } priv->contexts[IWL_RXON_CTX_PAN].is_active = true; - priv->_agn.hw_roc_channel = channel; - priv->_agn.hw_roc_chantype = channel_type; - priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); + priv->hw_roc_channel = channel; + priv->hw_roc_chantype = channel_type; + priv->hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); - queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work, + queue_delayed_work(priv->workqueue, &priv->hw_roc_work, msecs_to_jiffies(duration + 20)); msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */ @@ -2763,7 +2763,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) return -EOPNOTSUPP; - cancel_delayed_work_sync(&priv->_agn.hw_roc_work); + cancel_delayed_work_sync(&priv->hw_roc_work); mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); @@ -2790,7 +2790,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); - INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); + INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done); iwl_setup_scan_deferred_work(priv); @@ -2864,7 +2864,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; - priv->_agn.agg_tids_count = 0; + priv->agg_tids_count = 0; /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = @@ -3247,7 +3247,7 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) iwl_power_initialize(priv); iwl_tt_initialize(priv); - init_completion(&priv->_agn.firmware_loading_complete); + init_completion(&priv->firmware_loading_complete); err = iwl_request_firmware(priv, true); if (err) @@ -3274,7 +3274,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) { unsigned long flags; - wait_for_completion(&priv->_agn.firmware_loading_complete); + wait_for_completion(&priv->firmware_loading_complete); IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3be011137d0..9b9f462ea0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -840,12 +840,12 @@ static void iwlagn_abort_notification_waits(struct iwl_priv *priv) unsigned long flags; struct iwl_notification_wait *wait_entry; - spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags); - list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list) + spin_lock_irqsave(&priv->notif_wait_lock, flags); + list_for_each_entry(wait_entry, &priv->notif_waits, list) wait_entry->aborted = true; - spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags); + spin_unlock_irqrestore(&priv->notif_wait_lock, flags); - wake_up_all(&priv->_agn.notif_waitq); + wake_up_all(&priv->notif_waitq); } void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 6f9ebae8ca0..17aebf08dff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1915,121 +1915,121 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), - priv->_agn.reply_tx_stats.pp_delay); + priv->reply_tx_stats.pp_delay); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), - priv->_agn.reply_tx_stats.pp_few_bytes); + priv->reply_tx_stats.pp_few_bytes); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), - priv->_agn.reply_tx_stats.pp_bt_prio); + priv->reply_tx_stats.pp_bt_prio); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), - priv->_agn.reply_tx_stats.pp_quiet_period); + priv->reply_tx_stats.pp_quiet_period); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), - priv->_agn.reply_tx_stats.pp_calc_ttak); + priv->reply_tx_stats.pp_calc_ttak); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_tx_fail_reason( TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), - priv->_agn.reply_tx_stats.int_crossed_retry); + priv->reply_tx_stats.int_crossed_retry); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), - priv->_agn.reply_tx_stats.short_limit); + priv->reply_tx_stats.short_limit); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), - priv->_agn.reply_tx_stats.long_limit); + priv->reply_tx_stats.long_limit); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), - priv->_agn.reply_tx_stats.fifo_underrun); + priv->reply_tx_stats.fifo_underrun); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), - priv->_agn.reply_tx_stats.drain_flow); + priv->reply_tx_stats.drain_flow); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), - priv->_agn.reply_tx_stats.rfkill_flush); + priv->reply_tx_stats.rfkill_flush); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), - priv->_agn.reply_tx_stats.life_expire); + priv->reply_tx_stats.life_expire); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), - priv->_agn.reply_tx_stats.dest_ps); + priv->reply_tx_stats.dest_ps); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), - priv->_agn.reply_tx_stats.host_abort); + priv->reply_tx_stats.host_abort); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), - priv->_agn.reply_tx_stats.pp_delay); + priv->reply_tx_stats.pp_delay); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), - priv->_agn.reply_tx_stats.sta_invalid); + priv->reply_tx_stats.sta_invalid); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), - priv->_agn.reply_tx_stats.frag_drop); + priv->reply_tx_stats.frag_drop); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), - priv->_agn.reply_tx_stats.tid_disable); + priv->reply_tx_stats.tid_disable); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), - priv->_agn.reply_tx_stats.fifo_flush); + priv->reply_tx_stats.fifo_flush); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_tx_fail_reason( TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), - priv->_agn.reply_tx_stats.insuff_cf_poll); + priv->reply_tx_stats.insuff_cf_poll); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), - priv->_agn.reply_tx_stats.fail_hw_drop); + priv->reply_tx_stats.fail_hw_drop); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_tx_fail_reason( TX_STATUS_FAIL_NO_BEACON_ON_RADAR), - priv->_agn.reply_tx_stats.sta_color_mismatch); + priv->reply_tx_stats.sta_color_mismatch); pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", - priv->_agn.reply_tx_stats.unknown); + priv->reply_tx_stats.unknown); pos += scnprintf(buf + pos, bufsz - pos, "\nStatistics_Agg_TX_Error:\n"); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), - priv->_agn.reply_agg_tx_stats.underrun); + priv->reply_agg_tx_stats.underrun); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), - priv->_agn.reply_agg_tx_stats.bt_prio); + priv->reply_agg_tx_stats.bt_prio); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), - priv->_agn.reply_agg_tx_stats.few_bytes); + priv->reply_agg_tx_stats.few_bytes); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), - priv->_agn.reply_agg_tx_stats.abort); + priv->reply_agg_tx_stats.abort); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_LAST_SENT_TTL_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_ttl); + priv->reply_agg_tx_stats.last_sent_ttl); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_try); + priv->reply_agg_tx_stats.last_sent_try); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); + priv->reply_agg_tx_stats.last_sent_bt_kill); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), - priv->_agn.reply_agg_tx_stats.scd_query); + priv->reply_agg_tx_stats.scd_query); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_TEST_BAD_CRC32_MSK), - priv->_agn.reply_agg_tx_stats.bad_crc32); + priv->reply_agg_tx_stats.bad_crc32); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), - priv->_agn.reply_agg_tx_stats.response); + priv->reply_agg_tx_stats.response); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), - priv->_agn.reply_agg_tx_stats.dump_tx); + priv->reply_agg_tx_stats.dump_tx); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), - priv->_agn.reply_agg_tx_stats.delay_tx); + priv->reply_agg_tx_stats.delay_tx); pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", - priv->_agn.reply_agg_tx_stats.unknown); + priv->reply_agg_tx_stats.unknown); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index da9048856a3..c27380440b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1391,56 +1391,54 @@ struct iwl_priv { } accum_stats, delta_stats, max_delta_stats; #endif - struct { - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; - /* - * reporting the number of tids has AGG on. 0 means - * no AGGREGATION - */ - u8 agg_tids_count; - - struct iwl_rx_phy_res last_phy_res; - bool last_phy_res_valid; - - struct completion firmware_loading_complete; - - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; - - /* - * chain noise reset and gain commands are the - * two extra calibration commands follows the standard - * phy calibration commands - */ - u8 phy_calib_chain_noise_reset_cmd; - u8 phy_calib_chain_noise_gain_cmd; - - /* counts reply_tx error */ - struct reply_tx_error_statistics reply_tx_stats; - struct reply_agg_tx_error_statistics reply_agg_tx_stats; - /* notification wait support */ - struct list_head notif_waits; - spinlock_t notif_wait_lock; - wait_queue_head_t notif_waitq; - - /* remain-on-channel offload support */ - struct ieee80211_channel *hw_roc_channel; - struct delayed_work hw_roc_work; - enum nl80211_channel_type hw_roc_chantype; - int hw_roc_duration; - bool hw_roc_setup; - - struct sk_buff *offchan_tx_skb; - int offchan_tx_timeout; - struct ieee80211_channel *offchan_tx_chan; - } _agn; + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; + /* + * reporting the number of tids has AGG on. 0 means + * no AGGREGATION + */ + u8 agg_tids_count; + + struct iwl_rx_phy_res last_phy_res; + bool last_phy_res_valid; + + struct completion firmware_loading_complete; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; + + /* + * chain noise reset and gain commands are the + * two extra calibration commands follows the standard + * phy calibration commands + */ + u8 phy_calib_chain_noise_reset_cmd; + u8 phy_calib_chain_noise_gain_cmd; + + /* counts reply_tx error */ + struct reply_tx_error_statistics reply_tx_stats; + struct reply_agg_tx_error_statistics reply_agg_tx_stats; + /* notification wait support */ + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; + + /* remain-on-channel offload support */ + struct ieee80211_channel *hw_roc_channel; + struct delayed_work hw_roc_work; + enum nl80211_channel_type hw_roc_chantype; + int hw_roc_duration; + bool hw_roc_setup; + + struct sk_buff *offchan_tx_skb; + int offchan_tx_timeout; + struct ieee80211_channel *offchan_tx_chan; /* bt coex */ u8 bt_enable_flag; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f67931d408b..8e314003b63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -170,7 +170,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, int actual_delta, expected_delta, ba_timeout_delta; struct statistics_tx *old; - if (priv->_agn.agg_tids_count) + if (priv->agg_tids_count) return true; old = &priv->statistics.tx; @@ -592,8 +592,8 @@ static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); - priv->_agn.last_phy_res_valid = true; - memcpy(&priv->_agn.last_phy_res, pkt->u.raw, + priv->last_phy_res_valid = true; + memcpy(&priv->last_phy_res, pkt->u.raw, sizeof(struct iwl_rx_phy_res)); } @@ -841,11 +841,11 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, phy_res->cfg_phy_cnt + len); ampdu_status = le32_to_cpu(rx_pkt_status); } else { - if (!priv->_agn.last_phy_res_valid) { + if (!priv->last_phy_res_valid) { IWL_ERR(priv, "MPDU frame without cached PHY data\n"); return; } - phy_res = &priv->_agn.last_phy_res; + phy_res = &priv->last_phy_res; amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); len = le16_to_cpu(amsdu->byte_count); @@ -972,9 +972,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; /* set up notification wait support */ - spin_lock_init(&priv->_agn.notif_wait_lock); - INIT_LIST_HEAD(&priv->_agn.notif_waits); - init_waitqueue_head(&priv->_agn.notif_waitq); + spin_lock_init(&priv->notif_wait_lock); + INIT_LIST_HEAD(&priv->notif_waits); + init_waitqueue_head(&priv->notif_waitq); /* Set up BT Rx handlers */ if (priv->cfg->lib->bt_rx_handler_setup) @@ -991,11 +991,11 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) * even if the RX handler consumes the RXB we have * access to it in the notification wait entry. */ - if (!list_empty(&priv->_agn.notif_waits)) { + if (!list_empty(&priv->notif_waits)) { struct iwl_notification_wait *w; - spin_lock(&priv->_agn.notif_wait_lock); - list_for_each_entry(w, &priv->_agn.notif_waits, list) { + spin_lock(&priv->notif_wait_lock); + list_for_each_entry(w, &priv->notif_waits, list) { if (w->cmd != pkt->hdr.cmd) continue; IWL_DEBUG_RX(priv, @@ -1006,9 +1006,9 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) if (w->fn) w->fn(priv, pkt, w->fn_data); } - spin_unlock(&priv->_agn.notif_wait_lock); + spin_unlock(&priv->notif_wait_lock); - wake_up_all(&priv->_agn.notif_waitq); + wake_up_all(&priv->notif_waitq); } if (priv->pre_rx_handler) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 0505b1ac756..dd6937e9705 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -565,10 +565,10 @@ static void iwl_bg_scan_completed(struct work_struct *work) goto out_settings; } - if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) { + if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) { ieee80211_tx_status_irqsafe(priv->hw, - priv->_agn.offchan_tx_skb); - priv->_agn.offchan_tx_skb = NULL; + priv->offchan_tx_skb); + priv->offchan_tx_skb = NULL; } if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 74343589f28..47486029040 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -510,9 +510,9 @@ void iwl_irq_tasklet(struct iwl_priv *priv) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(priv, CSR_INT, priv->_agn.inta | ~priv->inta_mask); + iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); - inta = priv->_agn.inta; + inta = priv->inta; #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_ISR) { @@ -525,8 +525,8 @@ void iwl_irq_tasklet(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - /* saved interrupt in inta variable now we can reset priv->_agn.inta */ - priv->_agn.inta = 0; + /* saved interrupt in inta variable now we can reset priv->inta */ + priv->inta = 0; /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { @@ -703,16 +703,16 @@ void iwl_irq_tasklet(struct iwl_priv *priv) /* Free dram table */ void iwl_free_isr_ict(struct iwl_priv *priv) { - if (priv->_agn.ict_tbl_vir) { + if (priv->ict_tbl_vir) { dma_free_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - priv->_agn.ict_tbl_vir, - priv->_agn.ict_tbl_dma); - priv->_agn.ict_tbl_vir = NULL; - memset(&priv->_agn.ict_tbl_dma, 0, - sizeof(priv->_agn.ict_tbl_dma)); - memset(&priv->_agn.aligned_ict_tbl_dma, 0, - sizeof(priv->_agn.aligned_ict_tbl_dma)); + priv->ict_tbl_vir, + priv->ict_tbl_dma); + priv->ict_tbl_vir = NULL; + memset(&priv->ict_tbl_dma, 0, + sizeof(priv->ict_tbl_dma)); + memset(&priv->aligned_ict_tbl_dma, 0, + sizeof(priv->aligned_ict_tbl_dma)); } } @@ -724,36 +724,36 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) { /* allocate shrared data table */ - priv->_agn.ict_tbl_vir = + priv->ict_tbl_vir = dma_alloc_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &priv->_agn.ict_tbl_dma, GFP_KERNEL); - if (!priv->_agn.ict_tbl_vir) + &priv->ict_tbl_dma, GFP_KERNEL); + if (!priv->ict_tbl_vir) return -ENOMEM; /* align table to PAGE_SIZE boundary */ - priv->_agn.aligned_ict_tbl_dma = - ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE); + priv->aligned_ict_tbl_dma = + ALIGN(priv->ict_tbl_dma, PAGE_SIZE); IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)priv->_agn.ict_tbl_dma, - (unsigned long long)priv->_agn.aligned_ict_tbl_dma, - (int)(priv->_agn.aligned_ict_tbl_dma - - priv->_agn.ict_tbl_dma)); + (unsigned long long)priv->ict_tbl_dma, + (unsigned long long)priv->aligned_ict_tbl_dma, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); - priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir + - (priv->_agn.aligned_ict_tbl_dma - - priv->_agn.ict_tbl_dma); + priv->ict_tbl = priv->ict_tbl_vir + + (priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma); IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", - priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir, - (int)(priv->_agn.aligned_ict_tbl_dma - - priv->_agn.ict_tbl_dma)); + priv->ict_tbl, priv->ict_tbl_vir, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); /* reset table and index to all 0 */ - memset(priv->_agn.ict_tbl_vir, 0, + memset(priv->ict_tbl_vir, 0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - priv->_agn.ict_index = 0; + priv->ict_index = 0; /* add periodic RX interrupt */ priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; @@ -768,15 +768,15 @@ int iwl_reset_ict(struct iwl_priv *priv) u32 val; unsigned long flags; - if (!priv->_agn.ict_tbl_vir) + if (!priv->ict_tbl_vir) return 0; spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); - memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT; + val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; @@ -784,11 +784,11 @@ int iwl_reset_ict(struct iwl_priv *priv) IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " "aligned dma address %Lx\n", val, - (unsigned long long)priv->_agn.aligned_ict_tbl_dma); + (unsigned long long)priv->aligned_ict_tbl_dma); iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); - priv->_agn.use_ict = true; - priv->_agn.ict_index = 0; + priv->use_ict = true; + priv->ict_index = 0; iwl_write32(priv, CSR_INT, priv->inta_mask); iwl_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -802,7 +802,7 @@ void iwl_disable_ict(struct iwl_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - priv->_agn.use_ict = false; + priv->use_ict = false; spin_unlock_irqrestore(&priv->lock, flags); } @@ -852,12 +852,12 @@ static irqreturn_t iwl_isr(int irq, void *data) } #endif - priv->_agn.inta |= inta; + priv->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&priv->irq_tasklet); else if (test_bit(STATUS_INT_ENABLED, &priv->status) && - !priv->_agn.inta) + !priv->inta) iwl_enable_interrupts(priv); unplugged: @@ -867,7 +867,7 @@ static irqreturn_t iwl_isr(int irq, void *data) none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) iwl_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -895,7 +895,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* dram interrupt table not set yet, * use legacy interrupt. */ - if (!priv->_agn.use_ict) + if (!priv->use_ict) return iwl_isr(irq, data); spin_lock_irqsave(&priv->lock, flags); @@ -912,21 +912,21 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ - if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) { + if (!priv->ict_tbl[priv->ict_index]) { IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); goto none; } /* read all entries that not 0 start with ict_index */ - while (priv->_agn.ict_tbl[priv->_agn.ict_index]) { + while (priv->ict_tbl[priv->ict_index]) { - val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]); + val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", - priv->_agn.ict_index, + priv->ict_index, le32_to_cpu( - priv->_agn.ict_tbl[priv->_agn.ict_index])); - priv->_agn.ict_tbl[priv->_agn.ict_index] = 0; - priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index, + priv->ict_tbl[priv->ict_index])); + priv->ict_tbl[priv->ict_index] = 0; + priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, ICT_COUNT); } @@ -950,13 +950,13 @@ irqreturn_t iwl_isr_ict(int irq, void *data) inta, inta_mask, val); inta &= priv->inta_mask; - priv->_agn.inta |= inta; + priv->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&priv->irq_tasklet); else if (test_bit(STATUS_INT_ENABLED, &priv->status) && - !priv->_agn.inta) { + !priv->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, * tasklet will enable it. @@ -971,7 +971,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) iwl_enable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); -- cgit v1.2.3-70-g09d2 From c8ac61cf6e53fefb3b439fc58390fb65d2730e63 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 15 Jul 2011 13:23:45 -0700 Subject: iwlagn: implement WoWLAN Implement WoWLAN support in iwlagn. The device supports a number of wakeup triggers and can do GTK rekeying when asleep (if HW crypto is used). Unfortunately, we need to disconnect from the AP after resume since we can't yet get all the info out of the wowlan uCode to stay connected safely. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 + drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 21 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 517 ++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-commands.h | 128 ++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 6 +- drivers/net/wireless/iwlwifi/iwl-csr.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 15 + drivers/net/wireless/iwlwifi/iwl-dev.h | 12 +- drivers/net/wireless/iwlwifi/iwl-power.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 6 + 11 files changed, 705 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e77f91380a4..3bee0f119bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -400,6 +400,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct ieee80211_tx_info *info; struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + struct ieee80211_hdr *hdr; struct iwl_tx_info *txb; u32 status = le16_to_cpu(tx_resp->status.status); int tid; @@ -426,6 +427,11 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) IWLAGN_TX_RES_RA_POS; spin_lock_irqsave(&priv->sta_lock, flags); + + hdr = (void *)txb->skb->data; + if (!ieee80211_is_data_qos(hdr->frame_control)) + priv->last_seq_ctl = tx_resp->seq_ctl; + if (txq->sched_retry) { const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); struct iwl_ht_agg *agg; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 71487487d60..d78a4659dbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -855,6 +855,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, iwl_wake_any_queue(priv, ctx); } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + + if (ctx->ctxid == IWL_RXON_CTX_BSS) + priv->have_rekey_data = false; } iwlagn_bt_coex_rssi_monitor(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 946d3a16e49..a895a099d08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -513,14 +513,21 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return -EIO; } - ret = iwl_verify_ucode(priv, image); - if (ret) { - priv->ucode_type = old_type; - return ret; - } + /* + * This step takes a long time (60-80ms!!) and + * WoWLAN image should be loaded quickly, so + * skip it for WoWLAN. + */ + if (ucode_type != IWL_UCODE_WOWLAN) { + ret = iwl_verify_ucode(priv, image); + if (ret) { + priv->ucode_type = old_type; + return ret; + } - /* delay a bit to give rfkill time to run */ - msleep(5); + /* delay a bit to give rfkill time to run */ + msleep(5); + } ret = iwlagn_alive_notify(priv); if (ret) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0bab1956339..299acb491f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -593,6 +593,7 @@ static void iwl_dealloc_ucode(struct iwl_priv *priv) { iwl_free_fw_img(priv, &priv->ucode_rt); iwl_free_fw_img(priv, &priv->ucode_init); + iwl_free_fw_img(priv, &priv->ucode_wowlan); } static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, @@ -662,8 +663,9 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) } struct iwlagn_firmware_pieces { - const void *inst, *data, *init, *init_data; - size_t inst_size, data_size, init_size, init_data_size; + const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; + size_t inst_size, data_size, init_size, init_data_size, + wowlan_inst_size, wowlan_data_size; u32 build; @@ -902,6 +904,14 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, goto invalid_tlv_len; priv->enhance_sensitivity_table = true; break; + case IWL_UCODE_TLV_WOWLAN_INST: + pieces->wowlan_inst = tlv_data; + pieces->wowlan_inst_size = tlv_len; + break; + case IWL_UCODE_TLV_WOWLAN_DATA: + pieces->wowlan_data = tlv_data; + pieces->wowlan_data_size = tlv_len; + break; case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: if (tlv_len != sizeof(u32)) goto invalid_tlv_len; @@ -1096,6 +1106,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto err_pci_alloc; } + /* WoWLAN instructions and data */ + if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { + if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.code, + pieces.wowlan_inst, + pieces.wowlan_inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.data, + pieces.wowlan_data, + pieces.wowlan_data_size)) + goto err_pci_alloc; + } + /* Now that we can no longer fail, copy information */ /* @@ -1698,7 +1720,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Configure Tx antenna selection based on H/W config */ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); - if (iwl_is_associated_ctx(ctx)) { + if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ @@ -1713,7 +1735,10 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_set_rxon_chain(priv, ctx); } - iwl_reset_run_time_calib(priv); + if (!priv->wowlan) { + /* WoWLAN ucode will not reply in the same way, skip it */ + iwl_reset_run_time_calib(priv); + } set_bit(STATUS_READY, &priv->status); @@ -2153,6 +2178,23 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; + if (priv->ucode_wowlan.code.len && device_can_wakeup(priv->bus->dev)) { + hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_RFKILL_RELEASE; + if (!iwlagn_mod_params.sw_crypto) + hw->wiphy->wowlan.flags |= + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE; + + hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS; + hw->wiphy->wowlan.pattern_min_len = + IWLAGN_WOWLAN_MIN_PATTERN_LEN; + hw->wiphy->wowlan.pattern_max_len = + IWLAGN_WOWLAN_MAX_PATTERN_LEN; + } + if (iwlagn_mod_params.power_save) hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; else @@ -2237,6 +2279,467 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "leave\n"); } +static int iwlagn_send_patterns(struct iwl_priv *priv, + struct cfg80211_wowlan *wowlan) +{ + struct iwlagn_wowlan_patterns_cmd *pattern_cmd; + struct iwl_host_cmd cmd = { + .id = REPLY_WOWLAN_PATTERNS, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + .flags = CMD_SYNC, + }; + int i, err; + + if (!wowlan->n_patterns) + return 0; + + cmd.len[0] = sizeof(*pattern_cmd) + + wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern); + + pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); + if (!pattern_cmd) + return -ENOMEM; + + pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns); + + for (i = 0; i < wowlan->n_patterns; i++) { + int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); + + memcpy(&pattern_cmd->patterns[i].mask, + wowlan->patterns[i].mask, mask_len); + memcpy(&pattern_cmd->patterns[i].pattern, + wowlan->patterns[i].pattern, + wowlan->patterns[i].pattern_len); + pattern_cmd->patterns[i].mask_size = mask_len; + pattern_cmd->patterns[i].pattern_size = + wowlan->patterns[i].pattern_len; + } + + cmd.data[0] = pattern_cmd; + err = trans_send_cmd(&priv->trans, &cmd); + kfree(pattern_cmd); + return err; +} + +static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_gtk_rekey_data *data) +{ + struct iwl_priv *priv = hw->priv; + + if (iwlagn_mod_params.sw_crypto) + return; + + mutex_lock(&priv->mutex); + + if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) + goto out; + + memcpy(priv->kek, data->kek, NL80211_KEK_LEN); + memcpy(priv->kck, data->kck, NL80211_KCK_LEN); + priv->replay_ctr = cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr)); + priv->have_rekey_data = true; + + out: + mutex_unlock(&priv->mutex); +} + +struct wowlan_key_data { + struct iwl_rxon_context *ctx; + struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc; + struct iwlagn_wowlan_tkip_params_cmd *tkip; + const u8 *bssid; + bool error, use_rsc_tsc, use_tkip; +}; + +static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) +{ + int i; + + for (i = 0; i < IWLAGN_P1K_SIZE; i++) + out[i] = cpu_to_le16(p1k[i]); +} + +static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *_data) +{ + struct iwl_priv *priv = hw->priv; + struct wowlan_key_data *data = _data; + struct iwl_rxon_context *ctx = data->ctx; + struct aes_sc *aes_sc, *aes_tx_sc = NULL; + struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL; + struct iwlagn_p1k_cache *rx_p1ks; + u8 *rx_mic_key; + struct ieee80211_key_seq seq; + u32 cur_rx_iv32 = 0; + u16 p1k[IWLAGN_P1K_SIZE]; + int ret, i; + + mutex_lock(&priv->mutex); + + if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) && + !sta && !ctx->key_mapping_keys) + ret = iwl_set_default_wep_key(priv, ctx, key); + else + ret = iwl_set_dynamic_key(priv, ctx, key, sta); + + if (ret) { + IWL_ERR(priv, "Error setting key during suspend!\n"); + data->error = true; + } + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + if (sta) { + tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; + tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc; + + rx_p1ks = data->tkip->rx_uni; + + ieee80211_get_key_tx_seq(key, &seq); + tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16); + tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32); + + ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k); + iwlagn_convert_p1k(p1k, data->tkip->tx.p1k); + + memcpy(data->tkip->mic_keys.tx, + &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], + IWLAGN_MIC_KEY_SIZE); + + rx_mic_key = data->tkip->mic_keys.rx_unicast; + } else { + tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc; + rx_p1ks = data->tkip->rx_multi; + rx_mic_key = data->tkip->mic_keys.rx_mcast; + } + + /* + * For non-QoS this relies on the fact that both the uCode and + * mac80211 use TID 0 (as they need to to avoid replay attacks) + * for checking the IV in the frames. + */ + for (i = 0; i < IWLAGN_NUM_RSC; i++) { + ieee80211_get_key_rx_seq(key, i, &seq); + tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16); + tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32); + /* wrapping isn't allowed, AP must rekey */ + if (seq.tkip.iv32 > cur_rx_iv32) + cur_rx_iv32 = seq.tkip.iv32; + } + + ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k); + iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k); + ieee80211_get_tkip_rx_p1k(key, data->bssid, + cur_rx_iv32 + 1, p1k); + iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k); + + memcpy(rx_mic_key, + &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], + IWLAGN_MIC_KEY_SIZE); + + data->use_tkip = true; + data->use_rsc_tsc = true; + break; + case WLAN_CIPHER_SUITE_CCMP: + if (sta) { + u8 *pn = seq.ccmp.pn; + + aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; + aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; + + ieee80211_get_key_tx_seq(key, &seq); + aes_tx_sc->pn = cpu_to_le64( + (u64)pn[5] | + ((u64)pn[4] << 8) | + ((u64)pn[3] << 16) | + ((u64)pn[2] << 24) | + ((u64)pn[1] << 32) | + ((u64)pn[0] << 40)); + } else + aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; + + /* + * For non-QoS this relies on the fact that both the uCode and + * mac80211 use TID 0 for checking the IV in the frames. + */ + for (i = 0; i < IWLAGN_NUM_RSC; i++) { + u8 *pn = seq.ccmp.pn; + + ieee80211_get_key_rx_seq(key, i, &seq); + aes_sc->pn = cpu_to_le64( + (u64)pn[5] | + ((u64)pn[4] << 8) | + ((u64)pn[3] << 16) | + ((u64)pn[2] << 24) | + ((u64)pn[1] << 32) | + ((u64)pn[0] << 40)); + } + data->use_rsc_tsc = true; + break; + } + + mutex_unlock(&priv->mutex); +} + +static int iwlagn_mac_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct iwl_priv *priv = hw->priv; + struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd; + struct iwl_rxon_cmd rxon; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; + struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; + struct wowlan_key_data key_data = { + .ctx = ctx, + .bssid = ctx->active.bssid_addr, + .use_rsc_tsc = false, + .tkip = &tkip_cmd, + .use_tkip = false, + }; + int ret, i; + u16 seq; + + if (WARN_ON(!wowlan)) + return -EINVAL; + + mutex_lock(&priv->mutex); + + /* Don't attempt WoWLAN when not associated, tear down instead. */ + if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || + !iwl_is_associated_ctx(ctx)) { + ret = 1; + goto out; + } + + key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); + if (!key_data.rsc_tsc) { + ret = -ENOMEM; + goto out; + } + + memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd)); + + /* + * We know the last used seqno, and the uCode expects to know that + * one, it will increment before TX. + */ + seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ; + wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq); + + /* + * For QoS counters, we store the one to use next, so subtract 0x10 + * since the uCode will add 0x10 before using the value. + */ + for (i = 0; i < 8; i++) { + seq = priv->stations[IWL_AP_ID].tid[i].seq_number; + seq -= 0x10; + wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); + } + + if (wowlan->disconnect) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS | + IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE); + if (wowlan->magic_pkt) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET); + if (wowlan->gtk_rekey_failure) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL); + if (wowlan->eap_identity_req) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ); + if (wowlan->four_way_handshake) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE); + if (wowlan->rfkill_release) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_RFKILL); + if (wowlan->n_patterns) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH); + + iwl_scan_cancel_timeout(priv, 200); + + memcpy(&rxon, &ctx->active, sizeof(rxon)); + + trans_stop_device(&priv->trans); + + priv->wowlan = true; + + ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan, + IWL_UCODE_WOWLAN); + if (ret) + goto error; + + /* now configure WoWLAN ucode */ + ret = iwl_alive_start(priv); + if (ret) + goto error; + + memcpy(&ctx->staging, &rxon, sizeof(rxon)); + ret = iwlagn_commit_rxon(priv, ctx); + if (ret) + goto error; + + ret = iwl_power_update_mode(priv, true); + if (ret) + goto error; + + if (!iwlagn_mod_params.sw_crypto) { + /* mark all keys clear */ + priv->ucode_key_table = 0; + ctx->key_mapping_keys = 0; + + /* + * This needs to be unlocked due to lock ordering + * constraints. Since we're in the suspend path + * that isn't really a problem though. + */ + mutex_unlock(&priv->mutex); + ieee80211_iter_keys(priv->hw, ctx->vif, + iwlagn_wowlan_program_keys, + &key_data); + mutex_lock(&priv->mutex); + if (key_data.error) { + ret = -EIO; + goto error; + } + + if (key_data.use_rsc_tsc) { + struct iwl_host_cmd rsc_tsc_cmd = { + .id = REPLY_WOWLAN_TSC_RSC_PARAMS, + .flags = CMD_SYNC, + .data[0] = key_data.rsc_tsc, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + .len[0] = sizeof(*key_data.rsc_tsc), + }; + + ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd); + if (ret) + goto error; + } + + if (key_data.use_tkip) { + ret = trans_send_cmd_pdu(&priv->trans, + REPLY_WOWLAN_TKIP_PARAMS, + CMD_SYNC, sizeof(tkip_cmd), + &tkip_cmd); + if (ret) + goto error; + } + + if (priv->have_rekey_data) { + memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd)); + memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN); + kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN); + memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN); + kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); + kek_kck_cmd.replay_ctr = priv->replay_ctr; + + ret = trans_send_cmd_pdu(&priv->trans, + REPLY_WOWLAN_KEK_KCK_MATERIAL, + CMD_SYNC, sizeof(kek_kck_cmd), + &kek_kck_cmd); + if (ret) + goto error; + } + } + + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER, + CMD_SYNC, sizeof(wakeup_filter_cmd), + &wakeup_filter_cmd); + if (ret) + goto error; + + ret = iwlagn_send_patterns(priv, wowlan); + if (ret) + goto error; + + device_set_wakeup_enable(priv->bus->dev, true); + + /* Now let the ucode operate on its own */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + + goto out; + + error: + priv->wowlan = false; + iwlagn_prepare_restart(priv); + ieee80211_restart_hw(priv->hw); + out: + mutex_unlock(&priv->mutex); + kfree(key_data.rsc_tsc); + return ret; +} + +static int iwlagn_mac_resume(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif; + unsigned long flags; + u32 base, status = 0xffffffff; + int ret = -EIO; + + mutex_lock(&priv->mutex); + + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + + base = priv->device_pointers.error_event_table; + if (iwlagn_hw_valid_rtc_data_addr(base)) { + spin_lock_irqsave(&priv->reg_lock, flags); + ret = iwl_grab_nic_access_silent(priv); + if (ret == 0) { + iwl_write32(priv, HBUS_TARG_MEM_RADDR, base); + status = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, flags); + +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (ret == 0) { + if (!priv->wowlan_sram) + priv->wowlan_sram = + kzalloc(priv->ucode_wowlan.data.len, + GFP_KERNEL); + + if (priv->wowlan_sram) + _iwl_read_targ_mem_words( + priv, 0x800000, priv->wowlan_sram, + priv->ucode_wowlan.data.len / 4); + } +#endif + } + + /* we'll clear ctx->vif during iwlagn_prepare_restart() */ + vif = ctx->vif; + + priv->wowlan = false; + + device_set_wakeup_enable(priv->bus->dev, false); + + iwlagn_prepare_restart(priv); + + memset((void *)&ctx->active, 0, sizeof(ctx->active)); + iwl_connection_init_rx_config(priv, ctx); + iwlagn_set_rxon_chain(priv, ctx); + + mutex_unlock(&priv->mutex); + + ieee80211_resume_disconnect(vif); + + return 1; +} + static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; @@ -2926,6 +3429,9 @@ static void iwl_uninit_drv(struct iwl_priv *priv) iwl_free_channel_map(priv); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); +#ifdef CONFIG_IWLWIFI_DEBUGFS + kfree(priv->wowlan_sram); +#endif } static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, @@ -2955,6 +3461,8 @@ struct ieee80211_ops iwlagn_hw_ops = { .tx = iwlagn_mac_tx, .start = iwlagn_mac_start, .stop = iwlagn_mac_stop, + .suspend = iwlagn_mac_suspend, + .resume = iwlagn_mac_resume, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .change_interface = iwl_mac_change_interface, @@ -2962,6 +3470,7 @@ struct ieee80211_ops iwlagn_hw_ops = { .configure_filter = iwlagn_configure_filter, .set_key = iwlagn_mac_set_key, .update_tkip_key = iwlagn_mac_update_tkip_key, + .set_rekey_data = iwlagn_mac_set_rekey_data, .conf_tx = iwl_mac_conf_tx, .bss_info_changed = iwlagn_bss_info_changed, .ampdu_action = iwlagn_mac_ampdu_action, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index b58985373a7..5769ca5cebc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -188,6 +188,13 @@ enum { REPLY_WIPAN_NOA_NOTIFICATION = 0xbc, REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd, + REPLY_WOWLAN_PATTERNS = 0xe0, + REPLY_WOWLAN_WAKEUP_FILTER = 0xe1, + REPLY_WOWLAN_TSC_RSC_PARAMS = 0xe2, + REPLY_WOWLAN_TKIP_PARAMS = 0xe3, + REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4, + REPLY_WOWLAN_GET_STATUS = 0xe5, + REPLY_MAX = 0xff }; @@ -3764,6 +3771,127 @@ struct iwl_bt_coex_prot_env_cmd { u8 reserved[2]; } __attribute__((packed)); +/* + * REPLY_WOWLAN_PATTERNS + */ +#define IWLAGN_WOWLAN_MIN_PATTERN_LEN 16 +#define IWLAGN_WOWLAN_MAX_PATTERN_LEN 128 + +struct iwlagn_wowlan_pattern { + u8 mask[IWLAGN_WOWLAN_MAX_PATTERN_LEN / 8]; + u8 pattern[IWLAGN_WOWLAN_MAX_PATTERN_LEN]; + u8 mask_size; + u8 pattern_size; + __le16 reserved; +} __packed; + +#define IWLAGN_WOWLAN_MAX_PATTERNS 20 + +struct iwlagn_wowlan_patterns_cmd { + __le32 n_patterns; + struct iwlagn_wowlan_pattern patterns[]; +} __packed; + +/* + * REPLY_WOWLAN_WAKEUP_FILTER + */ +enum iwlagn_wowlan_wakeup_filters { + IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0), + IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1), + IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2), + IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3), + IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4), + IWLAGN_WOWLAN_WAKEUP_RFKILL = BIT(5), + IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR = BIT(6), + IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(7), + IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(8), + IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(9), + IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(10), +}; + +struct iwlagn_wowlan_wakeup_filter_cmd { + __le32 enabled; + __le16 non_qos_seq; + u8 min_sleep_seconds; + u8 reserved; + __le16 qos_seq[8]; +}; + +/* + * REPLY_WOWLAN_TSC_RSC_PARAMS + */ +#define IWLAGN_NUM_RSC 16 + +struct tkip_sc { + __le16 iv16; + __le16 pad; + __le32 iv32; +} __packed; + +struct iwlagn_tkip_rsc_tsc { + struct tkip_sc unicast_rsc[IWLAGN_NUM_RSC]; + struct tkip_sc multicast_rsc[IWLAGN_NUM_RSC]; + struct tkip_sc tsc; +} __packed; + +struct aes_sc { + __le64 pn; +} __packed; + +struct iwlagn_aes_rsc_tsc { + struct aes_sc unicast_rsc[IWLAGN_NUM_RSC]; + struct aes_sc multicast_rsc[IWLAGN_NUM_RSC]; + struct aes_sc tsc; +} __packed; + +union iwlagn_all_tsc_rsc { + struct iwlagn_tkip_rsc_tsc tkip; + struct iwlagn_aes_rsc_tsc aes; +}; + +struct iwlagn_wowlan_rsc_tsc_params_cmd { + union iwlagn_all_tsc_rsc all_tsc_rsc; +} __packed; + +/* + * REPLY_WOWLAN_TKIP_PARAMS + */ +#define IWLAGN_MIC_KEY_SIZE 8 +#define IWLAGN_P1K_SIZE 5 +struct iwlagn_mic_keys { + u8 tx[IWLAGN_MIC_KEY_SIZE]; + u8 rx_unicast[IWLAGN_MIC_KEY_SIZE]; + u8 rx_mcast[IWLAGN_MIC_KEY_SIZE]; +} __packed; + +struct iwlagn_p1k_cache { + __le16 p1k[IWLAGN_P1K_SIZE]; +} __packed; + +#define IWLAGN_NUM_RX_P1K_CACHE 2 + +struct iwlagn_wowlan_tkip_params_cmd { + struct iwlagn_mic_keys mic_keys; + struct iwlagn_p1k_cache tx; + struct iwlagn_p1k_cache rx_uni[IWLAGN_NUM_RX_P1K_CACHE]; + struct iwlagn_p1k_cache rx_multi[IWLAGN_NUM_RX_P1K_CACHE]; +} __packed; + +/* + * REPLY_WOWLAN_KEK_KCK_MATERIAL + */ + +#define IWLAGN_KCK_MAX_SIZE 32 +#define IWLAGN_KEK_MAX_SIZE 32 + +struct iwlagn_wowlan_kek_kck_material_cmd { + u8 kck[IWLAGN_KCK_MAX_SIZE]; + u8 kek[IWLAGN_KEK_MAX_SIZE]; + __le16 kck_len; + __le16 kek_len; + __le64 replay_ctr; +} __packed; + /****************************************************************************** * (13) * Union of all expected notifications/responses: diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9b9f462ea0f..2f42547622d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1903,8 +1903,12 @@ int iwl_suspend(struct iwl_priv *priv) * first but since iwl_mac_stop() has no knowledge of who the caller is, * it will not call apm_ops.stop() to stop the DMA operation. * Calling apm_ops.stop here to make sure we stop the DMA. + * + * But of course ... if we have configured WoWLAN then we did other + * things already :-) */ - iwl_apm_stop(priv); + if (!priv->wowlan) + iwl_apm_stop(priv); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 5ab90ba7a02..d6dbb042304 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -351,6 +351,7 @@ #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) +#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE (0x00000020) /* GP Driver */ #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 17aebf08dff..ec1485b2d3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -322,6 +322,19 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + + if (!priv->wowlan_sram) + return -ENODATA; + + return simple_read_from_buffer(user_buf, count, ppos, + priv->wowlan_sram, + priv->ucode_wowlan.data.len); +} static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -856,6 +869,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, } DEBUGFS_READ_WRITE_FILE_OPS(sram); +DEBUGFS_READ_FILE_OPS(wowlan_sram); DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); @@ -2667,6 +2681,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c27380440b6..fc238734245 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -551,7 +551,8 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, - /* 16 and 17 reserved for future use */ + IWL_UCODE_TLV_WOWLAN_INST = 16, + IWL_UCODE_TLV_WOWLAN_DATA = 17, IWL_UCODE_TLV_FLAGS = 18, }; @@ -1284,6 +1285,7 @@ struct iwl_priv { struct fw_img ucode_rt; struct fw_img ucode_init; + struct fw_img ucode_wowlan; enum iwlagn_ucode_type ucode_type; u8 ucode_write_complete; /* the image write is complete */ @@ -1356,6 +1358,8 @@ struct iwl_priv { u8 mac80211_registered; + bool wowlan; + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; @@ -1508,6 +1512,7 @@ struct iwl_priv { struct dentry *debugfs_dir; u32 dbgfs_sram_offset, dbgfs_sram_len; bool disable_ht40; + void *wowlan_sram; #endif /* CONFIG_IWLWIFI_DEBUGFS */ struct work_struct txpower_work; @@ -1528,6 +1533,11 @@ struct iwl_priv { u32 tm_fixed_rate; #endif + /* WoWLAN GTK rekey data */ + u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; + __le64 replay_ctr; + __le16 last_seq_ctl; + bool have_rekey_data; }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index de4f33304ed..3ec619c6881 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -347,7 +347,9 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) + if (priv->wowlan) + iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); + else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (iwl_tt_is_low_power_state(priv)) { /* in thermal throttling low power state */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 27f78fed2ec..a6b2b1db0b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -866,6 +866,12 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); + IWL_CMD(REPLY_WOWLAN_PATTERNS); + IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER); + IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS); + IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS); + IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL); + IWL_CMD(REPLY_WOWLAN_GET_STATUS); default: return "UNKNOWN"; -- cgit v1.2.3-70-g09d2 From bbb05cb55a1b57003b17d47b5a7ac809bab60f80 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Jul 2011 01:59:22 -0700 Subject: iwlagn: track beacon interval sent to device Sometimes, when mac80211 changes the beacon interval or when it isn't yet set in mac80211 before association, the uCode will sysassert because we send it confusing RXON timing vs. PAN parameters. To fix this, track the last beacon interval sent to the device and use that in PAN parameter calculations. This fixes a bug during P2P group formation as a client (and possibly association to a regular AP) while connected to another AP. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 11 +++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/iwl-dev.h') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index d78a4659dbf..d42ef1763a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -342,7 +342,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) slot1 = priv->hw_roc_duration; slot0 = IWL_MIN_SLOT_TIME; } else if (ctx_bss->vif && ctx_pan->vif) { - int bcnint = ctx_pan->vif->bss_conf.beacon_int; + int bcnint = ctx_pan->beacon_int; int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; /* should be set, but seems unused?? */ @@ -350,14 +350,13 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) if (ctx_pan->vif->type == NL80211_IFTYPE_AP && bcnint && - bcnint != ctx_bss->vif->bss_conf.beacon_int) { + bcnint != ctx_bss->beacon_int) { IWL_ERR(priv, "beacon intervals don't match (%d, %d)\n", - ctx_bss->vif->bss_conf.beacon_int, - ctx_pan->vif->bss_conf.beacon_int); + ctx_bss->beacon_int, ctx_pan->beacon_int); } else bcnint = max_t(int, bcnint, - ctx_bss->vif->bss_conf.beacon_int); + ctx_bss->beacon_int); if (!bcnint) bcnint = DEFAULT_BEACON_INTERVAL; slot0 = bcnint / 2; @@ -376,7 +375,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) } else if (ctx_pan->vif) { slot0 = 0; slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * - ctx_pan->vif->bss_conf.beacon_int; + ctx_pan->beacon_int; slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); if (test_bit(STATUS_SCAN_HW, &priv->status)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2f42547622d..cf376f62b2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -363,6 +363,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } + ctx->beacon_int = beacon_int; + tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ interval_tm = beacon_int * TIME_UNIT; rem = do_div(tsf, interval_tm); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fc238734245..8da38bef356 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1152,6 +1152,8 @@ struct iwl_rxon_context { __le32 station_flags; + int beacon_int; + struct { bool non_gf_sta_present; u8 protection; -- cgit v1.2.3-70-g09d2