aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-02-26 02:26:21 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-26 02:26:21 -0500
commit19bc291c99f018bd4f2c38bbf69144086dca903f (patch)
tree9d3cf9bc0c5a78e363dc0547da8bcd1e7c394265 /net/mac80211
parent04488734806948624dabc4514f96f14cd75b9a50 (diff)
parent4a6967b88af02eebeedfbb91bc09160750225bb5 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/iwlwifi/iwl-core.h drivers/net/wireless/rt2x00/rt2800pci.c
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c12
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/mlme.c35
-rw-r--r--net/mac80211/rx.c140
-rw-r--r--net/mac80211/status.c7
6 files changed, 157 insertions, 45 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e1731b7c2523..b7116ef84a3b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * mac80211 configuration hooks for cfg80211 2 * mac80211 configuration hooks for cfg80211
3 * 3 *
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * 5 *
6 * This file is GPLv2 as found in COPYING. 6 * This file is GPLv2 as found in COPYING.
7 */ 7 */
@@ -1448,6 +1448,15 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
1448 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); 1448 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
1449} 1449}
1450 1450
1451static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
1452 struct ieee80211_channel *chan,
1453 enum nl80211_channel_type channel_type,
1454 const u8 *buf, size_t len, u64 *cookie)
1455{
1456 return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan,
1457 channel_type, buf, len, cookie);
1458}
1459
1451struct cfg80211_ops mac80211_config_ops = { 1460struct cfg80211_ops mac80211_config_ops = {
1452 .add_virtual_intf = ieee80211_add_iface, 1461 .add_virtual_intf = ieee80211_add_iface,
1453 .del_virtual_intf = ieee80211_del_iface, 1462 .del_virtual_intf = ieee80211_del_iface,
@@ -1496,4 +1505,5 @@ struct cfg80211_ops mac80211_config_ops = {
1496 .set_bitrate_mask = ieee80211_set_bitrate_mask, 1505 .set_bitrate_mask = ieee80211_set_bitrate_mask,
1497 .remain_on_channel = ieee80211_remain_on_channel, 1506 .remain_on_channel = ieee80211_remain_on_channel,
1498 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, 1507 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
1508 .action = ieee80211_action,
1499}; 1509};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9dd98b674cbc..241533e1bc03 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005, Devicescape Software, Inc. 3 * Copyright 2005, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -966,6 +966,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
966int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, 966int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
967 struct cfg80211_disassoc_request *req, 967 struct cfg80211_disassoc_request *req,
968 void *cookie); 968 void *cookie);
969int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
970 struct ieee80211_channel *chan,
971 enum nl80211_channel_type channel_type,
972 const u8 *buf, size_t len, u64 *cookie);
969ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, 973ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
970 struct sk_buff *skb); 974 struct sk_buff *skb);
971void ieee80211_send_pspoll(struct ieee80211_local *local, 975void ieee80211_send_pspoll(struct ieee80211_local *local,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 09fff4662e80..0793d7a8d743 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1031,7 +1031,7 @@ static int netdev_notify(struct notifier_block *nb,
1031 1031
1032 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1032 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1033 1033
1034 memcpy(sdata->name, sdata->name, IFNAMSIZ); 1034 memcpy(sdata->name, dev->name, IFNAMSIZ);
1035 1035
1036 ieee80211_debugfs_rename_netdev(sdata); 1036 ieee80211_debugfs_rename_netdev(sdata);
1037 return 0; 1037 return 0;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index bfc4a5070013..41812a15eea0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2084,3 +2084,38 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2084 2084
2085 return 0; 2085 return 0;
2086} 2086}
2087
2088int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
2089 struct ieee80211_channel *chan,
2090 enum nl80211_channel_type channel_type,
2091 const u8 *buf, size_t len, u64 *cookie)
2092{
2093 struct ieee80211_local *local = sdata->local;
2094 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2095 struct sk_buff *skb;
2096
2097 /* Check that we are on the requested channel for transmission */
2098 if ((chan != local->tmp_channel ||
2099 channel_type != local->tmp_channel_type) &&
2100 (chan != local->oper_channel ||
2101 channel_type != local->oper_channel_type))
2102 return -EBUSY;
2103
2104 skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
2105 if (!skb)
2106 return -ENOMEM;
2107 skb_reserve(skb, local->hw.extra_tx_headroom);
2108
2109 memcpy(skb_put(skb, len), buf, len);
2110
2111 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
2112 IEEE80211_SKB_CB(skb)->flags |=
2113 IEEE80211_TX_INTFL_DONT_ENCRYPT;
2114 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX |
2115 IEEE80211_TX_CTL_REQ_TX_STATUS;
2116 skb->dev = sdata->dev;
2117 ieee80211_tx_skb(sdata, skb);
2118
2119 *cookie = (unsigned long) skb;
2120 return 0;
2121}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c9755f3d986c..b5c48de81d8b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -1397,6 +1397,21 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
1397 ieee80211_is_data(fc) && 1397 ieee80211_is_data(fc) &&
1398 (rx->key || rx->sdata->drop_unencrypted))) 1398 (rx->key || rx->sdata->drop_unencrypted)))
1399 return -EACCES; 1399 return -EACCES;
1400
1401 return 0;
1402}
1403
1404static int
1405ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
1406{
1407 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
1408 __le16 fc = hdr->frame_control;
1409 int res;
1410
1411 res = ieee80211_drop_unencrypted(rx, fc);
1412 if (unlikely(res))
1413 return res;
1414
1400 if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { 1415 if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
1401 if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && 1416 if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
1402 rx->key)) 1417 rx->key))
@@ -1855,23 +1870,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1855 struct ieee80211_local *local = rx->local; 1870 struct ieee80211_local *local = rx->local;
1856 struct ieee80211_sub_if_data *sdata = rx->sdata; 1871 struct ieee80211_sub_if_data *sdata = rx->sdata;
1857 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 1872 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1873 struct sk_buff *nskb;
1874 struct ieee80211_rx_status *status;
1858 int len = rx->skb->len; 1875 int len = rx->skb->len;
1859 1876
1860 if (!ieee80211_is_action(mgmt->frame_control)) 1877 if (!ieee80211_is_action(mgmt->frame_control))
1861 return RX_CONTINUE; 1878 return RX_CONTINUE;
1862 1879
1863 if (!rx->sta) 1880 /* drop too small frames */
1864 return RX_DROP_MONITOR; 1881 if (len < IEEE80211_MIN_ACTION_SIZE)
1882 return RX_DROP_UNUSABLE;
1865 1883
1866 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1884 if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
1867 return RX_DROP_MONITOR; 1885 return RX_DROP_UNUSABLE;
1868 1886
1869 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) 1887 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1870 return RX_DROP_MONITOR; 1888 return RX_DROP_UNUSABLE;
1871 1889
1872 /* all categories we currently handle have action_code */ 1890 if (ieee80211_drop_unencrypted_mgmt(rx))
1873 if (len < IEEE80211_MIN_ACTION_SIZE + 1) 1891 return RX_DROP_UNUSABLE;
1874 return RX_DROP_MONITOR;
1875 1892
1876 switch (mgmt->u.action.category) { 1893 switch (mgmt->u.action.category) {
1877 case WLAN_CATEGORY_BACK: 1894 case WLAN_CATEGORY_BACK:
@@ -1884,7 +1901,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1884 if (sdata->vif.type != NL80211_IFTYPE_STATION && 1901 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
1885 sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1902 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
1886 sdata->vif.type != NL80211_IFTYPE_AP) 1903 sdata->vif.type != NL80211_IFTYPE_AP)
1887 return RX_DROP_MONITOR; 1904 break;
1905
1906 /* verify action_code is present */
1907 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1908 break;
1888 1909
1889 switch (mgmt->u.action.u.addba_req.action_code) { 1910 switch (mgmt->u.action.u.addba_req.action_code) {
1890 case WLAN_ACTION_ADDBA_REQ: 1911 case WLAN_ACTION_ADDBA_REQ:
@@ -1892,45 +1913,49 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1892 sizeof(mgmt->u.action.u.addba_req))) 1913 sizeof(mgmt->u.action.u.addba_req)))
1893 return RX_DROP_MONITOR; 1914 return RX_DROP_MONITOR;
1894 ieee80211_process_addba_request(local, rx->sta, mgmt, len); 1915 ieee80211_process_addba_request(local, rx->sta, mgmt, len);
1895 break; 1916 goto handled;
1896 case WLAN_ACTION_ADDBA_RESP: 1917 case WLAN_ACTION_ADDBA_RESP:
1897 if (len < (IEEE80211_MIN_ACTION_SIZE + 1918 if (len < (IEEE80211_MIN_ACTION_SIZE +
1898 sizeof(mgmt->u.action.u.addba_resp))) 1919 sizeof(mgmt->u.action.u.addba_resp)))
1899 return RX_DROP_MONITOR; 1920 break;
1900 ieee80211_process_addba_resp(local, rx->sta, mgmt, len); 1921 ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
1901 break; 1922 goto handled;
1902 case WLAN_ACTION_DELBA: 1923 case WLAN_ACTION_DELBA:
1903 if (len < (IEEE80211_MIN_ACTION_SIZE + 1924 if (len < (IEEE80211_MIN_ACTION_SIZE +
1904 sizeof(mgmt->u.action.u.delba))) 1925 sizeof(mgmt->u.action.u.delba)))
1905 return RX_DROP_MONITOR; 1926 break;
1906 ieee80211_process_delba(sdata, rx->sta, mgmt, len); 1927 ieee80211_process_delba(sdata, rx->sta, mgmt, len);
1907 break; 1928 goto handled;
1908 } 1929 }
1909 break; 1930 break;
1910 case WLAN_CATEGORY_SPECTRUM_MGMT: 1931 case WLAN_CATEGORY_SPECTRUM_MGMT:
1911 if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) 1932 if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
1912 return RX_DROP_MONITOR; 1933 break;
1913 1934
1914 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1935 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1915 return RX_DROP_MONITOR; 1936 break;
1937
1938 /* verify action_code is present */
1939 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1940 break;
1916 1941
1917 switch (mgmt->u.action.u.measurement.action_code) { 1942 switch (mgmt->u.action.u.measurement.action_code) {
1918 case WLAN_ACTION_SPCT_MSR_REQ: 1943 case WLAN_ACTION_SPCT_MSR_REQ:
1919 if (len < (IEEE80211_MIN_ACTION_SIZE + 1944 if (len < (IEEE80211_MIN_ACTION_SIZE +
1920 sizeof(mgmt->u.action.u.measurement))) 1945 sizeof(mgmt->u.action.u.measurement)))
1921 return RX_DROP_MONITOR; 1946 break;
1922 ieee80211_process_measurement_req(sdata, mgmt, len); 1947 ieee80211_process_measurement_req(sdata, mgmt, len);
1923 break; 1948 goto handled;
1924 case WLAN_ACTION_SPCT_CHL_SWITCH: 1949 case WLAN_ACTION_SPCT_CHL_SWITCH:
1925 if (len < (IEEE80211_MIN_ACTION_SIZE + 1950 if (len < (IEEE80211_MIN_ACTION_SIZE +
1926 sizeof(mgmt->u.action.u.chan_switch))) 1951 sizeof(mgmt->u.action.u.chan_switch)))
1927 return RX_DROP_MONITOR; 1952 break;
1928 1953
1929 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1954 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1930 return RX_DROP_MONITOR; 1955 break;
1931 1956
1932 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) 1957 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
1933 return RX_DROP_MONITOR; 1958 break;
1934 1959
1935 return ieee80211_sta_rx_mgmt(sdata, rx->skb); 1960 return ieee80211_sta_rx_mgmt(sdata, rx->skb);
1936 } 1961 }
@@ -1938,30 +1963,64 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1938 case WLAN_CATEGORY_SA_QUERY: 1963 case WLAN_CATEGORY_SA_QUERY:
1939 if (len < (IEEE80211_MIN_ACTION_SIZE + 1964 if (len < (IEEE80211_MIN_ACTION_SIZE +
1940 sizeof(mgmt->u.action.u.sa_query))) 1965 sizeof(mgmt->u.action.u.sa_query)))
1941 return RX_DROP_MONITOR; 1966 break;
1967
1942 switch (mgmt->u.action.u.sa_query.action) { 1968 switch (mgmt->u.action.u.sa_query.action) {
1943 case WLAN_ACTION_SA_QUERY_REQUEST: 1969 case WLAN_ACTION_SA_QUERY_REQUEST:
1944 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1970 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1945 return RX_DROP_MONITOR; 1971 break;
1946 ieee80211_process_sa_query_req(sdata, mgmt, len); 1972 ieee80211_process_sa_query_req(sdata, mgmt, len);
1947 break; 1973 goto handled;
1948 case WLAN_ACTION_SA_QUERY_RESPONSE:
1949 /*
1950 * SA Query response is currently only used in AP mode
1951 * and it is processed in user space.
1952 */
1953 return RX_CONTINUE;
1954 } 1974 }
1955 break; 1975 break;
1956 default: 1976 }
1957 /* do not process rejected action frames */
1958 if (mgmt->u.action.category & 0x80)
1959 return RX_DROP_MONITOR;
1960 1977
1961 return RX_CONTINUE; 1978 /*
1979 * For AP mode, hostapd is responsible for handling any action
1980 * frames that we didn't handle, including returning unknown
1981 * ones. For all other modes we will return them to the sender,
1982 * setting the 0x80 bit in the action category, as required by
1983 * 802.11-2007 7.3.1.11.
1984 */
1985 if (sdata->vif.type == NL80211_IFTYPE_AP ||
1986 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1987 return RX_DROP_MONITOR;
1988
1989 /*
1990 * Getting here means the kernel doesn't know how to handle
1991 * it, but maybe userspace does ... include returned frames
1992 * so userspace can register for those to know whether ones
1993 * it transmitted were processed or returned.
1994 */
1995 status = IEEE80211_SKB_RXCB(rx->skb);
1996
1997 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1998 cfg80211_rx_action(rx->sdata->dev, status->freq,
1999 rx->skb->data, rx->skb->len,
2000 GFP_ATOMIC))
2001 goto handled;
2002
2003 /* do not return rejected action frames */
2004 if (mgmt->u.action.category & 0x80)
2005 return RX_DROP_UNUSABLE;
2006
2007 nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
2008 GFP_ATOMIC);
2009 if (nskb) {
2010 struct ieee80211_mgmt *mgmt = (void *)nskb->data;
2011
2012 mgmt->u.action.category |= 0x80;
2013 memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
2014 memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
2015
2016 memset(nskb->cb, 0, sizeof(nskb->cb));
2017
2018 ieee80211_tx_skb(rx->sdata, nskb);
1962 } 2019 }
1963 2020
1964 rx->sta->rx_packets++; 2021 handled:
2022 if (rx->sta)
2023 rx->sta->rx_packets++;
1965 dev_kfree_skb(rx->skb); 2024 dev_kfree_skb(rx->skb);
1966 return RX_QUEUED; 2025 return RX_QUEUED;
1967} 2026}
@@ -1970,14 +2029,13 @@ static ieee80211_rx_result debug_noinline
1970ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) 2029ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
1971{ 2030{
1972 struct ieee80211_sub_if_data *sdata = rx->sdata; 2031 struct ieee80211_sub_if_data *sdata = rx->sdata;
1973 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1974 ieee80211_rx_result rxs; 2032 ieee80211_rx_result rxs;
1975 2033
1976 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 2034 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1977 return RX_DROP_MONITOR; 2035 return RX_DROP_MONITOR;
1978 2036
1979 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) 2037 if (ieee80211_drop_unencrypted_mgmt(rx))
1980 return RX_DROP_MONITOR; 2038 return RX_DROP_UNUSABLE;
1981 2039
1982 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); 2040 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
1983 if (rxs != RX_CONTINUE) 2041 if (rxs != RX_CONTINUE)
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index ded98730c111..56d5b9a6ec5b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -288,6 +288,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
288 msecs_to_jiffies(10)); 288 msecs_to_jiffies(10));
289 } 289 }
290 290
291 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
292 cfg80211_action_tx_status(
293 skb->dev, (unsigned long) skb, skb->data, skb->len,
294 !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
295
291 /* this was a transmitted frame, but now we want to reuse it */ 296 /* this was a transmitted frame, but now we want to reuse it */
292 skb_orphan(skb); 297 skb_orphan(skb);
293 298