aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/main.c
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2011-03-31 04:06:59 -0400
committerLuciano Coelho <coelho@ti.com>2011-04-19 09:49:19 -0400
commit990f5de7384f9e5922e4c7c7572cbf4f29a9441e (patch)
tree3294cf7224a4aadfefc35660cbe5406f01ab6c94 /drivers/net/wireless/wl12xx/main.c
parent0da13da767cd568c1fe2a7b5b936e86e521b5ae7 (diff)
wl12xx: Clean up the dummy packet mechanism
The current implementation allocates a skb each time one is requested by the firmware. Since dummy packets are handled differently than regular packets, the skb needs to be marked. Currently, this is done by setting the pkt_type member to 5. This might not be safe, as we cannot be sure that there won't be any other packets with this pkt_type value. Since the packet does not change from one request to another, we can simply allocate a dummy packet template and always send it. All changes to the skb done during packet preparation must be reverted, so the same skb can be reused. The dummy packets are not transmitted, therefore there's no need to set the BSSID or our own MAC address. In addition, the header portion of the packet was zeroed by mistake, so fix that as well. Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r--drivers/net/wireless/wl12xx/main.c79
1 files changed, 54 insertions, 25 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 1cd396306e7b..7dce24c0b331 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1212,20 +1212,46 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1212 spin_unlock_irqrestore(&wl->wl_lock, flags); 1212 spin_unlock_irqrestore(&wl->wl_lock, flags);
1213} 1213}
1214 1214
1215#define TX_DUMMY_PACKET_SIZE 1400
1216int wl1271_tx_dummy_packet(struct wl1271 *wl) 1215int wl1271_tx_dummy_packet(struct wl1271 *wl)
1217{ 1216{
1218 struct sk_buff *skb = NULL; 1217 unsigned long flags;
1218
1219 spin_lock_irqsave(&wl->wl_lock, flags);
1220 set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
1221 wl->tx_queue_count++;
1222 spin_unlock_irqrestore(&wl->wl_lock, flags);
1223
1224 /* The FW is low on RX memory blocks, so send the dummy packet asap */
1225 if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
1226 wl1271_tx_work_locked(wl);
1227
1228 /*
1229 * If the FW TX is busy, TX work will be scheduled by the threaded
1230 * interrupt handler function
1231 */
1232 return 0;
1233}
1234
1235/*
1236 * The size of the dummy packet should be at least 1400 bytes. However, in
1237 * order to minimize the number of bus transactions, aligning it to 512 bytes
1238 * boundaries could be beneficial, performance wise
1239 */
1240#define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512))
1241
1242struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
1243{
1244 struct sk_buff *skb;
1219 struct ieee80211_hdr_3addr *hdr; 1245 struct ieee80211_hdr_3addr *hdr;
1220 int ret = 0; 1246 unsigned int dummy_packet_size;
1247
1248 dummy_packet_size = TOTAL_TX_DUMMY_PACKET_SIZE -
1249 sizeof(struct wl1271_tx_hw_descr) - sizeof(*hdr);
1221 1250
1222 skb = dev_alloc_skb( 1251 skb = dev_alloc_skb(TOTAL_TX_DUMMY_PACKET_SIZE);
1223 sizeof(struct wl1271_tx_hw_descr) + sizeof(*hdr) +
1224 TX_DUMMY_PACKET_SIZE);
1225 if (!skb) { 1252 if (!skb) {
1226 wl1271_warning("failed to allocate buffer for dummy packet"); 1253 wl1271_warning("Failed to allocate a dummy packet skb");
1227 ret = -ENOMEM; 1254 return NULL;
1228 goto out;
1229 } 1255 }
1230 1256
1231 skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); 1257 skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr));
@@ -1233,29 +1259,22 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)
1233 hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); 1259 hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
1234 memset(hdr, 0, sizeof(*hdr)); 1260 memset(hdr, 0, sizeof(*hdr));
1235 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 1261 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
1236 IEEE80211_FCTL_TODS | 1262 IEEE80211_STYPE_NULLFUNC |
1237 IEEE80211_STYPE_NULLFUNC); 1263 IEEE80211_FCTL_TODS);
1238
1239 memcpy(hdr->addr1, wl->bssid, ETH_ALEN);
1240 memcpy(hdr->addr2, wl->mac_addr, ETH_ALEN);
1241 memcpy(hdr->addr3, wl->bssid, ETH_ALEN);
1242 1264
1243 skb_put(skb, TX_DUMMY_PACKET_SIZE); 1265 memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size);
1244 1266
1245 memset(skb->data, 0, TX_DUMMY_PACKET_SIZE);
1246
1247 skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ;
1248 /* Dummy packets require the TID to be management */ 1267 /* Dummy packets require the TID to be management */
1249 skb->priority = WL1271_TID_MGMT; 1268 skb->priority = WL1271_TID_MGMT;
1250 /* CONF_TX_AC_VO */
1251 skb->queue_mapping = 0;
1252 1269
1253 wl1271_op_tx(wl->hw, skb); 1270 /* Initialize all fields that might be used */
1271 skb->queue_mapping = 0;
1272 memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info));
1254 1273
1255out: 1274 return skb;
1256 return ret;
1257} 1275}
1258 1276
1277
1259static struct notifier_block wl1271_dev_notifier = { 1278static struct notifier_block wl1271_dev_notifier = {
1260 .notifier_call = wl1271_dev_notify, 1279 .notifier_call = wl1271_dev_notify,
1261}; 1280};
@@ -3653,11 +3672,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
3653 goto err_hw; 3672 goto err_hw;
3654 } 3673 }
3655 3674
3675 wl->dummy_packet = wl12xx_alloc_dummy_packet(wl);
3676 if (!wl->dummy_packet) {
3677 ret = -ENOMEM;
3678 goto err_aggr;
3679 }
3680
3656 /* Register platform device */ 3681 /* Register platform device */
3657 ret = platform_device_register(wl->plat_dev); 3682 ret = platform_device_register(wl->plat_dev);
3658 if (ret) { 3683 if (ret) {
3659 wl1271_error("couldn't register platform device"); 3684 wl1271_error("couldn't register platform device");
3660 goto err_aggr; 3685 goto err_dummy_packet;
3661 } 3686 }
3662 dev_set_drvdata(&wl->plat_dev->dev, wl); 3687 dev_set_drvdata(&wl->plat_dev->dev, wl);
3663 3688
@@ -3683,6 +3708,9 @@ err_bt_coex_state:
3683err_platform: 3708err_platform:
3684 platform_device_unregister(wl->plat_dev); 3709 platform_device_unregister(wl->plat_dev);
3685 3710
3711err_dummy_packet:
3712 dev_kfree_skb(wl->dummy_packet);
3713
3686err_aggr: 3714err_aggr:
3687 free_pages((unsigned long)wl->aggr_buf, order); 3715 free_pages((unsigned long)wl->aggr_buf, order);
3688 3716
@@ -3702,6 +3730,7 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
3702int wl1271_free_hw(struct wl1271 *wl) 3730int wl1271_free_hw(struct wl1271 *wl)
3703{ 3731{
3704 platform_device_unregister(wl->plat_dev); 3732 platform_device_unregister(wl->plat_dev);
3733 dev_kfree_skb(wl->dummy_packet);
3705 free_pages((unsigned long)wl->aggr_buf, 3734 free_pages((unsigned long)wl->aggr_buf,
3706 get_order(WL1271_AGGR_BUFFER_SIZE)); 3735 get_order(WL1271_AGGR_BUFFER_SIZE));
3707 kfree(wl->plat_dev); 3736 kfree(wl->plat_dev);