diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-11-10 13:41:40 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-25 16:32:53 -0500 |
commit | c9c3b1a5deac4297503145840fffcd122b253db5 (patch) | |
tree | 7d5e0cf6510c1687ef6b18d32ba9009a5692fbfd /drivers/net/wireless/rt2x00/rt73usb.c | |
parent | 9764f3f9c3700620f9f8a1f9af57f58758e835da (diff) |
rt2x00: Cleanup indirect register access
All code which accessed indirect registers was similar
in respect to the for-loop, the given timeout, etc.
Move it into a seperate function, which for PCI drivers
can be moved into rt2x00pci.
This allows us to cleanup the cleanup the code further
by removing the goto statementsand making the codepath
look a bit nicer.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt73usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 147 |
1 files changed, 64 insertions, 83 deletions
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d1a63e0017d..b4ca8488bef 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -63,7 +63,7 @@ static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, | |||
63 | __le32 reg; | 63 | __le32 reg; |
64 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 64 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
65 | USB_VENDOR_REQUEST_IN, offset, | 65 | USB_VENDOR_REQUEST_IN, offset, |
66 | ®, sizeof(u32), REGISTER_TIMEOUT); | 66 | ®, sizeof(reg), REGISTER_TIMEOUT); |
67 | *value = le32_to_cpu(reg); | 67 | *value = le32_to_cpu(reg); |
68 | } | 68 | } |
69 | 69 | ||
@@ -73,7 +73,7 @@ static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev, | |||
73 | __le32 reg; | 73 | __le32 reg; |
74 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, | 74 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, |
75 | USB_VENDOR_REQUEST_IN, offset, | 75 | USB_VENDOR_REQUEST_IN, offset, |
76 | ®, sizeof(u32), REGISTER_TIMEOUT); | 76 | ®, sizeof(reg), REGISTER_TIMEOUT); |
77 | *value = le32_to_cpu(reg); | 77 | *value = le32_to_cpu(reg); |
78 | } | 78 | } |
79 | 79 | ||
@@ -93,7 +93,7 @@ static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev, | |||
93 | __le32 reg = cpu_to_le32(value); | 93 | __le32 reg = cpu_to_le32(value); |
94 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 94 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
95 | USB_VENDOR_REQUEST_OUT, offset, | 95 | USB_VENDOR_REQUEST_OUT, offset, |
96 | ®, sizeof(u32), REGISTER_TIMEOUT); | 96 | ®, sizeof(reg), REGISTER_TIMEOUT); |
97 | } | 97 | } |
98 | 98 | ||
99 | static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | 99 | static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, |
@@ -102,7 +102,7 @@ static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | |||
102 | __le32 reg = cpu_to_le32(value); | 102 | __le32 reg = cpu_to_le32(value); |
103 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, | 103 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, |
104 | USB_VENDOR_REQUEST_OUT, offset, | 104 | USB_VENDOR_REQUEST_OUT, offset, |
105 | ®, sizeof(u32), REGISTER_TIMEOUT); | 105 | ®, sizeof(reg), REGISTER_TIMEOUT); |
106 | } | 106 | } |
107 | 107 | ||
108 | static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | 108 | static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, |
@@ -115,21 +115,32 @@ static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
115 | REGISTER_TIMEOUT32(length)); | 115 | REGISTER_TIMEOUT32(length)); |
116 | } | 116 | } |
117 | 117 | ||
118 | static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev) | 118 | static int rt73usb_regbusy_read(struct rt2x00_dev *rt2x00dev, |
119 | const unsigned int offset, | ||
120 | struct rt2x00_field32 field, | ||
121 | u32 *reg) | ||
119 | { | 122 | { |
120 | u32 reg; | ||
121 | unsigned int i; | 123 | unsigned int i; |
122 | 124 | ||
123 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 125 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
124 | rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, ®); | 126 | rt73usb_register_read_lock(rt2x00dev, offset, reg); |
125 | if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | 127 | if (!rt2x00_get_field32(*reg, field)) |
126 | break; | 128 | return 1; |
127 | udelay(REGISTER_BUSY_DELAY); | 129 | udelay(REGISTER_BUSY_DELAY); |
128 | } | 130 | } |
129 | 131 | ||
130 | return reg; | 132 | ERROR(rt2x00dev, "Indirect register access failed: " |
133 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | ||
134 | *reg = ~0; | ||
135 | |||
136 | return 0; | ||
131 | } | 137 | } |
132 | 138 | ||
139 | #define WAIT_FOR_BBP(__dev, __reg) \ | ||
140 | rt73usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) | ||
141 | #define WAIT_FOR_RF(__dev, __reg) \ | ||
142 | rt73usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) | ||
143 | |||
133 | static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, | 144 | static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, |
134 | const unsigned int word, const u8 value) | 145 | const unsigned int word, const u8 value) |
135 | { | 146 | { |
@@ -138,30 +149,20 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
138 | mutex_lock(&rt2x00dev->csr_mutex); | 149 | mutex_lock(&rt2x00dev->csr_mutex); |
139 | 150 | ||
140 | /* | 151 | /* |
141 | * Wait until the BBP becomes ready. | 152 | * Wait until the BBP becomes available, afterwards we |
153 | * can safely write the new data into the register. | ||
142 | */ | 154 | */ |
143 | reg = rt73usb_bbp_check(rt2x00dev); | 155 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
144 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | 156 | reg = 0; |
145 | goto exit_fail; | 157 | rt2x00_set_field32(®, PHY_CSR3_VALUE, value); |
146 | 158 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | |
147 | /* | 159 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); |
148 | * Write the data into the BBP. | 160 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); |
149 | */ | 161 | |
150 | reg = 0; | 162 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); |
151 | rt2x00_set_field32(®, PHY_CSR3_VALUE, value); | 163 | } |
152 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | ||
153 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
154 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | ||
155 | |||
156 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); | ||
157 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
158 | |||
159 | return; | ||
160 | 164 | ||
161 | exit_fail: | ||
162 | mutex_unlock(&rt2x00dev->csr_mutex); | 165 | mutex_unlock(&rt2x00dev->csr_mutex); |
163 | |||
164 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | ||
165 | } | 166 | } |
166 | 167 | ||
167 | static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | 168 | static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -172,79 +173,59 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
172 | mutex_lock(&rt2x00dev->csr_mutex); | 173 | mutex_lock(&rt2x00dev->csr_mutex); |
173 | 174 | ||
174 | /* | 175 | /* |
175 | * Wait until the BBP becomes ready. | 176 | * Wait until the BBP becomes available, afterwards we |
177 | * can safely write the read request into the register. | ||
178 | * After the data has been written, we wait until hardware | ||
179 | * returns the correct value, if at any time the register | ||
180 | * doesn't become available in time, reg will be 0xffffffff | ||
181 | * which means we return 0xff to the caller. | ||
176 | */ | 182 | */ |
177 | reg = rt73usb_bbp_check(rt2x00dev); | 183 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
178 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | 184 | reg = 0; |
179 | goto exit_fail; | 185 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); |
186 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
187 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | ||
180 | 188 | ||
181 | /* | 189 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); |
182 | * Write the request into the BBP. | ||
183 | */ | ||
184 | reg = 0; | ||
185 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | ||
186 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
187 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | ||
188 | 190 | ||
189 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); | 191 | WAIT_FOR_BBP(rt2x00dev, ®); |
190 | 192 | } | |
191 | /* | ||
192 | * Wait until the BBP becomes ready. | ||
193 | */ | ||
194 | reg = rt73usb_bbp_check(rt2x00dev); | ||
195 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | ||
196 | goto exit_fail; | ||
197 | 193 | ||
198 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); | 194 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); |
199 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
200 | |||
201 | return; | ||
202 | 195 | ||
203 | exit_fail: | ||
204 | mutex_unlock(&rt2x00dev->csr_mutex); | 196 | mutex_unlock(&rt2x00dev->csr_mutex); |
205 | |||
206 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | ||
207 | *value = 0xff; | ||
208 | } | 197 | } |
209 | 198 | ||
210 | static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | 199 | static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, |
211 | const unsigned int word, const u32 value) | 200 | const unsigned int word, const u32 value) |
212 | { | 201 | { |
213 | u32 reg; | 202 | u32 reg; |
214 | unsigned int i; | ||
215 | 203 | ||
216 | if (!word) | 204 | if (!word) |
217 | return; | 205 | return; |
218 | 206 | ||
219 | mutex_lock(&rt2x00dev->csr_mutex); | 207 | mutex_lock(&rt2x00dev->csr_mutex); |
220 | 208 | ||
221 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
222 | rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®); | ||
223 | if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) | ||
224 | goto rf_write; | ||
225 | udelay(REGISTER_BUSY_DELAY); | ||
226 | } | ||
227 | |||
228 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
229 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); | ||
230 | return; | ||
231 | |||
232 | rf_write: | ||
233 | reg = 0; | ||
234 | rt2x00_set_field32(®, PHY_CSR4_VALUE, value); | ||
235 | |||
236 | /* | 209 | /* |
237 | * RF5225 and RF2527 contain 21 bits per RF register value, | 210 | * Wait until the RF becomes available, afterwards we |
238 | * all others contain 20 bits. | 211 | * can safely write the new data into the register. |
239 | */ | 212 | */ |
240 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, | 213 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
241 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 214 | reg = 0; |
242 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | 215 | rt2x00_set_field32(®, PHY_CSR4_VALUE, value); |
243 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | 216 | /* |
244 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | 217 | * RF5225 and RF2527 contain 21 bits per RF register value, |
245 | 218 | * all others contain 20 bits. | |
246 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); | 219 | */ |
247 | rt2x00_rf_write(rt2x00dev, word, value); | 220 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, |
221 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | ||
222 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | ||
223 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | ||
224 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | ||
225 | |||
226 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); | ||
227 | rt2x00_rf_write(rt2x00dev, word, value); | ||
228 | } | ||
248 | 229 | ||
249 | mutex_unlock(&rt2x00dev->csr_mutex); | 230 | mutex_unlock(&rt2x00dev->csr_mutex); |
250 | } | 231 | } |