GFS2: Check for glock already held in gfs2_getxattr
[deliverable/linux.git] / drivers / staging / csr / csr_wifi_hip_send.c
1 /*****************************************************************************
2
3 (c) Cambridge Silicon Radio Limited 2011
4 All rights reserved and confidential information of CSR
5
6 Refer to LICENSE.txt included with this source for details
7 on the license terms.
8
9 *****************************************************************************/
10
11 /*
12 * ***************************************************************************
13 *
14 * FILE: csr_wifi_hip_send.c
15 *
16 * PURPOSE:
17 * Code for adding a signal request to the from-host queue.
18 * When the driver bottom-half is run, it will take requests from the
19 * queue and pass them to the UniFi.
20 *
21 * ***************************************************************************
22 */
23 #include "csr_wifi_hip_unifi.h"
24 #include "csr_wifi_hip_conversions.h"
25 #include "csr_wifi_hip_sigs.h"
26 #include "csr_wifi_hip_card.h"
27
28 unifi_TrafficQueue unifi_frame_priority_to_queue(CSR_PRIORITY priority)
29 {
30 switch (priority)
31 {
32 case CSR_QOS_UP0:
33 case CSR_QOS_UP3:
34 return UNIFI_TRAFFIC_Q_BE;
35 case CSR_QOS_UP1:
36 case CSR_QOS_UP2:
37 return UNIFI_TRAFFIC_Q_BK;
38 case CSR_QOS_UP4:
39 case CSR_QOS_UP5:
40 return UNIFI_TRAFFIC_Q_VI;
41 case CSR_QOS_UP6:
42 case CSR_QOS_UP7:
43 case CSR_MANAGEMENT:
44 return UNIFI_TRAFFIC_Q_VO;
45 default:
46 return UNIFI_TRAFFIC_Q_BE;
47 }
48 }
49
50
51 CSR_PRIORITY unifi_get_default_downgrade_priority(unifi_TrafficQueue queue)
52 {
53 switch (queue)
54 {
55 case UNIFI_TRAFFIC_Q_BE:
56 return CSR_QOS_UP0;
57 case UNIFI_TRAFFIC_Q_BK:
58 return CSR_QOS_UP1;
59 case UNIFI_TRAFFIC_Q_VI:
60 return CSR_QOS_UP5;
61 case UNIFI_TRAFFIC_Q_VO:
62 return CSR_QOS_UP6;
63 default:
64 return CSR_QOS_UP0;
65 }
66 }
67
68
69 /*
70 * ---------------------------------------------------------------------------
71 * send_signal
72 *
73 * This function queues a signal for sending to UniFi. It first checks
74 * that there is space on the fh_signal_queue for another entry, then
75 * claims any bulk data slots required and copies data into them. Then
76 * increments the fh_signal_queue write count.
77 *
78 * The fh_signal_queue is later processed by the driver bottom half
79 * (in unifi_bh()).
80 *
81 * This function call unifi_pause_xmit() to pause the flow of data plane
82 * packets when:
83 * - the fh_signal_queue ring buffer is full
84 * - there are less than UNIFI_MAX_DATA_REFERENCES (2) bulk data
85 * slots available.
86 *
87 * Arguments:
88 * card Pointer to card context structure
89 * sigptr Pointer to the signal to write to UniFi.
90 * siglen Number of bytes pointer to by sigptr.
91 * bulkdata Array of pointers to an associated bulk data.
92 * sigq To which from-host queue to add the signal.
93 *
94 * Returns:
95 * CSR_RESULT_SUCCESS on success
96 * CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or
97 * no free signal queue entry
98 *
99 * Notes:
100 * Calls unifi_pause_xmit() when the last slots are used.
101 * ---------------------------------------------------------------------------
102 */
103 static CsrResult send_signal(card_t *card, const u8 *sigptr, u32 siglen,
104 const bulk_data_param_t *bulkdata,
105 q_t *sigq, u32 priority_q, u32 run_bh)
106 {
107 u16 i, data_slot_size;
108 card_signal_t *csptr;
109 s16 qe;
110 CsrResult r;
111 s16 debug_print = 0;
112
113 data_slot_size = CardGetDataSlotSize(card);
114
115 /* Check that the fh_data_queue has a free slot */
116 if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sigq))
117 {
118 unifi_trace(card->ospriv, UDBG3, "send_signal: %s full\n", sigq->name);
119
120 return CSR_WIFI_HIP_RESULT_NO_SPACE;
121 }
122
123 /*
124 * Now add the signal to the From Host signal queue
125 */
126 /* Get next slot on queue */
127 qe = CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq);
128 csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, qe);
129
130 /* Make up the card_signal struct */
131 csptr->signal_length = (u16)siglen;
132 memcpy((void *)csptr->sigbuf, (void *)sigptr, siglen);
133
134 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i)
135 {
136 if ((bulkdata != NULL) && (bulkdata->d[i].data_length != 0))
137 {
138 u32 datalen = bulkdata->d[i].data_length;
139
140 /* Make sure data will fit in a bulk data slot */
141 if (bulkdata->d[i].os_data_ptr == NULL)
142 {
143 unifi_error(card->ospriv, "send_signal - NULL bulkdata[%d]\n", i);
144 debug_print++;
145 csptr->bulkdata[i].data_length = 0;
146 }
147 else
148 {
149 if (datalen > data_slot_size)
150 {
151 unifi_error(card->ospriv,
152 "send_signal - Invalid data length %u (@%p), "
153 "truncating\n",
154 datalen, bulkdata->d[i].os_data_ptr);
155 datalen = data_slot_size;
156 debug_print++;
157 }
158 /* Store the bulk data info in the soft queue. */
159 csptr->bulkdata[i].os_data_ptr = (u8 *)bulkdata->d[i].os_data_ptr;
160 csptr->bulkdata[i].os_net_buf_ptr = (u8 *)bulkdata->d[i].os_net_buf_ptr;
161 csptr->bulkdata[i].net_buf_length = bulkdata->d[i].net_buf_length;
162 csptr->bulkdata[i].data_length = datalen;
163 }
164 }
165 else
166 {
167 UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]);
168 }
169 }
170
171 if (debug_print)
172 {
173 const u8 *sig = sigptr;
174
175 unifi_error(card->ospriv, "Signal(%d): %*ph\n", siglen,
176 16, sig);
177 unifi_error(card->ospriv, "Bulkdata pointer %p(%d), %p(%d)\n",
178 bulkdata != NULL?bulkdata->d[0].os_data_ptr : NULL,
179 bulkdata != NULL?bulkdata->d[0].data_length : 0,
180 bulkdata != NULL?bulkdata->d[1].os_data_ptr : NULL,
181 bulkdata != NULL?bulkdata->d[1].data_length : 0);
182 }
183
184 /* Advance the written count to say there is a new entry */
185 CSR_WIFI_HIP_Q_INC_W(sigq);
186
187 /*
188 * Set the flag to say reason for waking was a host request.
189 * Then ask the OS layer to run the unifi_bh.
190 */
191 if (run_bh == 1)
192 {
193 card->bh_reason_host = 1;
194 r = unifi_run_bh(card->ospriv);
195 if (r != CSR_RESULT_SUCCESS)
196 {
197 unifi_error(card->ospriv, "failed to run bh.\n");
198 card->bh_reason_host = 0;
199
200 /*
201 * The bulk data buffer will be freed by the caller.
202 * We need to invalidate the description of the bulk data in our
203 * soft queue, to prevent the core freeing the bulk data again later.
204 */
205 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i)
206 {
207 if (csptr->bulkdata[i].data_length != 0)
208 {
209 csptr->bulkdata[i].os_data_ptr = csptr->bulkdata[i].os_net_buf_ptr = NULL;
210 csptr->bulkdata[i].net_buf_length = csptr->bulkdata[i].data_length = 0;
211 }
212 }
213 return r;
214 }
215 }
216 else
217 {
218 unifi_error(card->ospriv, "run_bh=%d, bh not called.\n", run_bh);
219 }
220
221 /*
222 * Have we used up all the fh signal list entries?
223 */
224 if (CSR_WIFI_HIP_Q_SLOTS_FREE(sigq) == 0)
225 {
226 /* We have filled the queue, so stop the upper layer. The command queue
227 * is an exception, as suspending due to that being full could delay
228 * resume/retry until new commands or data are received.
229 */
230 if (sigq != &card->fh_command_queue)
231 {
232 /*
233 * Must call unifi_pause_xmit() *before* setting the paused flag.
234 * (the unifi_pause_xmit call should not be after setting the flag because of the possibility of being interrupted
235 * by the bh thread between our setting the flag and the call to unifi_pause_xmit()
236 * If bh thread then cleared the flag, we would end up paused, but without the flag set)
237 * Instead, setting it afterwards means that if this thread is interrupted by the bh thread
238 * the pause flag is still guaranteed to end up set
239 * However the potential deadlock now is that if bh thread emptied the queue and cleared the flag before this thread's
240 * call to unifi_pause_xmit(), then bh thread may not run again because it will be waiting for
241 * a packet to appear in the queue but nothing ever will because xmit is paused.
242 * So we will end up with the queue paused, and the flag set to say it is paused, but bh never runs to unpause it.
243 * (Note even this bad situation would not persist long in practice, because something else (eg rx, or tx in different queue)
244 * is likely to wake bh thread quite soon)
245 * But to avoid this deadlock completely, after setting the flag we check that there is something left in the queue.
246 * If there is, we know that bh thread has not emptied the queue yet.
247 * Since bh thread checks to unpause the queue *after* taking packets from the queue, we know that it is still going to make at
248 * least one more check to see whether it needs to unpause the queue. So all is well.
249 * If there are no packets in the queue, then the deadlock described above might happen. To make sure it does not, we
250 * unpause the queue here. A possible side effect is that unifi_restart_xmit() may (rarely) be called for second time
251 * unnecessarily, which is harmless
252 */
253
254 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
255 unifi_debug_log_to_buf("P");
256 #endif
257 unifi_pause_xmit(card->ospriv, (unifi_TrafficQueue)priority_q);
258 card_tx_q_pause(card, priority_q);
259 if (CSR_WIFI_HIP_Q_SLOTS_USED(sigq) == 0)
260 {
261 card_tx_q_unpause(card, priority_q);
262 unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue) priority_q);
263 }
264 }
265 else
266 {
267 unifi_warning(card->ospriv,
268 "send_signal: fh_cmd_q full, not pausing (run_bh=%d)\n",
269 run_bh);
270 }
271 }
272
273 return CSR_RESULT_SUCCESS;
274 } /* send_signal() */
275
276
277 /*
278 * ---------------------------------------------------------------------------
279 * unifi_send_signal
280 *
281 * Invokes send_signal() to queue a signal in the command or traffic queue
282 * If sigptr pointer is NULL, it pokes the bh to check if UniFi is responsive.
283 *
284 * Arguments:
285 * card Pointer to card context struct
286 * sigptr Pointer to signal from card.
287 * siglen Size of the signal
288 * bulkdata Pointer to the bulk data of the signal
289 *
290 * Returns:
291 * CSR_RESULT_SUCCESS on success
292 * CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or no free signal queue entry
293 *
294 * Notes:
295 * unifi_send_signal() is used to queue signals, created by the driver,
296 * to the device. Signals are constructed using the UniFi packed structures.
297 * ---------------------------------------------------------------------------
298 */
299 CsrResult unifi_send_signal(card_t *card, const u8 *sigptr, u32 siglen,
300 const bulk_data_param_t *bulkdata)
301 {
302 q_t *sig_soft_q;
303 u16 signal_id;
304 CsrResult r;
305 u32 run_bh;
306 u32 priority_q;
307
308 /* A NULL signal pointer is a request to check if UniFi is responsive */
309 if (sigptr == NULL)
310 {
311 card->bh_reason_host = 1;
312 return unifi_run_bh(card->ospriv);
313 }
314
315 priority_q = 0;
316 run_bh = 1;
317 signal_id = GET_SIGNAL_ID(sigptr);
318 /*
319 * If the signal is a CSR_MA_PACKET_REQUEST ,
320 * we send it using the traffic soft queue. Else we use the command soft queue.
321 */
322 if (signal_id == CSR_MA_PACKET_REQUEST_ID)
323 {
324 u16 frame_priority;
325
326 if (card->periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_ENABLED)
327 {
328 run_bh = 0;
329 }
330
331 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
332 unifi_debug_log_to_buf("D");
333 #endif
334 /* Sanity check: MA-PACKET.req must have a valid bulk data */
335 if ((bulkdata->d[0].data_length == 0) || (bulkdata->d[0].os_data_ptr == NULL))
336 {
337 unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n",
338 bulkdata->d[0].data_length, bulkdata->d[0].os_data_ptr);
339 dump((void *)sigptr, siglen);
340 return CSR_RESULT_FAILURE;
341 }
342
343 /* Map the frame priority to a traffic queue index. */
344 frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr);
345 priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority);
346
347 sig_soft_q = &card->fh_traffic_queue[priority_q];
348 }
349 else
350 {
351 sig_soft_q = &card->fh_command_queue;
352 }
353
354 r = send_signal(card, sigptr, siglen, bulkdata, sig_soft_q, priority_q, run_bh);
355 /* On error, the caller must free or requeue bulkdata buffers */
356
357 return r;
358 } /* unifi_send_signal() */
359
360
361 /*
362 * ---------------------------------------------------------------------------
363 * unifi_send_resources_available
364 *
365 * Examines whether there is available space to queue
366 * a signal in the command or traffic queue
367 *
368 * Arguments:
369 * card Pointer to card context struct
370 * sigptr Pointer to signal.
371 *
372 * Returns:
373 * CSR_RESULT_SUCCESS if resources available
374 * CSR_WIFI_HIP_RESULT_NO_SPACE if there was no free signal queue entry
375 *
376 * Notes:
377 * ---------------------------------------------------------------------------
378 */
379 CsrResult unifi_send_resources_available(card_t *card, const u8 *sigptr)
380 {
381 q_t *sig_soft_q;
382 u16 signal_id = GET_SIGNAL_ID(sigptr);
383
384 /*
385 * If the signal is a CSR_MA_PACKET_REQUEST ,
386 * we send it using the traffic soft queue. Else we use the command soft queue.
387 */
388 if (signal_id == CSR_MA_PACKET_REQUEST_ID)
389 {
390 u16 frame_priority;
391 u32 priority_q;
392
393 /* Map the frame priority to a traffic queue index. */
394 frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr);
395 priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority);
396
397 sig_soft_q = &card->fh_traffic_queue[priority_q];
398 }
399 else
400 {
401 sig_soft_q = &card->fh_command_queue;
402 }
403
404 /* Check that the fh_data_queue has a free slot */
405 if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sig_soft_q))
406 {
407 unifi_notice(card->ospriv, "unifi_send_resources_available: %s full\n",
408 sig_soft_q->name);
409 return CSR_WIFI_HIP_RESULT_NO_SPACE;
410 }
411
412 return CSR_RESULT_SUCCESS;
413 } /* unifi_send_resources_available() */
414
415
This page took 0.039723 seconds and 5 git commands to generate.