Path: blob/master/ALFA-W1F1/RTL8814AU/os_dep/osdep_service.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/141516#define _OSDEP_SERVICE_C_1718#include <drv_types.h>1920#define RT_TAG '1178'2122#ifdef DBG_MEMORY_LEAK23#ifdef PLATFORM_LINUX24atomic_t _malloc_cnt = ATOMIC_INIT(0);25atomic_t _malloc_size = ATOMIC_INIT(0);26#endif27#endif /* DBG_MEMORY_LEAK */282930#if defined(PLATFORM_LINUX)31/*32* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE33* @return: one of RTW_STATUS_CODE34*/35inline int RTW_STATUS_CODE(int error_code)36{37if (error_code >= 0)38return _SUCCESS;3940switch (error_code) {41/* case -ETIMEDOUT: */42/* return RTW_STATUS_TIMEDOUT; */43default:44return _FAIL;45}46}47#else48inline int RTW_STATUS_CODE(int error_code)49{50return error_code;51}52#endif5354u32 rtw_atoi(u8 *s)55{5657int num = 0, flag = 0;58int i;59for (i = 0; i <= strlen(s); i++) {60if (s[i] >= '0' && s[i] <= '9')61num = num * 10 + s[i] - '0';62else if (s[0] == '-' && i == 0)63flag = 1;64else65break;66}6768if (flag == 1)69num = num * -1;7071return num;7273}7475inline void *_rtw_vmalloc(u32 sz)76{77void *pbuf;78#ifdef PLATFORM_LINUX79pbuf = vmalloc(sz);80#endif81#ifdef PLATFORM_FREEBSD82pbuf = malloc(sz, M_DEVBUF, M_NOWAIT);83#endif8485#ifdef PLATFORM_WINDOWS86NdisAllocateMemoryWithTag(&pbuf, sz, RT_TAG);87#endif8889#ifdef DBG_MEMORY_LEAK90#ifdef PLATFORM_LINUX91if (pbuf != NULL) {92atomic_inc(&_malloc_cnt);93atomic_add(sz, &_malloc_size);94}95#endif96#endif /* DBG_MEMORY_LEAK */9798return pbuf;99}100101inline void *_rtw_zvmalloc(u32 sz)102{103void *pbuf;104#ifdef PLATFORM_LINUX105pbuf = _rtw_vmalloc(sz);106if (pbuf != NULL)107memset(pbuf, 0, sz);108#endif109#ifdef PLATFORM_FREEBSD110pbuf = malloc(sz, M_DEVBUF, M_ZERO | M_NOWAIT);111#endif112#ifdef PLATFORM_WINDOWS113NdisAllocateMemoryWithTag(&pbuf, sz, RT_TAG);114if (pbuf != NULL)115NdisFillMemory(pbuf, sz, 0);116#endif117118return pbuf;119}120121inline void _rtw_vmfree(void *pbuf, u32 sz)122{123#ifdef PLATFORM_LINUX124vfree(pbuf);125#endif126#ifdef PLATFORM_FREEBSD127free(pbuf, M_DEVBUF);128#endif129#ifdef PLATFORM_WINDOWS130NdisFreeMemory(pbuf, sz, 0);131#endif132133#ifdef DBG_MEMORY_LEAK134#ifdef PLATFORM_LINUX135atomic_dec(&_malloc_cnt);136atomic_sub(sz, &_malloc_size);137#endif138#endif /* DBG_MEMORY_LEAK */139}140141void *_rtw_malloc(u32 sz)142{143void *pbuf = NULL;144145#ifdef PLATFORM_LINUX146#ifdef RTK_DMP_PLATFORM147if (sz > 0x4000)148pbuf = dvr_malloc(sz);149else150#endif151pbuf = kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);152153#endif154#ifdef PLATFORM_FREEBSD155pbuf = malloc(sz, M_DEVBUF, M_NOWAIT);156#endif157#ifdef PLATFORM_WINDOWS158159NdisAllocateMemoryWithTag(&pbuf, sz, RT_TAG);160161#endif162163#ifdef DBG_MEMORY_LEAK164#ifdef PLATFORM_LINUX165if (pbuf != NULL) {166atomic_inc(&_malloc_cnt);167atomic_add(sz, &_malloc_size);168}169#endif170#endif /* DBG_MEMORY_LEAK */171172return pbuf;173174}175176177void *_rtw_zmalloc(u32 sz)178{179#ifdef PLATFORM_FREEBSD180return malloc(sz, M_DEVBUF, M_ZERO | M_NOWAIT);181#else /* PLATFORM_FREEBSD */182void *pbuf = _rtw_malloc(sz);183184if (pbuf != NULL) {185186#ifdef PLATFORM_LINUX187memset(pbuf, 0, sz);188#endif189190#ifdef PLATFORM_WINDOWS191NdisFillMemory(pbuf, sz, 0);192#endif193194}195196return pbuf;197#endif /* PLATFORM_FREEBSD */198}199200void _rtw_mfree(void *pbuf, u32 sz)201{202203#ifdef PLATFORM_LINUX204#ifdef RTK_DMP_PLATFORM205if (sz > 0x4000)206dvr_free(pbuf);207else208#endif209kfree(pbuf);210211#endif212#ifdef PLATFORM_FREEBSD213free(pbuf, M_DEVBUF);214#endif215#ifdef PLATFORM_WINDOWS216217NdisFreeMemory(pbuf, sz, 0);218219#endif220221#ifdef DBG_MEMORY_LEAK222#ifdef PLATFORM_LINUX223atomic_dec(&_malloc_cnt);224atomic_sub(sz, &_malloc_size);225#endif226#endif /* DBG_MEMORY_LEAK */227228}229230#ifdef PLATFORM_FREEBSD231/* review again */232struct sk_buff *dev_alloc_skb(unsigned int size)233{234struct sk_buff *skb = NULL;235u8 *data = NULL;236237/* skb = _rtw_zmalloc(sizeof(struct sk_buff)); */ /* for skb->len, etc. */238skb = _rtw_malloc(sizeof(struct sk_buff));239if (!skb)240goto out;241data = _rtw_malloc(size);242if (!data)243goto nodata;244245skb->head = (unsigned char *)data;246skb->data = (unsigned char *)data;247skb->tail = (unsigned char *)data;248skb->end = (unsigned char *)data + size;249skb->len = 0;250/* printf("%s()-%d: skb=%p, skb->head = %p\n", __FUNCTION__, __LINE__, skb, skb->head); */251252out:253return skb;254nodata:255_rtw_mfree(skb, sizeof(struct sk_buff));256skb = NULL;257goto out;258259}260261void dev_kfree_skb_any(struct sk_buff *skb)262{263/* printf("%s()-%d: skb->head = %p\n", __FUNCTION__, __LINE__, skb->head); */264if (skb->head)265_rtw_mfree(skb->head, 0);266/* printf("%s()-%d: skb = %p\n", __FUNCTION__, __LINE__, skb); */267if (skb)268_rtw_mfree(skb, 0);269}270struct sk_buff *skb_clone(const struct sk_buff *skb)271{272return NULL;273}274275#endif /* PLATFORM_FREEBSD */276277inline struct sk_buff *_rtw_skb_alloc(u32 sz)278{279#ifdef PLATFORM_LINUX280return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);281#endif /* PLATFORM_LINUX */282283#ifdef PLATFORM_FREEBSD284return dev_alloc_skb(sz);285#endif /* PLATFORM_FREEBSD */286}287288inline void _rtw_skb_free(struct sk_buff *skb)289{290dev_kfree_skb_any(skb);291}292293inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)294{295#ifdef PLATFORM_LINUX296return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);297#endif /* PLATFORM_LINUX */298299#ifdef PLATFORM_FREEBSD300return NULL;301#endif /* PLATFORM_FREEBSD */302}303304inline struct sk_buff *_rtw_skb_clone(struct sk_buff *skb)305{306#ifdef PLATFORM_LINUX307return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);308#endif /* PLATFORM_LINUX */309310#ifdef PLATFORM_FREEBSD311return skb_clone(skb);312#endif /* PLATFORM_FREEBSD */313}314inline struct sk_buff *_rtw_pskb_copy(struct sk_buff *skb)315{316#ifdef PLATFORM_LINUX317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36))318return pskb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);319#else320return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);321#endif322#endif /* PLATFORM_LINUX */323324#ifdef PLATFORM_FREEBSD325return NULL;326#endif /* PLATFORM_FREEBSD */327}328329inline int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb)330{331#if defined(PLATFORM_LINUX)332skb->dev = ndev;333return netif_rx(skb);334#elif defined(PLATFORM_FREEBSD)335return (*ndev->if_input)(ndev, skb);336#else337rtw_warn_on(1);338return -1;339#endif340}341342#ifdef CONFIG_RTW_NAPI343inline int _rtw_netif_receive_skb(_nic_hdl ndev, struct sk_buff *skb)344{345#if defined(PLATFORM_LINUX)346skb->dev = ndev;347return netif_receive_skb(skb);348#else349rtw_warn_on(1);350return -1;351#endif352}353354#ifdef CONFIG_RTW_GRO355inline gro_result_t _rtw_napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)356{357#if defined(PLATFORM_LINUX)358return napi_gro_receive(napi, skb);359#else360rtw_warn_on(1);361return -1;362#endif363}364#endif /* CONFIG_RTW_GRO */365#endif /* CONFIG_RTW_NAPI */366367void _rtw_skb_queue_purge(struct sk_buff_head *list)368{369struct sk_buff *skb;370371while ((skb = skb_dequeue(list)) != NULL)372_rtw_skb_free(skb);373}374375#ifdef CONFIG_USB_HCI376inline void *_rtw_usb_buffer_alloc(struct usb_device *dev, size_t size, dma_addr_t *dma)377{378#ifdef PLATFORM_LINUX379#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))380return usb_alloc_coherent(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma);381#else382return usb_buffer_alloc(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma);383#endif384#endif /* PLATFORM_LINUX */385386#ifdef PLATFORM_FREEBSD387return malloc(size, M_USBDEV, M_NOWAIT | M_ZERO);388#endif /* PLATFORM_FREEBSD */389}390inline void _rtw_usb_buffer_free(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma)391{392#ifdef PLATFORM_LINUX393#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))394usb_free_coherent(dev, size, addr, dma);395#else396usb_buffer_free(dev, size, addr, dma);397#endif398#endif /* PLATFORM_LINUX */399400#ifdef PLATFORM_FREEBSD401free(addr, M_USBDEV);402#endif /* PLATFORM_FREEBSD */403}404#endif /* CONFIG_USB_HCI */405406#if defined(DBG_MEM_ALLOC)407408struct rtw_mem_stat {409ATOMIC_T alloc; /* the memory bytes we allocate currently */410ATOMIC_T peak; /* the peak memory bytes we allocate */411ATOMIC_T alloc_cnt; /* the alloc count for alloc currently */412ATOMIC_T alloc_err_cnt; /* the error times we fail to allocate memory */413};414415struct rtw_mem_stat rtw_mem_type_stat[mstat_tf_idx(MSTAT_TYPE_MAX)];416#ifdef RTW_MEM_FUNC_STAT417struct rtw_mem_stat rtw_mem_func_stat[mstat_ff_idx(MSTAT_FUNC_MAX)];418#endif419420char *MSTAT_TYPE_str[] = {421"VIR",422"PHY",423"SKB",424"USB",425};426427#ifdef RTW_MEM_FUNC_STAT428char *MSTAT_FUNC_str[] = {429"UNSP",430"IO",431"TXIO",432"RXIO",433"TX",434"RX",435};436#endif437438void rtw_mstat_dump(void *sel)439{440int i;441int value_t[4][mstat_tf_idx(MSTAT_TYPE_MAX)];442#ifdef RTW_MEM_FUNC_STAT443int value_f[4][mstat_ff_idx(MSTAT_FUNC_MAX)];444#endif445446for (i = 0; i < mstat_tf_idx(MSTAT_TYPE_MAX); i++) {447value_t[0][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].alloc));448value_t[1][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].peak));449value_t[2][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].alloc_cnt));450value_t[3][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].alloc_err_cnt));451}452453#ifdef RTW_MEM_FUNC_STAT454for (i = 0; i < mstat_ff_idx(MSTAT_FUNC_MAX); i++) {455value_f[0][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].alloc));456value_f[1][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].peak));457value_f[2][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].alloc_cnt));458value_f[3][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].alloc_err_cnt));459}460#endif461462RTW_PRINT_SEL(sel, "===================== MSTAT =====================\n");463RTW_PRINT_SEL(sel, "%4s %10s %10s %10s %10s\n", "TAG", "alloc", "peak", "aloc_cnt", "err_cnt");464RTW_PRINT_SEL(sel, "-------------------------------------------------\n");465for (i = 0; i < mstat_tf_idx(MSTAT_TYPE_MAX); i++)466RTW_PRINT_SEL(sel, "%4s %10d %10d %10d %10d\n", MSTAT_TYPE_str[i], value_t[0][i], value_t[1][i], value_t[2][i], value_t[3][i]);467#ifdef RTW_MEM_FUNC_STAT468RTW_PRINT_SEL(sel, "-------------------------------------------------\n");469for (i = 0; i < mstat_ff_idx(MSTAT_FUNC_MAX); i++)470RTW_PRINT_SEL(sel, "%4s %10d %10d %10d %10d\n", MSTAT_FUNC_str[i], value_f[0][i], value_f[1][i], value_f[2][i], value_f[3][i]);471#endif472}473474void rtw_mstat_update(const enum mstat_f flags, const MSTAT_STATUS status, u32 sz)475{476static systime update_time = 0;477int peak, alloc;478int i;479480/* initialization */481if (!update_time) {482for (i = 0; i < mstat_tf_idx(MSTAT_TYPE_MAX); i++) {483ATOMIC_SET(&(rtw_mem_type_stat[i].alloc), 0);484ATOMIC_SET(&(rtw_mem_type_stat[i].peak), 0);485ATOMIC_SET(&(rtw_mem_type_stat[i].alloc_cnt), 0);486ATOMIC_SET(&(rtw_mem_type_stat[i].alloc_err_cnt), 0);487}488#ifdef RTW_MEM_FUNC_STAT489for (i = 0; i < mstat_ff_idx(MSTAT_FUNC_MAX); i++) {490ATOMIC_SET(&(rtw_mem_func_stat[i].alloc), 0);491ATOMIC_SET(&(rtw_mem_func_stat[i].peak), 0);492ATOMIC_SET(&(rtw_mem_func_stat[i].alloc_cnt), 0);493ATOMIC_SET(&(rtw_mem_func_stat[i].alloc_err_cnt), 0);494}495#endif496}497498switch (status) {499case MSTAT_ALLOC_SUCCESS:500ATOMIC_INC(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc_cnt));501alloc = ATOMIC_ADD_RETURN(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc), sz);502peak = ATOMIC_READ(&(rtw_mem_type_stat[mstat_tf_idx(flags)].peak));503if (peak < alloc)504ATOMIC_SET(&(rtw_mem_type_stat[mstat_tf_idx(flags)].peak), alloc);505506#ifdef RTW_MEM_FUNC_STAT507ATOMIC_INC(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc_cnt));508alloc = ATOMIC_ADD_RETURN(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc), sz);509peak = ATOMIC_READ(&(rtw_mem_func_stat[mstat_ff_idx(flags)].peak));510if (peak < alloc)511ATOMIC_SET(&(rtw_mem_func_stat[mstat_ff_idx(flags)].peak), alloc);512#endif513break;514515case MSTAT_ALLOC_FAIL:516ATOMIC_INC(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc_err_cnt));517#ifdef RTW_MEM_FUNC_STAT518ATOMIC_INC(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc_err_cnt));519#endif520break;521522case MSTAT_FREE:523ATOMIC_DEC(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc_cnt));524ATOMIC_SUB(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc), sz);525#ifdef RTW_MEM_FUNC_STAT526ATOMIC_DEC(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc_cnt));527ATOMIC_SUB(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc), sz);528#endif529break;530};531532/* if (rtw_get_passing_time_ms(update_time) > 5000) { */533/* rtw_mstat_dump(RTW_DBGDUMP); */534update_time = rtw_get_current_time();535/* } */536}537538#ifndef SIZE_MAX539#define SIZE_MAX (~(size_t)0)540#endif541542struct mstat_sniff_rule {543enum mstat_f flags;544size_t lb;545size_t hb;546};547548struct mstat_sniff_rule mstat_sniff_rules[] = {549{MSTAT_TYPE_PHY, 4097, SIZE_MAX},550};551552int mstat_sniff_rule_num = sizeof(mstat_sniff_rules) / sizeof(struct mstat_sniff_rule);553554bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size)555{556int i;557for (i = 0; i < mstat_sniff_rule_num; i++) {558if (mstat_sniff_rules[i].flags == flags559&& mstat_sniff_rules[i].lb <= size560&& mstat_sniff_rules[i].hb >= size)561return _TRUE;562}563564return _FALSE;565}566567inline void *dbg_rtw_vmalloc(u32 sz, const enum mstat_f flags, const char *func, const int line)568{569void *p;570571if (match_mstat_sniff_rules(flags, sz))572RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __FUNCTION__, (sz));573574p = _rtw_vmalloc((sz));575576rtw_mstat_update(577flags578, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL579, sz580);581582return p;583}584585inline void *dbg_rtw_zvmalloc(u32 sz, const enum mstat_f flags, const char *func, const int line)586{587void *p;588589if (match_mstat_sniff_rules(flags, sz))590RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __FUNCTION__, (sz));591592p = _rtw_zvmalloc((sz));593594rtw_mstat_update(595flags596, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL597, sz598);599600return p;601}602603inline void dbg_rtw_vmfree(void *pbuf, u32 sz, const enum mstat_f flags, const char *func, const int line)604{605606if (match_mstat_sniff_rules(flags, sz))607RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __FUNCTION__, (sz));608609_rtw_vmfree((pbuf), (sz));610611rtw_mstat_update(612flags613, MSTAT_FREE614, sz615);616}617618inline void *dbg_rtw_malloc(u32 sz, const enum mstat_f flags, const char *func, const int line)619{620void *p;621622if (match_mstat_sniff_rules(flags, sz))623RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __FUNCTION__, (sz));624625p = _rtw_malloc((sz));626627rtw_mstat_update(628flags629, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL630, sz631);632633return p;634}635636inline void *dbg_rtw_zmalloc(u32 sz, const enum mstat_f flags, const char *func, const int line)637{638void *p;639640if (match_mstat_sniff_rules(flags, sz))641RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __FUNCTION__, (sz));642643p = _rtw_zmalloc((sz));644645rtw_mstat_update(646flags647, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL648, sz649);650651return p;652}653654inline void dbg_rtw_mfree(void *pbuf, u32 sz, const enum mstat_f flags, const char *func, const int line)655{656if (match_mstat_sniff_rules(flags, sz))657RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __FUNCTION__, (sz));658659_rtw_mfree((pbuf), (sz));660661rtw_mstat_update(662flags663, MSTAT_FREE664, sz665);666}667668inline struct sk_buff *dbg_rtw_skb_alloc(unsigned int size, const enum mstat_f flags, const char *func, int line)669{670struct sk_buff *skb;671unsigned int truesize = 0;672673skb = _rtw_skb_alloc(size);674675if (skb)676truesize = skb->truesize;677678if (!skb || truesize < size || match_mstat_sniff_rules(flags, truesize))679RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, size, skb, truesize);680681rtw_mstat_update(682flags683, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL684, truesize685);686687return skb;688}689690inline void dbg_rtw_skb_free(struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)691{692unsigned int truesize = skb->truesize;693694if (match_mstat_sniff_rules(flags, truesize))695RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);696697_rtw_skb_free(skb);698699rtw_mstat_update(700flags701, MSTAT_FREE702, truesize703);704}705706inline struct sk_buff *dbg_rtw_skb_copy(const struct sk_buff *skb, const enum mstat_f flags, const char *func, const int line)707{708struct sk_buff *skb_cp;709unsigned int truesize = skb->truesize;710unsigned int cp_truesize = 0;711712skb_cp = _rtw_skb_copy(skb);713if (skb_cp)714cp_truesize = skb_cp->truesize;715716if (!skb_cp || cp_truesize < truesize || match_mstat_sniff_rules(flags, cp_truesize))717RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u), skb_cp:%p, cp_truesize=%u\n", func, line, __FUNCTION__, truesize, skb_cp, cp_truesize);718719rtw_mstat_update(720flags721, skb_cp ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL722, cp_truesize723);724725return skb_cp;726}727728inline struct sk_buff *dbg_rtw_skb_clone(struct sk_buff *skb, const enum mstat_f flags, const char *func, const int line)729{730struct sk_buff *skb_cl;731unsigned int truesize = skb->truesize;732unsigned int cl_truesize = 0;733734skb_cl = _rtw_skb_clone(skb);735if (skb_cl)736cl_truesize = skb_cl->truesize;737738if (!skb_cl || cl_truesize < truesize || match_mstat_sniff_rules(flags, cl_truesize))739RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u), skb_cl:%p, cl_truesize=%u\n", func, line, __FUNCTION__, truesize, skb_cl, cl_truesize);740741rtw_mstat_update(742flags743, skb_cl ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL744, cl_truesize745);746747return skb_cl;748}749750inline int dbg_rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)751{752int ret;753unsigned int truesize = skb->truesize;754755if (match_mstat_sniff_rules(flags, truesize))756RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);757758ret = _rtw_netif_rx(ndev, skb);759760rtw_mstat_update(761flags762, MSTAT_FREE763, truesize764);765766return ret;767}768769#ifdef CONFIG_RTW_NAPI770inline int dbg_rtw_netif_receive_skb(_nic_hdl ndev, struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)771{772int ret;773unsigned int truesize = skb->truesize;774775if (match_mstat_sniff_rules(flags, truesize))776RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);777778ret = _rtw_netif_receive_skb(ndev, skb);779780rtw_mstat_update(781flags782, MSTAT_FREE783, truesize784);785786return ret;787}788789#ifdef CONFIG_RTW_GRO790inline gro_result_t dbg_rtw_napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)791{792int ret;793unsigned int truesize = skb->truesize;794795if (match_mstat_sniff_rules(flags, truesize))796RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);797798ret = _rtw_napi_gro_receive(napi, skb);799800rtw_mstat_update(801flags802, MSTAT_FREE803, truesize804);805806return ret;807}808#endif /* CONFIG_RTW_GRO */809#endif /* CONFIG_RTW_NAPI */810811inline void dbg_rtw_skb_queue_purge(struct sk_buff_head *list, enum mstat_f flags, const char *func, int line)812{813struct sk_buff *skb;814815while ((skb = skb_dequeue(list)) != NULL)816dbg_rtw_skb_free(skb, flags, func, line);817}818819#ifdef CONFIG_USB_HCI820inline void *dbg_rtw_usb_buffer_alloc(struct usb_device *dev, size_t size, dma_addr_t *dma, const enum mstat_f flags, const char *func, int line)821{822void *p;823824if (match_mstat_sniff_rules(flags, size))825RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%zu)\n", func, line, __FUNCTION__, size);826827p = _rtw_usb_buffer_alloc(dev, size, dma);828829rtw_mstat_update(830flags831, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL832, size833);834835return p;836}837838inline void dbg_rtw_usb_buffer_free(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma, const enum mstat_f flags, const char *func, int line)839{840841if (match_mstat_sniff_rules(flags, size))842RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%zu)\n", func, line, __FUNCTION__, size);843844_rtw_usb_buffer_free(dev, size, addr, dma);845846rtw_mstat_update(847flags848, MSTAT_FREE849, size850);851}852#endif /* CONFIG_USB_HCI */853854#endif /* defined(DBG_MEM_ALLOC) */855856void *rtw_malloc2d(int h, int w, size_t size)857{858int j;859860void **a = (void **) rtw_zmalloc(h * sizeof(void *) + h * w * size);861if (a == NULL) {862RTW_INFO("%s: alloc memory fail!\n", __FUNCTION__);863return NULL;864}865866for (j = 0; j < h; j++)867a[j] = ((char *)(a + h)) + j * w * size;868869return a;870}871872void rtw_mfree2d(void *pbuf, int h, int w, int size)873{874rtw_mfree((u8 *)pbuf, h * sizeof(void *) + w * h * size);875}876877inline void rtw_os_pkt_free(_pkt *pkt)878{879#if defined(PLATFORM_LINUX)880rtw_skb_free(pkt);881#elif defined(PLATFORM_FREEBSD)882m_freem(pkt);883#else884#error "TBD\n"885#endif886}887888inline _pkt *rtw_os_pkt_copy(_pkt *pkt)889{890#if defined(PLATFORM_LINUX)891return rtw_skb_copy(pkt);892#elif defined(PLATFORM_FREEBSD)893return m_dup(pkt, M_NOWAIT);894#else895#error "TBD\n"896#endif897}898899inline void *rtw_os_pkt_data(_pkt *pkt)900{901#if defined(PLATFORM_LINUX)902return pkt->data;903#elif defined(PLATFORM_FREEBSD)904return pkt->m_data;905#else906#error "TBD\n"907#endif908}909910inline u32 rtw_os_pkt_len(_pkt *pkt)911{912#if defined(PLATFORM_LINUX)913return pkt->len;914#elif defined(PLATFORM_FREEBSD)915return pkt->m_pkthdr.len;916#else917#error "TBD\n"918#endif919}920921void _rtw_memcpy(void *dst, const void *src, u32 sz)922{923924#if defined(PLATFORM_LINUX) || defined (PLATFORM_FREEBSD)925926memcpy(dst, src, sz);927928#endif929930#ifdef PLATFORM_WINDOWS931932NdisMoveMemory(dst, src, sz);933934#endif935936}937938inline void _rtw_memmove(void *dst, const void *src, u32 sz)939{940#if defined(PLATFORM_LINUX)941memmove(dst, src, sz);942#else943#error "TBD\n"944#endif945}946947int _rtw_memcmp(const void *dst, const void *src, u32 sz)948{949950#if defined(PLATFORM_LINUX) || defined (PLATFORM_FREEBSD)951/* under Linux/GNU/GLibc, the return value of memcmp for two same mem. chunk is 0 */952953if (!(memcmp(dst, src, sz)))954return _TRUE;955else956return _FALSE;957#endif958959960#ifdef PLATFORM_WINDOWS961/* under Windows, the return value of NdisEqualMemory for two same mem. chunk is 1 */962963if (NdisEqualMemory(dst, src, sz))964return _TRUE;965else966return _FALSE;967968#endif969970971972}973974void _rtw_memset(void *pbuf, int c, u32 sz)975{976977#if defined(PLATFORM_LINUX) || defined (PLATFORM_FREEBSD)978979memset(pbuf, c, sz);980981#endif982983#ifdef PLATFORM_WINDOWS984#if 0985NdisZeroMemory(pbuf, sz);986if (c != 0)987memset(pbuf, c, sz);988#else989NdisFillMemory(pbuf, sz, c);990#endif991#endif992993}994995#ifdef PLATFORM_FREEBSD996static inline void __list_add(_list *pnew, _list *pprev, _list *pnext)997{998pnext->prev = pnew;999pnew->next = pnext;1000pnew->prev = pprev;1001pprev->next = pnew;1002}1003#endif /* PLATFORM_FREEBSD */100410051006void _rtw_init_listhead(_list *list)1007{10081009#ifdef PLATFORM_LINUX10101011INIT_LIST_HEAD(list);10121013#endif10141015#ifdef PLATFORM_FREEBSD1016list->next = list;1017list->prev = list;1018#endif1019#ifdef PLATFORM_WINDOWS10201021NdisInitializeListHead(list);10221023#endif10241025}102610271028/*1029For the following list_xxx operations,1030caller must guarantee the atomic context.1031Otherwise, there will be racing condition.1032*/1033u32 rtw_is_list_empty(_list *phead)1034{10351036#ifdef PLATFORM_LINUX10371038if (list_empty(phead))1039return _TRUE;1040else1041return _FALSE;10421043#endif1044#ifdef PLATFORM_FREEBSD10451046if (phead->next == phead)1047return _TRUE;1048else1049return _FALSE;10501051#endif105210531054#ifdef PLATFORM_WINDOWS10551056if (IsListEmpty(phead))1057return _TRUE;1058else1059return _FALSE;10601061#endif106210631064}10651066void rtw_list_insert_head(_list *plist, _list *phead)1067{10681069#ifdef PLATFORM_LINUX1070list_add(plist, phead);1071#endif10721073#ifdef PLATFORM_FREEBSD1074__list_add(plist, phead, phead->next);1075#endif10761077#ifdef PLATFORM_WINDOWS1078InsertHeadList(phead, plist);1079#endif1080}10811082void rtw_list_insert_tail(_list *plist, _list *phead)1083{10841085#ifdef PLATFORM_LINUX10861087list_add_tail(plist, phead);10881089#endif1090#ifdef PLATFORM_FREEBSD10911092__list_add(plist, phead->prev, phead);10931094#endif1095#ifdef PLATFORM_WINDOWS10961097InsertTailList(phead, plist);10981099#endif11001101}11021103inline void rtw_list_splice(_list *list, _list *head)1104{1105#ifdef PLATFORM_LINUX1106list_splice(list, head);1107#else1108#error "TBD\n"1109#endif1110}11111112inline void rtw_list_splice_init(_list *list, _list *head)1113{1114#ifdef PLATFORM_LINUX1115list_splice_init(list, head);1116#else1117#error "TBD\n"1118#endif1119}11201121inline void rtw_list_splice_tail(_list *list, _list *head)1122{1123#ifdef PLATFORM_LINUX1124#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27))1125if (!list_empty(list))1126__list_splice(list, head);1127#else1128list_splice_tail(list, head);1129#endif1130#else1131#error "TBD\n"1132#endif1133}11341135inline void rtw_hlist_head_init(rtw_hlist_head *h)1136{1137#ifdef PLATFORM_LINUX1138INIT_HLIST_HEAD(h);1139#else1140#error "TBD\n"1141#endif1142}11431144inline void rtw_hlist_add_head(rtw_hlist_node *n, rtw_hlist_head *h)1145{1146#ifdef PLATFORM_LINUX1147hlist_add_head(n, h);1148#else1149#error "TBD\n"1150#endif1151}11521153inline void rtw_hlist_del(rtw_hlist_node *n)1154{1155#ifdef PLATFORM_LINUX1156hlist_del(n);1157#else1158#error "TBD\n"1159#endif1160}11611162inline void rtw_hlist_add_head_rcu(rtw_hlist_node *n, rtw_hlist_head *h)1163{1164#ifdef PLATFORM_LINUX1165hlist_add_head_rcu(n, h);1166#else1167#error "TBD\n"1168#endif1169}11701171inline void rtw_hlist_del_rcu(rtw_hlist_node *n)1172{1173#ifdef PLATFORM_LINUX1174hlist_del_rcu(n);1175#else1176#error "TBD\n"1177#endif1178}11791180void rtw_init_timer(_timer *ptimer, void *padapter, void *pfunc, void *ctx)1181{1182_adapter *adapter = (_adapter *)padapter;11831184#ifdef PLATFORM_LINUX1185_init_timer(ptimer, adapter->pnetdev, pfunc, ctx);1186#endif1187#ifdef PLATFORM_FREEBSD1188_init_timer(ptimer, adapter->pifp, pfunc, ctx);1189#endif1190#ifdef PLATFORM_WINDOWS1191_init_timer(ptimer, adapter->hndis_adapter, pfunc, ctx);1192#endif1193}11941195/*11961197Caller must check if the list is empty before calling rtw_list_delete11981199*/120012011202void _rtw_init_sema(_sema *sema, int init_val)1203{12041205#ifdef PLATFORM_LINUX12061207sema_init(sema, init_val);12081209#endif1210#ifdef PLATFORM_FREEBSD1211sema_init(sema, init_val, "rtw_drv");1212#endif1213#ifdef PLATFORM_OS_XP12141215KeInitializeSemaphore(sema, init_val, SEMA_UPBND); /* count=0; */12161217#endif12181219#ifdef PLATFORM_OS_CE1220if (*sema == NULL)1221*sema = CreateSemaphore(NULL, init_val, SEMA_UPBND, NULL);1222#endif12231224}12251226void _rtw_free_sema(_sema *sema)1227{1228#ifdef PLATFORM_FREEBSD1229sema_destroy(sema);1230#endif1231#ifdef PLATFORM_OS_CE1232CloseHandle(*sema);1233#endif12341235}12361237void _rtw_up_sema(_sema *sema)1238{12391240#ifdef PLATFORM_LINUX12411242up(sema);12431244#endif1245#ifdef PLATFORM_FREEBSD1246sema_post(sema);1247#endif1248#ifdef PLATFORM_OS_XP12491250KeReleaseSemaphore(sema, IO_NETWORK_INCREMENT, 1, FALSE);12511252#endif12531254#ifdef PLATFORM_OS_CE1255ReleaseSemaphore(*sema, 1, NULL);1256#endif1257}12581259u32 _rtw_down_sema(_sema *sema)1260{12611262#ifdef PLATFORM_LINUX12631264if (down_interruptible(sema))1265return _FAIL;1266else1267return _SUCCESS;12681269#endif1270#ifdef PLATFORM_FREEBSD1271sema_wait(sema);1272return _SUCCESS;1273#endif1274#ifdef PLATFORM_OS_XP12751276if (STATUS_SUCCESS == KeWaitForSingleObject(sema, Executive, KernelMode, TRUE, NULL))1277return _SUCCESS;1278else1279return _FAIL;1280#endif12811282#ifdef PLATFORM_OS_CE1283if (WAIT_OBJECT_0 == WaitForSingleObject(*sema, INFINITE))1284return _SUCCESS;1285else1286return _FAIL;1287#endif1288}12891290inline void thread_exit(_completion *comp)1291{1292#ifdef PLATFORM_LINUX1293#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))1294kthread_complete_and_exit(comp, 0);1295#else1296complete_and_exit(comp, 0);1297#endif1298#endif12991300#ifdef PLATFORM_FREEBSD1301printf("%s", "RTKTHREAD_exit");1302#endif13031304#ifdef PLATFORM_OS_CE1305ExitThread(STATUS_SUCCESS);1306#endif13071308#ifdef PLATFORM_OS_XP1309PsTerminateSystemThread(STATUS_SUCCESS);1310#endif1311}13121313inline void _rtw_init_completion(_completion *comp)1314{1315#ifdef PLATFORM_LINUX1316init_completion(comp);1317#endif1318}1319inline void _rtw_wait_for_comp_timeout(_completion *comp)1320{1321#ifdef PLATFORM_LINUX1322wait_for_completion_timeout(comp, msecs_to_jiffies(3000));1323#endif1324}1325inline void _rtw_wait_for_comp(_completion *comp)1326{1327#ifdef PLATFORM_LINUX1328wait_for_completion(comp);1329#endif1330}13311332void _rtw_mutex_init(_mutex *pmutex)1333{1334#ifdef PLATFORM_LINUX13351336#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))1337mutex_init(pmutex);1338#else1339init_MUTEX(pmutex);1340#endif13411342#endif1343#ifdef PLATFORM_FREEBSD1344mtx_init(pmutex, "", NULL, MTX_DEF | MTX_RECURSE);1345#endif1346#ifdef PLATFORM_OS_XP13471348KeInitializeMutex(pmutex, 0);13491350#endif13511352#ifdef PLATFORM_OS_CE1353*pmutex = CreateMutex(NULL, _FALSE, NULL);1354#endif1355}13561357void _rtw_mutex_free(_mutex *pmutex);1358void _rtw_mutex_free(_mutex *pmutex)1359{1360#ifdef PLATFORM_LINUX13611362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))1363mutex_destroy(pmutex);1364#else1365#endif13661367#ifdef PLATFORM_FREEBSD1368sema_destroy(pmutex);1369#endif13701371#endif13721373#ifdef PLATFORM_OS_XP13741375#endif13761377#ifdef PLATFORM_OS_CE13781379#endif1380}13811382void _rtw_spinlock_init(_lock *plock)1383{13841385#ifdef PLATFORM_LINUX13861387spin_lock_init(plock);13881389#endif1390#ifdef PLATFORM_FREEBSD1391mtx_init(plock, "", NULL, MTX_DEF | MTX_RECURSE);1392#endif1393#ifdef PLATFORM_WINDOWS13941395NdisAllocateSpinLock(plock);13961397#endif13981399}14001401void _rtw_spinlock_free(_lock *plock)1402{1403#ifdef PLATFORM_FREEBSD1404mtx_destroy(plock);1405#endif14061407#ifdef PLATFORM_WINDOWS14081409NdisFreeSpinLock(plock);14101411#endif14121413}1414#ifdef PLATFORM_FREEBSD1415extern PADAPTER prtw_lock;14161417void rtw_mtx_lock(_lock *plock)1418{1419if (prtw_lock)1420mtx_lock(&prtw_lock->glock);1421else1422printf("%s prtw_lock==NULL", __FUNCTION__);1423}1424void rtw_mtx_unlock(_lock *plock)1425{1426if (prtw_lock)1427mtx_unlock(&prtw_lock->glock);1428else1429printf("%s prtw_lock==NULL", __FUNCTION__);14301431}1432#endif /* PLATFORM_FREEBSD */143314341435void _rtw_spinlock(_lock *plock)1436{14371438#ifdef PLATFORM_LINUX14391440spin_lock(plock);14411442#endif1443#ifdef PLATFORM_FREEBSD1444mtx_lock(plock);1445#endif1446#ifdef PLATFORM_WINDOWS14471448NdisAcquireSpinLock(plock);14491450#endif14511452}14531454void _rtw_spinunlock(_lock *plock)1455{14561457#ifdef PLATFORM_LINUX14581459spin_unlock(plock);14601461#endif1462#ifdef PLATFORM_FREEBSD1463mtx_unlock(plock);1464#endif1465#ifdef PLATFORM_WINDOWS14661467NdisReleaseSpinLock(plock);14681469#endif1470}147114721473void _rtw_spinlock_ex(_lock *plock)1474{14751476#ifdef PLATFORM_LINUX14771478spin_lock(plock);14791480#endif1481#ifdef PLATFORM_FREEBSD1482mtx_lock(plock);1483#endif1484#ifdef PLATFORM_WINDOWS14851486NdisDprAcquireSpinLock(plock);14871488#endif14891490}14911492void _rtw_spinunlock_ex(_lock *plock)1493{14941495#ifdef PLATFORM_LINUX14961497spin_unlock(plock);14981499#endif1500#ifdef PLATFORM_FREEBSD1501mtx_unlock(plock);1502#endif1503#ifdef PLATFORM_WINDOWS15041505NdisDprReleaseSpinLock(plock);15061507#endif1508}1509151015111512void _rtw_init_queue(_queue *pqueue)1513{1514_rtw_init_listhead(&(pqueue->queue));1515_rtw_spinlock_init(&(pqueue->lock));1516}15171518void _rtw_deinit_queue(_queue *pqueue)1519{1520_rtw_spinlock_free(&(pqueue->lock));1521}15221523u32 _rtw_queue_empty(_queue *pqueue)1524{1525return rtw_is_list_empty(&(pqueue->queue));1526}152715281529u32 rtw_end_of_queue_search(_list *head, _list *plist)1530{1531if (head == plist)1532return _TRUE;1533else1534return _FALSE;1535}153615371538systime _rtw_get_current_time(void)1539{15401541#ifdef PLATFORM_LINUX1542return jiffies;1543#endif1544#ifdef PLATFORM_FREEBSD1545struct timeval tvp;1546getmicrotime(&tvp);1547return tvp.tv_sec;1548#endif1549#ifdef PLATFORM_WINDOWS1550LARGE_INTEGER SystemTime;1551NdisGetCurrentSystemTime(&SystemTime);1552return SystemTime.LowPart;/* count of 100-nanosecond intervals */1553#endif1554}15551556inline u32 _rtw_systime_to_ms(systime stime)1557{1558#ifdef PLATFORM_LINUX1559return jiffies_to_msecs(stime);1560#endif1561#ifdef PLATFORM_FREEBSD1562return stime * 1000;1563#endif1564#ifdef PLATFORM_WINDOWS1565return stime / 10000 ;1566#endif1567}15681569inline systime _rtw_ms_to_systime(u32 ms)1570{1571#ifdef PLATFORM_LINUX1572return msecs_to_jiffies(ms);1573#endif1574#ifdef PLATFORM_FREEBSD1575return ms / 1000;1576#endif1577#ifdef PLATFORM_WINDOWS1578return ms * 10000 ;1579#endif1580}15811582inline systime _rtw_us_to_systime(u32 us)1583{1584#ifdef PLATFORM_LINUX1585return usecs_to_jiffies(us);1586#else1587#error "TBD\n"1588#endif1589}15901591/* the input parameter start use the same unit as returned by rtw_get_current_time */1592inline s32 _rtw_get_passing_time_ms(systime start)1593{1594return _rtw_systime_to_ms(_rtw_get_current_time() - start);1595}15961597inline s32 _rtw_get_remaining_time_ms(systime end)1598{1599return _rtw_systime_to_ms(end - _rtw_get_current_time());1600}16011602inline s32 _rtw_get_time_interval_ms(systime start, systime end)1603{1604return _rtw_systime_to_ms(end - start);1605}16061607inline bool _rtw_time_after(systime a, systime b)1608{1609#ifdef PLATFORM_LINUX1610return time_after(a, b);1611#else1612#error "TBD\n"1613#endif1614}16151616void rtw_sleep_schedulable(int ms)1617{16181619#ifdef PLATFORM_LINUX16201621u32 delta;16221623delta = (ms * HZ) / 1000; /* (ms) */1624if (delta == 0) {1625delta = 1;/* 1 ms */1626}1627set_current_state(TASK_INTERRUPTIBLE);1628schedule_timeout(delta);1629return;16301631#endif1632#ifdef PLATFORM_FREEBSD1633DELAY(ms * 1000);1634return ;1635#endif16361637#ifdef PLATFORM_WINDOWS16381639NdisMSleep(ms * 1000); /* (us)*1000=(ms) */16401641#endif16421643}164416451646void rtw_msleep_os(int ms)1647{16481649#ifdef PLATFORM_LINUX1650#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36))1651if (ms < 20) {1652unsigned long us = ms * 1000UL;1653usleep_range(us, us + 1000UL);1654} else1655#endif1656msleep((unsigned int)ms);16571658#endif1659#ifdef PLATFORM_FREEBSD1660/* Delay for delay microseconds */1661DELAY(ms * 1000);1662return ;1663#endif1664#ifdef PLATFORM_WINDOWS16651666NdisMSleep(ms * 1000); /* (us)*1000=(ms) */16671668#endif166916701671}1672void rtw_usleep_os(int us)1673{1674#ifdef PLATFORM_LINUX16751676/* msleep((unsigned int)us); */1677#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36))1678usleep_range(us, us + 1);1679#else1680if (1 < (us / 1000))1681msleep(1);1682else1683msleep((us / 1000) + 1);1684#endif1685#endif16861687#ifdef PLATFORM_FREEBSD1688/* Delay for delay microseconds */1689DELAY(us);16901691return ;1692#endif1693#ifdef PLATFORM_WINDOWS16941695NdisMSleep(us); /* (us) */16961697#endif169816991700}170117021703#ifdef DBG_DELAY_OS1704void _rtw_mdelay_os(int ms, const char *func, const int line)1705{1706#if 01707if (ms > 10)1708RTW_INFO("%s:%d %s(%d)\n", func, line, __FUNCTION__, ms);1709rtw_msleep_os(ms);1710return;1711#endif171217131714RTW_INFO("%s:%d %s(%d)\n", func, line, __FUNCTION__, ms);17151716#if defined(PLATFORM_LINUX)17171718mdelay((unsigned long)ms);17191720#elif defined(PLATFORM_WINDOWS)17211722NdisStallExecution(ms * 1000); /* (us)*1000=(ms) */17231724#endif172517261727}1728void _rtw_udelay_os(int us, const char *func, const int line)1729{17301731#if 01732if (us > 1000) {1733RTW_INFO("%s:%d %s(%d)\n", func, line, __FUNCTION__, us);1734rtw_usleep_os(us);1735return;1736}1737#endif173817391740RTW_INFO("%s:%d %s(%d)\n", func, line, __FUNCTION__, us);174117421743#if defined(PLATFORM_LINUX)17441745udelay((unsigned long)us);17461747#elif defined(PLATFORM_WINDOWS)17481749NdisStallExecution(us); /* (us) */17501751#endif17521753}1754#else1755void rtw_mdelay_os(int ms)1756{17571758#ifdef PLATFORM_LINUX17591760mdelay((unsigned long)ms);17611762#endif1763#ifdef PLATFORM_FREEBSD1764DELAY(ms * 1000);1765return ;1766#endif1767#ifdef PLATFORM_WINDOWS17681769NdisStallExecution(ms * 1000); /* (us)*1000=(ms) */17701771#endif177217731774}1775void rtw_udelay_os(int us)1776{17771778#ifdef PLATFORM_LINUX17791780udelay((unsigned long)us);17811782#endif1783#ifdef PLATFORM_FREEBSD1784/* Delay for delay microseconds */1785DELAY(us);1786return ;1787#endif1788#ifdef PLATFORM_WINDOWS17891790NdisStallExecution(us); /* (us) */17911792#endif17931794}1795#endif17961797void rtw_yield_os(void)1798{1799#ifdef PLATFORM_LINUX1800yield();1801#endif1802#ifdef PLATFORM_FREEBSD1803yield();1804#endif1805#ifdef PLATFORM_WINDOWS1806SwitchToThread();1807#endif1808}18091810bool rtw_macaddr_is_larger(const u8 *a, const u8 *b)1811{1812u32 va, vb;18131814va = be32_to_cpu(*((u32 *)a));1815vb = be32_to_cpu(*((u32 *)b));1816if (va > vb)1817return 1;1818else if (va < vb)1819return 0;18201821return be16_to_cpu(*((u16 *)(a + 4))) > be16_to_cpu(*((u16 *)(b + 4)));1822}18231824#define RTW_SUSPEND_LOCK_NAME "rtw_wifi"1825#define RTW_SUSPEND_TRAFFIC_LOCK_NAME "rtw_wifi_traffic"1826#define RTW_SUSPEND_RESUME_LOCK_NAME "rtw_wifi_resume"1827#ifdef CONFIG_WAKELOCK1828static struct wake_lock rtw_suspend_lock;1829static struct wake_lock rtw_suspend_traffic_lock;1830static struct wake_lock rtw_suspend_resume_lock;1831#elif defined(CONFIG_ANDROID_POWER)1832static android_suspend_lock_t rtw_suspend_lock = {1833.name = RTW_SUSPEND_LOCK_NAME1834};1835static android_suspend_lock_t rtw_suspend_traffic_lock = {1836.name = RTW_SUSPEND_TRAFFIC_LOCK_NAME1837};1838static android_suspend_lock_t rtw_suspend_resume_lock = {1839.name = RTW_SUSPEND_RESUME_LOCK_NAME1840};1841#endif18421843inline void rtw_suspend_lock_init(void)1844{1845#ifdef CONFIG_WAKELOCK1846wake_lock_init(&rtw_suspend_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_LOCK_NAME);1847wake_lock_init(&rtw_suspend_traffic_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_TRAFFIC_LOCK_NAME);1848wake_lock_init(&rtw_suspend_resume_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_RESUME_LOCK_NAME);1849#elif defined(CONFIG_ANDROID_POWER)1850android_init_suspend_lock(&rtw_suspend_lock);1851android_init_suspend_lock(&rtw_suspend_traffic_lock);1852android_init_suspend_lock(&rtw_suspend_resume_lock);1853#endif1854}18551856inline void rtw_suspend_lock_uninit(void)1857{1858#ifdef CONFIG_WAKELOCK1859wake_lock_destroy(&rtw_suspend_lock);1860wake_lock_destroy(&rtw_suspend_traffic_lock);1861wake_lock_destroy(&rtw_suspend_resume_lock);1862#elif defined(CONFIG_ANDROID_POWER)1863android_uninit_suspend_lock(&rtw_suspend_lock);1864android_uninit_suspend_lock(&rtw_suspend_traffic_lock);1865android_uninit_suspend_lock(&rtw_suspend_resume_lock);1866#endif1867}18681869inline void rtw_lock_suspend(void)1870{1871#ifdef CONFIG_WAKELOCK1872wake_lock(&rtw_suspend_lock);1873#elif defined(CONFIG_ANDROID_POWER)1874android_lock_suspend(&rtw_suspend_lock);1875#endif18761877#if defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)1878/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __FUNCTION__, rtw_suspend_lock.stat.count); */1879#endif1880}18811882inline void rtw_unlock_suspend(void)1883{1884#ifdef CONFIG_WAKELOCK1885wake_unlock(&rtw_suspend_lock);1886#elif defined(CONFIG_ANDROID_POWER)1887android_unlock_suspend(&rtw_suspend_lock);1888#endif18891890#if defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)1891/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __FUNCTION__, rtw_suspend_lock.stat.count); */1892#endif1893}18941895inline void rtw_resume_lock_suspend(void)1896{1897#ifdef CONFIG_WAKELOCK1898wake_lock(&rtw_suspend_resume_lock);1899#elif defined(CONFIG_ANDROID_POWER)1900android_lock_suspend(&rtw_suspend_resume_lock);1901#endif19021903#if defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)1904/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __FUNCTION__, rtw_suspend_lock.stat.count); */1905#endif1906}19071908inline void rtw_resume_unlock_suspend(void)1909{1910#ifdef CONFIG_WAKELOCK1911wake_unlock(&rtw_suspend_resume_lock);1912#elif defined(CONFIG_ANDROID_POWER)1913android_unlock_suspend(&rtw_suspend_resume_lock);1914#endif19151916#if defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)1917/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __FUNCTION__, rtw_suspend_lock.stat.count); */1918#endif1919}19201921inline void rtw_lock_suspend_timeout(u32 timeout_ms)1922{1923#ifdef CONFIG_WAKELOCK1924wake_lock_timeout(&rtw_suspend_lock, rtw_ms_to_systime(timeout_ms));1925#elif defined(CONFIG_ANDROID_POWER)1926android_lock_suspend_auto_expire(&rtw_suspend_lock, rtw_ms_to_systime(timeout_ms));1927#endif1928}192919301931inline void rtw_lock_traffic_suspend_timeout(u32 timeout_ms)1932{1933#ifdef CONFIG_WAKELOCK1934wake_lock_timeout(&rtw_suspend_traffic_lock, rtw_ms_to_systime(timeout_ms));1935#elif defined(CONFIG_ANDROID_POWER)1936android_lock_suspend_auto_expire(&rtw_suspend_traffic_lock, rtw_ms_to_systime(timeout_ms));1937#endif1938/* RTW_INFO("traffic lock timeout:%d\n", timeout_ms); */1939}19401941inline void rtw_set_bit(int nr, unsigned long *addr)1942{1943#ifdef PLATFORM_LINUX1944set_bit(nr, addr);1945#else1946#error "TBD\n";1947#endif1948}19491950inline void rtw_clear_bit(int nr, unsigned long *addr)1951{1952#ifdef PLATFORM_LINUX1953clear_bit(nr, addr);1954#else1955#error "TBD\n";1956#endif1957}19581959inline int rtw_test_and_clear_bit(int nr, unsigned long *addr)1960{1961#ifdef PLATFORM_LINUX1962return test_and_clear_bit(nr, addr);1963#else1964#error "TBD\n";1965#endif1966}19671968inline void ATOMIC_SET(ATOMIC_T *v, int i)1969{1970#ifdef PLATFORM_LINUX1971atomic_set(v, i);1972#elif defined(PLATFORM_WINDOWS)1973*v = i; /* other choice???? */1974#elif defined(PLATFORM_FREEBSD)1975atomic_set_int(v, i);1976#endif1977}19781979inline int ATOMIC_READ(ATOMIC_T *v)1980{1981#ifdef PLATFORM_LINUX1982return atomic_read(v);1983#elif defined(PLATFORM_WINDOWS)1984return *v; /* other choice???? */1985#elif defined(PLATFORM_FREEBSD)1986return atomic_load_acq_32(v);1987#endif1988}19891990inline void ATOMIC_ADD(ATOMIC_T *v, int i)1991{1992#ifdef PLATFORM_LINUX1993atomic_add(i, v);1994#elif defined(PLATFORM_WINDOWS)1995InterlockedAdd(v, i);1996#elif defined(PLATFORM_FREEBSD)1997atomic_add_int(v, i);1998#endif1999}2000inline void ATOMIC_SUB(ATOMIC_T *v, int i)2001{2002#ifdef PLATFORM_LINUX2003atomic_sub(i, v);2004#elif defined(PLATFORM_WINDOWS)2005InterlockedAdd(v, -i);2006#elif defined(PLATFORM_FREEBSD)2007atomic_subtract_int(v, i);2008#endif2009}20102011inline void ATOMIC_INC(ATOMIC_T *v)2012{2013#ifdef PLATFORM_LINUX2014atomic_inc(v);2015#elif defined(PLATFORM_WINDOWS)2016InterlockedIncrement(v);2017#elif defined(PLATFORM_FREEBSD)2018atomic_add_int(v, 1);2019#endif2020}20212022inline void ATOMIC_DEC(ATOMIC_T *v)2023{2024#ifdef PLATFORM_LINUX2025atomic_dec(v);2026#elif defined(PLATFORM_WINDOWS)2027InterlockedDecrement(v);2028#elif defined(PLATFORM_FREEBSD)2029atomic_subtract_int(v, 1);2030#endif2031}20322033inline int ATOMIC_ADD_RETURN(ATOMIC_T *v, int i)2034{2035#ifdef PLATFORM_LINUX2036return atomic_add_return(i, v);2037#elif defined(PLATFORM_WINDOWS)2038return InterlockedAdd(v, i);2039#elif defined(PLATFORM_FREEBSD)2040atomic_add_int(v, i);2041return atomic_load_acq_32(v);2042#endif2043}20442045inline int ATOMIC_SUB_RETURN(ATOMIC_T *v, int i)2046{2047#ifdef PLATFORM_LINUX2048return atomic_sub_return(i, v);2049#elif defined(PLATFORM_WINDOWS)2050return InterlockedAdd(v, -i);2051#elif defined(PLATFORM_FREEBSD)2052atomic_subtract_int(v, i);2053return atomic_load_acq_32(v);2054#endif2055}20562057inline int ATOMIC_INC_RETURN(ATOMIC_T *v)2058{2059#ifdef PLATFORM_LINUX2060return atomic_inc_return(v);2061#elif defined(PLATFORM_WINDOWS)2062return InterlockedIncrement(v);2063#elif defined(PLATFORM_FREEBSD)2064atomic_add_int(v, 1);2065return atomic_load_acq_32(v);2066#endif2067}20682069inline int ATOMIC_DEC_RETURN(ATOMIC_T *v)2070{2071#ifdef PLATFORM_LINUX2072return atomic_dec_return(v);2073#elif defined(PLATFORM_WINDOWS)2074return InterlockedDecrement(v);2075#elif defined(PLATFORM_FREEBSD)2076atomic_subtract_int(v, 1);2077return atomic_load_acq_32(v);2078#endif2079}20802081inline bool ATOMIC_INC_UNLESS(ATOMIC_T *v, int u)2082{2083#ifdef PLATFORM_LINUX2084#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15))2085return atomic_add_unless(v, 1, u);2086#else2087/* only make sure not exceed after this function */2088if (ATOMIC_INC_RETURN(v) > u) {2089ATOMIC_DEC(v);2090return 0;2091}2092return 1;2093#endif2094#else2095#error "TBD\n"2096#endif2097}20982099#ifdef PLATFORM_LINUX2100/*2101* Open a file with the specific @param path, @param flag, @param mode2102* @param fpp the pointer of struct file pointer to get struct file pointer while file opening is success2103* @param path the path of the file to open2104* @param flag file operation flags, please refer to linux document2105* @param mode please refer to linux document2106* @return Linux specific error code2107*/2108static int openFile(struct file **fpp, const char *path, int flag, int mode)2109{2110struct file *fp;21112112fp = filp_open(path, flag, mode);2113if (IS_ERR(fp)) {2114*fpp = NULL;2115return PTR_ERR(fp);2116} else {2117*fpp = fp;2118return 0;2119}2120}21212122/*2123* Close the file with the specific @param fp2124* @param fp the pointer of struct file to close2125* @return always 02126*/2127static int closeFile(struct file *fp)2128{2129filp_close(fp, NULL);2130return 0;2131}21322133static int readFile(struct file *fp, char *buf, int len)2134{2135int rlen = 0, sum = 0;21362137#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))2138if (!(fp->f_mode & FMODE_CAN_READ))2139#else2140if (!fp->f_op || !fp->f_op->read)2141#endif2142return -EPERM;21432144while (sum < len) {2145#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))2146rlen = kernel_read(fp, buf + sum, len - sum, &fp->f_pos);2147#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))2148rlen = __vfs_read(fp, buf + sum, len - sum, &fp->f_pos);2149#else2150rlen = fp->f_op->read(fp, buf + sum, len - sum, &fp->f_pos);2151#endif2152if (rlen > 0)2153sum += rlen;2154else if (0 != rlen)2155return rlen;2156else2157break;2158}21592160return sum;21612162}21632164static int writeFile(struct file *fp, char *buf, int len)2165{2166int wlen = 0, sum = 0;21672168#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))2169if (!(fp->f_mode & FMODE_CAN_WRITE))2170#else2171if (!fp->f_op || !fp->f_op->write)2172#endif2173return -EPERM;21742175while (sum < len) {2176#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))2177wlen = kernel_write(fp, buf + sum, len - sum, &fp->f_pos);2178#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))2179wlen = __vfs_write(fp, buf + sum, len - sum, &fp->f_pos);2180#else2181wlen = fp->f_op->write(fp, buf + sum, len - sum, &fp->f_pos);2182#endif2183if (wlen > 0)2184sum += wlen;2185else if (0 != wlen)2186return wlen;2187else2188break;2189}21902191return sum;21922193}21942195/*2196* Test if the specifi @param pathname is a direct and readable2197* If readable, @param sz is not used2198* @param pathname the name of the path to test2199* @return Linux specific error code2200*/2201static int isDirReadable(const char *pathname, u32 *sz)2202{2203struct path path;2204int error = 0;22052206return kern_path(pathname, LOOKUP_FOLLOW, &path);2207}22082209/*2210* Test if the specifi @param path is a file and readable2211* If readable, @param sz is got2212* @param path the path of the file to test2213* @return Linux specific error code2214*/2215static int isFileReadable(const char *path, u32 *sz)2216{2217struct file *fp;2218int ret = 0;2219#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2220mm_segment_t oldfs;2221#endif2222char buf;22232224fp = filp_open(path, O_RDONLY, 0);2225if (IS_ERR(fp))2226ret = PTR_ERR(fp);2227else {2228#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2229oldfs = get_fs();2230#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))2231set_fs(KERNEL_DS);2232#else2233set_fs(get_ds());2234#endif2235#endif22362237if (1 != readFile(fp, &buf, 1))2238ret = PTR_ERR(fp);22392240if (ret == 0 && sz) {2241#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))2242*sz = i_size_read(fp->f_path.dentry->d_inode);2243#else2244*sz = i_size_read(fp->f_dentry->d_inode);2245#endif2246}22472248#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2249set_fs(oldfs);2250#endif2251filp_close(fp, NULL);2252}2253return ret;2254}22552256/*2257* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most2258* @param path the path of the file to open and read2259* @param buf the starting address of the buffer to store file content2260* @param sz how many bytes to read at most2261* @return the byte we've read, or Linux specific error code2262*/2263static int retriveFromFile(const char *path, u8 *buf, u32 sz)2264{2265int ret = -1;2266#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2267mm_segment_t oldfs;2268#endif2269struct file *fp;22702271if (path && buf) {2272ret = openFile(&fp, path, O_RDONLY, 0);2273if (0 == ret) {2274RTW_INFO("%s openFile path:%s fp=%p\n", __FUNCTION__, path , fp);22752276#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2277oldfs = get_fs();2278#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))2279set_fs(KERNEL_DS);2280#else2281set_fs(get_ds());2282#endif2283#endif2284ret = readFile(fp, buf, sz);2285#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2286set_fs(oldfs);2287#endif2288closeFile(fp);22892290RTW_INFO("%s readFile, ret:%d\n", __FUNCTION__, ret);22912292} else2293RTW_INFO("%s openFile path:%s Fail, ret:%d\n", __FUNCTION__, path, ret);2294} else {2295RTW_INFO("%s NULL pointer\n", __FUNCTION__);2296ret = -EINVAL;2297}2298return ret;2299}23002301/*2302* Open the file with @param path and wirte @param sz byte of data starting from @param buf into the file2303* @param path the path of the file to open and write2304* @param buf the starting address of the data to write into file2305* @param sz how many bytes to write at most2306* @return the byte we've written, or Linux specific error code2307*/2308static int storeToFile(const char *path, u8 *buf, u32 sz)2309{2310int ret = 0;2311#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2312mm_segment_t oldfs;2313#endif2314struct file *fp;23152316if (path && buf) {2317ret = openFile(&fp, path, O_CREAT | O_WRONLY, 0666);2318if (0 == ret) {2319RTW_INFO("%s openFile path:%s fp=%p\n", __FUNCTION__, path , fp);23202321#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2322oldfs = get_fs();2323#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))2324set_fs(KERNEL_DS);2325#else2326set_fs(get_ds());2327#endif2328#endif2329ret = writeFile(fp, buf, sz);2330#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))2331set_fs(oldfs);2332#endif2333closeFile(fp);23342335RTW_INFO("%s writeFile, ret:%d\n", __FUNCTION__, ret);23362337} else2338RTW_INFO("%s openFile path:%s Fail, ret:%d\n", __FUNCTION__, path, ret);2339} else {2340RTW_INFO("%s NULL pointer\n", __FUNCTION__);2341ret = -EINVAL;2342}2343return ret;2344}2345#endif /* PLATFORM_LINUX */23462347/*2348* Test if the specifi @param path is a direct and readable2349* @param path the path of the direct to test2350* @return _TRUE or _FALSE2351*/2352int rtw_is_dir_readable(const char *path)2353{2354#ifdef PLATFORM_LINUX2355if (isDirReadable(path, NULL) == 0)2356return _TRUE;2357else2358return _FALSE;2359#else2360/* Todo... */2361return _FALSE;2362#endif2363}23642365/*2366* Test if the specifi @param path is a file and readable2367* @param path the path of the file to test2368* @return _TRUE or _FALSE2369*/2370int rtw_is_file_readable(const char *path)2371{2372#ifdef PLATFORM_LINUX2373if (isFileReadable(path, NULL) == 0)2374return _TRUE;2375else2376return _FALSE;2377#else2378/* Todo... */2379return _FALSE;2380#endif2381}23822383/*2384* Test if the specifi @param path is a file and readable.2385* If readable, @param sz is got2386* @param path the path of the file to test2387* @return _TRUE or _FALSE2388*/2389int rtw_is_file_readable_with_size(const char *path, u32 *sz)2390{2391#ifdef PLATFORM_LINUX2392if (isFileReadable(path, sz) == 0)2393return _TRUE;2394else2395return _FALSE;2396#else2397/* Todo... */2398return _FALSE;2399#endif2400}24012402/*2403* Test if the specifi @param path is a readable file with valid size.2404* If readable, @param sz is got2405* @param path the path of the file to test2406* @return _TRUE or _FALSE2407*/2408int rtw_readable_file_sz_chk(const char *path, u32 sz)2409{2410u32 fsz;24112412if (rtw_is_file_readable_with_size(path, &fsz) == _FALSE)2413return _FALSE;24142415if (fsz > sz)2416return _FALSE;24172418return _TRUE;2419}24202421/*2422* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most2423* @param path the path of the file to open and read2424* @param buf the starting address of the buffer to store file content2425* @param sz how many bytes to read at most2426* @return the byte we've read2427*/2428int rtw_retrieve_from_file(const char *path, u8 *buf, u32 sz)2429{2430#ifdef PLATFORM_LINUX2431int ret = retriveFromFile(path, buf, sz);2432return ret >= 0 ? ret : 0;2433#else2434/* Todo... */2435return 0;2436#endif2437}24382439/*2440* Open the file with @param path and wirte @param sz byte of data starting from @param buf into the file2441* @param path the path of the file to open and write2442* @param buf the starting address of the data to write into file2443* @param sz how many bytes to write at most2444* @return the byte we've written2445*/2446int rtw_store_to_file(const char *path, u8 *buf, u32 sz)2447{2448#ifdef PLATFORM_LINUX2449int ret = storeToFile(path, buf, sz);2450return ret >= 0 ? ret : 0;2451#else2452/* Todo... */2453return 0;2454#endif2455}24562457#ifdef PLATFORM_LINUX2458struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)2459{2460struct net_device *pnetdev;2461struct rtw_netdev_priv_indicator *pnpi;24622463#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))2464pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);2465#else2466pnetdev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));2467#endif2468if (!pnetdev)2469goto RETURN;24702471pnpi = netdev_priv(pnetdev);2472pnpi->priv = old_priv;2473pnpi->sizeof_priv = sizeof_priv;24742475RETURN:2476return pnetdev;2477}24782479struct net_device *rtw_alloc_etherdev(int sizeof_priv)2480{2481struct net_device *pnetdev;2482struct rtw_netdev_priv_indicator *pnpi;24832484#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))2485pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);2486#else2487pnetdev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));2488#endif2489if (!pnetdev)2490goto RETURN;24912492pnpi = netdev_priv(pnetdev);24932494pnpi->priv = rtw_zvmalloc(sizeof_priv);2495if (!pnpi->priv) {2496free_netdev(pnetdev);2497pnetdev = NULL;2498goto RETURN;2499}25002501pnpi->sizeof_priv = sizeof_priv;2502RETURN:2503return pnetdev;2504}25052506void rtw_free_netdev(struct net_device *netdev)2507{2508struct rtw_netdev_priv_indicator *pnpi;25092510if (!netdev)2511goto RETURN;25122513pnpi = netdev_priv(netdev);25142515if (!pnpi->priv)2516goto RETURN;25172518free_netdev(netdev);25192520RETURN:2521return;2522}25232524int rtw_change_ifname(_adapter *padapter, const char *ifname)2525{2526struct dvobj_priv *dvobj;2527struct net_device *pnetdev;2528struct net_device *cur_pnetdev;2529struct rereg_nd_name_data *rereg_priv;2530int ret;2531u8 rtnl_lock_needed;25322533if (!padapter)2534goto error;25352536dvobj = adapter_to_dvobj(padapter);2537cur_pnetdev = padapter->pnetdev;2538rereg_priv = &padapter->rereg_nd_name_priv;25392540/* free the old_pnetdev */2541if (rereg_priv->old_pnetdev) {2542free_netdev(rereg_priv->old_pnetdev);2543rereg_priv->old_pnetdev = NULL;2544}25452546rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);25472548if (rtnl_lock_needed)2549unregister_netdev(cur_pnetdev);2550else2551unregister_netdevice(cur_pnetdev);25522553rereg_priv->old_pnetdev = cur_pnetdev;25542555pnetdev = rtw_init_netdev(padapter);2556if (!pnetdev) {2557ret = -1;2558goto error;2559}25602561SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));25622563rtw_init_netdev_name(pnetdev, ifname);25642565_rtw_memcpy(pnetdev->dev_addr, adapter_mac_addr(padapter), ETH_ALEN);25662567if (rtnl_lock_needed)2568ret = register_netdev(pnetdev);2569else2570ret = register_netdevice(pnetdev);25712572if (ret != 0) {2573goto error;2574}25752576return 0;25772578error:25792580return -1;25812582}2583#endif25842585#ifdef PLATFORM_FREEBSD2586/*2587* Copy a buffer from userspace and write into kernel address2588* space.2589*2590* This emulation just calls the FreeBSD copyin function (to2591* copy data from user space buffer into a kernel space buffer)2592* and is designed to be used with the above io_write_wrapper.2593*2594* This function should return the number of bytes not copied.2595* I.e. success results in a zero value.2596* Negative error values are not returned.2597*/2598unsigned long2599copy_from_user(void *to, const void *from, unsigned long n)2600{2601if (copyin(from, to, n) != 0) {2602/* Any errors will be treated as a failure2603to copy any of the requested bytes */2604return n;2605}26062607return 0;2608}26092610unsigned long2611copy_to_user(void *to, const void *from, unsigned long n)2612{2613if (copyout(from, to, n) != 0) {2614/* Any errors will be treated as a failure2615to copy any of the requested bytes */2616return n;2617}26182619return 0;2620}262126222623/*2624* The usb_register and usb_deregister functions are used to register2625* usb drivers with the usb subsystem. In this compatibility layer2626* emulation a list of drivers (struct usb_driver) is maintained2627* and is used for probing/attaching etc.2628*2629* usb_register and usb_deregister simply call these functions.2630*/2631int2632usb_register(struct usb_driver *driver)2633{2634rtw_usb_linux_register(driver);2635return 0;2636}263726382639int2640usb_deregister(struct usb_driver *driver)2641{2642rtw_usb_linux_deregister(driver);2643return 0;2644}26452646void module_init_exit_wrapper(void *arg)2647{2648int (*func)(void) = arg;2649func();2650return;2651}26522653#endif /* PLATFORM_FREEBSD */26542655#ifdef CONFIG_PLATFORM_SPRD2656#ifdef do_div2657#undef do_div2658#endif2659#include <asm-generic/div64.h>2660#endif26612662u64 rtw_modular64(u64 x, u64 y)2663{2664#ifdef PLATFORM_LINUX2665return do_div(x, y);2666#elif defined(PLATFORM_WINDOWS)2667return x % y;2668#elif defined(PLATFORM_FREEBSD)2669return x % y;2670#endif2671}26722673u64 rtw_division64(u64 x, u64 y)2674{2675#ifdef PLATFORM_LINUX2676do_div(x, y);2677return x;2678#elif defined(PLATFORM_WINDOWS)2679return x / y;2680#elif defined(PLATFORM_FREEBSD)2681return x / y;2682#endif2683}26842685inline u32 rtw_random32(void)2686{2687#ifdef PLATFORM_LINUX2688#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))2689return get_random_u32();2690#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))2691return prandom_u32();2692#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18))2693u32 random_int;2694get_random_bytes(&random_int , 4);2695return random_int;2696#else2697return random32();2698#endif2699#elif defined(PLATFORM_WINDOWS)2700#error "to be implemented\n"2701#elif defined(PLATFORM_FREEBSD)2702#error "to be implemented\n"2703#endif2704}27052706void rtw_buf_free(u8 **buf, u32 *buf_len)2707{2708u32 ori_len;27092710if (!buf || !buf_len)2711return;27122713ori_len = *buf_len;27142715if (*buf) {2716u32 tmp_buf_len = *buf_len;2717*buf_len = 0;2718rtw_mfree(*buf, tmp_buf_len);2719*buf = NULL;2720}2721}27222723void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)2724{2725u32 ori_len = 0, dup_len = 0;2726u8 *ori = NULL;2727u8 *dup = NULL;27282729if (!buf || !buf_len)2730return;27312732if (!src || !src_len)2733goto keep_ori;27342735/* duplicate src */2736dup = rtw_malloc(src_len);2737if (dup) {2738dup_len = src_len;2739_rtw_memcpy(dup, src, dup_len);2740}27412742keep_ori:2743ori = *buf;2744ori_len = *buf_len;27452746/* replace buf with dup */2747*buf_len = 0;2748*buf = dup;2749*buf_len = dup_len;27502751/* free ori */2752if (ori && ori_len > 0)2753rtw_mfree(ori, ori_len);2754}275527562757/**2758* rtw_cbuf_full - test if cbuf is full2759* @cbuf: pointer of struct rtw_cbuf2760*2761* Returns: _TRUE if cbuf is full2762*/2763inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)2764{2765return (cbuf->write == cbuf->read - 1) ? _TRUE : _FALSE;2766}27672768/**2769* rtw_cbuf_empty - test if cbuf is empty2770* @cbuf: pointer of struct rtw_cbuf2771*2772* Returns: _TRUE if cbuf is empty2773*/2774inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)2775{2776return (cbuf->write == cbuf->read) ? _TRUE : _FALSE;2777}27782779/**2780* rtw_cbuf_push - push a pointer into cbuf2781* @cbuf: pointer of struct rtw_cbuf2782* @buf: pointer to push in2783*2784* Lock free operation, be careful of the use scheme2785* Returns: _TRUE push success2786*/2787bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)2788{2789if (rtw_cbuf_full(cbuf))2790return _FAIL;27912792if (0)2793RTW_INFO("%s on %u\n", __func__, cbuf->write);2794cbuf->bufs[cbuf->write] = buf;2795cbuf->write = (cbuf->write + 1) % cbuf->size;27962797return _SUCCESS;2798}27992800/**2801* rtw_cbuf_pop - pop a pointer from cbuf2802* @cbuf: pointer of struct rtw_cbuf2803*2804* Lock free operation, be careful of the use scheme2805* Returns: pointer popped out2806*/2807void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)2808{2809void *buf;2810if (rtw_cbuf_empty(cbuf))2811return NULL;28122813if (0)2814RTW_INFO("%s on %u\n", __func__, cbuf->read);2815buf = cbuf->bufs[cbuf->read];2816cbuf->read = (cbuf->read + 1) % cbuf->size;28172818return buf;2819}28202821/**2822* rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization2823* @size: size of pointer2824*2825* Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure2826*/2827struct rtw_cbuf *rtw_cbuf_alloc(u32 size)2828{2829struct rtw_cbuf *cbuf;28302831cbuf = (struct rtw_cbuf *)rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);28322833if (cbuf) {2834cbuf->write = cbuf->read = 0;2835cbuf->size = size;2836}28372838return cbuf;2839}28402841/**2842* rtw_cbuf_free - free the given rtw_cbuf2843* @cbuf: pointer of struct rtw_cbuf to free2844*/2845void rtw_cbuf_free(struct rtw_cbuf *cbuf)2846{2847rtw_mfree((u8 *)cbuf, sizeof(*cbuf) + sizeof(void *) * cbuf->size);2848}28492850/**2851* map_readN - read a range of map data2852* @map: map to read2853* @offset: start address to read2854* @len: length to read2855* @buf: pointer of buffer to store data read2856*2857* Returns: _SUCCESS or _FAIL2858*/2859int map_readN(const struct map_t *map, u16 offset, u16 len, u8 *buf)2860{2861const struct map_seg_t *seg;2862int ret = _FAIL;2863int i;28642865if (len == 0) {2866rtw_warn_on(1);2867goto exit;2868}28692870if (offset + len > map->len) {2871rtw_warn_on(1);2872goto exit;2873}28742875_rtw_memset(buf, map->init_value, len);28762877for (i = 0; i < map->seg_num; i++) {2878u8 *c_dst, *c_src;2879u16 c_len;28802881seg = map->segs + i;2882if (seg->sa + seg->len <= offset || seg->sa >= offset + len)2883continue;28842885if (seg->sa >= offset) {2886c_dst = buf + (seg->sa - offset);2887c_src = seg->c;2888if (seg->sa + seg->len <= offset + len)2889c_len = seg->len;2890else2891c_len = offset + len - seg->sa;2892} else {2893c_dst = buf;2894c_src = seg->c + (offset - seg->sa);2895if (seg->sa + seg->len >= offset + len)2896c_len = len;2897else2898c_len = seg->sa + seg->len - offset;2899}29002901_rtw_memcpy(c_dst, c_src, c_len);2902}29032904exit:2905return ret;2906}29072908/**2909* map_read8 - read 1 byte of map data2910* @map: map to read2911* @offset: address to read2912*2913* Returns: value of data of specified offset. map.init_value if offset is out of range2914*/2915u8 map_read8(const struct map_t *map, u16 offset)2916{2917const struct map_seg_t *seg;2918u8 val = map->init_value;2919int i;29202921if (offset + 1 > map->len) {2922rtw_warn_on(1);2923goto exit;2924}29252926for (i = 0; i < map->seg_num; i++) {2927seg = map->segs + i;2928if (seg->sa + seg->len <= offset || seg->sa >= offset + 1)2929continue;29302931val = *(seg->c + offset - seg->sa);2932break;2933}29342935exit:2936return val;2937}29382939int rtw_blacklist_add(_queue *blist, const u8 *addr, u32 timeout_ms)2940{2941struct blacklist_ent *ent;2942_list *list, *head;2943u8 exist = _FALSE, timeout = _FALSE;29442945enter_critical_bh(&blist->lock);29462947head = &blist->queue;2948list = get_next(head);2949while (rtw_end_of_queue_search(head, list) == _FALSE) {2950ent = LIST_CONTAINOR(list, struct blacklist_ent, list);2951list = get_next(list);29522953if (_rtw_memcmp(ent->addr, addr, ETH_ALEN) == _TRUE) {2954exist = _TRUE;2955if (rtw_time_after(rtw_get_current_time(), ent->exp_time))2956timeout = _TRUE;2957ent->exp_time = rtw_get_current_time()2958+ rtw_ms_to_systime(timeout_ms);2959break;2960}29612962if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) {2963rtw_list_delete(&ent->list);2964rtw_mfree(ent, sizeof(struct blacklist_ent));2965}2966}29672968if (exist == _FALSE) {2969ent = rtw_malloc(sizeof(struct blacklist_ent));2970if (ent) {2971_rtw_memcpy(ent->addr, addr, ETH_ALEN);2972ent->exp_time = rtw_get_current_time()2973+ rtw_ms_to_systime(timeout_ms);2974rtw_list_insert_tail(&ent->list, head);2975}2976}29772978exit_critical_bh(&blist->lock);29792980return (exist == _TRUE && timeout == _FALSE) ? RTW_ALREADY : (ent ? _SUCCESS : _FAIL);2981}29822983int rtw_blacklist_del(_queue *blist, const u8 *addr)2984{2985struct blacklist_ent *ent = NULL;2986_list *list, *head;2987u8 exist = _FALSE;29882989enter_critical_bh(&blist->lock);2990head = &blist->queue;2991list = get_next(head);2992while (rtw_end_of_queue_search(head, list) == _FALSE) {2993ent = LIST_CONTAINOR(list, struct blacklist_ent, list);2994list = get_next(list);29952996if (_rtw_memcmp(ent->addr, addr, ETH_ALEN) == _TRUE) {2997rtw_list_delete(&ent->list);2998rtw_mfree(ent, sizeof(struct blacklist_ent));2999exist = _TRUE;3000break;3001}30023003if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) {3004rtw_list_delete(&ent->list);3005rtw_mfree(ent, sizeof(struct blacklist_ent));3006}3007}30083009exit_critical_bh(&blist->lock);30103011return exist == _TRUE ? _SUCCESS : RTW_ALREADY;3012}30133014int rtw_blacklist_search(_queue *blist, const u8 *addr)3015{3016struct blacklist_ent *ent = NULL;3017_list *list, *head;3018u8 exist = _FALSE;30193020enter_critical_bh(&blist->lock);3021head = &blist->queue;3022list = get_next(head);3023while (rtw_end_of_queue_search(head, list) == _FALSE) {3024ent = LIST_CONTAINOR(list, struct blacklist_ent, list);3025list = get_next(list);30263027if (_rtw_memcmp(ent->addr, addr, ETH_ALEN) == _TRUE) {3028if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) {3029rtw_list_delete(&ent->list);3030rtw_mfree(ent, sizeof(struct blacklist_ent));3031} else3032exist = _TRUE;3033break;3034}30353036if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) {3037rtw_list_delete(&ent->list);3038rtw_mfree(ent, sizeof(struct blacklist_ent));3039}3040}30413042exit_critical_bh(&blist->lock);30433044return exist;3045}30463047void rtw_blacklist_flush(_queue *blist)3048{3049struct blacklist_ent *ent;3050_list *list, *head;3051_list tmp;30523053_rtw_init_listhead(&tmp);30543055enter_critical_bh(&blist->lock);3056rtw_list_splice_init(&blist->queue, &tmp);3057exit_critical_bh(&blist->lock);30583059head = &tmp;3060list = get_next(head);3061while (rtw_end_of_queue_search(head, list) == _FALSE) {3062ent = LIST_CONTAINOR(list, struct blacklist_ent, list);3063list = get_next(list);3064rtw_list_delete(&ent->list);3065rtw_mfree(ent, sizeof(struct blacklist_ent));3066}3067}30683069void dump_blacklist(void *sel, _queue *blist, const char *title)3070{3071struct blacklist_ent *ent = NULL;3072_list *list, *head;30733074enter_critical_bh(&blist->lock);3075head = &blist->queue;3076list = get_next(head);30773078if (rtw_end_of_queue_search(head, list) == _FALSE) {3079if (title)3080RTW_PRINT_SEL(sel, "%s:\n", title);30813082while (rtw_end_of_queue_search(head, list) == _FALSE) {3083ent = LIST_CONTAINOR(list, struct blacklist_ent, list);3084list = get_next(list);30853086if (rtw_time_after(rtw_get_current_time(), ent->exp_time))3087RTW_PRINT_SEL(sel, MAC_FMT" expired\n", MAC_ARG(ent->addr));3088else3089RTW_PRINT_SEL(sel, MAC_FMT" %u\n", MAC_ARG(ent->addr)3090, rtw_get_remaining_time_ms(ent->exp_time));3091}30923093}3094exit_critical_bh(&blist->lock);3095}30963097/**3098* is_null -3099*3100* Return TRUE if c is null character3101* FALSE otherwise.3102*/3103inline BOOLEAN is_null(char c)3104{3105if (c == '\0')3106return _TRUE;3107else3108return _FALSE;3109}31103111inline BOOLEAN is_all_null(char *c, int len)3112{3113for (; len > 0; len--)3114if (c[len - 1] != '\0')3115return _FALSE;31163117return _TRUE;3118}31193120/**3121* is_eol -3122*3123* Return TRUE if c is represent for EOL (end of line)3124* FALSE otherwise.3125*/3126inline BOOLEAN is_eol(char c)3127{3128if (c == '\r' || c == '\n')3129return _TRUE;3130else3131return _FALSE;3132}31333134/**3135* is_space -3136*3137* Return TRUE if c is represent for space3138* FALSE otherwise.3139*/3140inline BOOLEAN is_space(char c)3141{3142if (c == ' ' || c == '\t')3143return _TRUE;3144else3145return _FALSE;3146}31473148/**3149* IsHexDigit -3150*3151* Return TRUE if chTmp is represent for hex digit3152* FALSE otherwise.3153*/3154inline BOOLEAN IsHexDigit(char chTmp)3155{3156if ((chTmp >= '0' && chTmp <= '9') ||3157(chTmp >= 'a' && chTmp <= 'f') ||3158(chTmp >= 'A' && chTmp <= 'F'))3159return _TRUE;3160else3161return _FALSE;3162}31633164/**3165* is_alpha -3166*3167* Return TRUE if chTmp is represent for alphabet3168* FALSE otherwise.3169*/3170inline BOOLEAN is_alpha(char chTmp)3171{3172if ((chTmp >= 'a' && chTmp <= 'z') ||3173(chTmp >= 'A' && chTmp <= 'Z'))3174return _TRUE;3175else3176return _FALSE;3177}31783179inline char alpha_to_upper(char c)3180{3181if ((c >= 'a' && c <= 'z'))3182c = 'A' + (c - 'a');3183return c;3184}31853186int hex2num_i(char c)3187{3188if (c >= '0' && c <= '9')3189return c - '0';3190if (c >= 'a' && c <= 'f')3191return c - 'a' + 10;3192if (c >= 'A' && c <= 'F')3193return c - 'A' + 10;3194return -1;3195}31963197int hex2byte_i(const char *hex)3198{3199int a, b;3200a = hex2num_i(*hex++);3201if (a < 0)3202return -1;3203b = hex2num_i(*hex++);3204if (b < 0)3205return -1;3206return (a << 4) | b;3207}32083209int hexstr2bin(const char *hex, u8 *buf, size_t len)3210{3211size_t i;3212int a;3213const char *ipos = hex;3214u8 *opos = buf;32153216for (i = 0; i < len; i++) {3217a = hex2byte_i(ipos);3218if (a < 0)3219return -1;3220*opos++ = a;3221ipos += 2;3222}3223return 0;3224}3225322632273228