xref: /OK3568_Linux_fs/external/rkwifibt/drivers/bcmdhd/linux_osl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Linux OS Independent Layer
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2020, Broadcom.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *      Unless you and Broadcom execute a separate written software license
7*4882a593Smuzhiyun  * agreement governing use of this software, this software is licensed to you
8*4882a593Smuzhiyun  * under the terms of the GNU General Public License version 2 (the "GPL"),
9*4882a593Smuzhiyun  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10*4882a593Smuzhiyun  * following added to such license:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *      As a special exception, the copyright holders of this software give you
13*4882a593Smuzhiyun  * permission to link this software with independent modules, and to copy and
14*4882a593Smuzhiyun  * distribute the resulting executable under terms of your choice, provided that
15*4882a593Smuzhiyun  * you also meet, for each linked independent module, the terms and conditions of
16*4882a593Smuzhiyun  * the license of that module.  An independent module is a module which is not
17*4882a593Smuzhiyun  * derived from this software.  The special exception does not apply to any
18*4882a593Smuzhiyun  * modifications of the software.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * <<Broadcom-WL-IPTag/Dual:>>
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define LINUX_PORT
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include <typedefs.h>
27*4882a593Smuzhiyun #include <bcmendian.h>
28*4882a593Smuzhiyun #include <linuxver.h>
29*4882a593Smuzhiyun #include <bcmdefs.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
32*4882a593Smuzhiyun #include <asm/cacheflush.h>
33*4882a593Smuzhiyun #endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/random.h>
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include <osl.h>
38*4882a593Smuzhiyun #include <bcmutils.h>
39*4882a593Smuzhiyun #include <linux/delay.h>
40*4882a593Smuzhiyun #include <linux/vmalloc.h>
41*4882a593Smuzhiyun #include <pcicfg.h>
42*4882a593Smuzhiyun #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 8, 0))
43*4882a593Smuzhiyun #include <asm-generic/pci-dma-compat.h>
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #if defined(BCMASSERT_LOG) && !defined(OEM_ANDROID)
47*4882a593Smuzhiyun #include <bcm_assert_log.h>
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #include <linux/fs.h>
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #ifdef BCM_OBJECT_TRACE
53*4882a593Smuzhiyun #include <bcmutils.h>
54*4882a593Smuzhiyun #endif /* BCM_OBJECT_TRACE */
55*4882a593Smuzhiyun #include "linux_osl_priv.h"
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define PCI_CFG_RETRY		10	/* PR15065: retry count for pci cfg accesses */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define DUMPBUFSZ 1024
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #ifdef CUSTOMER_HW4_DEBUG
62*4882a593Smuzhiyun uint32 g_assert_type = 1; /* By Default not cause Kernel Panic */
63*4882a593Smuzhiyun #else
64*4882a593Smuzhiyun uint32 g_assert_type = 0; /* By Default Kernel Panic */
65*4882a593Smuzhiyun #endif /* CUSTOMER_HW4_DEBUG */
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun module_param(g_assert_type, int, 0);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #if defined(BCMSLTGT)
70*4882a593Smuzhiyun /* !!!make sure htclkratio is not 0!!! */
71*4882a593Smuzhiyun extern uint htclkratio;
72*4882a593Smuzhiyun #endif
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun #ifdef USE_DMA_LOCK
75*4882a593Smuzhiyun static void osl_dma_lock(osl_t *osh);
76*4882a593Smuzhiyun static void osl_dma_unlock(osl_t *osh);
77*4882a593Smuzhiyun static void osl_dma_lock_init(osl_t *osh);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define DMA_LOCK(osh)		osl_dma_lock(osh)
80*4882a593Smuzhiyun #define DMA_UNLOCK(osh)		osl_dma_unlock(osh)
81*4882a593Smuzhiyun #define DMA_LOCK_INIT(osh)	osl_dma_lock_init(osh);
82*4882a593Smuzhiyun #else
83*4882a593Smuzhiyun #define DMA_LOCK(osh)		do { /* noop */ } while(0)
84*4882a593Smuzhiyun #define DMA_UNLOCK(osh)		do { /* noop */ } while(0)
85*4882a593Smuzhiyun #define DMA_LOCK_INIT(osh)	do { /* noop */ } while(0)
86*4882a593Smuzhiyun #endif /* USE_DMA_LOCK */
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun static int16 linuxbcmerrormap[] =
89*4882a593Smuzhiyun {	0,				/* 0 */
90*4882a593Smuzhiyun 	-EINVAL,		/* BCME_ERROR */
91*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADARG */
92*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADOPTION */
93*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTUP */
94*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTDOWN */
95*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTAP */
96*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTSTA */
97*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADKEYIDX */
98*4882a593Smuzhiyun 	-EINVAL,		/* BCME_RADIOOFF */
99*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTBANDLOCKED */
100*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOCLK */
101*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADRATESET */
102*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADBAND */
103*4882a593Smuzhiyun 	-E2BIG,			/* BCME_BUFTOOSHORT */
104*4882a593Smuzhiyun 	-E2BIG,			/* BCME_BUFTOOLONG */
105*4882a593Smuzhiyun 	-EBUSY,			/* BCME_BUSY */
106*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTASSOCIATED */
107*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADSSIDLEN */
108*4882a593Smuzhiyun 	-EINVAL,		/* BCME_OUTOFRANGECHAN */
109*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BADCHAN */
110*4882a593Smuzhiyun 	-EFAULT,		/* BCME_BADADDR */
111*4882a593Smuzhiyun 	-ENOMEM,		/* BCME_NORESOURCE */
112*4882a593Smuzhiyun 	-EOPNOTSUPP,		/* BCME_UNSUPPORTED */
113*4882a593Smuzhiyun 	-EMSGSIZE,		/* BCME_BADLENGTH */
114*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTREADY */
115*4882a593Smuzhiyun 	-EPERM,			/* BCME_EPERM */
116*4882a593Smuzhiyun 	-ENOMEM,		/* BCME_NOMEM */
117*4882a593Smuzhiyun 	-EINVAL,		/* BCME_ASSOCIATED */
118*4882a593Smuzhiyun 	-ERANGE,		/* BCME_RANGE */
119*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOTFOUND */
120*4882a593Smuzhiyun 	-EINVAL,		/* BCME_WME_NOT_ENABLED */
121*4882a593Smuzhiyun 	-EINVAL,		/* BCME_TSPEC_NOTFOUND */
122*4882a593Smuzhiyun 	-EINVAL,		/* BCME_ACM_NOTSUPPORTED */
123*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOT_WME_ASSOCIATION */
124*4882a593Smuzhiyun 	-EIO,			/* BCME_SDIO_ERROR */
125*4882a593Smuzhiyun 	-ENODEV,		/* BCME_DONGLE_DOWN */
126*4882a593Smuzhiyun 	-EINVAL,		/* BCME_VERSION */
127*4882a593Smuzhiyun 	-EIO,			/* BCME_TXFAIL */
128*4882a593Smuzhiyun 	-EIO,			/* BCME_RXFAIL */
129*4882a593Smuzhiyun 	-ENODEV,		/* BCME_NODEVICE */
130*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NMODE_DISABLED */
131*4882a593Smuzhiyun 	-ENODATA,		/* BCME_NONRESIDENT */
132*4882a593Smuzhiyun 	-EINVAL,		/* BCME_SCANREJECT */
133*4882a593Smuzhiyun 	-EINVAL,		/* BCME_USAGE_ERROR */
134*4882a593Smuzhiyun 	-EIO,			/* BCME_IOCTL_ERROR */
135*4882a593Smuzhiyun 	-EIO,			/* BCME_SERIAL_PORT_ERR */
136*4882a593Smuzhiyun 	-EOPNOTSUPP,		/* BCME_DISABLED, BCME_NOTENABLED */
137*4882a593Smuzhiyun 	-EIO,			/* BCME_DECERR */
138*4882a593Smuzhiyun 	-EIO,			/* BCME_ENCERR */
139*4882a593Smuzhiyun 	-EIO,			/* BCME_MICERR */
140*4882a593Smuzhiyun 	-ERANGE,		/* BCME_REPLAY */
141*4882a593Smuzhiyun 	-EINVAL,		/* BCME_IE_NOTFOUND */
142*4882a593Smuzhiyun 	-EINVAL,		/* BCME_DATA_NOTFOUND */
143*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOT_GC */
144*4882a593Smuzhiyun 	-EINVAL,		/* BCME_PRS_REQ_FAILED */
145*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NO_P2P_SE */
146*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOA_PND */
147*4882a593Smuzhiyun 	-EINVAL,		/* BCME_FRAG_Q_FAILED */
148*4882a593Smuzhiyun 	-EINVAL,		/* BCME_GET_AF_FAILED */
149*4882a593Smuzhiyun 	-EINVAL,		/* BCME_MSCH_NOTREADY */
150*4882a593Smuzhiyun 	-EINVAL,		/* BCME_IOV_LAST_CMD */
151*4882a593Smuzhiyun 	-EINVAL,		/* BCME_MINIPMU_CAL_FAIL */
152*4882a593Smuzhiyun 	-EINVAL,		/* BCME_RCAL_FAIL */
153*4882a593Smuzhiyun 	-EINVAL,		/* BCME_LPF_RCCAL_FAIL */
154*4882a593Smuzhiyun 	-EINVAL,		/* BCME_DACBUF_RCCAL_FAIL */
155*4882a593Smuzhiyun 	-EINVAL,		/* BCME_VCOCAL_FAIL */
156*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BANDLOCKED */
157*4882a593Smuzhiyun 	-EINVAL,		/* BCME_BAD_IE_DATA */
158*4882a593Smuzhiyun 	-EINVAL,		/* BCME_REG_FAILED */
159*4882a593Smuzhiyun 	-EINVAL,		/* BCME_NOCHAN */
160*4882a593Smuzhiyun 	-EINVAL,		/* BCME_PKTTOSS */
161*4882a593Smuzhiyun 	-EINVAL,		/* BCME_DNGL_DEVRESET */
162*4882a593Smuzhiyun 	-EINVAL,		/* BCME_ROAM */
163*4882a593Smuzhiyun 	-EOPNOTSUPP,		/* BCME_NO_SIG_FILE */
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /* When an new error code is added to bcmutils.h, add os
166*4882a593Smuzhiyun  * specific error translation here as well
167*4882a593Smuzhiyun  */
168*4882a593Smuzhiyun /* check if BCME_LAST changed since the last time this function was updated */
169*4882a593Smuzhiyun #if BCME_LAST != BCME_NO_SIG_FILE
170*4882a593Smuzhiyun #error "You need to add a OS error translation in the linuxbcmerrormap \
171*4882a593Smuzhiyun 	for new error code defined in bcmutils.h"
172*4882a593Smuzhiyun #endif
173*4882a593Smuzhiyun };
174*4882a593Smuzhiyun uint lmtest = FALSE;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun #ifdef DHD_MAP_LOGGING
177*4882a593Smuzhiyun #define DHD_MAP_LOG_SIZE 2048
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun typedef struct dhd_map_item {
180*4882a593Smuzhiyun 	dmaaddr_t pa;		/* DMA address (physical) */
181*4882a593Smuzhiyun 	uint64 ts_nsec;		/* timestamp: nsec */
182*4882a593Smuzhiyun 	uint32 size;		/* mapping size */
183*4882a593Smuzhiyun 	uint8 rsvd[4];		/* reserved for future use */
184*4882a593Smuzhiyun } dhd_map_item_t;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun typedef struct dhd_map_record {
187*4882a593Smuzhiyun 	uint32 items;		/* number of total items */
188*4882a593Smuzhiyun 	uint32 idx;		/* current index of metadata */
189*4882a593Smuzhiyun 	dhd_map_item_t map[0];	/* metadata storage */
190*4882a593Smuzhiyun } dhd_map_log_t;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun void
osl_dma_map_dump(osl_t * osh)193*4882a593Smuzhiyun osl_dma_map_dump(osl_t *osh)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	dhd_map_log_t *map_log, *unmap_log;
196*4882a593Smuzhiyun 	uint64 ts_sec, ts_usec;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	map_log = (dhd_map_log_t *)(osh->dhd_map_log);
199*4882a593Smuzhiyun 	unmap_log = (dhd_map_log_t *)(osh->dhd_unmap_log);
200*4882a593Smuzhiyun 	osl_get_localtime(&ts_sec, &ts_usec);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	if (map_log && unmap_log) {
203*4882a593Smuzhiyun 		printf("%s: map_idx=%d unmap_idx=%d "
204*4882a593Smuzhiyun 			"current time=[%5lu.%06lu]\n", __FUNCTION__,
205*4882a593Smuzhiyun 			map_log->idx, unmap_log->idx, (unsigned long)ts_sec,
206*4882a593Smuzhiyun 			(unsigned long)ts_usec);
207*4882a593Smuzhiyun 		printf("%s: dhd_map_log(pa)=0x%llx size=%d,"
208*4882a593Smuzhiyun 			" dma_unmap_log(pa)=0x%llx size=%d\n", __FUNCTION__,
209*4882a593Smuzhiyun 			(uint64)__virt_to_phys((ulong)(map_log->map)),
210*4882a593Smuzhiyun 			(uint32)(sizeof(dhd_map_item_t) * map_log->items),
211*4882a593Smuzhiyun 			(uint64)__virt_to_phys((ulong)(unmap_log->map)),
212*4882a593Smuzhiyun 			(uint32)(sizeof(dhd_map_item_t) * unmap_log->items));
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun static void *
osl_dma_map_log_init(uint32 item_len)217*4882a593Smuzhiyun osl_dma_map_log_init(uint32 item_len)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	dhd_map_log_t *map_log;
220*4882a593Smuzhiyun 	gfp_t flags;
221*4882a593Smuzhiyun 	uint32 alloc_size = (uint32)(sizeof(dhd_map_log_t) +
222*4882a593Smuzhiyun 		(item_len * sizeof(dhd_map_item_t)));
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	flags = CAN_SLEEP() ? GFP_KERNEL : GFP_ATOMIC;
225*4882a593Smuzhiyun 	map_log = (dhd_map_log_t *)kmalloc(alloc_size, flags);
226*4882a593Smuzhiyun 	if (map_log) {
227*4882a593Smuzhiyun 		memset(map_log, 0, alloc_size);
228*4882a593Smuzhiyun 		map_log->items = item_len;
229*4882a593Smuzhiyun 		map_log->idx = 0;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	return (void *)map_log;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun static void
osl_dma_map_log_deinit(osl_t * osh)236*4882a593Smuzhiyun osl_dma_map_log_deinit(osl_t *osh)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	if (osh->dhd_map_log) {
239*4882a593Smuzhiyun 		kfree(osh->dhd_map_log);
240*4882a593Smuzhiyun 		osh->dhd_map_log = NULL;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (osh->dhd_unmap_log) {
244*4882a593Smuzhiyun 		kfree(osh->dhd_unmap_log);
245*4882a593Smuzhiyun 		osh->dhd_unmap_log = NULL;
246*4882a593Smuzhiyun 	}
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun static void
osl_dma_map_logging(osl_t * osh,void * handle,dmaaddr_t pa,uint32 len)250*4882a593Smuzhiyun osl_dma_map_logging(osl_t *osh, void *handle, dmaaddr_t pa, uint32 len)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	dhd_map_log_t *log = (dhd_map_log_t *)handle;
253*4882a593Smuzhiyun 	uint32 idx;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (log == NULL) {
256*4882a593Smuzhiyun 		printf("%s: log is NULL\n", __FUNCTION__);
257*4882a593Smuzhiyun 		return;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	idx = log->idx;
261*4882a593Smuzhiyun 	log->map[idx].ts_nsec = osl_localtime_ns();
262*4882a593Smuzhiyun 	log->map[idx].pa = pa;
263*4882a593Smuzhiyun 	log->map[idx].size = len;
264*4882a593Smuzhiyun 	log->idx = (idx + 1) % log->items;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun #endif /* DHD_MAP_LOGGING */
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /* translate bcmerrors into linux errors */
269*4882a593Smuzhiyun int
osl_error(int bcmerror)270*4882a593Smuzhiyun osl_error(int bcmerror)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	if (bcmerror > 0)
273*4882a593Smuzhiyun 		bcmerror = 0;
274*4882a593Smuzhiyun 	else if (bcmerror < BCME_LAST)
275*4882a593Smuzhiyun 		bcmerror = BCME_ERROR;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	/* Array bounds covered by ASSERT in osl_attach */
278*4882a593Smuzhiyun 	return linuxbcmerrormap[-bcmerror];
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun osl_t *
osl_attach(void * pdev,uint bustype,bool pkttag,void ** osl_cmn)282*4882a593Smuzhiyun osl_attach(void *pdev, uint bustype, bool pkttag
283*4882a593Smuzhiyun #ifdef SHARED_OSL_CMN
284*4882a593Smuzhiyun 	, void **osl_cmn
285*4882a593Smuzhiyun #endif /* SHARED_OSL_CMN */
286*4882a593Smuzhiyun )
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun #ifndef SHARED_OSL_CMN
289*4882a593Smuzhiyun 	void **osl_cmn = NULL;
290*4882a593Smuzhiyun #endif /* SHARED_OSL_CMN */
291*4882a593Smuzhiyun 	osl_t *osh;
292*4882a593Smuzhiyun 	gfp_t flags;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
295*4882a593Smuzhiyun 	if (!(osh = kmalloc(sizeof(osl_t), flags)))
296*4882a593Smuzhiyun 		return osh;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	ASSERT(osh);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	bzero(osh, sizeof(osl_t));
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (osl_cmn == NULL || *osl_cmn == NULL) {
303*4882a593Smuzhiyun 		if (!(osh->cmn = kmalloc(sizeof(osl_cmn_t), flags))) {
304*4882a593Smuzhiyun 			kfree(osh);
305*4882a593Smuzhiyun 			return NULL;
306*4882a593Smuzhiyun 		}
307*4882a593Smuzhiyun 		bzero(osh->cmn, sizeof(osl_cmn_t));
308*4882a593Smuzhiyun 		if (osl_cmn)
309*4882a593Smuzhiyun 			*osl_cmn = osh->cmn;
310*4882a593Smuzhiyun 		atomic_set(&osh->cmn->malloced, 0);
311*4882a593Smuzhiyun 		osh->cmn->dbgmem_list = NULL;
312*4882a593Smuzhiyun 		spin_lock_init(&(osh->cmn->dbgmem_lock));
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun #ifdef BCMDBG_PKT
315*4882a593Smuzhiyun 		spin_lock_init(&(osh->cmn->pktlist_lock));
316*4882a593Smuzhiyun #endif
317*4882a593Smuzhiyun 		spin_lock_init(&(osh->cmn->pktalloc_lock));
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	} else {
320*4882a593Smuzhiyun 		osh->cmn = *osl_cmn;
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 	atomic_add(1, &osh->cmn->refcount);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	bcm_object_trace_init();
325*4882a593Smuzhiyun 	/* Check that error map has the right number of entries in it */
326*4882a593Smuzhiyun 	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
327*4882a593Smuzhiyun 	osh->failed = 0;
328*4882a593Smuzhiyun 	osh->pdev = pdev;
329*4882a593Smuzhiyun 	osh->pub.pkttag = pkttag;
330*4882a593Smuzhiyun 	osh->bustype = bustype;
331*4882a593Smuzhiyun 	osh->magic = OS_HANDLE_MAGIC;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	switch (bustype) {
334*4882a593Smuzhiyun 		case PCI_BUS:
335*4882a593Smuzhiyun 		case SI_BUS:
336*4882a593Smuzhiyun 			osh->pub.mmbus = TRUE;
337*4882a593Smuzhiyun 			break;
338*4882a593Smuzhiyun 		case SDIO_BUS:
339*4882a593Smuzhiyun 		case USB_BUS:
340*4882a593Smuzhiyun 		case SPI_BUS:
341*4882a593Smuzhiyun 		case RPC_BUS:
342*4882a593Smuzhiyun 			osh->pub.mmbus = FALSE;
343*4882a593Smuzhiyun 			break;
344*4882a593Smuzhiyun 		default:
345*4882a593Smuzhiyun 			ASSERT(FALSE);
346*4882a593Smuzhiyun 			break;
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun #ifdef BCMDBG_CTRACE
350*4882a593Smuzhiyun 	spin_lock_init(&osh->ctrace_lock);
351*4882a593Smuzhiyun 	INIT_LIST_HEAD(&osh->ctrace_list);
352*4882a593Smuzhiyun 	osh->ctrace_num = 0;
353*4882a593Smuzhiyun #endif /* BCMDBG_CTRACE */
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	DMA_LOCK_INIT(osh);
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun #ifdef BCMDBG_ASSERT
358*4882a593Smuzhiyun 	if (pkttag) {
359*4882a593Smuzhiyun 		struct sk_buff *skb;
360*4882a593Smuzhiyun 		BCM_REFERENCE(skb);
361*4882a593Smuzhiyun 		ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb));
362*4882a593Smuzhiyun 	}
363*4882a593Smuzhiyun #endif
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun #ifdef DHD_MAP_LOGGING
366*4882a593Smuzhiyun 	osh->dhd_map_log = osl_dma_map_log_init(DHD_MAP_LOG_SIZE);
367*4882a593Smuzhiyun 	if (osh->dhd_map_log == NULL) {
368*4882a593Smuzhiyun 		printf("%s: Failed to alloc dhd_map_log\n", __FUNCTION__);
369*4882a593Smuzhiyun 	}
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	osh->dhd_unmap_log = osl_dma_map_log_init(DHD_MAP_LOG_SIZE);
372*4882a593Smuzhiyun 	if (osh->dhd_unmap_log == NULL) {
373*4882a593Smuzhiyun 		printf("%s: Failed to alloc dhd_unmap_log\n", __FUNCTION__);
374*4882a593Smuzhiyun 	}
375*4882a593Smuzhiyun #endif /* DHD_MAP_LOGGING */
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	return osh;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
osl_set_bus_handle(osl_t * osh,void * bus_handle)380*4882a593Smuzhiyun void osl_set_bus_handle(osl_t *osh, void *bus_handle)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	osh->bus_handle = bus_handle;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
osl_get_bus_handle(osl_t * osh)385*4882a593Smuzhiyun void* osl_get_bus_handle(osl_t *osh)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	return osh->bus_handle;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun #if defined(AXI_TIMEOUTS_NIC)
osl_set_bpt_cb(osl_t * osh,void * bpt_cb,void * bpt_ctx)391*4882a593Smuzhiyun void osl_set_bpt_cb(osl_t *osh, void *bpt_cb, void *bpt_ctx)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	if (osh) {
394*4882a593Smuzhiyun 		osh->bpt_cb = (bpt_cb_fn)bpt_cb;
395*4882a593Smuzhiyun 		osh->sih = bpt_ctx;
396*4882a593Smuzhiyun 	}
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun #endif	/* AXI_TIMEOUTS_NIC */
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun void
osl_detach(osl_t * osh)401*4882a593Smuzhiyun osl_detach(osl_t *osh)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	if (osh == NULL)
404*4882a593Smuzhiyun 		return;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun #ifdef BCMDBG_MEM
407*4882a593Smuzhiyun 	if (MEMORY_LEFTOVER(osh)) {
408*4882a593Smuzhiyun 		static char dumpbuf[DUMPBUFSZ];
409*4882a593Smuzhiyun 		struct bcmstrbuf b;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 		printf("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh));
412*4882a593Smuzhiyun 		bcm_binit(&b, dumpbuf, DUMPBUFSZ);
413*4882a593Smuzhiyun 		MALLOC_DUMP(osh, &b);
414*4882a593Smuzhiyun 		printf("%s", b.origbuf);
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun #endif
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	bcm_object_trace_deinit();
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun #ifdef DHD_MAP_LOGGING
421*4882a593Smuzhiyun 	osl_dma_map_log_deinit(osh);
422*4882a593Smuzhiyun #endif /* DHD_MAP_LOGGING */
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	ASSERT(osh->magic == OS_HANDLE_MAGIC);
425*4882a593Smuzhiyun 	atomic_sub(1, &osh->cmn->refcount);
426*4882a593Smuzhiyun 	if (atomic_read(&osh->cmn->refcount) == 0) {
427*4882a593Smuzhiyun 			kfree(osh->cmn);
428*4882a593Smuzhiyun 	}
429*4882a593Smuzhiyun 	kfree(osh);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun /* APIs to set/get specific quirks in OSL layer */
433*4882a593Smuzhiyun void
BCMFASTPATH(osl_flag_set)434*4882a593Smuzhiyun BCMFASTPATH(osl_flag_set)(osl_t *osh, uint32 mask)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	osh->flags |= mask;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun void
osl_flag_clr(osl_t * osh,uint32 mask)440*4882a593Smuzhiyun osl_flag_clr(osl_t *osh, uint32 mask)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	osh->flags &= ~mask;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun bool
osl_is_flag_set(osl_t * osh,uint32 mask)446*4882a593Smuzhiyun osl_is_flag_set(osl_t *osh, uint32 mask)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun 	return (osh->flags & mask);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun #if (defined(BCMPCIE) && defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING))
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun inline void
BCMFASTPATH(osl_cache_flush)454*4882a593Smuzhiyun BCMFASTPATH(osl_cache_flush)(void *va, uint size)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	if (size > 0)
457*4882a593Smuzhiyun 		dma_sync_single_for_device(OSH_NULL, virt_to_dma(OSH_NULL, va), size,
458*4882a593Smuzhiyun 			DMA_TO_DEVICE);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun inline void
BCMFASTPATH(osl_cache_inv)462*4882a593Smuzhiyun BCMFASTPATH(osl_cache_inv)(void *va, uint size)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun 	dma_sync_single_for_cpu(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_FROM_DEVICE);
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun inline void
BCMFASTPATH(osl_prefetch)468*4882a593Smuzhiyun BCMFASTPATH(osl_prefetch)(const void *ptr)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	__asm__ __volatile__("pld\t%0" :: "o"(*(const char *)ptr) : "cc");
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun #endif /* !__ARM_ARCH_7A__ */
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun uint32
osl_pci_read_config(osl_t * osh,uint offset,uint size)476*4882a593Smuzhiyun osl_pci_read_config(osl_t *osh, uint offset, uint size)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun 	uint val = 0;
479*4882a593Smuzhiyun 	uint retry = PCI_CFG_RETRY;	 /* PR15065: faulty cardbus controller bug */
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	/* only 4byte access supported */
484*4882a593Smuzhiyun 	ASSERT(size == 4);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	do {
487*4882a593Smuzhiyun 		pci_read_config_dword(osh->pdev, offset, &val);
488*4882a593Smuzhiyun 		if (val != 0xffffffff)
489*4882a593Smuzhiyun 			break;
490*4882a593Smuzhiyun 	} while (retry--);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun #ifdef BCMDBG
493*4882a593Smuzhiyun 	if (retry < PCI_CFG_RETRY)
494*4882a593Smuzhiyun 		printf("PCI CONFIG READ access to %d required %d retries\n", offset,
495*4882a593Smuzhiyun 		       (PCI_CFG_RETRY - retry));
496*4882a593Smuzhiyun #endif /* BCMDBG */
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	return (val);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun void
osl_pci_write_config(osl_t * osh,uint offset,uint size,uint val)502*4882a593Smuzhiyun osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	uint retry = PCI_CFG_RETRY;	 /* PR15065: faulty cardbus controller bug */
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	/* only 4byte access supported */
509*4882a593Smuzhiyun 	ASSERT(size == 4);
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	do {
512*4882a593Smuzhiyun 		pci_write_config_dword(osh->pdev, offset, val);
513*4882a593Smuzhiyun 		/* PR15065: PCI_BAR0_WIN is believed to be the only pci cfg write that can occur
514*4882a593Smuzhiyun 		 * when dma activity is possible
515*4882a593Smuzhiyun 		 */
516*4882a593Smuzhiyun 		if (offset != PCI_BAR0_WIN)
517*4882a593Smuzhiyun 			break;
518*4882a593Smuzhiyun 		if (osl_pci_read_config(osh, offset, size) == val)
519*4882a593Smuzhiyun 			break;
520*4882a593Smuzhiyun 	} while (retry--);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun #ifdef BCMDBG
523*4882a593Smuzhiyun 	if (retry < PCI_CFG_RETRY)
524*4882a593Smuzhiyun 		printf("PCI CONFIG WRITE access to %d required %d retries\n", offset,
525*4882a593Smuzhiyun 		       (PCI_CFG_RETRY - retry));
526*4882a593Smuzhiyun #endif /* BCMDBG */
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun #ifdef BCMPCIE
530*4882a593Smuzhiyun /* return bus # for the pci device pointed by osh->pdev */
531*4882a593Smuzhiyun uint
osl_pci_bus(osl_t * osh)532*4882a593Smuzhiyun osl_pci_bus(osl_t *osh)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun #if defined(__ARM_ARCH_7A__)
537*4882a593Smuzhiyun 	return pci_domain_nr(((struct pci_dev *)osh->pdev)->bus);
538*4882a593Smuzhiyun #else
539*4882a593Smuzhiyun 	return ((struct pci_dev *)osh->pdev)->bus->number;
540*4882a593Smuzhiyun #endif
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun /* return slot # for the pci device pointed by osh->pdev */
544*4882a593Smuzhiyun uint
osl_pci_slot(osl_t * osh)545*4882a593Smuzhiyun osl_pci_slot(osl_t *osh)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun 	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun #if defined(__ARM_ARCH_7A__)
550*4882a593Smuzhiyun 	return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1;
551*4882a593Smuzhiyun #else
552*4882a593Smuzhiyun 	return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
553*4882a593Smuzhiyun #endif
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun /* return domain # for the pci device pointed by osh->pdev */
557*4882a593Smuzhiyun uint
osl_pcie_domain(osl_t * osh)558*4882a593Smuzhiyun osl_pcie_domain(osl_t *osh)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	return pci_domain_nr(((struct pci_dev *)osh->pdev)->bus);
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun /* return bus # for the pci device pointed by osh->pdev */
566*4882a593Smuzhiyun uint
osl_pcie_bus(osl_t * osh)567*4882a593Smuzhiyun osl_pcie_bus(osl_t *osh)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	return ((struct pci_dev *)osh->pdev)->bus->number;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun /* return the pci device pointed by osh->pdev */
575*4882a593Smuzhiyun struct pci_dev *
osl_pci_device(osl_t * osh)576*4882a593Smuzhiyun osl_pci_device(osl_t *osh)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun 	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	return osh->pdev;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun #endif
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun #ifdef BCMDBG_MEM
585*4882a593Smuzhiyun /* In BCMDBG_MEM configurations osl_malloc is only used internally in
586*4882a593Smuzhiyun  * the implementation of osl_debug_malloc.  Because we are using the GCC
587*4882a593Smuzhiyun  * -Wstrict-prototypes compile option, we must always have a prototype
588*4882a593Smuzhiyun  * for a global/external function.  So make osl_malloc static in
589*4882a593Smuzhiyun  * the BCMDBG_MEM case.
590*4882a593Smuzhiyun  */
591*4882a593Smuzhiyun static
592*4882a593Smuzhiyun #endif
593*4882a593Smuzhiyun void *
osl_malloc(osl_t * osh,uint size)594*4882a593Smuzhiyun osl_malloc(osl_t *osh, uint size)
595*4882a593Smuzhiyun {
596*4882a593Smuzhiyun 	void *addr;
597*4882a593Smuzhiyun 	gfp_t flags;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	/* only ASSERT if osh is defined */
600*4882a593Smuzhiyun 	if (osh)
601*4882a593Smuzhiyun 		ASSERT(osh->magic == OS_HANDLE_MAGIC);
602*4882a593Smuzhiyun #ifdef CONFIG_DHD_USE_STATIC_BUF
603*4882a593Smuzhiyun 	if (bcm_static_buf)
604*4882a593Smuzhiyun 	{
605*4882a593Smuzhiyun 		unsigned long irq_flags;
606*4882a593Smuzhiyun 		int i = 0;
607*4882a593Smuzhiyun 		if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE))
608*4882a593Smuzhiyun 		{
609*4882a593Smuzhiyun 			OSL_STATIC_BUF_LOCK(&bcm_static_buf->static_lock, irq_flags);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 			for (i = 0; i < STATIC_BUF_MAX_NUM; i++)
612*4882a593Smuzhiyun 			{
613*4882a593Smuzhiyun 				if (bcm_static_buf->buf_use[i] == 0)
614*4882a593Smuzhiyun 					break;
615*4882a593Smuzhiyun 			}
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 			if (i == STATIC_BUF_MAX_NUM)
618*4882a593Smuzhiyun 			{
619*4882a593Smuzhiyun 				OSL_STATIC_BUF_UNLOCK(&bcm_static_buf->static_lock, irq_flags);
620*4882a593Smuzhiyun 				printf("all static buff in use!\n");
621*4882a593Smuzhiyun 				goto original;
622*4882a593Smuzhiyun 			}
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 			bcm_static_buf->buf_use[i] = 1;
625*4882a593Smuzhiyun 			OSL_STATIC_BUF_UNLOCK(&bcm_static_buf->static_lock, irq_flags);
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 			bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size);
628*4882a593Smuzhiyun 			if (osh)
629*4882a593Smuzhiyun 				atomic_add(size, &osh->cmn->malloced);
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 			return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i));
632*4882a593Smuzhiyun 		}
633*4882a593Smuzhiyun 	}
634*4882a593Smuzhiyun original:
635*4882a593Smuzhiyun #endif /* CONFIG_DHD_USE_STATIC_BUF */
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
638*4882a593Smuzhiyun 	if ((addr = kmalloc(size, flags)) == NULL) {
639*4882a593Smuzhiyun 		if (osh)
640*4882a593Smuzhiyun 			osh->failed++;
641*4882a593Smuzhiyun 		return (NULL);
642*4882a593Smuzhiyun 	}
643*4882a593Smuzhiyun 	if (osh && osh->cmn)
644*4882a593Smuzhiyun 		atomic_add(size, &osh->cmn->malloced);
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	return (addr);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun #ifndef BCMDBG_MEM
650*4882a593Smuzhiyun void *
osl_mallocz(osl_t * osh,uint size)651*4882a593Smuzhiyun osl_mallocz(osl_t *osh, uint size)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	void *ptr;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	ptr = osl_malloc(osh, size);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	if (ptr != NULL) {
658*4882a593Smuzhiyun 		bzero(ptr, size);
659*4882a593Smuzhiyun 	}
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	return ptr;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun #endif
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun #ifdef BCMDBG_MEM
666*4882a593Smuzhiyun /* In BCMDBG_MEM configurations osl_mfree is only used internally in
667*4882a593Smuzhiyun  * the implementation of osl_debug_mfree.  Because we are using the GCC
668*4882a593Smuzhiyun  * -Wstrict-prototypes compile option, we must always have a prototype
669*4882a593Smuzhiyun  * for a global/external function.  So make osl_mfree static in
670*4882a593Smuzhiyun  * the BCMDBG_MEM case.
671*4882a593Smuzhiyun  */
672*4882a593Smuzhiyun static
673*4882a593Smuzhiyun #endif
674*4882a593Smuzhiyun void
osl_mfree(osl_t * osh,void * addr,uint size)675*4882a593Smuzhiyun osl_mfree(osl_t *osh, void *addr, uint size)
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun #ifdef CONFIG_DHD_USE_STATIC_BUF
678*4882a593Smuzhiyun 	unsigned long flags;
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	if (addr == NULL) {
681*4882a593Smuzhiyun 		return;
682*4882a593Smuzhiyun 	}
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	if (bcm_static_buf)
685*4882a593Smuzhiyun 	{
686*4882a593Smuzhiyun 		if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr
687*4882a593Smuzhiyun 			<= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
688*4882a593Smuzhiyun 		{
689*4882a593Smuzhiyun 			int buf_idx = 0;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 			buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 			OSL_STATIC_BUF_LOCK(&bcm_static_buf->static_lock, flags);
694*4882a593Smuzhiyun 			bcm_static_buf->buf_use[buf_idx] = 0;
695*4882a593Smuzhiyun 			OSL_STATIC_BUF_UNLOCK(&bcm_static_buf->static_lock, flags);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 			if (osh && osh->cmn) {
698*4882a593Smuzhiyun 				ASSERT(osh->magic == OS_HANDLE_MAGIC);
699*4882a593Smuzhiyun 				atomic_sub(size, &osh->cmn->malloced);
700*4882a593Smuzhiyun 			}
701*4882a593Smuzhiyun 			return;
702*4882a593Smuzhiyun 		}
703*4882a593Smuzhiyun 	}
704*4882a593Smuzhiyun #endif /* CONFIG_DHD_USE_STATIC_BUF */
705*4882a593Smuzhiyun 	if (osh && osh->cmn) {
706*4882a593Smuzhiyun 		ASSERT(osh->magic == OS_HANDLE_MAGIC);
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 		ASSERT(size <= osl_malloced(osh));
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 		atomic_sub(size, &osh->cmn->malloced);
711*4882a593Smuzhiyun 	}
712*4882a593Smuzhiyun 	kfree(addr);
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun #ifdef BCMDBG_MEM
716*4882a593Smuzhiyun /* In BCMDBG_MEM configurations osl_vmalloc is only used internally in
717*4882a593Smuzhiyun  * the implementation of osl_debug_vmalloc.  Because we are using the GCC
718*4882a593Smuzhiyun  * -Wstrict-prototypes compile option, we must always have a prototype
719*4882a593Smuzhiyun  * for a global/external function.  So make osl_vmalloc static in
720*4882a593Smuzhiyun  * the BCMDBG_MEM case.
721*4882a593Smuzhiyun  */
722*4882a593Smuzhiyun static
723*4882a593Smuzhiyun #endif
724*4882a593Smuzhiyun void *
osl_vmalloc(osl_t * osh,uint size)725*4882a593Smuzhiyun osl_vmalloc(osl_t *osh, uint size)
726*4882a593Smuzhiyun {
727*4882a593Smuzhiyun 	void *addr;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	/* only ASSERT if osh is defined */
730*4882a593Smuzhiyun 	if (osh)
731*4882a593Smuzhiyun 		ASSERT(osh->magic == OS_HANDLE_MAGIC);
732*4882a593Smuzhiyun 	if ((addr = vmalloc(size)) == NULL) {
733*4882a593Smuzhiyun 		if (osh)
734*4882a593Smuzhiyun 			osh->failed++;
735*4882a593Smuzhiyun 		return (NULL);
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 	if (osh && osh->cmn)
738*4882a593Smuzhiyun 		atomic_add(size, &osh->cmn->malloced);
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	return (addr);
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun #ifndef BCMDBG_MEM
744*4882a593Smuzhiyun void *
osl_vmallocz(osl_t * osh,uint size)745*4882a593Smuzhiyun osl_vmallocz(osl_t *osh, uint size)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun 	void *ptr;
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	ptr = osl_vmalloc(osh, size);
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (ptr != NULL) {
752*4882a593Smuzhiyun 		bzero(ptr, size);
753*4882a593Smuzhiyun 	}
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	return ptr;
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun #endif
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun #ifdef BCMDBG_MEM
760*4882a593Smuzhiyun /* In BCMDBG_MEM configurations osl_vmfree is only used internally in
761*4882a593Smuzhiyun  * the implementation of osl_debug_vmfree.  Because we are using the GCC
762*4882a593Smuzhiyun  * -Wstrict-prototypes compile option, we must always have a prototype
763*4882a593Smuzhiyun  * for a global/external function.  So make osl_vmfree static in
764*4882a593Smuzhiyun  * the BCMDBG_MEM case.
765*4882a593Smuzhiyun  */
766*4882a593Smuzhiyun static
767*4882a593Smuzhiyun #endif
768*4882a593Smuzhiyun void
osl_vmfree(osl_t * osh,void * addr,uint size)769*4882a593Smuzhiyun osl_vmfree(osl_t *osh, void *addr, uint size)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun 	if (osh && osh->cmn) {
772*4882a593Smuzhiyun 		ASSERT(osh->magic == OS_HANDLE_MAGIC);
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 		ASSERT(size <= osl_malloced(osh));
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 		atomic_sub(size, &osh->cmn->malloced);
777*4882a593Smuzhiyun 	}
778*4882a593Smuzhiyun 	vfree(addr);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun uint
osl_check_memleak(osl_t * osh)782*4882a593Smuzhiyun osl_check_memleak(osl_t *osh)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
785*4882a593Smuzhiyun 	if (atomic_read(&osh->cmn->refcount) == 1)
786*4882a593Smuzhiyun 		return (atomic_read(&osh->cmn->malloced));
787*4882a593Smuzhiyun 	else
788*4882a593Smuzhiyun 		return 0;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun uint
osl_malloced(osl_t * osh)792*4882a593Smuzhiyun osl_malloced(osl_t *osh)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
795*4882a593Smuzhiyun 	return (atomic_read(&osh->cmn->malloced));
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun uint
osl_malloc_failed(osl_t * osh)799*4882a593Smuzhiyun osl_malloc_failed(osl_t *osh)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
802*4882a593Smuzhiyun 	return (osh->failed);
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun #ifdef BCMDBG_MEM
806*4882a593Smuzhiyun void *
osl_debug_malloc(osl_t * osh,uint size,int line,const char * file)807*4882a593Smuzhiyun osl_debug_malloc(osl_t *osh, uint size, int line, const char* file)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun 	bcm_mem_link_t *p;
810*4882a593Smuzhiyun 	const char* basename;
811*4882a593Smuzhiyun 	unsigned long flags = 0;
812*4882a593Smuzhiyun 	if (!size) {
813*4882a593Smuzhiyun 		printf("%s: allocating zero sized mem at %s line %d\n", __FUNCTION__, file, line);
814*4882a593Smuzhiyun 		ASSERT(0);
815*4882a593Smuzhiyun 	}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	if ((p = (bcm_mem_link_t*)osl_malloc(osh, sizeof(bcm_mem_link_t) + size)) == NULL) {
818*4882a593Smuzhiyun 		return (NULL);
819*4882a593Smuzhiyun 	}
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	if (osh) {
822*4882a593Smuzhiyun 		OSL_MEMLIST_LOCK(&osh->cmn->dbgmem_lock, flags);
823*4882a593Smuzhiyun 	}
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	p->size = size;
826*4882a593Smuzhiyun 	p->line = line;
827*4882a593Smuzhiyun 	p->osh = (void *)osh;
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun 	basename = strrchr(file, '/');
830*4882a593Smuzhiyun 	/* skip the '/' */
831*4882a593Smuzhiyun 	if (basename)
832*4882a593Smuzhiyun 		basename++;
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	if (!basename)
835*4882a593Smuzhiyun 		basename = file;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	strlcpy(p->file, basename, sizeof(p->file));
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	/* link this block */
840*4882a593Smuzhiyun 	if (osh) {
841*4882a593Smuzhiyun 		p->prev = NULL;
842*4882a593Smuzhiyun 		p->next = osh->cmn->dbgmem_list;
843*4882a593Smuzhiyun 		if (p->next)
844*4882a593Smuzhiyun 			p->next->prev = p;
845*4882a593Smuzhiyun 		osh->cmn->dbgmem_list = p;
846*4882a593Smuzhiyun 		OSL_MEMLIST_UNLOCK(&osh->cmn->dbgmem_lock, flags);
847*4882a593Smuzhiyun 	}
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	return p + 1;
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun void *
osl_debug_mallocz(osl_t * osh,uint size,int line,const char * file)853*4882a593Smuzhiyun osl_debug_mallocz(osl_t *osh, uint size, int line, const char* file)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun 	void *ptr;
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	ptr = osl_debug_malloc(osh, size, line, file);
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	if (ptr != NULL) {
860*4882a593Smuzhiyun 		bzero(ptr, size);
861*4882a593Smuzhiyun 	}
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	return ptr;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun void
osl_debug_mfree(osl_t * osh,void * addr,uint size,int line,const char * file)867*4882a593Smuzhiyun osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, const char* file)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun 	bcm_mem_link_t *p;
870*4882a593Smuzhiyun 	unsigned long flags = 0;
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	ASSERT(osh == NULL || osh->magic == OS_HANDLE_MAGIC);
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	if (addr == NULL) {
875*4882a593Smuzhiyun 		return;
876*4882a593Smuzhiyun 	}
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t));
879*4882a593Smuzhiyun 	if (p->size == 0) {
880*4882a593Smuzhiyun 		printf("osl_debug_mfree: double free on addr %p size %d at line %d file %s\n",
881*4882a593Smuzhiyun 			addr, size, line, file);
882*4882a593Smuzhiyun 		prhex("bcm_mem_link_t", (void *)p, sizeof(*p));
883*4882a593Smuzhiyun 		ASSERT(p->size);
884*4882a593Smuzhiyun 		return;
885*4882a593Smuzhiyun 	}
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	if (p->size != size) {
888*4882a593Smuzhiyun 		printf("%s: dealloca size does not match alloc size\n", __FUNCTION__);
889*4882a593Smuzhiyun 		printf("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
890*4882a593Smuzhiyun 		printf("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
891*4882a593Smuzhiyun 		prhex("bcm_mem_link_t", (void *)p, sizeof(*p));
892*4882a593Smuzhiyun 		ASSERT(p->size == size);
893*4882a593Smuzhiyun 		return;
894*4882a593Smuzhiyun 	}
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	if (osh && ((osl_t*)p->osh)->cmn != osh->cmn) {
897*4882a593Smuzhiyun 		printf("osl_debug_mfree: alloc osh %p does not match dealloc osh %p\n",
898*4882a593Smuzhiyun 			((osl_t*)p->osh)->cmn, osh->cmn);
899*4882a593Smuzhiyun 		printf("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
900*4882a593Smuzhiyun 		printf("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
901*4882a593Smuzhiyun 		prhex("bcm_mem_link_t", (void *)p, sizeof(*p));
902*4882a593Smuzhiyun 		ASSERT(((osl_t*)p->osh)->cmn == osh->cmn);
903*4882a593Smuzhiyun 		return;
904*4882a593Smuzhiyun 	}
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	/* unlink this block */
907*4882a593Smuzhiyun 	if (osh && osh->cmn) {
908*4882a593Smuzhiyun 		OSL_MEMLIST_LOCK(&osh->cmn->dbgmem_lock, flags);
909*4882a593Smuzhiyun 		if (p->prev)
910*4882a593Smuzhiyun 			p->prev->next = p->next;
911*4882a593Smuzhiyun 		if (p->next)
912*4882a593Smuzhiyun 			p->next->prev = p->prev;
913*4882a593Smuzhiyun 		if (osh->cmn->dbgmem_list == p)
914*4882a593Smuzhiyun 			osh->cmn->dbgmem_list = p->next;
915*4882a593Smuzhiyun 		p->next = p->prev = NULL;
916*4882a593Smuzhiyun 	}
917*4882a593Smuzhiyun 	p->size = 0;
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	if (osh && osh->cmn) {
920*4882a593Smuzhiyun 		OSL_MEMLIST_UNLOCK(&osh->cmn->dbgmem_lock, flags);
921*4882a593Smuzhiyun 	}
922*4882a593Smuzhiyun 	osl_mfree(osh, p, size + sizeof(bcm_mem_link_t));
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun void *
osl_debug_vmalloc(osl_t * osh,uint size,int line,const char * file)926*4882a593Smuzhiyun osl_debug_vmalloc(osl_t *osh, uint size, int line, const char* file)
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun 	bcm_mem_link_t *p;
929*4882a593Smuzhiyun 	const char* basename;
930*4882a593Smuzhiyun 	unsigned long flags = 0;
931*4882a593Smuzhiyun 	if (!size) {
932*4882a593Smuzhiyun 		printf("%s: allocating zero sized mem at %s line %d\n", __FUNCTION__, file, line);
933*4882a593Smuzhiyun 		ASSERT(0);
934*4882a593Smuzhiyun 	}
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	if ((p = (bcm_mem_link_t*)osl_vmalloc(osh, sizeof(bcm_mem_link_t) + size)) == NULL) {
937*4882a593Smuzhiyun 		return (NULL);
938*4882a593Smuzhiyun 	}
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	if (osh) {
941*4882a593Smuzhiyun 		OSL_MEMLIST_LOCK(&osh->cmn->dbgmem_lock, flags);
942*4882a593Smuzhiyun 	}
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 	p->size = size;
945*4882a593Smuzhiyun 	p->line = line;
946*4882a593Smuzhiyun 	p->osh = (void *)osh;
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	basename = strrchr(file, '/');
949*4882a593Smuzhiyun 	/* skip the '/' */
950*4882a593Smuzhiyun 	if (basename)
951*4882a593Smuzhiyun 		basename++;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	if (!basename)
954*4882a593Smuzhiyun 		basename = file;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	strlcpy(p->file, basename, sizeof(p->file));
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	/* link this block */
959*4882a593Smuzhiyun 	if (osh) {
960*4882a593Smuzhiyun 		p->prev = NULL;
961*4882a593Smuzhiyun 		p->next = osh->cmn->dbgvmem_list;
962*4882a593Smuzhiyun 		if (p->next)
963*4882a593Smuzhiyun 			p->next->prev = p;
964*4882a593Smuzhiyun 		osh->cmn->dbgvmem_list = p;
965*4882a593Smuzhiyun 		OSL_MEMLIST_UNLOCK(&osh->cmn->dbgmem_lock, flags);
966*4882a593Smuzhiyun 	}
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	return p + 1;
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun void *
osl_debug_vmallocz(osl_t * osh,uint size,int line,const char * file)972*4882a593Smuzhiyun osl_debug_vmallocz(osl_t *osh, uint size, int line, const char* file)
973*4882a593Smuzhiyun {
974*4882a593Smuzhiyun 	void *ptr;
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	ptr = osl_debug_vmalloc(osh, size, line, file);
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	if (ptr != NULL) {
979*4882a593Smuzhiyun 		bzero(ptr, size);
980*4882a593Smuzhiyun 	}
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun 	return ptr;
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun void
osl_debug_vmfree(osl_t * osh,void * addr,uint size,int line,const char * file)986*4882a593Smuzhiyun osl_debug_vmfree(osl_t *osh, void *addr, uint size, int line, const char* file)
987*4882a593Smuzhiyun {
988*4882a593Smuzhiyun 	bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t));
989*4882a593Smuzhiyun 	unsigned long flags = 0;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	ASSERT(osh == NULL || osh->magic == OS_HANDLE_MAGIC);
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	if (p->size == 0) {
994*4882a593Smuzhiyun 		printf("osl_debug_mfree: double free on addr %p size %d at line %d file %s\n",
995*4882a593Smuzhiyun 			addr, size, line, file);
996*4882a593Smuzhiyun 		ASSERT(p->size);
997*4882a593Smuzhiyun 		return;
998*4882a593Smuzhiyun 	}
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	if (p->size != size) {
1001*4882a593Smuzhiyun 		printf("%s: dealloca size does not match alloc size\n", __FUNCTION__);
1002*4882a593Smuzhiyun 		printf("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
1003*4882a593Smuzhiyun 		printf("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
1004*4882a593Smuzhiyun 		ASSERT(p->size == size);
1005*4882a593Smuzhiyun 		return;
1006*4882a593Smuzhiyun 	}
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	if (osh && ((osl_t*)p->osh)->cmn != osh->cmn) {
1009*4882a593Smuzhiyun 		printf("osl_debug_mfree: alloc osh %p does not match dealloc osh %p\n",
1010*4882a593Smuzhiyun 			((osl_t*)p->osh)->cmn, osh->cmn);
1011*4882a593Smuzhiyun 		printf("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
1012*4882a593Smuzhiyun 		printf("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
1013*4882a593Smuzhiyun 		ASSERT(((osl_t*)p->osh)->cmn == osh->cmn);
1014*4882a593Smuzhiyun 		return;
1015*4882a593Smuzhiyun 	}
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	/* unlink this block */
1018*4882a593Smuzhiyun 	if (osh && osh->cmn) {
1019*4882a593Smuzhiyun 		OSL_MEMLIST_LOCK(&osh->cmn->dbgmem_lock, flags);
1020*4882a593Smuzhiyun 		if (p->prev)
1021*4882a593Smuzhiyun 			p->prev->next = p->next;
1022*4882a593Smuzhiyun 		if (p->next)
1023*4882a593Smuzhiyun 			p->next->prev = p->prev;
1024*4882a593Smuzhiyun 		if (osh->cmn->dbgvmem_list == p)
1025*4882a593Smuzhiyun 			osh->cmn->dbgvmem_list = p->next;
1026*4882a593Smuzhiyun 		p->next = p->prev = NULL;
1027*4882a593Smuzhiyun 	}
1028*4882a593Smuzhiyun 	p->size = 0;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	if (osh && osh->cmn) {
1031*4882a593Smuzhiyun 		OSL_MEMLIST_UNLOCK(&osh->cmn->dbgmem_lock, flags);
1032*4882a593Smuzhiyun 	}
1033*4882a593Smuzhiyun 	osl_vmfree(osh, p, size + sizeof(bcm_mem_link_t));
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun int
osl_debug_memdump(osl_t * osh,struct bcmstrbuf * b)1037*4882a593Smuzhiyun osl_debug_memdump(osl_t *osh, struct bcmstrbuf *b)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun 	bcm_mem_link_t *p;
1040*4882a593Smuzhiyun 	unsigned long flags = 0;
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun 	OSL_MEMLIST_LOCK(&osh->cmn->dbgmem_lock, flags);
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun 	if (osl_check_memleak(osh) && osh->cmn->dbgmem_list) {
1047*4882a593Smuzhiyun 		if (b != NULL)
1048*4882a593Smuzhiyun 			bcm_bprintf(b, "   Address   Size File:line\n");
1049*4882a593Smuzhiyun 		else
1050*4882a593Smuzhiyun 			printf("   Address   Size File:line\n");
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 		for (p = osh->cmn->dbgmem_list; p; p = p->next) {
1053*4882a593Smuzhiyun 			if (b != NULL)
1054*4882a593Smuzhiyun 				bcm_bprintf(b, "%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
1055*4882a593Smuzhiyun 					p->size, p->file, p->line);
1056*4882a593Smuzhiyun 			else
1057*4882a593Smuzhiyun 				printk("%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
1058*4882a593Smuzhiyun 					p->size, p->file, p->line);
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 			/* Detects loop-to-self so we don't enter infinite loop */
1061*4882a593Smuzhiyun 			if (p == p->next) {
1062*4882a593Smuzhiyun 				if (b != NULL)
1063*4882a593Smuzhiyun 					bcm_bprintf(b, "WARNING: loop-to-self "
1064*4882a593Smuzhiyun 						"p %p p->next %p\n", p, p->next);
1065*4882a593Smuzhiyun 				else
1066*4882a593Smuzhiyun 					printk("WARNING: loop-to-self "
1067*4882a593Smuzhiyun 						"p %p p->next %p\n", p, p->next);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 				break;
1070*4882a593Smuzhiyun 			}
1071*4882a593Smuzhiyun 		}
1072*4882a593Smuzhiyun 	}
1073*4882a593Smuzhiyun 	if (osl_check_memleak(osh) && osh->cmn->dbgvmem_list) {
1074*4882a593Smuzhiyun 		if (b != NULL)
1075*4882a593Smuzhiyun 			bcm_bprintf(b, "Vmem\n   Address   Size File:line\n");
1076*4882a593Smuzhiyun 		else
1077*4882a593Smuzhiyun 			printf("Vmem\n   Address   Size File:line\n");
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 		for (p = osh->cmn->dbgvmem_list; p; p = p->next) {
1080*4882a593Smuzhiyun 			if (b != NULL)
1081*4882a593Smuzhiyun 				bcm_bprintf(b, "%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
1082*4882a593Smuzhiyun 					p->size, p->file, p->line);
1083*4882a593Smuzhiyun 			else
1084*4882a593Smuzhiyun 				printk("%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
1085*4882a593Smuzhiyun 					p->size, p->file, p->line);
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 			/* Detects loop-to-self so we don't enter infinite loop */
1088*4882a593Smuzhiyun 			if (p == p->next) {
1089*4882a593Smuzhiyun 				if (b != NULL)
1090*4882a593Smuzhiyun 					bcm_bprintf(b, "WARNING: loop-to-self "
1091*4882a593Smuzhiyun 						"p %p p->next %p\n", p, p->next);
1092*4882a593Smuzhiyun 				else
1093*4882a593Smuzhiyun 					printk("WARNING: loop-to-self "
1094*4882a593Smuzhiyun 						"p %p p->next %p\n", p, p->next);
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 				break;
1097*4882a593Smuzhiyun 			}
1098*4882a593Smuzhiyun 		}
1099*4882a593Smuzhiyun 	}
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun 	OSL_MEMLIST_UNLOCK(&osh->cmn->dbgmem_lock, flags);
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun 	return 0;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun #endif	/* BCMDBG_MEM */
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun uint
osl_dma_consistent_align(void)1109*4882a593Smuzhiyun osl_dma_consistent_align(void)
1110*4882a593Smuzhiyun {
1111*4882a593Smuzhiyun 	return (PAGE_SIZE);
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun 
1114*4882a593Smuzhiyun void*
osl_dma_alloc_consistent(osl_t * osh,uint size,uint16 align_bits,uint * alloced,dmaaddr_t * pap)1115*4882a593Smuzhiyun osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, dmaaddr_t *pap)
1116*4882a593Smuzhiyun {
1117*4882a593Smuzhiyun 	void *va;
1118*4882a593Smuzhiyun 	uint16 align = (1 << align_bits);
1119*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
1122*4882a593Smuzhiyun 		size += align;
1123*4882a593Smuzhiyun 	*alloced = size;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun #if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING))
1126*4882a593Smuzhiyun 	va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
1127*4882a593Smuzhiyun 	if (va)
1128*4882a593Smuzhiyun 		*pap = (ulong)__virt_to_phys((ulong)va);
1129*4882a593Smuzhiyun #else
1130*4882a593Smuzhiyun 	{
1131*4882a593Smuzhiyun 		dma_addr_t pap_lin;
1132*4882a593Smuzhiyun 		struct pci_dev *hwdev = osh->pdev;
1133*4882a593Smuzhiyun 		gfp_t flags;
1134*4882a593Smuzhiyun #ifdef DHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL
1135*4882a593Smuzhiyun 		flags = GFP_ATOMIC;
1136*4882a593Smuzhiyun #else
1137*4882a593Smuzhiyun 		flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
1138*4882a593Smuzhiyun #endif /* DHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL */
1139*4882a593Smuzhiyun #ifdef DHD_ALLOC_COHERENT_MEM_WITH_GFP_COMP
1140*4882a593Smuzhiyun 		flags |= __GFP_COMP;
1141*4882a593Smuzhiyun #endif /* DHD_ALLOC_COHERENT_MEM_WITH_GFP_COMP */
1142*4882a593Smuzhiyun 		va = dma_alloc_coherent(&hwdev->dev, size, &pap_lin, flags);
1143*4882a593Smuzhiyun #ifdef BCMDMA64OSL
1144*4882a593Smuzhiyun 		PHYSADDRLOSET(*pap, pap_lin & 0xffffffff);
1145*4882a593Smuzhiyun 		PHYSADDRHISET(*pap, (pap_lin >> 32) & 0xffffffff);
1146*4882a593Smuzhiyun #else
1147*4882a593Smuzhiyun 		*pap = (dmaaddr_t)pap_lin;
1148*4882a593Smuzhiyun #endif /* BCMDMA64OSL */
1149*4882a593Smuzhiyun 	}
1150*4882a593Smuzhiyun #endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	return va;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun void
osl_dma_free_consistent(osl_t * osh,void * va,uint size,dmaaddr_t pa)1156*4882a593Smuzhiyun osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa)
1157*4882a593Smuzhiyun {
1158*4882a593Smuzhiyun #ifdef BCMDMA64OSL
1159*4882a593Smuzhiyun 	dma_addr_t paddr;
1160*4882a593Smuzhiyun #endif /* BCMDMA64OSL */
1161*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun #if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING))
1164*4882a593Smuzhiyun 	kfree(va);
1165*4882a593Smuzhiyun #else
1166*4882a593Smuzhiyun #ifdef BCMDMA64OSL
1167*4882a593Smuzhiyun 	PHYSADDRTOULONG(pa, paddr);
1168*4882a593Smuzhiyun 	pci_free_consistent(osh->pdev, size, va, paddr);
1169*4882a593Smuzhiyun #else
1170*4882a593Smuzhiyun 	pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
1171*4882a593Smuzhiyun #endif /* BCMDMA64OSL */
1172*4882a593Smuzhiyun #endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
1173*4882a593Smuzhiyun }
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun void *
osl_virt_to_phys(void * va)1176*4882a593Smuzhiyun osl_virt_to_phys(void *va)
1177*4882a593Smuzhiyun {
1178*4882a593Smuzhiyun 	return (void *)(uintptr)virt_to_phys(va);
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun 
1181*4882a593Smuzhiyun #include <asm/cacheflush.h>
1182*4882a593Smuzhiyun void
BCMFASTPATH(osl_dma_flush)1183*4882a593Smuzhiyun BCMFASTPATH(osl_dma_flush)(osl_t *osh, void *va, uint size, int direction, void *p,
1184*4882a593Smuzhiyun 	hnddma_seg_map_t *dmah)
1185*4882a593Smuzhiyun {
1186*4882a593Smuzhiyun 	return;
1187*4882a593Smuzhiyun }
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun dmaaddr_t
BCMFASTPATH(osl_dma_map)1190*4882a593Smuzhiyun BCMFASTPATH(osl_dma_map)(osl_t *osh, void *va, uint size, int direction, void *p,
1191*4882a593Smuzhiyun 	hnddma_seg_map_t *dmah)
1192*4882a593Smuzhiyun {
1193*4882a593Smuzhiyun 	int dir;
1194*4882a593Smuzhiyun 	dmaaddr_t ret_addr;
1195*4882a593Smuzhiyun 	dma_addr_t map_addr;
1196*4882a593Smuzhiyun 	int ret;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	DMA_LOCK(osh);
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1201*4882a593Smuzhiyun 	dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	map_addr = pci_map_single(osh->pdev, va, size, dir);
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	ret = pci_dma_mapping_error(osh->pdev, map_addr);
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	if (ret) {
1208*4882a593Smuzhiyun 		printf("%s: Failed to map memory\n", __FUNCTION__);
1209*4882a593Smuzhiyun 		PHYSADDRLOSET(ret_addr, 0);
1210*4882a593Smuzhiyun 		PHYSADDRHISET(ret_addr, 0);
1211*4882a593Smuzhiyun 	} else {
1212*4882a593Smuzhiyun 		PHYSADDRLOSET(ret_addr, map_addr & 0xffffffff);
1213*4882a593Smuzhiyun 		PHYSADDRHISET(ret_addr, (map_addr >> 32) & 0xffffffff);
1214*4882a593Smuzhiyun 	}
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun #ifdef DHD_MAP_LOGGING
1217*4882a593Smuzhiyun 	osl_dma_map_logging(osh, osh->dhd_map_log, ret_addr, size);
1218*4882a593Smuzhiyun #endif /* DHD_MAP_LOGGING */
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	DMA_UNLOCK(osh);
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	return ret_addr;
1223*4882a593Smuzhiyun }
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun void
BCMFASTPATH(osl_dma_unmap)1226*4882a593Smuzhiyun BCMFASTPATH(osl_dma_unmap)(osl_t *osh, dmaaddr_t pa, uint size, int direction)
1227*4882a593Smuzhiyun {
1228*4882a593Smuzhiyun 	int dir;
1229*4882a593Smuzhiyun #ifdef BCMDMA64OSL
1230*4882a593Smuzhiyun 	dma_addr_t paddr;
1231*4882a593Smuzhiyun #endif /* BCMDMA64OSL */
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1234*4882a593Smuzhiyun 
1235*4882a593Smuzhiyun 	DMA_LOCK(osh);
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun #ifdef DHD_MAP_LOGGING
1240*4882a593Smuzhiyun 	osl_dma_map_logging(osh, osh->dhd_unmap_log, pa, size);
1241*4882a593Smuzhiyun #endif /* DHD_MAP_LOGGING */
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun #ifdef BCMDMA64OSL
1244*4882a593Smuzhiyun 	PHYSADDRTOULONG(pa, paddr);
1245*4882a593Smuzhiyun 	pci_unmap_single(osh->pdev, paddr, size, dir);
1246*4882a593Smuzhiyun #else /* BCMDMA64OSL */
1247*4882a593Smuzhiyun 	pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
1248*4882a593Smuzhiyun #endif /* BCMDMA64OSL */
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	DMA_UNLOCK(osh);
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun /* OSL function for CPU relax */
1254*4882a593Smuzhiyun inline void
BCMFASTPATH(osl_cpu_relax)1255*4882a593Smuzhiyun BCMFASTPATH(osl_cpu_relax)(void)
1256*4882a593Smuzhiyun {
1257*4882a593Smuzhiyun 	cpu_relax();
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun 
osl_preempt_disable(osl_t * osh)1260*4882a593Smuzhiyun extern void osl_preempt_disable(osl_t *osh)
1261*4882a593Smuzhiyun {
1262*4882a593Smuzhiyun 	preempt_disable();
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun 
osl_preempt_enable(osl_t * osh)1265*4882a593Smuzhiyun extern void osl_preempt_enable(osl_t *osh)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun 	preempt_enable();
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun 
1270*4882a593Smuzhiyun #if defined(BCMDBG_ASSERT) || defined(BCMASSERT_LOG)
1271*4882a593Smuzhiyun void
osl_assert(const char * exp,const char * file,int line)1272*4882a593Smuzhiyun osl_assert(const char *exp, const char *file, int line)
1273*4882a593Smuzhiyun {
1274*4882a593Smuzhiyun 	char tempbuf[256];
1275*4882a593Smuzhiyun 	const char *basename;
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun 	basename = strrchr(file, '/');
1278*4882a593Smuzhiyun 	/* skip the '/' */
1279*4882a593Smuzhiyun 	if (basename)
1280*4882a593Smuzhiyun 		basename++;
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun 	if (!basename)
1283*4882a593Smuzhiyun 		basename = file;
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun #ifdef BCMASSERT_LOG
1286*4882a593Smuzhiyun 	snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n",
1287*4882a593Smuzhiyun 		exp, basename, line);
1288*4882a593Smuzhiyun #ifndef OEM_ANDROID
1289*4882a593Smuzhiyun 	bcm_assert_log(tempbuf);
1290*4882a593Smuzhiyun #endif /* OEM_ANDROID */
1291*4882a593Smuzhiyun #endif /* BCMASSERT_LOG */
1292*4882a593Smuzhiyun 
1293*4882a593Smuzhiyun #ifdef BCMDBG_ASSERT
1294*4882a593Smuzhiyun 	snprintf(tempbuf, 256, "assertion \"%s\" failed: file \"%s\", line %d\n",
1295*4882a593Smuzhiyun 		exp, basename, line);
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	/* Print assert message and give it time to be written to /var/log/messages */
1298*4882a593Smuzhiyun 	if (!in_interrupt() && g_assert_type != 1 && g_assert_type != 3) {
1299*4882a593Smuzhiyun 		const int delay = 3;
1300*4882a593Smuzhiyun 		printf("%s", tempbuf);
1301*4882a593Smuzhiyun 		printf("panic in %d seconds\n", delay);
1302*4882a593Smuzhiyun 		set_current_state(TASK_INTERRUPTIBLE);
1303*4882a593Smuzhiyun 		schedule_timeout(delay * HZ);
1304*4882a593Smuzhiyun 	}
1305*4882a593Smuzhiyun #endif /* BCMDBG_ASSERT */
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun 	switch (g_assert_type) {
1308*4882a593Smuzhiyun 	case 0:
1309*4882a593Smuzhiyun 		printf("%s", tempbuf);
1310*4882a593Smuzhiyun 		BUG();
1311*4882a593Smuzhiyun 		break;
1312*4882a593Smuzhiyun 	case 1:
1313*4882a593Smuzhiyun 		/* fall through */
1314*4882a593Smuzhiyun 	case 3:
1315*4882a593Smuzhiyun 		printf("%s", tempbuf);
1316*4882a593Smuzhiyun 		break;
1317*4882a593Smuzhiyun 	case 2:
1318*4882a593Smuzhiyun 		printf("%s", tempbuf);
1319*4882a593Smuzhiyun 		BUG();
1320*4882a593Smuzhiyun 		break;
1321*4882a593Smuzhiyun 	default:
1322*4882a593Smuzhiyun 		break;
1323*4882a593Smuzhiyun 	}
1324*4882a593Smuzhiyun }
1325*4882a593Smuzhiyun #endif /* BCMDBG_ASSERT || BCMASSERT_LOG */
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun void
osl_delay(uint usec)1328*4882a593Smuzhiyun osl_delay(uint usec)
1329*4882a593Smuzhiyun {
1330*4882a593Smuzhiyun 	uint d;
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun #ifdef BCMSLTGT
1333*4882a593Smuzhiyun 	usec *= htclkratio;
1334*4882a593Smuzhiyun #endif
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 	while (usec > 0) {
1337*4882a593Smuzhiyun 		d = MIN(usec, 1000);
1338*4882a593Smuzhiyun 		udelay(d);
1339*4882a593Smuzhiyun 		usec -= d;
1340*4882a593Smuzhiyun 	}
1341*4882a593Smuzhiyun }
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun void
osl_sleep(uint ms)1344*4882a593Smuzhiyun osl_sleep(uint ms)
1345*4882a593Smuzhiyun {
1346*4882a593Smuzhiyun #ifdef BCMSLTGT
1347*4882a593Smuzhiyun 	ms *= htclkratio;
1348*4882a593Smuzhiyun #endif
1349*4882a593Smuzhiyun 
1350*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1351*4882a593Smuzhiyun 	if (ms < 20)
1352*4882a593Smuzhiyun 		usleep_range(ms*1000, ms*1000 + 1000);
1353*4882a593Smuzhiyun 	else
1354*4882a593Smuzhiyun #endif
1355*4882a593Smuzhiyun 		msleep(ms);
1356*4882a593Smuzhiyun }
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun uint64
osl_sysuptime_us(void)1359*4882a593Smuzhiyun osl_sysuptime_us(void)
1360*4882a593Smuzhiyun {
1361*4882a593Smuzhiyun 	struct osl_timespec tv;
1362*4882a593Smuzhiyun 	uint64 usec;
1363*4882a593Smuzhiyun 
1364*4882a593Smuzhiyun 	osl_do_gettimeofday(&tv);
1365*4882a593Smuzhiyun 	/* tv_usec content is fraction of a second */
1366*4882a593Smuzhiyun 	usec = (uint64)tv.tv_sec * 1000000ul + tv.tv_usec;
1367*4882a593Smuzhiyun #ifdef BCMSLTGT
1368*4882a593Smuzhiyun 	/* scale down the time to match the slow target roughly */
1369*4882a593Smuzhiyun 	usec /= htclkratio;
1370*4882a593Smuzhiyun #endif
1371*4882a593Smuzhiyun 	return usec;
1372*4882a593Smuzhiyun }
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun uint64
osl_localtime_ns(void)1375*4882a593Smuzhiyun osl_localtime_ns(void)
1376*4882a593Smuzhiyun {
1377*4882a593Smuzhiyun 	uint64 ts_nsec = 0;
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun #ifdef BCMDONGLEHOST
1380*4882a593Smuzhiyun 	/* Some Linux based platform cannot use local_clock()
1381*4882a593Smuzhiyun 	 * since it is defined by EXPORT_SYMBOL_GPL().
1382*4882a593Smuzhiyun 	 * GPL-incompatible module (NIC builds wl.ko)
1383*4882a593Smuzhiyun 	 * cannnot use the GPL-only symbol.
1384*4882a593Smuzhiyun 	 */
1385*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1386*4882a593Smuzhiyun 	ts_nsec = local_clock();
1387*4882a593Smuzhiyun #else
1388*4882a593Smuzhiyun 	ts_nsec = cpu_clock(smp_processor_id());
1389*4882a593Smuzhiyun #endif
1390*4882a593Smuzhiyun #endif /* BCMDONGLEHOST */
1391*4882a593Smuzhiyun 	return ts_nsec;
1392*4882a593Smuzhiyun }
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun void
osl_get_localtime(uint64 * sec,uint64 * usec)1395*4882a593Smuzhiyun osl_get_localtime(uint64 *sec, uint64 *usec)
1396*4882a593Smuzhiyun {
1397*4882a593Smuzhiyun 	uint64 ts_nsec = 0;
1398*4882a593Smuzhiyun 	unsigned long rem_nsec = 0;
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun #ifdef BCMDONGLEHOST
1401*4882a593Smuzhiyun 	/* Some Linux based platform cannot use local_clock()
1402*4882a593Smuzhiyun 	 * since it is defined by EXPORT_SYMBOL_GPL().
1403*4882a593Smuzhiyun 	 * GPL-incompatible module (NIC builds wl.ko) can
1404*4882a593Smuzhiyun 	 * not use the GPL-only symbol.
1405*4882a593Smuzhiyun 	 */
1406*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1407*4882a593Smuzhiyun 	ts_nsec = local_clock();
1408*4882a593Smuzhiyun #else
1409*4882a593Smuzhiyun 	ts_nsec = cpu_clock(smp_processor_id());
1410*4882a593Smuzhiyun #endif
1411*4882a593Smuzhiyun 	rem_nsec = do_div(ts_nsec, NSEC_PER_SEC);
1412*4882a593Smuzhiyun #endif /* BCMDONGLEHOST */
1413*4882a593Smuzhiyun 	*sec = (uint64)ts_nsec;
1414*4882a593Smuzhiyun 	*usec = (uint64)(rem_nsec / MSEC_PER_SEC);
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun 
1417*4882a593Smuzhiyun uint64
osl_systztime_us(void)1418*4882a593Smuzhiyun osl_systztime_us(void)
1419*4882a593Smuzhiyun {
1420*4882a593Smuzhiyun 	struct osl_timespec tv;
1421*4882a593Smuzhiyun 	uint64 tzusec;
1422*4882a593Smuzhiyun 
1423*4882a593Smuzhiyun 	osl_do_gettimeofday(&tv);
1424*4882a593Smuzhiyun 	/* apply timezone */
1425*4882a593Smuzhiyun 	tzusec = (uint64)((tv.tv_sec - (sys_tz.tz_minuteswest * 60)) *
1426*4882a593Smuzhiyun 		USEC_PER_SEC);
1427*4882a593Smuzhiyun 	tzusec += tv.tv_usec;
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 	return tzusec;
1430*4882a593Smuzhiyun }
1431*4882a593Smuzhiyun 
1432*4882a593Smuzhiyun /*
1433*4882a593Smuzhiyun  * OSLREGOPS specifies the use of osl_XXX routines to be used for register access
1434*4882a593Smuzhiyun  */
1435*4882a593Smuzhiyun #ifdef OSLREGOPS
1436*4882a593Smuzhiyun uint8
osl_readb(osl_t * osh,volatile uint8 * r)1437*4882a593Smuzhiyun osl_readb(osl_t *osh, volatile uint8 *r)
1438*4882a593Smuzhiyun {
1439*4882a593Smuzhiyun 	osl_rreg_fn_t rreg	= ((osl_pubinfo_t*)osh)->rreg_fn;
1440*4882a593Smuzhiyun 	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun 	return (uint8)((rreg)(ctx, (volatile void*)r, sizeof(uint8)));
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun 
1445*4882a593Smuzhiyun uint16
osl_readw(osl_t * osh,volatile uint16 * r)1446*4882a593Smuzhiyun osl_readw(osl_t *osh, volatile uint16 *r)
1447*4882a593Smuzhiyun {
1448*4882a593Smuzhiyun 	osl_rreg_fn_t rreg	= ((osl_pubinfo_t*)osh)->rreg_fn;
1449*4882a593Smuzhiyun 	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
1450*4882a593Smuzhiyun 
1451*4882a593Smuzhiyun 	return (uint16)((rreg)(ctx, (volatile void*)r, sizeof(uint16)));
1452*4882a593Smuzhiyun }
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun uint32
osl_readl(osl_t * osh,volatile uint32 * r)1455*4882a593Smuzhiyun osl_readl(osl_t *osh, volatile uint32 *r)
1456*4882a593Smuzhiyun {
1457*4882a593Smuzhiyun 	osl_rreg_fn_t rreg	= ((osl_pubinfo_t*)osh)->rreg_fn;
1458*4882a593Smuzhiyun 	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun 	return (uint32)((rreg)(ctx, (volatile void*)r, sizeof(uint32)));
1461*4882a593Smuzhiyun }
1462*4882a593Smuzhiyun 
1463*4882a593Smuzhiyun void
osl_writeb(osl_t * osh,volatile uint8 * r,uint8 v)1464*4882a593Smuzhiyun osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v)
1465*4882a593Smuzhiyun {
1466*4882a593Smuzhiyun 	osl_wreg_fn_t wreg	= ((osl_pubinfo_t*)osh)->wreg_fn;
1467*4882a593Smuzhiyun 	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
1468*4882a593Smuzhiyun 
1469*4882a593Smuzhiyun 	((wreg)(ctx, (volatile void*)r, v, sizeof(uint8)));
1470*4882a593Smuzhiyun }
1471*4882a593Smuzhiyun 
1472*4882a593Smuzhiyun void
osl_writew(osl_t * osh,volatile uint16 * r,uint16 v)1473*4882a593Smuzhiyun osl_writew(osl_t *osh, volatile uint16 *r, uint16 v)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun 	osl_wreg_fn_t wreg	= ((osl_pubinfo_t*)osh)->wreg_fn;
1476*4882a593Smuzhiyun 	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
1477*4882a593Smuzhiyun 
1478*4882a593Smuzhiyun 	((wreg)(ctx, (volatile void*)r, v, sizeof(uint16)));
1479*4882a593Smuzhiyun }
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun void
osl_writel(osl_t * osh,volatile uint32 * r,uint32 v)1482*4882a593Smuzhiyun osl_writel(osl_t *osh, volatile uint32 *r, uint32 v)
1483*4882a593Smuzhiyun {
1484*4882a593Smuzhiyun 	osl_wreg_fn_t wreg	= ((osl_pubinfo_t*)osh)->wreg_fn;
1485*4882a593Smuzhiyun 	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun 	((wreg)(ctx, (volatile void*)r, v, sizeof(uint32)));
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun #endif /* OSLREGOPS */
1490*4882a593Smuzhiyun 
1491*4882a593Smuzhiyun /*
1492*4882a593Smuzhiyun  * BINOSL selects the slightly slower function-call-based binary compatible osl.
1493*4882a593Smuzhiyun  */
1494*4882a593Smuzhiyun #ifdef BINOSL
1495*4882a593Smuzhiyun 
1496*4882a593Smuzhiyun uint32
osl_sysuptime(void)1497*4882a593Smuzhiyun osl_sysuptime(void)
1498*4882a593Smuzhiyun {
1499*4882a593Smuzhiyun 	uint32 msec = ((uint32)jiffies * (1000 / HZ));
1500*4882a593Smuzhiyun #ifdef BCMSLTGT
1501*4882a593Smuzhiyun 	/* scale down the time to match the slow target roughly */
1502*4882a593Smuzhiyun 	msec /= htclkratio;
1503*4882a593Smuzhiyun #endif
1504*4882a593Smuzhiyun 	return msec;
1505*4882a593Smuzhiyun }
1506*4882a593Smuzhiyun 
1507*4882a593Smuzhiyun int
osl_printf(const char * format,...)1508*4882a593Smuzhiyun osl_printf(const char *format, ...)
1509*4882a593Smuzhiyun {
1510*4882a593Smuzhiyun 	va_list args;
1511*4882a593Smuzhiyun 	static char printbuf[1024];
1512*4882a593Smuzhiyun 	int len;
1513*4882a593Smuzhiyun 
1514*4882a593Smuzhiyun 	/* sprintf into a local buffer because there *is* no "vprintk()".. */
1515*4882a593Smuzhiyun 	va_start(args, format);
1516*4882a593Smuzhiyun 	len = vsnprintf(printbuf, 1024, format, args);
1517*4882a593Smuzhiyun 	va_end(args);
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun 	if (len > sizeof(printbuf)) {
1520*4882a593Smuzhiyun 		printf("osl_printf: buffer overrun\n");
1521*4882a593Smuzhiyun 		return (0);
1522*4882a593Smuzhiyun 	}
1523*4882a593Smuzhiyun 
1524*4882a593Smuzhiyun 	return (printf("%s", printbuf));
1525*4882a593Smuzhiyun }
1526*4882a593Smuzhiyun 
1527*4882a593Smuzhiyun int
osl_sprintf(char * buf,const char * format,...)1528*4882a593Smuzhiyun osl_sprintf(char *buf, const char *format, ...)
1529*4882a593Smuzhiyun {
1530*4882a593Smuzhiyun 	va_list args;
1531*4882a593Smuzhiyun 	int rc;
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun 	va_start(args, format);
1534*4882a593Smuzhiyun 	rc = vsprintf(buf, format, args);
1535*4882a593Smuzhiyun 	va_end(args);
1536*4882a593Smuzhiyun 	return (rc);
1537*4882a593Smuzhiyun }
1538*4882a593Smuzhiyun 
1539*4882a593Smuzhiyun int
osl_snprintf(char * buf,size_t n,const char * format,...)1540*4882a593Smuzhiyun osl_snprintf(char *buf, size_t n, const char *format, ...)
1541*4882a593Smuzhiyun {
1542*4882a593Smuzhiyun 	va_list args;
1543*4882a593Smuzhiyun 	int rc;
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 	va_start(args, format);
1546*4882a593Smuzhiyun 	rc = vsnprintf(buf, n, format, args);
1547*4882a593Smuzhiyun 	va_end(args);
1548*4882a593Smuzhiyun 	return (rc);
1549*4882a593Smuzhiyun }
1550*4882a593Smuzhiyun 
1551*4882a593Smuzhiyun int
osl_vsprintf(char * buf,const char * format,va_list ap)1552*4882a593Smuzhiyun osl_vsprintf(char *buf, const char *format, va_list ap)
1553*4882a593Smuzhiyun {
1554*4882a593Smuzhiyun 	return (vsprintf(buf, format, ap));
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun 
1557*4882a593Smuzhiyun int
osl_vsnprintf(char * buf,size_t n,const char * format,va_list ap)1558*4882a593Smuzhiyun osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap)
1559*4882a593Smuzhiyun {
1560*4882a593Smuzhiyun 	return (vsnprintf(buf, n, format, ap));
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun 
1563*4882a593Smuzhiyun int
osl_strcmp(const char * s1,const char * s2)1564*4882a593Smuzhiyun osl_strcmp(const char *s1, const char *s2)
1565*4882a593Smuzhiyun {
1566*4882a593Smuzhiyun 	return (strcmp(s1, s2));
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun 
1569*4882a593Smuzhiyun int
osl_strncmp(const char * s1,const char * s2,uint n)1570*4882a593Smuzhiyun osl_strncmp(const char *s1, const char *s2, uint n)
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun 	return (strncmp(s1, s2, n));
1573*4882a593Smuzhiyun }
1574*4882a593Smuzhiyun 
1575*4882a593Smuzhiyun int
osl_strlen(const char * s)1576*4882a593Smuzhiyun osl_strlen(const char *s)
1577*4882a593Smuzhiyun {
1578*4882a593Smuzhiyun 	return (strlen(s));
1579*4882a593Smuzhiyun }
1580*4882a593Smuzhiyun 
1581*4882a593Smuzhiyun char*
osl_strcpy(char * d,const char * s)1582*4882a593Smuzhiyun osl_strcpy(char *d, const char *s)
1583*4882a593Smuzhiyun {
1584*4882a593Smuzhiyun 	return (strcpy(d, s));
1585*4882a593Smuzhiyun }
1586*4882a593Smuzhiyun 
1587*4882a593Smuzhiyun char*
osl_strncpy(char * d,const char * s,uint n)1588*4882a593Smuzhiyun osl_strncpy(char *d, const char *s, uint n)
1589*4882a593Smuzhiyun {
1590*4882a593Smuzhiyun 	return (strlcpy(d, s, n));
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun char*
osl_strchr(const char * s,int c)1594*4882a593Smuzhiyun osl_strchr(const char *s, int c)
1595*4882a593Smuzhiyun {
1596*4882a593Smuzhiyun 	return (strchr(s, c));
1597*4882a593Smuzhiyun }
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun char*
osl_strrchr(const char * s,int c)1600*4882a593Smuzhiyun osl_strrchr(const char *s, int c)
1601*4882a593Smuzhiyun {
1602*4882a593Smuzhiyun 	return (strrchr(s, c));
1603*4882a593Smuzhiyun }
1604*4882a593Smuzhiyun 
1605*4882a593Smuzhiyun void*
osl_memset(void * d,int c,size_t n)1606*4882a593Smuzhiyun osl_memset(void *d, int c, size_t n)
1607*4882a593Smuzhiyun {
1608*4882a593Smuzhiyun 	return memset(d, c, n);
1609*4882a593Smuzhiyun }
1610*4882a593Smuzhiyun 
1611*4882a593Smuzhiyun void*
osl_memcpy(void * d,const void * s,size_t n)1612*4882a593Smuzhiyun osl_memcpy(void *d, const void *s, size_t n)
1613*4882a593Smuzhiyun {
1614*4882a593Smuzhiyun 	return memcpy(d, s, n);
1615*4882a593Smuzhiyun }
1616*4882a593Smuzhiyun 
1617*4882a593Smuzhiyun void*
osl_memmove(void * d,const void * s,size_t n)1618*4882a593Smuzhiyun osl_memmove(void *d, const void *s, size_t n)
1619*4882a593Smuzhiyun {
1620*4882a593Smuzhiyun 	return memmove(d, s, n);
1621*4882a593Smuzhiyun }
1622*4882a593Smuzhiyun 
1623*4882a593Smuzhiyun int
osl_memcmp(const void * s1,const void * s2,size_t n)1624*4882a593Smuzhiyun osl_memcmp(const void *s1, const void *s2, size_t n)
1625*4882a593Smuzhiyun {
1626*4882a593Smuzhiyun 	return memcmp(s1, s2, n);
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun 
1629*4882a593Smuzhiyun uint32
osl_readl(volatile uint32 * r)1630*4882a593Smuzhiyun osl_readl(volatile uint32 *r)
1631*4882a593Smuzhiyun {
1632*4882a593Smuzhiyun 	return (readl(r));
1633*4882a593Smuzhiyun }
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun uint16
osl_readw(volatile uint16 * r)1636*4882a593Smuzhiyun osl_readw(volatile uint16 *r)
1637*4882a593Smuzhiyun {
1638*4882a593Smuzhiyun 	return (readw(r));
1639*4882a593Smuzhiyun }
1640*4882a593Smuzhiyun 
1641*4882a593Smuzhiyun uint8
osl_readb(volatile uint8 * r)1642*4882a593Smuzhiyun osl_readb(volatile uint8 *r)
1643*4882a593Smuzhiyun {
1644*4882a593Smuzhiyun 	return (readb(r));
1645*4882a593Smuzhiyun }
1646*4882a593Smuzhiyun 
1647*4882a593Smuzhiyun void
osl_writel(uint32 v,volatile uint32 * r)1648*4882a593Smuzhiyun osl_writel(uint32 v, volatile uint32 *r)
1649*4882a593Smuzhiyun {
1650*4882a593Smuzhiyun 	writel(v, r);
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun 
1653*4882a593Smuzhiyun void
osl_writew(uint16 v,volatile uint16 * r)1654*4882a593Smuzhiyun osl_writew(uint16 v, volatile uint16 *r)
1655*4882a593Smuzhiyun {
1656*4882a593Smuzhiyun 	writew(v, r);
1657*4882a593Smuzhiyun }
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun void
osl_writeb(uint8 v,volatile uint8 * r)1660*4882a593Smuzhiyun osl_writeb(uint8 v, volatile uint8 *r)
1661*4882a593Smuzhiyun {
1662*4882a593Smuzhiyun 	writeb(v, r);
1663*4882a593Smuzhiyun }
1664*4882a593Smuzhiyun 
1665*4882a593Smuzhiyun void *
osl_uncached(void * va)1666*4882a593Smuzhiyun osl_uncached(void *va)
1667*4882a593Smuzhiyun {
1668*4882a593Smuzhiyun 	return ((void*)va);
1669*4882a593Smuzhiyun }
1670*4882a593Smuzhiyun 
1671*4882a593Smuzhiyun void *
osl_cached(void * va)1672*4882a593Smuzhiyun osl_cached(void *va)
1673*4882a593Smuzhiyun {
1674*4882a593Smuzhiyun 	return ((void*)va);
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun uint
osl_getcycles(void)1678*4882a593Smuzhiyun osl_getcycles(void)
1679*4882a593Smuzhiyun {
1680*4882a593Smuzhiyun 	uint cycles;
1681*4882a593Smuzhiyun 
1682*4882a593Smuzhiyun #if defined(__i386__)
1683*4882a593Smuzhiyun 	rdtscl(cycles);
1684*4882a593Smuzhiyun #else
1685*4882a593Smuzhiyun 	cycles = 0;
1686*4882a593Smuzhiyun #endif /* __i386__ */
1687*4882a593Smuzhiyun 	return cycles;
1688*4882a593Smuzhiyun }
1689*4882a593Smuzhiyun 
1690*4882a593Smuzhiyun void *
osl_reg_map(uint32 pa,uint size)1691*4882a593Smuzhiyun osl_reg_map(uint32 pa, uint size)
1692*4882a593Smuzhiyun {
1693*4882a593Smuzhiyun 	return (ioremap_nocache((unsigned long)pa, (unsigned long)size));
1694*4882a593Smuzhiyun }
1695*4882a593Smuzhiyun 
1696*4882a593Smuzhiyun void
osl_reg_unmap(void * va)1697*4882a593Smuzhiyun osl_reg_unmap(void *va)
1698*4882a593Smuzhiyun {
1699*4882a593Smuzhiyun 	iounmap(va);
1700*4882a593Smuzhiyun }
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun int
osl_busprobe(uint32 * val,uint32 addr)1703*4882a593Smuzhiyun osl_busprobe(uint32 *val, uint32 addr)
1704*4882a593Smuzhiyun {
1705*4882a593Smuzhiyun 	*val = readl((uint32 *)(uintptr)addr);
1706*4882a593Smuzhiyun 
1707*4882a593Smuzhiyun 	return 0;
1708*4882a593Smuzhiyun }
1709*4882a593Smuzhiyun #endif	/* BINOSL */
1710*4882a593Smuzhiyun 
1711*4882a593Smuzhiyun uint32
osl_rand(void)1712*4882a593Smuzhiyun osl_rand(void)
1713*4882a593Smuzhiyun {
1714*4882a593Smuzhiyun 	uint32 rand;
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun 	get_random_bytes(&rand, sizeof(rand));
1717*4882a593Smuzhiyun 
1718*4882a593Smuzhiyun 	return rand;
1719*4882a593Smuzhiyun }
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun /* Linux Kernel: File Operations: end */
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun #if defined(AXI_TIMEOUTS_NIC)
osl_bpt_rreg(osl_t * osh,ulong addr,volatile void * v,uint size)1724*4882a593Smuzhiyun inline void osl_bpt_rreg(osl_t *osh, ulong addr, volatile void *v, uint size)
1725*4882a593Smuzhiyun {
1726*4882a593Smuzhiyun 	bool poll_timeout = FALSE;
1727*4882a593Smuzhiyun 	static int in_si_clear = FALSE;
1728*4882a593Smuzhiyun 
1729*4882a593Smuzhiyun 	switch (size) {
1730*4882a593Smuzhiyun 	case sizeof(uint8):
1731*4882a593Smuzhiyun 		*(volatile uint8*)v = readb((volatile uint8*)(addr));
1732*4882a593Smuzhiyun 		if (*(volatile uint8*)v == 0xff)
1733*4882a593Smuzhiyun 			poll_timeout = TRUE;
1734*4882a593Smuzhiyun 		break;
1735*4882a593Smuzhiyun 	case sizeof(uint16):
1736*4882a593Smuzhiyun 		*(volatile uint16*)v = readw((volatile uint16*)(addr));
1737*4882a593Smuzhiyun 		if (*(volatile uint16*)v == 0xffff)
1738*4882a593Smuzhiyun 			poll_timeout = TRUE;
1739*4882a593Smuzhiyun 		break;
1740*4882a593Smuzhiyun 	case sizeof(uint32):
1741*4882a593Smuzhiyun 		*(volatile uint32*)v = readl((volatile uint32*)(addr));
1742*4882a593Smuzhiyun 		if (*(volatile uint32*)v == 0xffffffff)
1743*4882a593Smuzhiyun 			poll_timeout = TRUE;
1744*4882a593Smuzhiyun 		break;
1745*4882a593Smuzhiyun 	case sizeof(uint64):
1746*4882a593Smuzhiyun 		*(volatile uint64*)v = *((volatile uint64*)(addr));
1747*4882a593Smuzhiyun 		if (*(volatile uint64*)v == 0xffffffffffffffff)
1748*4882a593Smuzhiyun 			poll_timeout = TRUE;
1749*4882a593Smuzhiyun 		break;
1750*4882a593Smuzhiyun 	}
1751*4882a593Smuzhiyun 
1752*4882a593Smuzhiyun 	if (osh && osh->sih && (in_si_clear == FALSE) && poll_timeout && osh->bpt_cb) {
1753*4882a593Smuzhiyun 		in_si_clear = TRUE;
1754*4882a593Smuzhiyun 		osh->bpt_cb((void *)osh->sih, (void *)addr);
1755*4882a593Smuzhiyun 		in_si_clear = FALSE;
1756*4882a593Smuzhiyun 	}
1757*4882a593Smuzhiyun }
1758*4882a593Smuzhiyun #endif /* AXI_TIMEOUTS_NIC */
1759*4882a593Smuzhiyun 
1760*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
1761*4882a593Smuzhiyun void
timer_cb_compat(struct timer_list * tl)1762*4882a593Smuzhiyun timer_cb_compat(struct timer_list *tl)
1763*4882a593Smuzhiyun {
1764*4882a593Smuzhiyun 	timer_list_compat_t *t = container_of(tl, timer_list_compat_t, timer);
1765*4882a593Smuzhiyun 	t->callback((ulong)t->arg);
1766*4882a593Smuzhiyun }
1767*4882a593Smuzhiyun #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) */
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun /* timer apis */
1770*4882a593Smuzhiyun /* Note: All timer api's are thread unsafe and should be protected with locks by caller */
1771*4882a593Smuzhiyun 
1772*4882a593Smuzhiyun osl_timer_t *
osl_timer_init(osl_t * osh,const char * name,void (* fn)(void * arg),void * arg)1773*4882a593Smuzhiyun osl_timer_init(osl_t *osh, const char *name, void (*fn)(void *arg), void *arg)
1774*4882a593Smuzhiyun {
1775*4882a593Smuzhiyun 	osl_timer_t *t;
1776*4882a593Smuzhiyun 	BCM_REFERENCE(fn);
1777*4882a593Smuzhiyun 	if ((t = MALLOCZ(NULL, sizeof(osl_timer_t))) == NULL) {
1778*4882a593Smuzhiyun 		printf(KERN_ERR "osl_timer_init: out of memory, malloced %d bytes\n",
1779*4882a593Smuzhiyun 			(int)sizeof(osl_timer_t));
1780*4882a593Smuzhiyun 		return (NULL);
1781*4882a593Smuzhiyun 	}
1782*4882a593Smuzhiyun 	bzero(t, sizeof(osl_timer_t));
1783*4882a593Smuzhiyun 	if ((t->timer = MALLOCZ(NULL, sizeof(timer_list_compat_t))) == NULL) {
1784*4882a593Smuzhiyun 		printf("osl_timer_init: malloc failed\n");
1785*4882a593Smuzhiyun 		MFREE(NULL, t, sizeof(osl_timer_t));
1786*4882a593Smuzhiyun 		return (NULL);
1787*4882a593Smuzhiyun 	}
1788*4882a593Smuzhiyun 
1789*4882a593Smuzhiyun 	t->set = TRUE;
1790*4882a593Smuzhiyun #ifdef BCMDBG
1791*4882a593Smuzhiyun 	if ((t->name = MALLOCZ(NULL, strlen(name) + 1)) != NULL) {
1792*4882a593Smuzhiyun 		strcpy(t->name, name);
1793*4882a593Smuzhiyun 	}
1794*4882a593Smuzhiyun #endif
1795*4882a593Smuzhiyun 
1796*4882a593Smuzhiyun 	init_timer_compat(t->timer, (linux_timer_fn)fn, arg);
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun 	return (t);
1799*4882a593Smuzhiyun }
1800*4882a593Smuzhiyun 
1801*4882a593Smuzhiyun void
osl_timer_add(osl_t * osh,osl_timer_t * t,uint32 ms,bool periodic)1802*4882a593Smuzhiyun osl_timer_add(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic)
1803*4882a593Smuzhiyun {
1804*4882a593Smuzhiyun 	if (t == NULL) {
1805*4882a593Smuzhiyun 		printf("%s: Timer handle is NULL\n", __FUNCTION__);
1806*4882a593Smuzhiyun 		return;
1807*4882a593Smuzhiyun 	}
1808*4882a593Smuzhiyun 	ASSERT(!t->set);
1809*4882a593Smuzhiyun 
1810*4882a593Smuzhiyun 	t->set = TRUE;
1811*4882a593Smuzhiyun 	if (periodic) {
1812*4882a593Smuzhiyun 		printf("Periodic timers are not supported by Linux timer apis\n");
1813*4882a593Smuzhiyun 	}
1814*4882a593Smuzhiyun #if defined(BCMSLTGT)
1815*4882a593Smuzhiyun 	timer_expires(t->timer) = jiffies + ms*HZ/1000*htclkratio;
1816*4882a593Smuzhiyun #else
1817*4882a593Smuzhiyun 	timer_expires(t->timer) = jiffies + ms*HZ/1000;
1818*4882a593Smuzhiyun #endif /* defined(BCMSLTGT) */
1819*4882a593Smuzhiyun 
1820*4882a593Smuzhiyun 	add_timer(t->timer);
1821*4882a593Smuzhiyun 
1822*4882a593Smuzhiyun 	return;
1823*4882a593Smuzhiyun }
1824*4882a593Smuzhiyun 
1825*4882a593Smuzhiyun void
osl_timer_update(osl_t * osh,osl_timer_t * t,uint32 ms,bool periodic)1826*4882a593Smuzhiyun osl_timer_update(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic)
1827*4882a593Smuzhiyun {
1828*4882a593Smuzhiyun 	if (t == NULL) {
1829*4882a593Smuzhiyun 		printf("%s: Timer handle is NULL\n", __FUNCTION__);
1830*4882a593Smuzhiyun 		return;
1831*4882a593Smuzhiyun 	}
1832*4882a593Smuzhiyun 	if (periodic) {
1833*4882a593Smuzhiyun 		printf("Periodic timers are not supported by Linux timer apis\n");
1834*4882a593Smuzhiyun 	}
1835*4882a593Smuzhiyun 	t->set = TRUE;
1836*4882a593Smuzhiyun #if defined(BCMSLTGT)
1837*4882a593Smuzhiyun 	timer_expires(t->timer) = jiffies + ms*HZ/1000*htclkratio;
1838*4882a593Smuzhiyun #else
1839*4882a593Smuzhiyun 	timer_expires(t->timer) = jiffies + ms*HZ/1000;
1840*4882a593Smuzhiyun #endif /* defined(BCMSLTGT) */
1841*4882a593Smuzhiyun 
1842*4882a593Smuzhiyun 	mod_timer(t->timer, timer_expires(t->timer));
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun 	return;
1845*4882a593Smuzhiyun }
1846*4882a593Smuzhiyun 
1847*4882a593Smuzhiyun /*
1848*4882a593Smuzhiyun  * Return TRUE if timer successfully deleted, FALSE if still pending
1849*4882a593Smuzhiyun  */
1850*4882a593Smuzhiyun bool
osl_timer_del(osl_t * osh,osl_timer_t * t)1851*4882a593Smuzhiyun osl_timer_del(osl_t *osh, osl_timer_t *t)
1852*4882a593Smuzhiyun {
1853*4882a593Smuzhiyun 	if (t == NULL) {
1854*4882a593Smuzhiyun 		printf("%s: Timer handle is NULL\n", __FUNCTION__);
1855*4882a593Smuzhiyun 		return (FALSE);
1856*4882a593Smuzhiyun 	}
1857*4882a593Smuzhiyun 	if (t->set) {
1858*4882a593Smuzhiyun 		t->set = FALSE;
1859*4882a593Smuzhiyun 		if (t->timer) {
1860*4882a593Smuzhiyun 			del_timer(t->timer);
1861*4882a593Smuzhiyun 			MFREE(NULL, t->timer, sizeof(struct timer_list));
1862*4882a593Smuzhiyun 		}
1863*4882a593Smuzhiyun #ifdef BCMDBG
1864*4882a593Smuzhiyun 		if (t->name) {
1865*4882a593Smuzhiyun 			MFREE(NULL, t->name, strlen(t->name) + 1);
1866*4882a593Smuzhiyun 		}
1867*4882a593Smuzhiyun #endif
1868*4882a593Smuzhiyun 		MFREE(NULL, t, sizeof(osl_timer_t));
1869*4882a593Smuzhiyun 	}
1870*4882a593Smuzhiyun 	return (TRUE);
1871*4882a593Smuzhiyun }
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
1874*4882a593Smuzhiyun int
kernel_read_compat(struct file * file,loff_t offset,char * addr,unsigned long count)1875*4882a593Smuzhiyun kernel_read_compat(struct file *file, loff_t offset, char *addr, unsigned long count)
1876*4882a593Smuzhiyun {
1877*4882a593Smuzhiyun #ifdef DHD_SUPPORT_VFS_CALL
1878*4882a593Smuzhiyun 	return (int)kernel_read(file, addr, (size_t)count, &offset);
1879*4882a593Smuzhiyun #else
1880*4882a593Smuzhiyun 	return 0;
1881*4882a593Smuzhiyun #endif /* DHD_SUPPORT_VFS_CALL */
1882*4882a593Smuzhiyun }
1883*4882a593Smuzhiyun #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) */
1884*4882a593Smuzhiyun 
1885*4882a593Smuzhiyun /* Linux specific multipurpose spinlock API */
1886*4882a593Smuzhiyun void *
osl_spin_lock_init(osl_t * osh)1887*4882a593Smuzhiyun osl_spin_lock_init(osl_t *osh)
1888*4882a593Smuzhiyun {
1889*4882a593Smuzhiyun 	/* Adding 4 bytes since the sizeof(spinlock_t) could be 0 */
1890*4882a593Smuzhiyun 	/* if CONFIG_SMP and CONFIG_DEBUG_SPINLOCK are not defined */
1891*4882a593Smuzhiyun 	/* and this results in kernel asserts in internal builds */
1892*4882a593Smuzhiyun 	spinlock_t * lock = MALLOC(osh, sizeof(spinlock_t) + 4);
1893*4882a593Smuzhiyun 	if (lock)
1894*4882a593Smuzhiyun 		spin_lock_init(lock);
1895*4882a593Smuzhiyun 	return ((void *)lock);
1896*4882a593Smuzhiyun }
1897*4882a593Smuzhiyun void
osl_spin_lock_deinit(osl_t * osh,void * lock)1898*4882a593Smuzhiyun osl_spin_lock_deinit(osl_t *osh, void *lock)
1899*4882a593Smuzhiyun {
1900*4882a593Smuzhiyun 	if (lock)
1901*4882a593Smuzhiyun 		MFREE(osh, lock, sizeof(spinlock_t) + 4);
1902*4882a593Smuzhiyun }
1903*4882a593Smuzhiyun 
1904*4882a593Smuzhiyun unsigned long
osl_spin_lock(void * lock)1905*4882a593Smuzhiyun osl_spin_lock(void *lock)
1906*4882a593Smuzhiyun {
1907*4882a593Smuzhiyun 	unsigned long flags = 0;
1908*4882a593Smuzhiyun 
1909*4882a593Smuzhiyun 	if (lock) {
1910*4882a593Smuzhiyun #ifdef DHD_USE_SPIN_LOCK_BH
1911*4882a593Smuzhiyun 		/* Calling spin_lock_bh with both irq and non-irq context will lead to deadlock */
1912*4882a593Smuzhiyun 		ASSERT(!in_irq());
1913*4882a593Smuzhiyun 		spin_lock_bh((spinlock_t *)lock);
1914*4882a593Smuzhiyun #else
1915*4882a593Smuzhiyun 		spin_lock_irqsave((spinlock_t *)lock, flags);
1916*4882a593Smuzhiyun #endif /* DHD_USE_SPIN_LOCK_BH */
1917*4882a593Smuzhiyun 	}
1918*4882a593Smuzhiyun 
1919*4882a593Smuzhiyun 	return flags;
1920*4882a593Smuzhiyun }
1921*4882a593Smuzhiyun 
1922*4882a593Smuzhiyun void
osl_spin_unlock(void * lock,unsigned long flags)1923*4882a593Smuzhiyun osl_spin_unlock(void *lock, unsigned long flags)
1924*4882a593Smuzhiyun {
1925*4882a593Smuzhiyun 	if (lock) {
1926*4882a593Smuzhiyun #ifdef DHD_USE_SPIN_LOCK_BH
1927*4882a593Smuzhiyun 		/* Calling spin_lock_bh with both irq and non-irq context will lead to deadlock */
1928*4882a593Smuzhiyun 		ASSERT(!in_irq());
1929*4882a593Smuzhiyun 		spin_unlock_bh((spinlock_t *)lock);
1930*4882a593Smuzhiyun #else
1931*4882a593Smuzhiyun 		spin_unlock_irqrestore((spinlock_t *)lock, flags);
1932*4882a593Smuzhiyun #endif /* DHD_USE_SPIN_LOCK_BH */
1933*4882a593Smuzhiyun 	}
1934*4882a593Smuzhiyun }
1935*4882a593Smuzhiyun 
1936*4882a593Smuzhiyun unsigned long
osl_spin_lock_irq(void * lock)1937*4882a593Smuzhiyun osl_spin_lock_irq(void *lock)
1938*4882a593Smuzhiyun {
1939*4882a593Smuzhiyun 	unsigned long flags = 0;
1940*4882a593Smuzhiyun 
1941*4882a593Smuzhiyun 	if (lock)
1942*4882a593Smuzhiyun 		spin_lock_irqsave((spinlock_t *)lock, flags);
1943*4882a593Smuzhiyun 
1944*4882a593Smuzhiyun 	return flags;
1945*4882a593Smuzhiyun }
1946*4882a593Smuzhiyun 
1947*4882a593Smuzhiyun void
osl_spin_unlock_irq(void * lock,unsigned long flags)1948*4882a593Smuzhiyun osl_spin_unlock_irq(void *lock, unsigned long flags)
1949*4882a593Smuzhiyun {
1950*4882a593Smuzhiyun 	if (lock)
1951*4882a593Smuzhiyun 		spin_unlock_irqrestore((spinlock_t *)lock, flags);
1952*4882a593Smuzhiyun }
1953*4882a593Smuzhiyun 
1954*4882a593Smuzhiyun unsigned long
osl_spin_lock_bh(void * lock)1955*4882a593Smuzhiyun osl_spin_lock_bh(void *lock)
1956*4882a593Smuzhiyun {
1957*4882a593Smuzhiyun 	unsigned long flags = 0;
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun 	if (lock) {
1960*4882a593Smuzhiyun 		/* Calling spin_lock_bh with both irq and non-irq context will lead to deadlock */
1961*4882a593Smuzhiyun 		ASSERT(!in_irq());
1962*4882a593Smuzhiyun 		spin_lock_bh((spinlock_t *)lock);
1963*4882a593Smuzhiyun 	}
1964*4882a593Smuzhiyun 
1965*4882a593Smuzhiyun 	return flags;
1966*4882a593Smuzhiyun }
1967*4882a593Smuzhiyun 
1968*4882a593Smuzhiyun void
osl_spin_unlock_bh(void * lock,unsigned long flags)1969*4882a593Smuzhiyun osl_spin_unlock_bh(void *lock, unsigned long flags)
1970*4882a593Smuzhiyun {
1971*4882a593Smuzhiyun 	if (lock) {
1972*4882a593Smuzhiyun 		/* Calling spin_lock_bh with both irq and non-irq context will lead to deadlock */
1973*4882a593Smuzhiyun 		ASSERT(!in_irq());
1974*4882a593Smuzhiyun 		spin_unlock_bh((spinlock_t *)lock);
1975*4882a593Smuzhiyun 	}
1976*4882a593Smuzhiyun }
1977*4882a593Smuzhiyun 
1978*4882a593Smuzhiyun void *
osl_mutex_lock_init(osl_t * osh)1979*4882a593Smuzhiyun osl_mutex_lock_init(osl_t *osh)
1980*4882a593Smuzhiyun {
1981*4882a593Smuzhiyun 	struct mutex *mtx = NULL;
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 	mtx = MALLOCZ(osh, sizeof(*mtx));
1984*4882a593Smuzhiyun 	if (mtx)
1985*4882a593Smuzhiyun 		mutex_init(mtx);
1986*4882a593Smuzhiyun 
1987*4882a593Smuzhiyun 	return mtx;
1988*4882a593Smuzhiyun }
1989*4882a593Smuzhiyun 
1990*4882a593Smuzhiyun void
osl_mutex_lock_deinit(osl_t * osh,void * mutex)1991*4882a593Smuzhiyun osl_mutex_lock_deinit(osl_t *osh, void *mutex)
1992*4882a593Smuzhiyun {
1993*4882a593Smuzhiyun 	struct mutex *mtx = mutex;
1994*4882a593Smuzhiyun 
1995*4882a593Smuzhiyun 	if (mtx) {
1996*4882a593Smuzhiyun 		mutex_destroy(mtx);
1997*4882a593Smuzhiyun 		MFREE(osh, mtx, sizeof(struct mutex));
1998*4882a593Smuzhiyun 	}
1999*4882a593Smuzhiyun }
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun /* For mutex lock/unlock unsigned long flags is used,
2002*4882a593Smuzhiyun  * this is to keep in sync with spin lock apis, so that
2003*4882a593Smuzhiyun  * locks can be easily interchanged based on contexts
2004*4882a593Smuzhiyun  */
2005*4882a593Smuzhiyun unsigned long
osl_mutex_lock(void * lock)2006*4882a593Smuzhiyun osl_mutex_lock(void *lock)
2007*4882a593Smuzhiyun {
2008*4882a593Smuzhiyun 	if (lock)
2009*4882a593Smuzhiyun 		mutex_lock((struct mutex *)lock);
2010*4882a593Smuzhiyun 
2011*4882a593Smuzhiyun 	return 0;
2012*4882a593Smuzhiyun }
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun void
osl_mutex_unlock(void * lock,unsigned long flags)2015*4882a593Smuzhiyun osl_mutex_unlock(void *lock, unsigned long flags)
2016*4882a593Smuzhiyun {
2017*4882a593Smuzhiyun 	if (lock)
2018*4882a593Smuzhiyun 		mutex_unlock((struct mutex *)lock);
2019*4882a593Smuzhiyun 	return;
2020*4882a593Smuzhiyun }
2021*4882a593Smuzhiyun 
2022*4882a593Smuzhiyun #ifdef USE_DMA_LOCK
2023*4882a593Smuzhiyun static void
osl_dma_lock(osl_t * osh)2024*4882a593Smuzhiyun osl_dma_lock(osl_t *osh)
2025*4882a593Smuzhiyun {
2026*4882a593Smuzhiyun 	/* The conditional check is to avoid the scheduling bug.
2027*4882a593Smuzhiyun 	 * If the spin_lock_bh is used under the spin_lock_irqsave,
2028*4882a593Smuzhiyun 	 * Kernel triggered the warning message as the spin_lock_irqsave
2029*4882a593Smuzhiyun 	 * disables the interrupt and the spin_lock_bh doesn't use in case
2030*4882a593Smuzhiyun 	 * interrupt is disabled.
2031*4882a593Smuzhiyun 	 * Please refer to the __local_bh_enable_ip() function
2032*4882a593Smuzhiyun 	 * in kernel/softirq.c to understand the condtion.
2033*4882a593Smuzhiyun 	 */
2034*4882a593Smuzhiyun 	if (likely(in_irq() || irqs_disabled())) {
2035*4882a593Smuzhiyun 		spin_lock(&osh->dma_lock);
2036*4882a593Smuzhiyun 	} else {
2037*4882a593Smuzhiyun 		spin_lock_bh(&osh->dma_lock);
2038*4882a593Smuzhiyun 		osh->dma_lock_bh = TRUE;
2039*4882a593Smuzhiyun 	}
2040*4882a593Smuzhiyun }
2041*4882a593Smuzhiyun 
2042*4882a593Smuzhiyun static void
osl_dma_unlock(osl_t * osh)2043*4882a593Smuzhiyun osl_dma_unlock(osl_t *osh)
2044*4882a593Smuzhiyun {
2045*4882a593Smuzhiyun 	if (unlikely(osh->dma_lock_bh)) {
2046*4882a593Smuzhiyun 		osh->dma_lock_bh = FALSE;
2047*4882a593Smuzhiyun 		spin_unlock_bh(&osh->dma_lock);
2048*4882a593Smuzhiyun 	} else {
2049*4882a593Smuzhiyun 		spin_unlock(&osh->dma_lock);
2050*4882a593Smuzhiyun 	}
2051*4882a593Smuzhiyun }
2052*4882a593Smuzhiyun 
2053*4882a593Smuzhiyun static void
osl_dma_lock_init(osl_t * osh)2054*4882a593Smuzhiyun osl_dma_lock_init(osl_t *osh)
2055*4882a593Smuzhiyun {
2056*4882a593Smuzhiyun 	spin_lock_init(&osh->dma_lock);
2057*4882a593Smuzhiyun 	osh->dma_lock_bh = FALSE;
2058*4882a593Smuzhiyun }
2059*4882a593Smuzhiyun #endif /* USE_DMA_LOCK */
2060*4882a593Smuzhiyun 
2061*4882a593Smuzhiyun void
osl_do_gettimeofday(struct osl_timespec * ts)2062*4882a593Smuzhiyun osl_do_gettimeofday(struct osl_timespec *ts)
2063*4882a593Smuzhiyun {
2064*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
2065*4882a593Smuzhiyun 	struct timespec64 curtime;
2066*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
2067*4882a593Smuzhiyun 	struct timespec curtime;
2068*4882a593Smuzhiyun #else
2069*4882a593Smuzhiyun 	struct timeval curtime;
2070*4882a593Smuzhiyun #endif
2071*4882a593Smuzhiyun 
2072*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
2073*4882a593Smuzhiyun 	ktime_get_real_ts64(&curtime);
2074*4882a593Smuzhiyun 	ts->tv_nsec = curtime.tv_nsec;
2075*4882a593Smuzhiyun 	ts->tv_usec	= curtime.tv_nsec / 1000;
2076*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
2077*4882a593Smuzhiyun 	getnstimeofday(&curtime);
2078*4882a593Smuzhiyun 	ts->tv_nsec = curtime.tv_nsec;
2079*4882a593Smuzhiyun 	ts->tv_usec = curtime.tv_nsec / 1000;
2080*4882a593Smuzhiyun #else
2081*4882a593Smuzhiyun 	do_gettimeofday(&curtime);
2082*4882a593Smuzhiyun 	ts->tv_usec = curtime.tv_usec;
2083*4882a593Smuzhiyun 	ts->tv_nsec = curtime.tv_usec * 1000;
2084*4882a593Smuzhiyun #endif
2085*4882a593Smuzhiyun 	ts->tv_sec = curtime.tv_sec;
2086*4882a593Smuzhiyun }
2087*4882a593Smuzhiyun 
2088*4882a593Smuzhiyun uint32
osl_do_gettimediff(struct osl_timespec * cur_ts,struct osl_timespec * old_ts)2089*4882a593Smuzhiyun osl_do_gettimediff(struct osl_timespec *cur_ts, struct osl_timespec *old_ts)
2090*4882a593Smuzhiyun {
2091*4882a593Smuzhiyun 	uint32 diff_s, diff_us, total_diff_us;
2092*4882a593Smuzhiyun 	bool pgc_g = FALSE;
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun 	diff_s = (uint32)cur_ts->tv_sec - (uint32)old_ts->tv_sec;
2095*4882a593Smuzhiyun 	pgc_g = (cur_ts->tv_usec > old_ts->tv_usec) ? TRUE : FALSE;
2096*4882a593Smuzhiyun 	diff_us = pgc_g ? (cur_ts->tv_usec - old_ts->tv_usec) : (old_ts->tv_usec - cur_ts->tv_usec);
2097*4882a593Smuzhiyun 	total_diff_us = pgc_g ? (diff_s * 1000000 + diff_us) : (diff_s * 1000000 - diff_us);
2098*4882a593Smuzhiyun 	return total_diff_us;
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun 
2101*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
2102*4882a593Smuzhiyun void
osl_get_monotonic_boottime(struct osl_timespec * ts)2103*4882a593Smuzhiyun osl_get_monotonic_boottime(struct osl_timespec *ts)
2104*4882a593Smuzhiyun {
2105*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
2106*4882a593Smuzhiyun 	struct timespec64 curtime;
2107*4882a593Smuzhiyun #else
2108*4882a593Smuzhiyun 	struct timespec curtime;
2109*4882a593Smuzhiyun #endif
2110*4882a593Smuzhiyun 
2111*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
2112*4882a593Smuzhiyun 	curtime = ktime_to_timespec64(ktime_get_boottime());
2113*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2114*4882a593Smuzhiyun 	curtime = ktime_to_timespec(ktime_get_boottime());
2115*4882a593Smuzhiyun #else
2116*4882a593Smuzhiyun 	get_monotonic_boottime(&curtime);
2117*4882a593Smuzhiyun #endif
2118*4882a593Smuzhiyun 	ts->tv_sec = curtime.tv_sec;
2119*4882a593Smuzhiyun 	ts->tv_nsec = curtime.tv_nsec;
2120*4882a593Smuzhiyun 	ts->tv_usec = curtime.tv_nsec / 1000;
2121*4882a593Smuzhiyun }
2122*4882a593Smuzhiyun #endif
2123