aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211/patches/513-ath9k_channelbw_debugfs.patch
blob: fe225cd5a8ee292fa43da05b74d05c664cdb0bd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -595,6 +595,7 @@ struct ath_softc {
 	struct ieee80211_hw *hw;
 	struct device *dev;
 
+	u32 chan_bw;
 	int chan_idx;
 	int chan_is_ht;
 	struct survey_info *cur_survey;
@@ -659,6 +660,7 @@ struct ath_softc {
 	u8 ant_tx, ant_rx;
 };
 
+int ath9k_config(struct ieee80211_hw *hw, u32 changed);
 void ath9k_tasklet(unsigned long data);
 int ath_cabq_update(struct ath_softc *);
 
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1663,6 +1663,50 @@ static const struct file_operations fops
 	.owner = THIS_MODULE
 };
 
+
+static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char buf[32];
+	unsigned int len;
+
+	len = sprintf(buf, "0x%08x\n", sc->chan_bw);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	unsigned long chan_bw;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (strict_strtoul(buf, 0, &chan_bw))
+		return -EINVAL;
+
+	sc->chan_bw = chan_bw;
+	if (!(sc->sc_flags & SC_OP_INVALID))
+		ath9k_config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
+
+	return count;
+}
+
+static const struct file_operations fops_chanbw = {
+	.read = read_file_chan_bw,
+	.write = write_file_chan_bw,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+
 int ath9k_init_debug(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -1727,6 +1771,9 @@ int ath9k_init_debug(struct ath_hw *ah)
 	debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_eeprom);
 
+	debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+			    sc, &fops_chanbw);
+
 	sc->debug.regidx = 0;
 	memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
 	sc->debug.sampidx = 0;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1559,7 +1559,7 @@ static void ath9k_disable_ps(struct ath_
 
 }
 
-static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
+int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
@@ -1609,9 +1609,11 @@ static int ath9k_config(struct ieee80211
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 		struct ieee80211_channel *curchan = hw->conf.channel;
+		struct ath9k_channel *hchan;
 		int pos = curchan->hw_value;
 		int old_pos = -1;
 		unsigned long flags;
+		u32 oldflags;
 
 		if (ah->curchan)
 			old_pos = ah->curchan - &ah->channels[0];
@@ -1659,7 +1661,23 @@ static int ath9k_config(struct ieee80211
 			memset(&sc->survey[pos], 0, sizeof(struct survey_info));
 		}
 
-		if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
+		hchan = &sc->sc_ah->channels[pos];
+		oldflags = hchan->channelFlags;
+		switch (sc->chan_bw) {
+		case 5:
+			hchan->channelFlags &= ~CHANNEL_HALF;
+			hchan->channelFlags |= CHANNEL_QUARTER;
+			break;
+		case 10:
+			hchan->channelFlags &= ~CHANNEL_QUARTER;
+			hchan->channelFlags |= CHANNEL_HALF;
+			break;
+		default:
+			hchan->channelFlags &= ~(CHANNEL_HALF | CHANNEL_QUARTER);
+			break;
+		}
+
+		if (ath_set_channel(sc, hw, hchan) < 0) {
 			ath_err(common, "Unable to set channel\n");
 			mutex_unlock(&sc->mutex);
 			return -EINVAL;
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1608,6 +1608,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 	    caldata->rtt_hist.num_readings)
 		allow_fbs = true;
 
+	if (!ah->curchan || ((ah->curchan->channelFlags ^ chan->channelFlags) &
+	    (CHANNEL_HALF | CHANNEL_QUARTER)))
+		bChannelChange = false;
+
 	if (bChannelChange &&
 	    (ah->chip_fullsleep != true) &&
 	    (ah->curchan != NULL) &&