aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-12-13 08:14:20 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-19 15:23:11 -0500
commit54fdb040b4760d5b2994d15c1371e297679420e9 (patch)
treee287e40aa879482c9509cf4e3abe30af05efe4d6 /drivers/net/wireless
parentd5e490362feb648048ef20db9b0b2531d5425775 (diff)
p54: move statistic timer update routine into a workqueue
This patch moves a good chunk of code from the former statistic update timer routine into a workqueue, which is kindly provided by mac80211. Also as a nice side-effect we can lay the foundation for other essential housekeeping features we want to do in the future. e.g: - drain the (clogged) tx_queue. - initiate bursts. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/p54/p54.h5
-rw-r--r--drivers/net/wireless/p54/p54common.c104
-rw-r--r--drivers/net/wireless/p54/p54common.h5
3 files changed, 68 insertions, 46 deletions
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index d2dbb9e15d97..23b80ef4d015 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -71,6 +71,7 @@ struct p54_edcf_queue_param {
71#define FW_LM20 0x4c4d3230 71#define FW_LM20 0x4c4d3230
72 72
73struct p54_common { 73struct p54_common {
74 struct ieee80211_hw *hw;
74 u32 rx_start; 75 u32 rx_start;
75 u32 rx_end; 76 u32 rx_end;
76 struct sk_buff_head tx_queue; 77 struct sk_buff_head tx_queue;
@@ -106,9 +107,7 @@ struct p54_common {
106 struct ieee80211_tx_queue_stats tx_stats[8]; 107 struct ieee80211_tx_queue_stats tx_stats[8];
107 struct p54_edcf_queue_param qos_params[8]; 108 struct p54_edcf_queue_param qos_params[8];
108 struct ieee80211_low_level_stats stats; 109 struct ieee80211_low_level_stats stats;
109 struct timer_list stats_timer; 110 struct delayed_work work;
110 struct completion stats_comp;
111 struct sk_buff *cached_stats;
112 struct sk_buff *cached_beacon; 111 struct sk_buff *cached_beacon;
113 int noise; 112 int noise;
114 void *eeprom; 113 void *eeprom;
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index a4e99b02af02..36310f881874 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -589,6 +589,9 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
589 589
590 ieee80211_rx_irqsafe(dev, skb, &rx_status); 590 ieee80211_rx_irqsafe(dev, skb, &rx_status);
591 591
592 queue_delayed_work(dev->workqueue, &priv->work,
593 msecs_to_jiffies(P54_STATISTICS_UPDATE));
594
592 return -1; 595 return -1;
593} 596}
594 597
@@ -652,6 +655,27 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
652} 655}
653EXPORT_SYMBOL_GPL(p54_free_skb); 656EXPORT_SYMBOL_GPL(p54_free_skb);
654 657
658static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
659 __le32 req_id)
660{
661 struct p54_common *priv = dev->priv;
662 struct sk_buff *entry = priv->tx_queue.next;
663 unsigned long flags;
664
665 spin_lock_irqsave(&priv->tx_queue.lock, flags);
666 while (entry != (struct sk_buff *)&priv->tx_queue) {
667 struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
668
669 if (hdr->req_id == req_id) {
670 spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
671 return entry;
672 }
673 entry = entry->next;
674 }
675 spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
676 return NULL;
677}
678
655static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) 679static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
656{ 680{
657 struct p54_common *priv = dev->priv; 681 struct p54_common *priv = dev->priv;
@@ -775,8 +799,12 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
775 struct p54_common *priv = dev->priv; 799 struct p54_common *priv = dev->priv;
776 struct p54_hdr *hdr = (struct p54_hdr *) skb->data; 800 struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
777 struct p54_statistics *stats = (struct p54_statistics *) hdr->data; 801 struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
778 u32 tsf32 = le32_to_cpu(stats->tsf32); 802 u32 tsf32;
803
804 if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
805 return ;
779 806
807 tsf32 = le32_to_cpu(stats->tsf32);
780 if (tsf32 < priv->tsf_low32) 808 if (tsf32 < priv->tsf_low32)
781 priv->tsf_high32++; 809 priv->tsf_high32++;
782 priv->tsf_low32 = tsf32; 810 priv->tsf_low32 = tsf32;
@@ -786,9 +814,8 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
786 priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs); 814 priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs);
787 815
788 priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise)); 816 priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise));
789 complete(&priv->stats_comp);
790 817
791 mod_timer(&priv->stats_timer, jiffies + 5 * HZ); 818 p54_free_skb(dev, p54_find_tx_entry(dev, hdr->req_id));
792} 819}
793 820
794static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) 821static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb)
@@ -897,6 +924,8 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
897 * have a few spare slots for control frames left. 924 * have a few spare slots for control frames left.
898 */ 925 */
899 ieee80211_stop_queues(dev); 926 ieee80211_stop_queues(dev);
927 queue_delayed_work(dev->workqueue, &priv->work,
928 msecs_to_jiffies(P54_TX_TIMEOUT));
900 929
901 if (unlikely(left == 32)) { 930 if (unlikely(left == 32)) {
902 /* 931 /*
@@ -1354,6 +1383,10 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
1354 if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len))) 1383 if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len)))
1355 goto err; 1384 goto err;
1356 priv->tx(dev, skb, 0); 1385 priv->tx(dev, skb, 0);
1386
1387 queue_delayed_work(dev->workqueue, &priv->work,
1388 msecs_to_jiffies(P54_TX_FRAME_LIFETIME));
1389
1357 return 0; 1390 return 0;
1358 1391
1359 err: 1392 err:
@@ -1579,20 +1612,6 @@ static int p54_set_edcf(struct ieee80211_hw *dev)
1579 return 0; 1612 return 0;
1580} 1613}
1581 1614
1582static int p54_init_stats(struct ieee80211_hw *dev)
1583{
1584 struct p54_common *priv = dev->priv;
1585
1586 priv->cached_stats = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL,
1587 sizeof(struct p54_hdr) + sizeof(struct p54_statistics),
1588 P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
1589 if (!priv->cached_stats)
1590 return -ENOMEM;
1591
1592 mod_timer(&priv->stats_timer, jiffies + HZ);
1593 return 0;
1594}
1595
1596static int p54_beacon_tim(struct sk_buff *skb) 1615static int p54_beacon_tim(struct sk_buff *skb)
1597{ 1616{
1598 /* 1617 /*
@@ -1686,9 +1705,6 @@ static int p54_start(struct ieee80211_hw *dev)
1686 err = p54_set_edcf(dev); 1705 err = p54_set_edcf(dev);
1687 if (err) 1706 if (err)
1688 goto out; 1707 goto out;
1689 err = p54_init_stats(dev);
1690 if (err)
1691 goto out;
1692 1708
1693 memset(priv->bssid, ~0, ETH_ALEN); 1709 memset(priv->bssid, ~0, ETH_ALEN);
1694 priv->mode = NL80211_IFTYPE_MONITOR; 1710 priv->mode = NL80211_IFTYPE_MONITOR;
@@ -1698,6 +1714,8 @@ static int p54_start(struct ieee80211_hw *dev)
1698 goto out; 1714 goto out;
1699 } 1715 }
1700 1716
1717 queue_delayed_work(dev->workqueue, &priv->work, 0);
1718
1701out: 1719out:
1702 mutex_unlock(&priv->conf_mutex); 1720 mutex_unlock(&priv->conf_mutex);
1703 return err; 1721 return err;
@@ -1710,9 +1728,7 @@ static void p54_stop(struct ieee80211_hw *dev)
1710 1728
1711 mutex_lock(&priv->conf_mutex); 1729 mutex_lock(&priv->conf_mutex);
1712 priv->mode = NL80211_IFTYPE_UNSPECIFIED; 1730 priv->mode = NL80211_IFTYPE_UNSPECIFIED;
1713 del_timer(&priv->stats_timer); 1731 cancel_delayed_work_sync(&priv->work);
1714 p54_free_skb(dev, priv->cached_stats);
1715 priv->cached_stats = NULL;
1716 if (priv->cached_beacon) 1732 if (priv->cached_beacon)
1717 p54_tx_cancel(dev, priv->cached_beacon); 1733 p54_tx_cancel(dev, priv->cached_beacon);
1718 1734
@@ -1889,14 +1905,29 @@ static int p54_init_xbow_synth(struct ieee80211_hw *dev)
1889 return 0; 1905 return 0;
1890} 1906}
1891 1907
1892static void p54_statistics_timer(unsigned long data) 1908static void p54_work(struct work_struct *work)
1893{ 1909{
1894 struct ieee80211_hw *dev = (struct ieee80211_hw *) data; 1910 struct p54_common *priv = container_of(work, struct p54_common,
1895 struct p54_common *priv = dev->priv; 1911 work.work);
1912 struct ieee80211_hw *dev = priv->hw;
1913 struct sk_buff *skb;
1914
1915 if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
1916 return ;
1917
1918 /*
1919 * TODO: walk through tx_queue and do the following tasks
1920 * 1. initiate bursts.
1921 * 2. cancel stuck frames / reset the device if necessary.
1922 */
1896 1923
1897 BUG_ON(!priv->cached_stats); 1924 skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(struct p54_hdr) +
1925 sizeof(struct p54_statistics),
1926 P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
1927 if (!skb)
1928 return ;
1898 1929
1899 priv->tx(dev, priv->cached_stats, 0); 1930 priv->tx(dev, skb, 0);
1900} 1931}
1901 1932
1902static int p54_get_stats(struct ieee80211_hw *dev, 1933static int p54_get_stats(struct ieee80211_hw *dev,
@@ -1904,17 +1935,7 @@ static int p54_get_stats(struct ieee80211_hw *dev,
1904{ 1935{
1905 struct p54_common *priv = dev->priv; 1936 struct p54_common *priv = dev->priv;
1906 1937
1907 del_timer(&priv->stats_timer);
1908 p54_statistics_timer((unsigned long)dev);
1909
1910 if (!wait_for_completion_interruptible_timeout(&priv->stats_comp, HZ)) {
1911 printk(KERN_ERR "%s: device does not respond!\n",
1912 wiphy_name(dev->wiphy));
1913 return -EBUSY;
1914 }
1915
1916 memcpy(stats, &priv->stats, sizeof(*stats)); 1938 memcpy(stats, &priv->stats, sizeof(*stats));
1917
1918 return 0; 1939 return 0;
1919} 1940}
1920 1941
@@ -2072,6 +2093,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
2072 return NULL; 2093 return NULL;
2073 2094
2074 priv = dev->priv; 2095 priv = dev->priv;
2096 priv->hw = dev;
2075 priv->mode = NL80211_IFTYPE_UNSPECIFIED; 2097 priv->mode = NL80211_IFTYPE_UNSPECIFIED;
2076 priv->basic_rate_mask = 0x15f; 2098 priv->basic_rate_mask = 0x15f;
2077 skb_queue_head_init(&priv->tx_queue); 2099 skb_queue_head_init(&priv->tx_queue);
@@ -2107,9 +2129,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
2107 2129
2108 mutex_init(&priv->conf_mutex); 2130 mutex_init(&priv->conf_mutex);
2109 init_completion(&priv->eeprom_comp); 2131 init_completion(&priv->eeprom_comp);
2110 init_completion(&priv->stats_comp); 2132 INIT_DELAYED_WORK(&priv->work, p54_work);
2111 setup_timer(&priv->stats_timer, p54_statistics_timer,
2112 (unsigned long)dev);
2113 2133
2114 return dev; 2134 return dev;
2115} 2135}
@@ -2118,8 +2138,6 @@ EXPORT_SYMBOL_GPL(p54_init_common);
2118void p54_free_common(struct ieee80211_hw *dev) 2138void p54_free_common(struct ieee80211_hw *dev)
2119{ 2139{
2120 struct p54_common *priv = dev->priv; 2140 struct p54_common *priv = dev->priv;
2121 del_timer(&priv->stats_timer);
2122 kfree_skb(priv->cached_stats);
2123 kfree(priv->iq_autocal); 2141 kfree(priv->iq_autocal);
2124 kfree(priv->output_limit); 2142 kfree(priv->output_limit);
2125 kfree(priv->curve_data); 2143 kfree(priv->curve_data);
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index 5a68fdae7730..06e1643cc295 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -355,6 +355,11 @@ struct p54_tx_data {
355 u8 align[0]; 355 u8 align[0];
356} __attribute__ ((packed)); 356} __attribute__ ((packed));
357 357
358/* unit is ms */
359#define P54_TX_FRAME_LIFETIME 2000
360#define P54_TX_TIMEOUT 4000
361#define P54_STATISTICS_UPDATE 5000
362
358#define P54_FILTER_TYPE_NONE 0 363#define P54_FILTER_TYPE_NONE 0
359#define P54_FILTER_TYPE_STATION BIT(0) 364#define P54_FILTER_TYPE_STATION BIT(0)
360#define P54_FILTER_TYPE_IBSS BIT(1) 365#define P54_FILTER_TYPE_IBSS BIT(1)