aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-03-21 08:30:03 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-04-13 02:35:47 -0400
commitf14d6b39c0b3519f8148e1371d2149c148893b61 (patch)
tree6fecbc98089f64d552cd23a7a70ab7f599568d9d /drivers/net/wireless
parent9a75b3df18477ef3bd16509bc05e83a7ce6a8019 (diff)
iwlwifi: pcie: implement GRO without NAPI
Use the new NAPI infrastructure added to mac80211 to get GRO. We don't really implement NAPI since we don't have a real poll function and we never schedule a NAPI poll. Instead of this, we collect all the packets we got from a single interrupt and then call napi_gro_flush(). This allows us to benefit from GRO. In half duplex medium like WiFi, its main advantage is that it reduces the number of TCP Acks, hence improving the TCP Rx performance. Since we call the Rx path with a spinlock held, remove the might_sleep mention from the op_mode's API. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Reviewed-by: Ido Yariv <ido@wizery.com> [Squash different patches and rewrite the commit message] Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h25
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c4
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h3
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c17
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c21
8 files changed, 86 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 6a6df71af1d7..6a00353768f3 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -2053,6 +2053,17 @@ static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
2053 return false; 2053 return false;
2054} 2054}
2055 2055
2056static void iwl_napi_add(struct iwl_op_mode *op_mode,
2057 struct napi_struct *napi,
2058 struct net_device *napi_dev,
2059 int (*poll)(struct napi_struct *, int),
2060 int weight)
2061{
2062 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2063
2064 ieee80211_napi_add(priv->hw, napi, napi_dev, poll, weight);
2065}
2066
2056static const struct iwl_op_mode_ops iwl_dvm_ops = { 2067static const struct iwl_op_mode_ops iwl_dvm_ops = {
2057 .start = iwl_op_mode_dvm_start, 2068 .start = iwl_op_mode_dvm_start,
2058 .stop = iwl_op_mode_dvm_stop, 2069 .stop = iwl_op_mode_dvm_stop,
@@ -2065,6 +2076,7 @@ static const struct iwl_op_mode_ops iwl_dvm_ops = {
2065 .cmd_queue_full = iwl_cmd_queue_full, 2076 .cmd_queue_full = iwl_cmd_queue_full,
2066 .nic_config = iwl_nic_config, 2077 .nic_config = iwl_nic_config,
2067 .wimax_active = iwl_wimax_active, 2078 .wimax_active = iwl_wimax_active,
2079 .napi_add = iwl_napi_add,
2068}; 2080};
2069 2081
2070/***************************************************************************** 2082/*****************************************************************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index ea29504ac617..99785c892f96 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -63,6 +63,7 @@
63#ifndef __iwl_op_mode_h__ 63#ifndef __iwl_op_mode_h__
64#define __iwl_op_mode_h__ 64#define __iwl_op_mode_h__
65 65
66#include <linux/netdevice.h>
66#include <linux/debugfs.h> 67#include <linux/debugfs.h>
67 68
68struct iwl_op_mode; 69struct iwl_op_mode;
@@ -112,8 +113,11 @@ struct iwl_cfg;
112 * @stop: stop the op_mode. Must free all the memory allocated. 113 * @stop: stop the op_mode. Must free all the memory allocated.
113 * May sleep 114 * May sleep
114 * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the 115 * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
115 * HCMD this Rx responds to. 116 * HCMD this Rx responds to. Can't sleep.
116 * This callback may sleep, it is called from a threaded IRQ handler. 117 * @napi_add: NAPI initialisation. The transport is fully responsible for NAPI,
118 * but the higher layers need to know about it (in particular mac80211 to
119 * to able to call the right NAPI RX functions); this function is needed
120 * to eventually call netif_napi_add() with higher layer involvement.
117 * @queue_full: notifies that a HW queue is full. 121 * @queue_full: notifies that a HW queue is full.
118 * Must be atomic and called with BH disabled. 122 * Must be atomic and called with BH disabled.
119 * @queue_not_full: notifies that a HW queue is not full any more. 123 * @queue_not_full: notifies that a HW queue is not full any more.
@@ -143,6 +147,11 @@ struct iwl_op_mode_ops {
143 void (*stop)(struct iwl_op_mode *op_mode); 147 void (*stop)(struct iwl_op_mode *op_mode);
144 int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, 148 int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
145 struct iwl_device_cmd *cmd); 149 struct iwl_device_cmd *cmd);
150 void (*napi_add)(struct iwl_op_mode *op_mode,
151 struct napi_struct *napi,
152 struct net_device *napi_dev,
153 int (*poll)(struct napi_struct *, int),
154 int weight);
146 void (*queue_full)(struct iwl_op_mode *op_mode, int queue); 155 void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
147 void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); 156 void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
148 bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); 157 bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
@@ -180,7 +189,6 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
180 struct iwl_rx_cmd_buffer *rxb, 189 struct iwl_rx_cmd_buffer *rxb,
181 struct iwl_device_cmd *cmd) 190 struct iwl_device_cmd *cmd)
182{ 191{
183 might_sleep();
184 return op_mode->ops->rx(op_mode, rxb, cmd); 192 return op_mode->ops->rx(op_mode, rxb, cmd);
185} 193}
186 194
@@ -249,4 +257,15 @@ static inline int iwl_op_mode_exit_d0i3(struct iwl_op_mode *op_mode)
249 return op_mode->ops->exit_d0i3(op_mode); 257 return op_mode->ops->exit_d0i3(op_mode);
250} 258}
251 259
260static inline void iwl_op_mode_napi_add(struct iwl_op_mode *op_mode,
261 struct napi_struct *napi,
262 struct net_device *napi_dev,
263 int (*poll)(struct napi_struct *, int),
264 int weight)
265{
266 if (!op_mode->ops->napi_add)
267 return;
268 op_mode->ops->napi_add(op_mode, napi, napi_dev, poll, weight);
269}
270
252#endif /* __iwl_op_mode_h__ */ 271#endif /* __iwl_op_mode_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 9545d7fdd4bf..e436c04083c2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -1183,6 +1183,17 @@ out:
1183 return ret; 1183 return ret;
1184} 1184}
1185 1185
1186static void iwl_mvm_napi_add(struct iwl_op_mode *op_mode,
1187 struct napi_struct *napi,
1188 struct net_device *napi_dev,
1189 int (*poll)(struct napi_struct *, int),
1190 int weight)
1191{
1192 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
1193
1194 ieee80211_napi_add(mvm->hw, napi, napi_dev, poll, weight);
1195}
1196
1186static const struct iwl_op_mode_ops iwl_mvm_ops = { 1197static const struct iwl_op_mode_ops iwl_mvm_ops = {
1187 .start = iwl_op_mode_mvm_start, 1198 .start = iwl_op_mode_mvm_start,
1188 .stop = iwl_op_mode_mvm_stop, 1199 .stop = iwl_op_mode_mvm_stop,
@@ -1196,4 +1207,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops = {
1196 .nic_config = iwl_mvm_nic_config, 1207 .nic_config = iwl_mvm_nic_config,
1197 .enter_d0i3 = iwl_mvm_enter_d0i3, 1208 .enter_d0i3 = iwl_mvm_enter_d0i3,
1198 .exit_d0i3 = iwl_mvm_exit_d0i3, 1209 .exit_d0i3 = iwl_mvm_exit_d0i3,
1210 .napi_add = iwl_mvm_napi_add,
1199}; 1211};
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 6061553a5e44..69f6aa694bfe 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -130,7 +130,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
130 130
131 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); 131 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
132 132
133 ieee80211_rx_ni(mvm->hw, skb); 133 ieee80211_rx(mvm->hw, skb);
134} 134}
135 135
136static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm, 136static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 0a4ad45949d5..ff1b630e130e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -640,7 +640,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
640 info->status.status_driver_data[0] = 640 info->status.status_driver_data[0] =
641 (void *)(uintptr_t)tx_resp->reduced_tpc; 641 (void *)(uintptr_t)tx_resp->reduced_tpc;
642 642
643 ieee80211_tx_status_ni(mvm->hw, skb); 643 ieee80211_tx_status(mvm->hw, skb);
644 } 644 }
645 645
646 if (txq_id >= mvm->first_agg_queue) { 646 if (txq_id >= mvm->first_agg_queue) {
@@ -944,7 +944,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
944 944
945 while (!skb_queue_empty(&reclaimed_skbs)) { 945 while (!skb_queue_empty(&reclaimed_skbs)) {
946 skb = __skb_dequeue(&reclaimed_skbs); 946 skb = __skb_dequeue(&reclaimed_skbs);
947 ieee80211_tx_status_ni(mvm->hw, skb); 947 ieee80211_tx_status(mvm->hw, skb);
948 } 948 }
949 949
950 return 0; 950 return 0;
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 9091513ea738..e2694686ebfc 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -270,6 +270,9 @@ struct iwl_trans_pcie {
270 struct iwl_trans *trans; 270 struct iwl_trans *trans;
271 struct iwl_drv *drv; 271 struct iwl_drv *drv;
272 272
273 struct net_device napi_dev;
274 struct napi_struct napi;
275
273 /* INT ICT Table */ 276 /* INT ICT Table */
274 __le32 *ict_tbl; 277 __le32 *ict_tbl;
275 dma_addr_t ict_tbl_dma; 278 dma_addr_t ict_tbl_dma;
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index fdfa3969cac9..e8e5afcaf42b 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -673,7 +673,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
673 /* Reuse the page if possible. For notification packets and 673 /* Reuse the page if possible. For notification packets and
674 * SKBs that fail to Rx correctly, add them back into the 674 * SKBs that fail to Rx correctly, add them back into the
675 * rx_free list for reuse later. */ 675 * rx_free list for reuse later. */
676 spin_lock(&rxq->lock);
677 if (rxb->page != NULL) { 676 if (rxb->page != NULL) {
678 rxb->page_dma = 677 rxb->page_dma =
679 dma_map_page(trans->dev, rxb->page, 0, 678 dma_map_page(trans->dev, rxb->page, 0,
@@ -694,7 +693,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
694 } 693 }
695 } else 694 } else
696 list_add_tail(&rxb->list, &rxq->rx_used); 695 list_add_tail(&rxb->list, &rxq->rx_used);
697 spin_unlock(&rxq->lock);
698} 696}
699 697
700/* 698/*
@@ -709,6 +707,8 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans)
709 u32 count = 8; 707 u32 count = 8;
710 int total_empty; 708 int total_empty;
711 709
710restart:
711 spin_lock(&rxq->lock);
712 /* uCode's read index (stored in shared DRAM) indicates the last Rx 712 /* uCode's read index (stored in shared DRAM) indicates the last Rx
713 * buffer that the driver may process (last buffer filled by ucode). */ 713 * buffer that the driver may process (last buffer filled by ucode). */
714 r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; 714 r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF;
@@ -743,18 +743,25 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans)
743 count++; 743 count++;
744 if (count >= 8) { 744 if (count >= 8) {
745 rxq->read = i; 745 rxq->read = i;
746 spin_unlock(&rxq->lock);
746 iwl_pcie_rx_replenish_now(trans); 747 iwl_pcie_rx_replenish_now(trans);
747 count = 0; 748 count = 0;
749 goto restart;
748 } 750 }
749 } 751 }
750 } 752 }
751 753
752 /* Backtrack one entry */ 754 /* Backtrack one entry */
753 rxq->read = i; 755 rxq->read = i;
756 spin_unlock(&rxq->lock);
757
754 if (fill_rx) 758 if (fill_rx)
755 iwl_pcie_rx_replenish_now(trans); 759 iwl_pcie_rx_replenish_now(trans);
756 else 760 else
757 iwl_pcie_rxq_restock(trans); 761 iwl_pcie_rxq_restock(trans);
762
763 if (trans_pcie->napi.poll)
764 napi_gro_flush(&trans_pcie->napi, false);
758} 765}
759 766
760/* 767/*
@@ -1068,8 +1075,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
1068 iwl_write8(trans, CSR_INT_PERIODIC_REG, 1075 iwl_write8(trans, CSR_INT_PERIODIC_REG,
1069 CSR_INT_PERIODIC_DIS); 1076 CSR_INT_PERIODIC_DIS);
1070 1077
1071 iwl_pcie_rx_handle(trans);
1072
1073 /* 1078 /*
1074 * Enable periodic interrupt in 8 msec only if we received 1079 * Enable periodic interrupt in 8 msec only if we received
1075 * real RX interrupt (instead of just periodic int), to catch 1080 * real RX interrupt (instead of just periodic int), to catch
@@ -1082,6 +1087,10 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
1082 CSR_INT_PERIODIC_ENA); 1087 CSR_INT_PERIODIC_ENA);
1083 1088
1084 isr_stats->rx++; 1089 isr_stats->rx++;
1090
1091 local_bh_disable();
1092 iwl_pcie_rx_handle(trans);
1093 local_bh_enable();
1085 } 1094 }
1086 1095
1087 /* This "Tx" DMA channel is used only for loading uCode */ 1096 /* This "Tx" DMA channel is used only for loading uCode */
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index dcfd6d866d09..97e6bd826880 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1053,6 +1053,12 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr,
1053 iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); 1053 iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
1054} 1054}
1055 1055
1056static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget)
1057{
1058 WARN_ON(1);
1059 return 0;
1060}
1061
1056static void iwl_trans_pcie_configure(struct iwl_trans *trans, 1062static void iwl_trans_pcie_configure(struct iwl_trans *trans,
1057 const struct iwl_trans_config *trans_cfg) 1063 const struct iwl_trans_config *trans_cfg)
1058{ 1064{
@@ -1079,6 +1085,18 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
1079 1085
1080 trans_pcie->command_names = trans_cfg->command_names; 1086 trans_pcie->command_names = trans_cfg->command_names;
1081 trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; 1087 trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
1088
1089 /* Initialize NAPI here - it should be before registering to mac80211
1090 * in the opmode but after the HW struct is allocated.
1091 * As this function may be called again in some corner cases don't
1092 * do anything if NAPI was already initialized.
1093 */
1094 if (!trans_pcie->napi.poll && trans->op_mode->ops->napi_add) {
1095 init_dummy_netdev(&trans_pcie->napi_dev);
1096 iwl_op_mode_napi_add(trans->op_mode, &trans_pcie->napi,
1097 &trans_pcie->napi_dev,
1098 iwl_pcie_dummy_napi_poll, 64);
1099 }
1082} 1100}
1083 1101
1084void iwl_trans_pcie_free(struct iwl_trans *trans) 1102void iwl_trans_pcie_free(struct iwl_trans *trans)
@@ -1099,6 +1117,9 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
1099 pci_disable_device(trans_pcie->pci_dev); 1117 pci_disable_device(trans_pcie->pci_dev);
1100 kmem_cache_destroy(trans->dev_cmd_pool); 1118 kmem_cache_destroy(trans->dev_cmd_pool);
1101 1119
1120 if (trans_pcie->napi.poll)
1121 netif_napi_del(&trans_pcie->napi);
1122
1102 kfree(trans); 1123 kfree(trans);
1103} 1124}
1104 1125