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

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

Update linux core to the 6.0 kernel

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