source: GPL/branches/uniaud32-exp/lib32/misc.c@ 737

Last change on this file since 737 was 737, checked in by Paul Smedley, 3 years ago

Initial commit of 5.17.15

File size: 26.3 KB
Line 
1/* $Id: misc.c,v 1.1.1.1 2003/07/02 13:57:02 eleph Exp $ */
2/*
3 * OS/2 implementation of misc. Linux kernel services
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * hweight32 based on Linux code (bitops.h)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
23 * USA.
24 *
25 */
26#include <limits.h>
27#include "linux.h"
28#include <linux/init.h>
29#include <linux/fs.h>
30#include <linux/of.h>
31#include <linux/poll.h>
32#define CONFIG_PROC_FS 1
33#include <linux/proc_fs.h>
34#include <asm/uaccess.h>
35#include <asm/hardirq.h>
36#include <linux\ioport.h>
37#include <linux\utsname.h>
38#include <linux\module.h>
39#include <linux/workqueue.h>
40#include <linux/firmware.h>
41#include <linux/ctype.h>
42#include <dbgos2.h>
43
44void StringOut(char *DbgStr);
45
46struct new_utsname system_utsname = {0};
47struct resource ioport_resource = {NULL, 0, 0, IORESOURCE_IO, NULL, NULL, NULL};
48struct resource iomem_resource = {NULL, 0, 0, IORESOURCE_MEM, NULL, NULL, NULL};
49mem_map_t *mem_map = 0;
50int this_module[64] = {0};
51
52#include <stdarg.h>
53
54char szLastALSAError1[128] = {0};
55char szOverrunTest1 = 0xCC;
56char szLastALSAError2[128] = {0};
57char szOverrunTest2 = 0xCC;
58int iLastError = 0;
59
60//******************************************************************************
61//Save error message in szLastALSAError; if card init failed, then we will
62//print it in drv32\init.cpp
63//******************************************************************************
64int printk(const char * fmt, ...)
65{
66 va_list argptr; /* -> variable argument list */
67
68 char *pszLastALSAError;
69
70 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
71
72 va_start(argptr, fmt); /* get pointer to argument list */
73 vsprintf(pszLastALSAError, fmt, argptr);
74// strcat(pszLastALSAError, "\r");
75 va_end(argptr); /* done with variable arguments */
76
77 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
78 DebugInt3();
79 }
80
81 StringOut(pszLastALSAError);
82// rprintf( (pszLastALSAError) );
83 if(++iLastError > 1) {
84 iLastError = 0;
85 }
86 return 0;
87}
88
89//******************************************************************************
90//Save error message in szLastALSAError; if card init failed, then we will
91//print it in drv32\init.cpp
92//******************************************************************************
93int dev_dbg(const struct device *dev, const char * fmt, ...)
94{
95 va_list argptr; /* -> variable argument list */
96
97 char *pszLastALSAError;
98
99 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
100
101 va_start(argptr, fmt); /* get pointer to argument list */
102 vsprintf(pszLastALSAError, fmt, argptr);
103// strcat(pszLastALSAError, "\r");
104 va_end(argptr); /* done with variable arguments */
105
106 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
107 DebugInt3();
108 }
109
110 StringOut(pszLastALSAError);
111// rprintf( (pszLastALSAError) );
112 if(++iLastError > 1) {
113 iLastError = 0;
114 }
115 return 0;
116}
117//******************************************************************************
118int pcm_dbg(struct snd_pcm *dev, const char * fmt, ...)
119{
120 va_list argptr; /* -> variable argument list */
121
122 char *pszLastALSAError;
123
124 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
125
126 va_start(argptr, fmt); /* get pointer to argument list */
127 vsprintf(pszLastALSAError, fmt, argptr);
128// strcat(pszLastALSAError, "\r");
129 va_end(argptr); /* done with variable arguments */
130
131 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
132 DebugInt3();
133 }
134
135 StringOut(pszLastALSAError);
136// rprintf( (pszLastALSAError) );
137 if(++iLastError > 1) {
138 iLastError = 0;
139 }
140 return 0;
141}
142//******************************************************************************
143int codec_dbg(struct hda_codec *dev, const char * fmt, ...)
144{
145 va_list argptr; /* -> variable argument list */
146
147 char *pszLastALSAError;
148
149 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
150
151 va_start(argptr, fmt); /* get pointer to argument list */
152 vsprintf(pszLastALSAError, fmt, argptr);
153// strcat(pszLastALSAError, "\r");
154 va_end(argptr); /* done with variable arguments */
155
156 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
157 DebugInt3();
158 }
159
160 StringOut(pszLastALSAError);
161// rprintf( (pszLastALSAError) );
162 if(++iLastError > 1) {
163 iLastError = 0;
164 }
165 return 0;
166}
167//******************************************************************************
168//******************************************************************************
169void schedule(void)
170{
171
172}
173//******************************************************************************
174//******************************************************************************
175void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
176{
177
178}
179//******************************************************************************
180//******************************************************************************
181int __check_region(struct resource *a, unsigned long b, unsigned long c)
182{
183 DebugInt3();
184 return 0;
185}
186
187/* --------------------------------------------------------------------- */
188/*
189 * hweightN: returns the hamming weight (i.e. the number
190 * of bits set) of a N-bit word
191 */
192
193#ifdef hweight32
194#undef hweight32
195#endif
196
197unsigned int hweight32(unsigned int w)
198{
199 unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
200 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
201 res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
202 res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
203 return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
204}
205//******************************************************************************
206//******************************************************************************
207#if 0
208mem_map_t *virt_to_page(int x)
209{
210 static mem_map_t map = {0};
211 return &map;
212}
213#endif
214//******************************************************************************
215//******************************************************************************
216struct proc_dir_entry proc_root = {0};
217//******************************************************************************
218//******************************************************************************
219struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
220 struct proc_dir_entry *parent)
221{
222 struct proc_dir_entry *proc;
223 proc = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), 0);
224 memset(proc, 0, sizeof(struct proc_dir_entry));
225
226 proc->name = name;
227 proc->mode = mode;
228 proc->parent = parent;
229
230 return proc;
231}
232//******************************************************************************
233//******************************************************************************
234void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
235{
236 return; //memory leak
237}
238//******************************************************************************
239//******************************************************************************
240int proc_register(struct proc_dir_entry *parent, struct proc_dir_entry *proc)
241{
242 return 0;
243}
244//******************************************************************************
245//******************************************************************************
246int proc_unregister(struct proc_dir_entry *proc, int bla)
247{
248 return 0;
249}
250//******************************************************************************
251//******************************************************************************
252struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
253 struct proc_dir_entry *parent){
254 struct proc_dir_entry *proc;
255 proc = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), 0);
256 memset(proc, 0, sizeof(struct proc_dir_entry));
257
258 proc->name = name;
259 proc->parent = parent;
260
261 return proc;
262}
263//******************************************************************************
264//******************************************************************************
265struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
266{
267 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
268}
269//******************************************************************************
270//******************************************************************************
271struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest)
272{
273 struct proc_dir_entry *proc;
274 proc = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), 0);
275 memset(proc, 0, sizeof(struct proc_dir_entry));
276
277 proc->name = name;
278 proc->parent = parent;
279 proc->data = (void*)dest;
280
281 return proc;
282}
283//******************************************************************************
284//******************************************************************************
285int fasync_helper(int a, struct file *b, int c, struct fasync_struct **d)
286{
287 return 0;
288}
289//******************************************************************************
290//******************************************************************************
291void kill_fasync(struct fasync_struct **a, int b, int c)
292{
293}
294//******************************************************************************
295//******************************************************************************
296int request_dma(unsigned int dmanr, const char * device_id) /* reserve a DMA channel */
297{
298 DebugInt3();
299 return 0;
300}
301//******************************************************************************
302//******************************************************************************
303void free_dma(unsigned int dmanr)
304{
305 DebugInt3();
306}
307//******************************************************************************
308/* enable/disable a specific DMA channel */
309//******************************************************************************
310void enable_dma(unsigned int dmanr)
311{
312 DebugInt3();
313}
314//******************************************************************************
315//******************************************************************************
316void disable_dma(unsigned int dmanr)
317{
318 DebugInt3();
319}
320//******************************************************************************
321//static struct notifier_block *reboot_notify_list = NULL;
322// No need to implement this right now. The ESS Maestro 3 driver uses it
323// to call pci_unregister_driver, which is always called from the shutdown
324// notification sent by OS2.
325// Same goes for es1968 & Yamaha's DS1/DS1E.
326//******************************************************************************
327int register_reboot_notifier(struct notifier_block *pnblock)
328{
329 return 0;
330}
331//******************************************************************************
332//******************************************************************************
333int unregister_reboot_notifier(struct notifier_block *pnblock)
334{
335 return 0;
336}
337//******************************************************************************
338//******************************************************************************
339static void __x_queue_work(struct workqueue_struct *wq, struct work_struct *work)
340{
341 unsigned long flags;
342
343 spin_lock_irqsave(&wq->lock, flags);
344 work->wq_data = wq;
345 list_add_tail(&work->entry, &wq->worklist);
346 wake_up(&wq->more_work);
347 spin_unlock_irqrestore(&wq->lock, flags);
348}
349//******************************************************************************
350//******************************************************************************
351int queue_work(struct workqueue_struct *wq, struct work_struct *work)
352{
353 if (!test_and_set_bit(0, &work->pending)) {
354 __x_queue_work(wq, work);
355 return 1;
356 }
357 return 0;
358}
359//******************************************************************************
360//******************************************************************************
361static void run_workqueue(struct workqueue_struct *wq)
362{
363 unsigned long flags;
364
365 spin_lock_irqsave(&wq->lock, flags);
366 while (!list_empty(&wq->worklist)) {
367 struct work_struct *work = list_entry(wq->worklist.next,
368 struct work_struct, entry);
369 void (*f) (void *) = work->func;
370 void *data = work->data;
371
372 list_del_init(wq->worklist.next);
373 spin_unlock_irqrestore(&wq->lock, flags);
374 clear_bit(0, &work->pending);
375 f(data);
376 spin_lock_irqsave(&wq->lock, flags);
377 wake_up(&wq->work_done);
378 }
379 spin_unlock_irqrestore(&wq->lock, flags);
380}
381//******************************************************************************
382//******************************************************************************
383void flush_workqueue(struct workqueue_struct *wq)
384{
385
386 if (wq->task == current) {
387 run_workqueue(wq);
388 } else {
389 struct wait_queue_entry wait;
390
391 init_waitqueue_entry(&wait, current);
392 set_current_state(TASK_UNINTERRUPTIBLE);
393 spin_lock_irq(&wq->lock);
394 add_wait_queue(&wq->work_done, &wait);
395#ifndef TARGET_OS2
396 while (!list_empty(&wq->worklist)) {
397 spin_unlock_irq(&wq->lock);
398 schedule(); // DAZ system hangs here because this function does nothing
399 spin_lock_irq(&wq->lock);
400 }
401#endif
402 set_current_state(TASK_RUNNING);
403 remove_wait_queue(&wq->work_done, &wait);
404 spin_unlock_irq(&wq->lock);
405 }
406}
407//******************************************************************************
408//******************************************************************************
409struct workqueue_struct *create_workqueue(const char *name)
410{
411 struct workqueue_struct *wq;
412
413 BUG_ON(strlen(name) > 10);
414
415 wq = kmalloc(sizeof(*wq), GFP_KERNEL);
416 if (!wq)
417 return NULL;
418 memset(wq, 0, sizeof(*wq));
419
420 spin_lock_init(&wq->lock);
421 INIT_LIST_HEAD(&wq->worklist);
422 init_waitqueue_head(&wq->more_work);
423 init_waitqueue_head(&wq->work_done);
424#ifndef TARGET_OS2
425 init_completion(&wq->thread_exited);
426 wq->name = name;
427 wq->task_pid = kernel_thread(xworker_thread, wq, 0);
428 if (wq->task_pid < 0) {
429 printk(KERN_ERR "snd: failed to start thread %s\n", name);
430 snd_compat_destroy_workqueue(wq);
431 wq = NULL;
432 }
433 wq->task = find_task_by_pid(wq->task_pid);
434#endif
435 return wq;
436}
437//******************************************************************************
438//******************************************************************************
439void destroy_workqueue(struct workqueue_struct *wq)
440{
441#ifndef TARGET_OS2
442 snd_compat_flush_workqueue(wq);
443 kill_proc(wq->task_pid, SIGKILL, 1);
444 if (wq->task_pid >= 0)
445 wait_for_completion(&wq->thread_exited);
446#endif
447 kfree(wq);
448}
449
450//******************************************************************************
451//******************************************************************************
452char *kstrdup(const char *s, unsigned int __nocast gfp_flags)
453{
454 int len;
455 char *buf;
456
457 if (!s) return NULL;
458
459 len = strlen(s) + 1;
460 buf = kmalloc(len, gfp_flags);
461 if (buf)
462 memcpy(buf, s, len);
463 return buf;
464}
465//******************************************************************************
466//******************************************************************************
467int mod_firmware_load(const char *fn, char **fp)
468{
469 return 0;
470}
471//******************************************************************************
472//******************************************************************************
473static int snd_try_load_firmware(const char *path, const char *name,
474 struct firmware *firmware)
475{
476 char filename[30 + FIRMWARE_NAME_MAX];
477
478 sprintf(filename, "%s/%s", path, name);
479 firmware->size = mod_firmware_load(filename, (char **)&firmware->data);
480 if (firmware->size)
481 printk(KERN_INFO "Loaded '%s'.", filename);
482 return firmware->size;
483}
484//******************************************************************************
485//******************************************************************************
486int request_firmware(const struct firmware **fw, const char *name,
487 struct device *device)
488{
489 struct firmware *firmware;
490
491 *fw = NULL;
492 firmware = kmalloc(sizeof *firmware, GFP_KERNEL);
493 if (!firmware)
494 return -ENOMEM;
495 if (!snd_try_load_firmware("/lib/firmware", name, firmware) &&
496 !snd_try_load_firmware("/lib/hotplug/firmware", name, firmware) &&
497 !snd_try_load_firmware("/usr/lib/hotplug/firmware", name, firmware)) {
498 kfree(firmware);
499 return -EIO;
500 }
501 *fw = firmware;
502 return 0;
503}
504//******************************************************************************
505//******************************************************************************
506void release_firmware(const struct firmware *fw)
507{
508 if (fw) {
509 vfree(fw->data);
510 kfree(fw);
511 }
512}
513//******************************************************************************
514//******************************************************************************
515void *memdup_user(const void __user *src, size_t len)
516{
517 void *p = kmalloc(len, GFP_KERNEL);
518 if (!p)
519 return ERR_PTR(-ENOMEM);
520 if (copy_from_user(p, src, len)) {
521 kfree(p);
522 return ERR_PTR(-EFAULT);
523 }
524 return p;
525}
526//******************************************************************************
527//******************************************************************************
528#define del_timer_sync(t) del_timer(t) /* FIXME: not quite correct on SMP */
529int cancel_delayed_work(struct delayed_work *dwork)
530{
531 struct work_struct *work = &dwork->work;
532 int ret;
533
534 ret = del_timer_sync(&work->timer);
535 if (ret)
536 clear_bit(0, &work->pending);
537 return ret;
538}
539//******************************************************************************
540//******************************************************************************
541struct workqueue_struct *system_wq;
542
543int schedule_work(struct work_struct *work)
544{
545#ifndef TARGET_OS2 // crashes
546 return queue_work(system_wq, work);
547#endif
548 return 0;
549}
550
551//******************************************************************************
552//******************************************************************************
553bool flush_delayed_work_sync(struct delayed_work *dwork)
554{
555 bool ret;
556 ret = cancel_delayed_work(dwork);
557 if (ret) {
558 schedule_delayed_work(dwork, 0);
559 flush_scheduled_work();
560 }
561 return ret;
562}
563//******************************************************************************
564//******************************************************************************
565static void delayed_work_timer_fn(unsigned long __data)
566{
567 struct work_struct *work = (struct work_struct *)__data;
568 struct workqueue_struct *wq = work->wq_data;
569
570 if (wq)
571 __x_queue_work(wq, work);
572 else
573 schedule_work(work);
574}
575//******************************************************************************
576//******************************************************************************
577int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay)
578{
579 struct work_struct *work = &dwork->work;
580 struct timer_list *timer = &work->timer;
581
582 if (!test_and_set_bit(0, &work->pending)) {
583 work->wq_data = wq;
584 timer->expires = jiffies + delay;
585 timer->data = (unsigned long)work;
586 timer->function = delayed_work_timer_fn;
587 add_timer(timer);
588 return 1;
589 }
590 return 0;
591}
592//******************************************************************************
593//******************************************************************************
594/* Greatest common divisor */
595unsigned long gcd(unsigned long a, unsigned long b)
596{
597 unsigned long r;
598 if (a < b) {
599 r = a;
600 a = b;
601 b = r;
602 }
603 while ((r = a % b) != 0) {
604 a = b;
605 b = r;
606 }
607 return b;
608}
609
610//******************************************************************************
611//******************************************************************************
612int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
613{
614 char *tail;
615 unsigned long val;
616 size_t len;
617
618 *res = 0;
619 len = strlen(cp);
620 if (len == 0)
621 return -EINVAL;
622
623 val = simple_strtoul(cp, &tail, base);
624 if (tail == cp)
625 return -EINVAL;
626
627 if ((*tail == '\0') ||
628 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
629 *res = val;
630 return 0;
631 }
632
633 return -EINVAL;
634}
635//******************************************************************************
636//******************************************************************************
637
638static void u32_swap(void *a, void *b, int size)
639{
640 u32 t = *(u32 *)a;
641 *(u32 *)a = *(u32 *)b;
642 *(u32 *)b = t;
643}
644
645static void generic_swap(void *a, void *b, int size)
646{
647 char t;
648
649 do {
650 t = *(char *)a;
651 *(char *)a++ = *(char *)b;
652 *(char *)b++ = t;
653 } while (--size > 0);
654}
655
656/**
657 * sort - sort an array of elements
658 * @base: pointer to data to sort
659 * @num: number of elements
660 * @size: size of each element
661 * @cmp_func: pointer to comparison function
662 * @swap_func: pointer to swap function or NULL
663 *
664 * This function does a heapsort on the given array. You may provide a
665 * swap_func function optimized to your element type.
666 *
667 * Sorting time is O(n log n) both on average and worst-case. While
668 * qsort is about 20% faster on average, it suffers from exploitable
669 * O(n*n) worst-case behavior and extra memory requirements that make
670 * it less suitable for kernel use.
671 */
672
673void sort(void *base, size_t num, size_t size,
674 int (*cmp_func)(const void *, const void *),
675 void (*swap_func)(void *, void *, int size))
676{
677 /* pre-scale counters for performance */
678 int i = (num/2 - 1) * size, n = num * size, c, r;
679
680 if (!swap_func)
681 swap_func = (size == 4 ? u32_swap : generic_swap);
682
683 /* heapify */
684 for ( ; i >= 0; i -= size) {
685 for (r = i; r * 2 + size < n; r = c) {
686 c = r * 2 + size;
687 if (c < n - size &&
688 cmp_func(base + c, base + c + size) < 0)
689 c += size;
690 if (cmp_func(base + r, base + c) >= 0)
691 break;
692 swap_func(base + r, base + c, size);
693 }
694 }
695
696 /* sort */
697 for (i = n - size; i > 0; i -= size) {
698 swap_func(base, base + i, size);
699 for (r = 0; r * 2 + size < i; r = c) {
700 c = r * 2 + size;
701 if (c < i - size &&
702 cmp_func(base + c, base + c + size) < 0)
703 c += size;
704 if (cmp_func(base + r, base + c) >= 0)
705 break;
706 swap_func(base + r, base + c, size);
707 }
708 }
709}
710//******************************************************************************
711//******************************************************************************
712
713/**
714 * hex_to_bin - convert a hex digit to its real value
715 * @ch: ascii character represents hex digit
716 *
717 * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
718 * input.
719 */
720int hex_to_bin(char ch)
721{
722 if ((ch >= '0') && (ch <= '9'))
723 return ch - '0';
724 ch = tolower(ch);
725 if ((ch >= 'a') && (ch <= 'f'))
726 return ch - 'a' + 10;
727 return -1;
728}
729//******************************************************************************
730
731
732/*
733 * stream_open is used by subsystems that want stream-like file descriptors.
734 * Such file descriptors are not seekable and don't have notion of position
735 * (file.f_pos is always 0). Contrary to file descriptors of other regular
736 * files, .read() and .write() can run simultaneously.
737 *
738 * stream_open never fails and is marked to return int so that it could be
739 * directly used as file_operations.open .
740 */
741int stream_open(struct inode *inode, struct file *filp)
742{
743 filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS);
744 //DAZ f_mode is 16 bit so FMODE_STREAM doesn't fit, but we don't use this on OS/2.
745 //filp->f_mode |= FMODE_STREAM;
746 return 0;
747}
748
749/**
750 * alloc_pages_exact - allocate pages with the given size
751 * @size: the size to allocate in bytes
752 * @gfp_flags: the allocation conditions, GFP_XXX
753 *
754 * Allocates the physically contiguous pages with the given size.
755 *
756 * Return: The pointer of the buffer, or %NULL if no enough memory.
757 */
758void *alloc_pages_exact(size_t size, gfp_t gfp_flags)
759{
760 int pg;
761
762 if (WARN_ON(!size))
763 return NULL;
764 if (WARN_ON(!gfp_flags))
765 return NULL;
766 gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
767 pg = get_order(size);
768 return (void *) __get_free_pages(gfp_flags, pg);
769}
770
771/**
772 * free_pages_exact - release the pages
773 * @ptr: the buffer pointer to release
774 * @size: the allocated buffer size
775 *
776 * Releases the buffer allocated via snd_malloc_pages().
777 */
778void free_pages_exact(void *ptr, size_t size)
779{
780 int pg;
781
782 if (ptr == NULL)
783 return;
784 pg = get_order(size);
785 free_pages((unsigned long) ptr, pg);
786}
787
788/**
789 * of_node_put() - Decrement refcount of a node
790 * @node: Node to dec refcount, NULL is supported to simplify writing of
791 * callers
792 */
793void of_node_put(struct device_node *node)
794{
795 if (node)
796 kobject_put(&node->kobj);
797}
798
799/**
800 * sysfs_streq - return true if strings are equal, modulo trailing newline
801 * @s1: one string
802 * @s2: another string
803 *
804 * This routine returns true iff two strings are equal, treating both
805 * NUL and newline-then-NUL as equivalent string terminations. It's
806 * geared for use with sysfs input strings, which generally terminate
807 * with newlines but are compared against values without newlines.
808 */
809bool sysfs_streq(const char *s1, const char *s2)
810{
811 while (*s1 && *s1 == *s2) {
812 s1++;
813 s2++;
814 }
815
816 if (*s1 == *s2)
817 return true;
818 if (!*s1 && *s2 == '\n' && !s2[1])
819 return true;
820 if (*s1 == '\n' && !s1[1] && !*s2)
821 return true;
822 return false;
823}
824EXPORT_SYMBOL(sysfs_streq);
Note: See TracBrowser for help on using the repository browser.