source: GPL/trunk/lib32/misc.c

Last change on this file was 772, checked in by David Azarewicz, 5 months ago

Merge in changes from 6.6-LTS branch.
Fixed additional 25+ problems.

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