aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2009-07-16 23:21:04 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:38:07 -0400
commit23b339062f247e0be84eaabb15e17b403c4388b6 (patch)
treea8ceb91545c7ee21ac30350ef6f1b0c84c49d4bd /drivers
parent7595d67a06466cc00e3aae1b86544278b57481ee (diff)
mwl8k: mwl8k_txq_xmit() rework
Various mwl8k_txq_xmit changes: - Extract the QoS field before adding the DMA header. - Only write to tx->status once, and only after all the other descriptor fields have been set. - Do all tx state manipulation under the tx spinlock. - Remove the priv->inconfig check, as all transmit queues will be frozen during config cycles, so we won't ever be asked to transmit if a config cycle is running. - Remove some more dead code. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/mwl8k.c145
1 files changed, 52 insertions, 93 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 65eefe835024..88ba52e13af2 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1257,46 +1257,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1257{ 1257{
1258 struct mwl8k_priv *priv = hw->priv; 1258 struct mwl8k_priv *priv = hw->priv;
1259 struct ieee80211_tx_info *tx_info; 1259 struct ieee80211_tx_info *tx_info;
1260 struct mwl8k_vif *mwl8k_vif;
1260 struct ieee80211_hdr *wh; 1261 struct ieee80211_hdr *wh;
1261 struct mwl8k_tx_queue *txq; 1262 struct mwl8k_tx_queue *txq;
1262 struct mwl8k_tx_desc *tx; 1263 struct mwl8k_tx_desc *tx;
1263 struct mwl8k_dma_data *tr;
1264 struct mwl8k_vif *mwl8k_vif;
1265 dma_addr_t dma; 1264 dma_addr_t dma;
1266 u16 qos = 0; 1265 u32 txstatus;
1267 bool qosframe = false, ampduframe = false; 1266 u8 txdatarate;
1268 bool mcframe = false, eapolframe = false; 1267 u16 qos;
1269 bool amsduframe = false;
1270 __le16 fc;
1271 1268
1272 txq = priv->txq + index; 1269 wh = (struct ieee80211_hdr *)skb->data;
1273 tx = txq->tx_desc_area + txq->tx_tail; 1270 if (ieee80211_is_data_qos(wh->frame_control))
1274 1271 qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
1275 BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); 1272 else
1273 qos = 0;
1276 1274
1277 /*
1278 * Append HW DMA header to start of packet.
1279 */
1280 mwl8k_add_dma_header(skb); 1275 mwl8k_add_dma_header(skb);
1276 wh = &((struct mwl8k_dma_data *)skb->data)->wh;
1281 1277
1282 tx_info = IEEE80211_SKB_CB(skb); 1278 tx_info = IEEE80211_SKB_CB(skb);
1283 mwl8k_vif = MWL8K_VIF(tx_info->control.vif); 1279 mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
1284 tr = (struct mwl8k_dma_data *)skb->data;
1285 wh = &tr->wh;
1286 fc = wh->frame_control;
1287 qosframe = ieee80211_is_data_qos(fc);
1288 mcframe = is_multicast_ether_addr(wh->addr1);
1289 ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
1290 1280
1291 if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 1281 if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1292 u16 seqno = mwl8k_vif->seqno; 1282 u16 seqno = mwl8k_vif->seqno;
1283
1293 wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 1284 wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
1294 wh->seq_ctrl |= cpu_to_le16(seqno << 4); 1285 wh->seq_ctrl |= cpu_to_le16(seqno << 4);
1295 mwl8k_vif->seqno = seqno++ % 4096; 1286 mwl8k_vif->seqno = seqno++ % 4096;
1296 } 1287 }
1297 1288
1298 if (qosframe) 1289 /* Setup firmware control bit fields for each frame type. */
1299 qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); 1290 txstatus = 0;
1291 txdatarate = 0;
1292 if (ieee80211_is_mgmt(wh->frame_control) ||
1293 ieee80211_is_ctl(wh->frame_control)) {
1294 txdatarate = 0;
1295 qos = mwl8k_qos_setbit_eosp(qos);
1296 /* Set Queue size to unspecified */
1297 qos = mwl8k_qos_setbit_qlen(qos, 0xff);
1298 } else if (ieee80211_is_data(wh->frame_control)) {
1299 txdatarate = 1;
1300 if (is_multicast_ether_addr(wh->addr1))
1301 txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
1302
1303 /* Send pkt in an aggregate if AMPDU frame. */
1304 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
1305 qos = mwl8k_qos_setbit_ack(qos,
1306 MWL8K_TXD_ACK_POLICY_BLOCKACK);
1307 else
1308 qos = mwl8k_qos_setbit_ack(qos,
1309 MWL8K_TXD_ACK_POLICY_NORMAL);
1310
1311 if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
1312 qos = mwl8k_qos_setbit_amsdu(qos);
1313 }
1300 1314
1301 dma = pci_map_single(priv->pdev, skb->data, 1315 dma = pci_map_single(priv->pdev, skb->data,
1302 skb->len, PCI_DMA_TODEVICE); 1316 skb->len, PCI_DMA_TODEVICE);
@@ -1304,95 +1318,40 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1304 if (pci_dma_mapping_error(priv->pdev, dma)) { 1318 if (pci_dma_mapping_error(priv->pdev, dma)) {
1305 printk(KERN_DEBUG "%s: failed to dma map skb, " 1319 printk(KERN_DEBUG "%s: failed to dma map skb, "
1306 "dropping TX frame.\n", priv->name); 1320 "dropping TX frame.\n", priv->name);
1307 1321 dev_kfree_skb(skb);
1308 if (skb != NULL)
1309 dev_kfree_skb(skb);
1310 return NETDEV_TX_OK; 1322 return NETDEV_TX_OK;
1311 } 1323 }
1312 1324
1313 /* Set desc header, cpu bit order. */ 1325 spin_lock_bh(&priv->tx_lock);
1314 tx->status = 0;
1315 tx->data_rate = 0;
1316 tx->tx_priority = index;
1317 tx->qos_control = 0;
1318 tx->rate_info = 0;
1319 tx->peer_id = mwl8k_vif->peer_id;
1320
1321 amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
1322
1323 /* Setup firmware control bit fields for each frame type. */
1324 if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
1325 tx->data_rate = 0;
1326 qos = mwl8k_qos_setbit_eosp(qos);
1327 /* Set Queue size to unspecified */
1328 qos = mwl8k_qos_setbit_qlen(qos, 0xff);
1329 } else if (ieee80211_is_data(fc)) {
1330 tx->data_rate = 1;
1331 if (mcframe)
1332 tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX;
1333 1326
1334 /* 1327 txq = priv->txq + index;
1335 * Tell firmware to not send EAPOL pkts in an
1336 * aggregate. Verify against mac80211 tx path. If
1337 * stack turns off AMPDU for an EAPOL frame this
1338 * check will be removed.
1339 */
1340 if (eapolframe) {
1341 qos = mwl8k_qos_setbit_ack(qos,
1342 MWL8K_TXD_ACK_POLICY_NORMAL);
1343 } else {
1344 /* Send pkt in an aggregate if AMPDU frame. */
1345 if (ampduframe)
1346 qos = mwl8k_qos_setbit_ack(qos,
1347 MWL8K_TXD_ACK_POLICY_BLOCKACK);
1348 else
1349 qos = mwl8k_qos_setbit_ack(qos,
1350 MWL8K_TXD_ACK_POLICY_NORMAL);
1351 1328
1352 if (amsduframe) 1329 BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
1353 qos = mwl8k_qos_setbit_amsdu(qos); 1330 txq->tx_skb[txq->tx_tail] = skb;
1354 }
1355 }
1356 1331
1357 /* Convert to little endian */ 1332 tx = txq->tx_desc_area + txq->tx_tail;
1333 tx->data_rate = txdatarate;
1334 tx->tx_priority = index;
1358 tx->qos_control = cpu_to_le16(qos); 1335 tx->qos_control = cpu_to_le16(qos);
1359 tx->status = cpu_to_le32(tx->status);
1360 tx->pkt_phys_addr = cpu_to_le32(dma); 1336 tx->pkt_phys_addr = cpu_to_le32(dma);
1361 tx->pkt_len = cpu_to_le16(skb->len); 1337 tx->pkt_len = cpu_to_le16(skb->len);
1362 1338 tx->rate_info = 0;
1363 txq->tx_skb[txq->tx_tail] = skb; 1339 tx->peer_id = mwl8k_vif->peer_id;
1364
1365 spin_lock_bh(&priv->tx_lock);
1366
1367 tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK |
1368 MWL8K_TXD_STATUS_FW_OWNED);
1369 wmb(); 1340 wmb();
1341 tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
1342
1343 txq->tx_stats.count++;
1370 txq->tx_stats.len++; 1344 txq->tx_stats.len++;
1371 priv->pending_tx_pkts++; 1345 priv->pending_tx_pkts++;
1372 txq->tx_stats.count++;
1373 txq->tx_tail++;
1374 1346
1347 txq->tx_tail++;
1375 if (txq->tx_tail == MWL8K_TX_DESCS) 1348 if (txq->tx_tail == MWL8K_TX_DESCS)
1376 txq->tx_tail = 0; 1349 txq->tx_tail = 0;
1350
1377 if (txq->tx_head == txq->tx_tail) 1351 if (txq->tx_head == txq->tx_tail)
1378 ieee80211_stop_queue(hw, index); 1352 ieee80211_stop_queue(hw, index);
1379 1353
1380 if (priv->inconfig) { 1354 mwl8k_tx_start(priv);
1381 /*
1382 * Silently queue packet when we are in the middle of
1383 * a config cycle. Notify firmware only if we are
1384 * waiting for TXQs to empty. If a packet is sent
1385 * before .config() is complete, perhaps it is better
1386 * to drop the packet, as the channel is being changed
1387 * and the packet will end up on the wrong channel.
1388 */
1389 printk(KERN_ERR "%s(): WARNING TX activity while "
1390 "in config\n", __func__);
1391
1392 if (priv->tx_wait != NULL)
1393 mwl8k_tx_start(priv);
1394 } else
1395 mwl8k_tx_start(priv);
1396 1355
1397 spin_unlock_bh(&priv->tx_lock); 1356 spin_unlock_bh(&priv->tx_lock);
1398 1357