Fix race condition between vxlan_sock_add and vxlan_sock_release
[cascardo/linux.git] / sound / pci / asihpi / hpicmn.c
1 /******************************************************************************
2
3     AudioScience HPI driver
4     Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of version 2 of the GNU General Public License as
8     published by the Free Software Foundation;
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19 \file hpicmn.c
20
21  Common functions used by hpixxxx.c modules
22
23 (C) Copyright AudioScience Inc. 1998-2003
24 *******************************************************************************/
25 #define SOURCEFILE_NAME "hpicmn.c"
26
27 #include "hpi_internal.h"
28 #include "hpidebug.h"
29 #include "hpimsginit.h"
30
31 #include "hpicmn.h"
32
33 struct hpi_adapters_list {
34         struct hpios_spinlock list_lock;
35         struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
36         u16 gw_num_adapters;
37 };
38
39 static struct hpi_adapters_list adapters;
40
41 /**
42 * Given an HPI Message that was sent out and a response that was received,
43 * validate that the response has the correct fields filled in,
44 * i.e ObjectType, Function etc
45 **/
46 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
47 {
48         if (phr->type != HPI_TYPE_RESPONSE) {
49                 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
50                 return HPI_ERROR_INVALID_RESPONSE;
51         }
52
53         if (phr->object != phm->object) {
54                 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
55                         phr->object);
56                 return HPI_ERROR_INVALID_RESPONSE;
57         }
58
59         if (phr->function != phm->function) {
60                 HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
61                         phr->function);
62                 return HPI_ERROR_INVALID_RESPONSE;
63         }
64
65         return 0;
66 }
67
68 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
69 {
70         u16 retval = 0;
71         /*HPI_ASSERT(pao->type); */
72
73         hpios_alistlock_lock(&adapters);
74
75         if (pao->index >= HPI_MAX_ADAPTERS) {
76                 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
77                 goto unlock;
78         }
79
80         if (adapters.adapter[pao->index].type) {
81                 int a;
82                 for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
83                         if (!adapters.adapter[a].type) {
84                                 HPI_DEBUG_LOG(WARNING,
85                                         "ASI%X duplicate index %d moved to %d\n",
86                                         pao->type, pao->index, a);
87                                 pao->index = a;
88                                 break;
89                         }
90                 }
91                 if (a < 0) {
92                         retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
93                         goto unlock;
94                 }
95         }
96         adapters.adapter[pao->index] = *pao;
97         hpios_dsplock_init(&adapters.adapter[pao->index]);
98         adapters.gw_num_adapters++;
99
100 unlock:
101         hpios_alistlock_unlock(&adapters);
102         return retval;
103 }
104
105 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
106 {
107         if (!pao->type) {
108                 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
109                 return;
110         }
111
112         hpios_alistlock_lock(&adapters);
113         if (adapters.adapter[pao->index].type)
114                 adapters.gw_num_adapters--;
115         memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
116         hpios_alistlock_unlock(&adapters);
117 }
118
119 /**
120 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
121 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
122 *
123 */
124 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
125 {
126         struct hpi_adapter_obj *pao = NULL;
127
128         if (adapter_index >= HPI_MAX_ADAPTERS) {
129                 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
130                         adapter_index);
131                 return NULL;
132         }
133
134         pao = &adapters.adapter[adapter_index];
135         if (pao->type != 0) {
136                 /*
137                    HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
138                    wAdapterIndex);
139                  */
140                 return pao;
141         } else {
142                 /*
143                    HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
144                    wAdapterIndex);
145                  */
146                 return NULL;
147         }
148 }
149
150 /**
151 *
152 * wipe an HPI_ADAPTERS_LIST structure.
153 *
154 **/
155 static void wipe_adapter_list(void)
156 {
157         memset(&adapters, 0, sizeof(adapters));
158 }
159
160 static void subsys_get_adapter(struct hpi_message *phm,
161         struct hpi_response *phr)
162 {
163         int count = phm->obj_index;
164         u16 index = 0;
165
166         /* find the nCount'th nonzero adapter in array */
167         for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
168                 if (adapters.adapter[index].type) {
169                         if (!count)
170                                 break;
171                         count--;
172                 }
173         }
174
175         if (index < HPI_MAX_ADAPTERS) {
176                 phr->u.s.adapter_index = adapters.adapter[index].index;
177                 phr->u.s.adapter_type = adapters.adapter[index].type;
178         } else {
179                 phr->u.s.adapter_index = 0;
180                 phr->u.s.adapter_type = 0;
181                 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
182         }
183 }
184
185 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
186 {
187         unsigned int i;
188         int cached = 0;
189         if (!pC)
190                 return 0;
191
192         if (pC->init)
193                 return pC->init;
194
195         if (!pC->p_cache)
196                 return 0;
197
198         if (pC->control_count && pC->cache_size_in_bytes) {
199                 char *p_master_cache;
200                 unsigned int byte_count = 0;
201
202                 p_master_cache = (char *)pC->p_cache;
203                 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
204                         pC->control_count);
205                 for (i = 0; i < pC->control_count; i++) {
206                         struct hpi_control_cache_info *info =
207                                 (struct hpi_control_cache_info *)
208                                 &p_master_cache[byte_count];
209
210                         if (!info->size_in32bit_words) {
211                                 if (!i) {
212                                         HPI_DEBUG_LOG(INFO,
213                                                 "adap %d cache not ready?\n",
214                                                 pC->adap_idx);
215                                         return 0;
216                                 }
217                                 /* The cache is invalid.
218                                  * Minimum valid entry size is
219                                  * sizeof(struct hpi_control_cache_info)
220                                  */
221                                 HPI_DEBUG_LOG(ERROR,
222                                         "adap %d zero size cache entry %d\n",
223                                         pC->adap_idx, i);
224                                 break;
225                         }
226
227                         if (info->control_type) {
228                                 pC->p_info[info->control_index] = info;
229                                 cached++;
230                         } else {        /* dummy cache entry */
231                                 pC->p_info[info->control_index] = NULL;
232                         }
233
234                         byte_count += info->size_in32bit_words * 4;
235
236                         HPI_DEBUG_LOG(VERBOSE,
237                                 "cached %d, pinfo %p index %d type %d size %d\n",
238                                 cached, pC->p_info[info->control_index],
239                                 info->control_index, info->control_type,
240                                 info->size_in32bit_words);
241
242                         /* quit loop early if whole cache has been scanned.
243                          * dwControlCount is the maximum possible entries
244                          * but some may be absent from the cache
245                          */
246                         if (byte_count >= pC->cache_size_in_bytes)
247                                 break;
248                         /* have seen last control index */
249                         if (info->control_index == pC->control_count - 1)
250                                 break;
251                 }
252
253                 if (byte_count != pC->cache_size_in_bytes)
254                         HPI_DEBUG_LOG(WARNING,
255                                 "adap %d bytecount %d != cache size %d\n",
256                                 pC->adap_idx, byte_count,
257                                 pC->cache_size_in_bytes);
258                 else
259                         HPI_DEBUG_LOG(DEBUG,
260                                 "adap %d cache good, bytecount == cache size = %d\n",
261                                 pC->adap_idx, byte_count);
262
263                 pC->init = (u16)cached;
264         }
265         return pC->init;
266 }
267
268 /** Find a control.
269 */
270 static short find_control(u16 control_index,
271         struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
272 {
273         if (!control_cache_alloc_check(p_cache)) {
274                 HPI_DEBUG_LOG(VERBOSE,
275                         "control_cache_alloc_check() failed %d\n",
276                         control_index);
277                 return 0;
278         }
279
280         *pI = p_cache->p_info[control_index];
281         if (!*pI) {
282                 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
283                         control_index);
284                 return 0;
285         } else {
286                 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
287                         (*pI)->control_type);
288         }
289         return 1;
290 }
291
292 /* allow unified treatment of several string fields within struct */
293 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
294         offsetof(struct hpi_control_cache_pad, m), \
295         sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
296
297 struct pad_ofs_size {
298         unsigned int offset;
299         unsigned int field_size;
300 };
301
302 static const struct pad_ofs_size pad_desc[] = {
303         HPICMN_PAD_OFS_AND_SIZE(c_channel),     /* HPI_PAD_CHANNEL_NAME */
304         HPICMN_PAD_OFS_AND_SIZE(c_artist),      /* HPI_PAD_ARTIST */
305         HPICMN_PAD_OFS_AND_SIZE(c_title),       /* HPI_PAD_TITLE */
306         HPICMN_PAD_OFS_AND_SIZE(c_comment),     /* HPI_PAD_COMMENT */
307 };
308
309 /** CheckControlCache checks the cache and fills the struct hpi_response
310  * accordingly. It returns one if a cache hit occurred, zero otherwise.
311  */
312 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
313         struct hpi_message *phm, struct hpi_response *phr)
314 {
315         short found = 1;
316         struct hpi_control_cache_info *pI;
317         struct hpi_control_cache_single *pC;
318         size_t response_size;
319         if (!find_control(phm->obj_index, p_cache, &pI)) {
320                 HPI_DEBUG_LOG(VERBOSE,
321                         "HPICMN find_control() failed for adap %d\n",
322                         phm->adapter_index);
323                 return 0;
324         }
325
326         phr->error = 0;
327         phr->specific_error = 0;
328         phr->version = 0;
329
330         /* set the default response size */
331         response_size =
332                 sizeof(struct hpi_response_header) +
333                 sizeof(struct hpi_control_res);
334
335         /* pC is the default cached control strucure. May be cast to
336            something else in the following switch statement.
337          */
338         pC = (struct hpi_control_cache_single *)pI;
339
340         switch (pI->control_type) {
341
342         case HPI_CONTROL_METER:
343                 if (phm->u.c.attribute == HPI_METER_PEAK) {
344                         phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
345                         phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
346                 } else if (phm->u.c.attribute == HPI_METER_RMS) {
347                         if (pC->u.meter.an_logRMS[0] ==
348                                 HPI_CACHE_INVALID_SHORT) {
349                                 phr->error =
350                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
351                                 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
352                                 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
353                         } else {
354                                 phr->u.c.an_log_value[0] =
355                                         pC->u.meter.an_logRMS[0];
356                                 phr->u.c.an_log_value[1] =
357                                         pC->u.meter.an_logRMS[1];
358                         }
359                 } else
360                         found = 0;
361                 break;
362         case HPI_CONTROL_VOLUME:
363                 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
364                         phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
365                         phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
366                 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
367                         if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
368                                 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
369                                         phr->u.c.param1 =
370                                                 HPI_BITMASK_ALL_CHANNELS;
371                                 else
372                                         phr->u.c.param1 = 0;
373                         } else {
374                                 phr->error =
375                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
376                                 phr->u.c.param1 = 0;
377                         }
378                 } else {
379                         found = 0;
380                 }
381                 break;
382         case HPI_CONTROL_MULTIPLEXER:
383                 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
384                         phr->u.c.param1 = pC->u.mux.source_node_type;
385                         phr->u.c.param2 = pC->u.mux.source_node_index;
386                 } else {
387                         found = 0;
388                 }
389                 break;
390         case HPI_CONTROL_CHANNEL_MODE:
391                 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
392                         phr->u.c.param1 = pC->u.mode.mode;
393                 else
394                         found = 0;
395                 break;
396         case HPI_CONTROL_LEVEL:
397                 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
398                         phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
399                         phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
400                 } else
401                         found = 0;
402                 break;
403         case HPI_CONTROL_TUNER:
404                 if (phm->u.c.attribute == HPI_TUNER_FREQ)
405                         phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
406                 else if (phm->u.c.attribute == HPI_TUNER_BAND)
407                         phr->u.c.param1 = pC->u.tuner.band;
408                 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
409                         if (pC->u.tuner.s_level_avg ==
410                                 HPI_CACHE_INVALID_SHORT) {
411                                 phr->u.cu.tuner.s_level = 0;
412                                 phr->error =
413                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
414                         } else
415                                 phr->u.cu.tuner.s_level =
416                                         pC->u.tuner.s_level_avg;
417                 else
418                         found = 0;
419                 break;
420         case HPI_CONTROL_AESEBU_RECEIVER:
421                 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
422                         phr->u.c.param1 = pC->u.aes3rx.error_status;
423                 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
424                         phr->u.c.param1 = pC->u.aes3rx.format;
425                 else
426                         found = 0;
427                 break;
428         case HPI_CONTROL_AESEBU_TRANSMITTER:
429                 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
430                         phr->u.c.param1 = pC->u.aes3tx.format;
431                 else
432                         found = 0;
433                 break;
434         case HPI_CONTROL_TONEDETECTOR:
435                 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
436                         phr->u.c.param1 = pC->u.tone.state;
437                 else
438                         found = 0;
439                 break;
440         case HPI_CONTROL_SILENCEDETECTOR:
441                 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
442                         phr->u.c.param1 = pC->u.silence.state;
443                 } else
444                         found = 0;
445                 break;
446         case HPI_CONTROL_MICROPHONE:
447                 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
448                         phr->u.c.param1 = pC->u.microphone.phantom_state;
449                 else
450                         found = 0;
451                 break;
452         case HPI_CONTROL_SAMPLECLOCK:
453                 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
454                         phr->u.c.param1 = pC->u.clk.source;
455                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
456                         if (pC->u.clk.source_index ==
457                                 HPI_CACHE_INVALID_UINT16) {
458                                 phr->u.c.param1 = 0;
459                                 phr->error =
460                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
461                         } else
462                                 phr->u.c.param1 = pC->u.clk.source_index;
463                 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
464                         phr->u.c.param1 = pC->u.clk.sample_rate;
465                 else
466                         found = 0;
467                 break;
468         case HPI_CONTROL_PAD:{
469                         struct hpi_control_cache_pad *p_pad;
470                         p_pad = (struct hpi_control_cache_pad *)pI;
471
472                         if (!(p_pad->field_valid_flags & (1 <<
473                                                 HPI_CTL_ATTR_INDEX(phm->u.c.
474                                                         attribute)))) {
475                                 phr->error =
476                                         HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
477                                 break;
478                         }
479
480                         if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
481                                 phr->u.c.param1 = p_pad->pI;
482                         else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
483                                 phr->u.c.param1 = p_pad->pTY;
484                         else {
485                                 unsigned int index =
486                                         HPI_CTL_ATTR_INDEX(phm->u.c.
487                                         attribute) - 1;
488                                 unsigned int offset = phm->u.c.param1;
489                                 unsigned int pad_string_len, field_size;
490                                 char *pad_string;
491                                 unsigned int tocopy;
492
493                                 if (index > ARRAY_SIZE(pad_desc) - 1) {
494                                         phr->error =
495                                                 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
496                                         break;
497                                 }
498
499                                 pad_string =
500                                         ((char *)p_pad) +
501                                         pad_desc[index].offset;
502                                 field_size = pad_desc[index].field_size;
503                                 /* Ensure null terminator */
504                                 pad_string[field_size - 1] = 0;
505
506                                 pad_string_len = strlen(pad_string) + 1;
507
508                                 if (offset > pad_string_len) {
509                                         phr->error =
510                                                 HPI_ERROR_INVALID_CONTROL_VALUE;
511                                         break;
512                                 }
513
514                                 tocopy = pad_string_len - offset;
515                                 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
516                                         tocopy = sizeof(phr->u.cu.chars8.
517                                                 sz_data);
518
519                                 memcpy(phr->u.cu.chars8.sz_data,
520                                         &pad_string[offset], tocopy);
521
522                                 phr->u.cu.chars8.remaining_chars =
523                                         pad_string_len - offset - tocopy;
524                         }
525                 }
526                 break;
527         default:
528                 found = 0;
529                 break;
530         }
531
532         HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
533                 found ? "Cached" : "Uncached", phm->adapter_index,
534                 pI->control_index, pI->control_type, phm->u.c.attribute);
535
536         if (found) {
537                 phr->size = (u16)response_size;
538                 phr->type = HPI_TYPE_RESPONSE;
539                 phr->object = phm->object;
540                 phr->function = phm->function;
541         }
542
543         return found;
544 }
545
546 /** Updates the cache with Set values.
547
548 Only update if no error.
549 Volume and Level return the limited values in the response, so use these
550 Multiplexer does so use sent values
551 */
552 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
553         struct hpi_message *phm, struct hpi_response *phr)
554 {
555         struct hpi_control_cache_single *pC;
556         struct hpi_control_cache_info *pI;
557
558         if (phr->error)
559                 return;
560
561         if (!find_control(phm->obj_index, p_cache, &pI)) {
562                 HPI_DEBUG_LOG(VERBOSE,
563                         "HPICMN find_control() failed for adap %d\n",
564                         phm->adapter_index);
565                 return;
566         }
567
568         /* pC is the default cached control strucure.
569            May be cast to something else in the following switch statement.
570          */
571         pC = (struct hpi_control_cache_single *)pI;
572
573         switch (pI->control_type) {
574         case HPI_CONTROL_VOLUME:
575                 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
576                         pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
577                         pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
578                 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
579                         if (phm->u.c.param1)
580                                 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
581                         else
582                                 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
583                 }
584                 break;
585         case HPI_CONTROL_MULTIPLEXER:
586                 /* mux does not return its setting on Set command. */
587                 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
588                         pC->u.mux.source_node_type = (u16)phm->u.c.param1;
589                         pC->u.mux.source_node_index = (u16)phm->u.c.param2;
590                 }
591                 break;
592         case HPI_CONTROL_CHANNEL_MODE:
593                 /* mode does not return its setting on Set command. */
594                 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
595                         pC->u.mode.mode = (u16)phm->u.c.param1;
596                 break;
597         case HPI_CONTROL_LEVEL:
598                 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
599                         pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
600                         pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
601                 }
602                 break;
603         case HPI_CONTROL_MICROPHONE:
604                 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
605                         pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
606                 break;
607         case HPI_CONTROL_AESEBU_TRANSMITTER:
608                 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
609                         pC->u.aes3tx.format = phm->u.c.param1;
610                 break;
611         case HPI_CONTROL_AESEBU_RECEIVER:
612                 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
613                         pC->u.aes3rx.format = phm->u.c.param1;
614                 break;
615         case HPI_CONTROL_SAMPLECLOCK:
616                 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
617                         pC->u.clk.source = (u16)phm->u.c.param1;
618                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
619                         pC->u.clk.source_index = (u16)phm->u.c.param1;
620                 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
621                         pC->u.clk.sample_rate = phm->u.c.param1;
622                 break;
623         default:
624                 break;
625         }
626 }
627
628 /** Allocate control cache.
629
630 \return Cache pointer, or NULL if allocation fails.
631 */
632 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
633         const u32 size_in_bytes, u8 *p_dsp_control_buffer)
634 {
635         struct hpi_control_cache *p_cache =
636                 kmalloc(sizeof(*p_cache), GFP_KERNEL);
637         if (!p_cache)
638                 return NULL;
639
640         p_cache->p_info = kcalloc(control_count, sizeof(*p_cache->p_info),
641                                   GFP_KERNEL);
642         if (!p_cache->p_info) {
643                 kfree(p_cache);
644                 return NULL;
645         }
646         p_cache->cache_size_in_bytes = size_in_bytes;
647         p_cache->control_count = control_count;
648         p_cache->p_cache = p_dsp_control_buffer;
649         p_cache->init = 0;
650         return p_cache;
651 }
652
653 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
654 {
655         if (p_cache) {
656                 kfree(p_cache->p_info);
657                 kfree(p_cache);
658         }
659 }
660
661 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
662 {
663         hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
664
665         switch (phm->function) {
666         case HPI_SUBSYS_OPEN:
667         case HPI_SUBSYS_CLOSE:
668         case HPI_SUBSYS_DRIVER_UNLOAD:
669                 break;
670         case HPI_SUBSYS_DRIVER_LOAD:
671                 wipe_adapter_list();
672                 hpios_alistlock_init(&adapters);
673                 break;
674         case HPI_SUBSYS_GET_ADAPTER:
675                 subsys_get_adapter(phm, phr);
676                 break;
677         case HPI_SUBSYS_GET_NUM_ADAPTERS:
678                 phr->u.s.num_adapters = adapters.gw_num_adapters;
679                 break;
680         case HPI_SUBSYS_CREATE_ADAPTER:
681                 break;
682         default:
683                 phr->error = HPI_ERROR_INVALID_FUNC;
684                 break;
685         }
686 }
687
688 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
689 {
690         switch (phm->type) {
691         case HPI_TYPE_REQUEST:
692                 switch (phm->object) {
693                 case HPI_OBJ_SUBSYSTEM:
694                         subsys_message(phm, phr);
695                         break;
696                 }
697                 break;
698
699         default:
700                 phr->error = HPI_ERROR_INVALID_TYPE;
701                 break;
702         }
703 }