linux-stable/drivers/staging/rt2860/rt_linux.c
Tejun Heo 5a0e3ad6af include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files.  percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.

percpu.h -> slab.h dependency is about to be removed.  Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability.  As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.

  http://userweb.kernel.org/~tj/misc/slabh-sweep.py

The script does the followings.

* Scan files for gfp and slab usages and update includes such that
  only the necessary includes are there.  ie. if only gfp is used,
  gfp.h, if slab is used, slab.h.

* When the script inserts a new include, it looks at the include
  blocks and try to put the new include such that its order conforms
  to its surrounding.  It's put in the include block which contains
  core kernel includes, in the same order that the rest are ordered -
  alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
  doesn't seem to be any matching order.

* If the script can't find a place to put a new include (mostly
  because the file doesn't have fitting include block), it prints out
  an error message indicating which .h file needs to be added to the
  file.

The conversion was done in the following steps.

1. The initial automatic conversion of all .c files updated slightly
   over 4000 files, deleting around 700 includes and adding ~480 gfp.h
   and ~3000 slab.h inclusions.  The script emitted errors for ~400
   files.

2. Each error was manually checked.  Some didn't need the inclusion,
   some needed manual addition while adding it to implementation .h or
   embedding .c file was more appropriate for others.  This step added
   inclusions to around 150 files.

3. The script was run again and the output was compared to the edits
   from #2 to make sure no file was left behind.

4. Several build tests were done and a couple of problems were fixed.
   e.g. lib/decompress_*.c used malloc/free() wrappers around slab
   APIs requiring slab.h to be added manually.

5. The script was run on all .h files but without automatically
   editing them as sprinkling gfp.h and slab.h inclusions around .h
   files could easily lead to inclusion dependency hell.  Most gfp.h
   inclusion directives were ignored as stuff from gfp.h was usually
   wildly available and often used in preprocessor macros.  Each
   slab.h inclusion directive was examined and added manually as
   necessary.

6. percpu.h was updated not to include slab.h.

7. Build test were done on the following configurations and failures
   were fixed.  CONFIG_GCOV_KERNEL was turned off for all tests (as my
   distributed build env didn't work with gcov compiles) and a few
   more options had to be turned off depending on archs to make things
   build (like ipr on powerpc/64 which failed due to missing writeq).

   * x86 and x86_64 UP and SMP allmodconfig and a custom test config.
   * powerpc and powerpc64 SMP allmodconfig
   * sparc and sparc64 SMP allmodconfig
   * ia64 SMP allmodconfig
   * s390 SMP allmodconfig
   * alpha SMP allmodconfig
   * um on x86_64 SMP allmodconfig

8. percpu.h modifications were reverted so that it could be applied as
   a separate patch and serve as bisection point.

Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.

Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-30 22:02:32 +09:00

1373 lines
36 KiB
C

/*
*************************************************************************
* Ralink Tech Inc.
* 5F., No.36, Taiyuan St., Jhubei City,
* Hsinchu County 302,
* Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
*************************************************************************
*/
#include <linux/firmware.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include "rt_config.h"
unsigned long RTDebugLevel = RT_DEBUG_ERROR;
/* for wireless system event message */
char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
/* system status event */
"had associated successfully", /* IW_ASSOC_EVENT_FLAG */
"had disassociated", /* IW_DISASSOC_EVENT_FLAG */
"had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */
"had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */
"occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */
"occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
"occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */
"occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */
"occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */
"occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */
"Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
"Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
"RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
"set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
"set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
"connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */
"disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
"scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */
"scan terminate! Busy! Enqueue fail!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
};
/* for wireless IDS_spoof_attack event message */
char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
"detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */
"detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
"detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
"detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
"detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */
"detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */
"detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */
"detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */
"detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
"detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */
};
/* for wireless IDS_flooding_attack event message */
char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
"detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */
"detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
"detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
"detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
"detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */
"detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */
"detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
};
/* timeout -- ms */
void RTMP_SetPeriodicTimer(struct timer_list * pTimer,
IN unsigned long timeout)
{
timeout = ((timeout * OS_HZ) / 1000);
pTimer->expires = jiffies + timeout;
add_timer(pTimer);
}
/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd,
struct timer_list * pTimer,
IN TIMER_FUNCTION function, void *data)
{
init_timer(pTimer);
pTimer->data = (unsigned long)data;
pTimer->function = function;
}
void RTMP_OS_Add_Timer(struct timer_list * pTimer,
IN unsigned long timeout)
{
if (timer_pending(pTimer))
return;
timeout = ((timeout * OS_HZ) / 1000);
pTimer->expires = jiffies + timeout;
add_timer(pTimer);
}
void RTMP_OS_Mod_Timer(struct timer_list * pTimer,
IN unsigned long timeout)
{
timeout = ((timeout * OS_HZ) / 1000);
mod_timer(pTimer, jiffies + timeout);
}
void RTMP_OS_Del_Timer(struct timer_list * pTimer,
OUT BOOLEAN * pCancelled)
{
if (timer_pending(pTimer)) {
*pCancelled = del_timer_sync(pTimer);
} else {
*pCancelled = TRUE;
}
}
void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry)
{
/*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */
}
/* Unify all delay routine by using udelay */
void RTMPusecDelay(unsigned long usec)
{
unsigned long i;
for (i = 0; i < (usec / 50); i++)
udelay(50);
if (usec % 50)
udelay(usec % 50);
}
void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time)
{
time->u.LowPart = jiffies;
}
/* pAd MUST allow to be NULL */
int os_alloc_mem(struct rt_rtmp_adapter *pAd, u8 ** mem, unsigned long size)
{
*mem = (u8 *)kmalloc(size, GFP_ATOMIC);
if (*mem)
return (NDIS_STATUS_SUCCESS);
else
return (NDIS_STATUS_FAILURE);
}
/* pAd MUST allow to be NULL */
int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem)
{
ASSERT(mem);
kfree(mem);
return (NDIS_STATUS_SUCCESS);
}
void *RtmpOSNetPktAlloc(struct rt_rtmp_adapter *pAd, IN int size)
{
struct sk_buff *skb;
/* Add 2 more bytes for ip header alignment */
skb = dev_alloc_skb(size + 2);
return ((void *)skb);
}
void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd,
unsigned long Length)
{
struct sk_buff *pkt;
pkt = dev_alloc_skb(Length);
if (pkt == NULL) {
DBGPRINT(RT_DEBUG_ERROR,
("can't allocate frag rx %ld size packet\n", Length));
}
if (pkt) {
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
}
return (void *)pkt;
}
void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd,
unsigned long Length,
IN BOOLEAN Cached,
void ** VirtualAddress)
{
struct sk_buff *pkt;
pkt = dev_alloc_skb(Length);
if (pkt == NULL) {
DBGPRINT(RT_DEBUG_ERROR,
("can't allocate tx %ld size packet\n", Length));
}
if (pkt) {
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
*VirtualAddress = (void *)pkt->data;
} else {
*VirtualAddress = (void *)NULL;
}
return (void *)pkt;
}
void build_tx_packet(struct rt_rtmp_adapter *pAd,
void *pPacket,
u8 *pFrame, unsigned long FrameLen)
{
struct sk_buff *pTxPkt;
ASSERT(pPacket);
pTxPkt = RTPKT_TO_OSPKT(pPacket);
NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
}
void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
{
struct os_cookie *os_cookie;
int index;
os_cookie = (struct os_cookie *)pAd->OS_Cookie;
if (pAd->BeaconBuf)
kfree(pAd->BeaconBuf);
NdisFreeSpinLock(&pAd->MgmtRingLock);
#ifdef RTMP_MAC_PCI
NdisFreeSpinLock(&pAd->RxRingLock);
#ifdef RT3090
NdisFreeSpinLock(&pAd->McuCmdLock);
#endif /* RT3090 // */
#endif /* RTMP_MAC_PCI // */
for (index = 0; index < NUM_OF_TX_RING; index++) {
NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
NdisFreeSpinLock(&pAd->DeQueueLock[index]);
pAd->DeQueueRunning[index] = FALSE;
}
NdisFreeSpinLock(&pAd->irq_lock);
release_firmware(pAd->firmware);
vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
if (os_cookie)
kfree(os_cookie);
}
BOOLEAN OS_Need_Clone_Packet(void)
{
return (FALSE);
}
/*
========================================================================
Routine Description:
clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
must have only one NDIS BUFFER
return - byte copied. 0 means can't create NDIS PACKET
NOTE: internally created char should be destroyed by RTMPFreeNdisPacket
Arguments:
pAd Pointer to our adapter
pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
*pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
Note:
========================================================================
*/
int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd,
IN BOOLEAN pInsAMSDUHdr,
void *pInPacket,
void ** ppOutPacket)
{
struct sk_buff *pkt;
ASSERT(pInPacket);
ASSERT(ppOutPacket);
/* 1. Allocate a packet */
pkt = dev_alloc_skb(2048);
if (pkt == NULL) {
return NDIS_STATUS_FAILURE;
}
skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket),
GET_OS_PKT_LEN(pInPacket));
*ppOutPacket = OSPKT_TO_RTPKT(pkt);
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
printk("###Clone###\n");
return NDIS_STATUS_SUCCESS;
}
/* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */
int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd,
void ** ppPacket,
u8 *pHeader,
u32 HeaderLen,
u8 *pData, u32 DataLen)
{
void *pPacket;
ASSERT(pData);
ASSERT(DataLen);
/* 1. Allocate a packet */
pPacket =
(void **) dev_alloc_skb(HeaderLen + DataLen +
RTMP_PKT_TAIL_PADDING);
if (pPacket == NULL) {
*ppPacket = NULL;
#ifdef DEBUG
printk("RTMPAllocateNdisPacket Fail\n");
#endif
return NDIS_STATUS_FAILURE;
}
/* 2. clone the frame content */
if (HeaderLen > 0)
NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
if (DataLen > 0)
NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData,
DataLen);
/* 3. update length of packet */
skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen + DataLen);
RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
/* printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket)); */
*ppPacket = pPacket;
return NDIS_STATUS_SUCCESS;
}
/*
========================================================================
Description:
This routine frees a miniport internally allocated char and its
corresponding NDIS_BUFFER and allocated memory.
========================================================================
*/
void RTMPFreeNdisPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
{
dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
}
/* IRQL = DISPATCH_LEVEL */
/* NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same */
/* scatter gather buffer */
int Sniff2BytesFromNdisBuffer(char *pFirstBuffer,
u8 DesiredOffset,
u8 *pByte0, u8 *pByte1)
{
*pByte0 = *(u8 *)(pFirstBuffer + DesiredOffset);
*pByte1 = *(u8 *)(pFirstBuffer + DesiredOffset + 1);
return NDIS_STATUS_SUCCESS;
}
void RTMP_QueryPacketInfo(void *pPacket,
struct rt_packet_info *pPacketInfo,
u8 ** pSrcBufVA, u32 * pSrcBufLen)
{
pPacketInfo->BufferCount = 1;
pPacketInfo->pFirstBuffer = (char *)GET_OS_PKT_DATAPTR(pPacket);
pPacketInfo->PhysicalBufferCount = 1;
pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
}
void RTMP_QueryNextPacketInfo(void ** ppPacket,
struct rt_packet_info *pPacketInfo,
u8 ** pSrcBufVA, u32 * pSrcBufLen)
{
void *pPacket = NULL;
if (*ppPacket)
pPacket = GET_OS_PKT_NEXT(*ppPacket);
if (pPacket) {
pPacketInfo->BufferCount = 1;
pPacketInfo->pFirstBuffer =
(char *)GET_OS_PKT_DATAPTR(pPacket);
pPacketInfo->PhysicalBufferCount = 1;
pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
*ppPacket = GET_OS_PKT_NEXT(pPacket);
} else {
pPacketInfo->BufferCount = 0;
pPacketInfo->pFirstBuffer = NULL;
pPacketInfo->PhysicalBufferCount = 0;
pPacketInfo->TotalPacketLength = 0;
*pSrcBufVA = NULL;
*pSrcBufLen = 0;
*ppPacket = NULL;
}
}
void *DuplicatePacket(struct rt_rtmp_adapter *pAd,
void *pPacket, u8 FromWhichBSSID)
{
struct sk_buff *skb;
void *pRetPacket = NULL;
u16 DataSize;
u8 *pData;
DataSize = (u16)GET_OS_PKT_LEN(pPacket);
pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
if (skb) {
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pRetPacket = OSPKT_TO_RTPKT(skb);
}
return pRetPacket;
}
void *duplicate_pkt(struct rt_rtmp_adapter *pAd,
u8 *pHeader802_3,
u32 HdrLen,
u8 *pData,
unsigned long DataSize, u8 FromWhichBSSID)
{
struct sk_buff *skb;
void *pPacket = NULL;
if ((skb =
__dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) {
skb_reserve(skb, 2);
NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
skb_put(skb, HdrLen);
NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
skb_put(skb, DataSize);
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pPacket = OSPKT_TO_RTPKT(skb);
}
return pPacket;
}
#define TKIP_TX_MIC_SIZE 8
void *duplicate_pkt_with_TKIP_MIC(struct rt_rtmp_adapter *pAd,
void *pPacket)
{
struct sk_buff *skb, *newskb;
skb = RTPKT_TO_OSPKT(pPacket);
if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) {
/* alloc a new skb and copy the packet */
newskb =
skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE,
GFP_ATOMIC);
dev_kfree_skb_any(skb);
if (newskb == NULL) {
DBGPRINT(RT_DEBUG_ERROR,
("Extend Tx.MIC for packet failed!, dropping packet!\n"));
return NULL;
}
skb = newskb;
}
return OSPKT_TO_RTPKT(skb);
}
void *ClonePacket(struct rt_rtmp_adapter *pAd,
void *pPacket,
u8 *pData, unsigned long DataSize)
{
struct sk_buff *pRxPkt;
struct sk_buff *pClonedPkt;
ASSERT(pPacket);
pRxPkt = RTPKT_TO_OSPKT(pPacket);
/* clone the packet */
pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
if (pClonedPkt) {
/* set the correct dataptr and data len */
pClonedPkt->dev = pRxPkt->dev;
pClonedPkt->data = pData;
pClonedPkt->len = DataSize;
skb_set_tail_pointer(pClonedPkt, DataSize)
ASSERT(DataSize < 1530);
}
return pClonedPkt;
}
/* */
/* change OS packet DataPtr and DataLen */
/* */
void update_os_packet_info(struct rt_rtmp_adapter *pAd,
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
{
struct sk_buff *pOSPkt;
ASSERT(pRxBlk->pRxPacket);
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pOSPkt->data = pRxBlk->pData;
pOSPkt->len = pRxBlk->DataSize;
skb_set_tail_pointer(pOSPkt, pOSPkt->len);
}
void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
struct rt_rx_blk *pRxBlk,
u8 *pHeader802_3,
u8 FromWhichBSSID)
{
struct sk_buff *pOSPkt;
ASSERT(pRxBlk->pRxPacket);
ASSERT(pHeader802_3);
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pOSPkt->data = pRxBlk->pData;
pOSPkt->len = pRxBlk->DataSize;
skb_set_tail_pointer(pOSPkt, pOSPkt->len);
/* */
/* copy 802.3 header */
/* */
/* */
NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3,
LENGTH_802_3);
}
void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *pPacket)
{
struct sk_buff *pRxPkt;
ASSERT(pPacket);
pRxPkt = RTPKT_TO_OSPKT(pPacket);
/* Push up the protocol stack */
pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
netif_rx(pRxPkt);
}
struct rt_rtmp_sg_list *
rt_get_sg_list_from_packet(void *pPacket, struct rt_rtmp_sg_list *sg)
{
sg->NumberOfElements = 1;
sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
return (sg);
}
void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
{
unsigned char *pt;
int x;
if (RTDebugLevel < RT_DEBUG_TRACE)
return;
pt = pSrcBufVA;
printk("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen);
for (x = 0; x < SrcBufLen; x++) {
if (x % 16 == 0)
printk("0x%04x : ", x);
printk("%02x ", ((unsigned char)pt[x]));
if (x % 16 == 15)
printk("\n");
}
printk("\n");
}
/*
========================================================================
Routine Description:
Send log message through wireless event
Support standard iw_event with IWEVCUSTOM. It is used below.
iwreq_data.data.flags is used to store event_flag that is defined by user.
iwreq_data.data.length is the length of the event log.
The format of the event log is composed of the entry's MAC address and
the desired log message (refer to pWirelessEventText).
ex: 11:22:33:44:55:66 has associated successfully
p.s. The requirement of Wireless Extension is v15 or newer.
========================================================================
*/
void RTMPSendWirelessEvent(struct rt_rtmp_adapter *pAd,
u16 Event_flag,
u8 *pAddr, u8 BssIdx, char Rssi)
{
/*union iwreq_data wrqu; */
char *pBuf = NULL, *pBufPtr = NULL;
u16 event, type, BufLen;
u8 event_table_len = 0;
type = Event_flag & 0xFF00;
event = Event_flag & 0x00FF;
switch (type) {
case IW_SYS_EVENT_FLAG_START:
event_table_len = IW_SYS_EVENT_TYPE_NUM;
break;
case IW_SPOOF_EVENT_FLAG_START:
event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
break;
case IW_FLOOD_EVENT_FLAG_START:
event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
break;
}
if (event_table_len == 0) {
DBGPRINT(RT_DEBUG_ERROR,
("%s : The type(%0x02x) is not valid.\n", __func__,
type));
return;
}
if (event >= event_table_len) {
DBGPRINT(RT_DEBUG_ERROR,
("%s : The event(%0x02x) is not valid.\n", __func__,
event));
return;
}
/*Allocate memory and copy the msg. */
if ((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) {
/*Prepare the payload */
memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
pBufPtr = pBuf;
if (pAddr)
pBufPtr +=
sprintf(pBufPtr,
"(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ",
PRINT_MAC(pAddr));
else if (BssIdx < MAX_MBSSID_NUM)
pBufPtr +=
sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
else
pBufPtr += sprintf(pBufPtr, "(RT2860) ");
if (type == IW_SYS_EVENT_FLAG_START)
pBufPtr +=
sprintf(pBufPtr, "%s",
pWirelessSysEventText[event]);
else if (type == IW_SPOOF_EVENT_FLAG_START)
pBufPtr +=
sprintf(pBufPtr, "%s (RSSI=%d)",
pWirelessSpoofEventText[event], Rssi);
else if (type == IW_FLOOD_EVENT_FLAG_START)
pBufPtr +=
sprintf(pBufPtr, "%s",
pWirelessFloodEventText[event]);
else
pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
pBufPtr[pBufPtr - pBuf] = '\0';
BufLen = pBufPtr - pBuf;
RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
(u8 *)pBuf, BufLen);
/*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */
kfree(pBuf);
} else
DBGPRINT(RT_DEBUG_ERROR,
("%s : Can't allocate memory for wireless event.\n",
__func__));
}
void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
{
struct sk_buff *pOSPkt;
struct rt_wlan_ng_prism2_header *ph;
int rate_index = 0;
u16 header_len = 0;
u8 temp_header[40] = { 0 };
u_int32_t ralinkrate[256] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 109, 110, 111, 112, 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, 27, 54, 81, 108, 162, 216, 243, 270, /* Last 38 */
54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115,
130, 144, 29, 59, 87, 115, 173, 230, 260, 288, 30, 60, 90,
120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540,
600, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80
};
ASSERT(pRxBlk->pRxPacket);
if (pRxBlk->DataSize < 10) {
DBGPRINT(RT_DEBUG_ERROR,
("%s : Size is too small! (%d)\n", __func__,
pRxBlk->DataSize));
goto err_free_sk_buff;
}
if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
RX_BUFFER_AGGRESIZE) {
DBGPRINT(RT_DEBUG_ERROR,
("%s : Size is too large! (%zu)\n", __func__,
pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header)));
goto err_free_sk_buff;
}
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) {
pRxBlk->DataSize -= LENGTH_802_11;
if ((pRxBlk->pHeader->FC.ToDs == 1) &&
(pRxBlk->pHeader->FC.FrDs == 1))
header_len = LENGTH_802_11_WITH_ADDR4;
else
header_len = LENGTH_802_11;
/* QOS */
if (pRxBlk->pHeader->FC.SubType & 0x08) {
header_len += 2;
/* Data skip QOS contorl field */
pRxBlk->DataSize -= 2;
}
/* Order bit: A-Ralink or HTC+ */
if (pRxBlk->pHeader->FC.Order) {
header_len += 4;
/* Data skip HTC contorl field */
pRxBlk->DataSize -= 4;
}
/* Copy Header */
if (header_len <= 40)
NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
/* skip HW padding */
if (pRxBlk->RxD.L2PAD)
pRxBlk->pData += (header_len + 2);
else
pRxBlk->pData += header_len;
} /*end if */
if (pRxBlk->DataSize < pOSPkt->len) {
skb_trim(pOSPkt, pRxBlk->DataSize);
} else {
skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len));
} /*end if */
if ((pRxBlk->pData - pOSPkt->data) > 0) {
skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
} /*end if */
if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
if (pskb_expand_head
(pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
GFP_ATOMIC)) {
DBGPRINT(RT_DEBUG_ERROR,
("%s : Reallocate header size of sk_buff fail!\n",
__func__));
goto err_free_sk_buff;
} /*end if */
} /*end if */
if (header_len > 0)
NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
header_len);
ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
sizeof(struct rt_wlan_ng_prism2_header));
NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
ph->msgcode = DIDmsg_lnxind_wlansniffrm;
ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
strcpy((char *)ph->devname, (char *)pAd->net_dev->name);
ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
ph->hosttime.status = 0;
ph->hosttime.len = 4;
ph->hosttime.data = jiffies;
ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
ph->mactime.status = 0;
ph->mactime.len = 0;
ph->mactime.data = 0;
ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
ph->istx.status = 0;
ph->istx.len = 0;
ph->istx.data = 0;
ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
ph->channel.status = 0;
ph->channel.len = 4;
ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel;
ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
ph->rssi.status = 0;
ph->rssi.len = 4;
ph->rssi.data =
(u_int32_t) RTMPMaxRssi(pAd,
ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0,
RSSI_0), ConvertToRssi(pAd,
pRxBlk->
pRxWI->
RSSI1,
RSSI_1),
ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2,
RSSI_2));;
ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
ph->signal.status = 0;
ph->signal.len = 4;
ph->signal.data = 0; /*rssi + noise; */
ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
ph->noise.status = 0;
ph->noise.len = 4;
ph->noise.data = 0;
if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) {
rate_index =
16 + ((u8)pRxBlk->pRxWI->BW * 16) +
((u8)pRxBlk->pRxWI->ShortGI * 32) +
((u8)pRxBlk->pRxWI->MCS);
} else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
else
rate_index = (u8)(pRxBlk->pRxWI->MCS);
if (rate_index < 0)
rate_index = 0;
if (rate_index > 255)
rate_index = 255;
ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
ph->rate.status = 0;
ph->rate.len = 4;
ph->rate.data = ralinkrate[rate_index];
ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
ph->frmlen.status = 0;
ph->frmlen.len = 4;
ph->frmlen.data = (u_int32_t) pRxBlk->DataSize;
pOSPkt->pkt_type = PACKET_OTHERHOST;
pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
pOSPkt->ip_summed = CHECKSUM_NONE;
netif_rx(pOSPkt);
return;
err_free_sk_buff:
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
return;
}
/*******************************************************************************
Device IRQ related functions.
*******************************************************************************/
int RtmpOSIRQRequest(struct net_device *pNetDev)
{
#ifdef RTMP_PCI_SUPPORT
struct net_device *net_dev = pNetDev;
struct rt_rtmp_adapter *pAd = NULL;
int retval = 0;
GET_PAD_FROM_NET_DEV(pAd, pNetDev);
ASSERT(pAd);
if (pAd->infType == RTMP_DEV_INF_PCI) {
struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie);
RTMP_MSI_ENABLE(pAd);
retval =
request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ,
(net_dev)->name, (net_dev));
if (retval != 0)
printk("RT2860: request_irq ERROR(%d)\n", retval);
}
return retval;
#else
return 0;
#endif
}
int RtmpOSIRQRelease(struct net_device *pNetDev)
{
struct net_device *net_dev = pNetDev;
struct rt_rtmp_adapter *pAd = NULL;
GET_PAD_FROM_NET_DEV(pAd, net_dev);
ASSERT(pAd);
#ifdef RTMP_PCI_SUPPORT
if (pAd->infType == RTMP_DEV_INF_PCI) {
struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie);
synchronize_irq(pObj->pci_dev->irq);
free_irq(pObj->pci_dev->irq, (net_dev));
RTMP_MSI_DISABLE(pAd);
}
#endif /* RTMP_PCI_SUPPORT // */
return 0;
}
/*******************************************************************************
File open/close related functions.
*******************************************************************************/
struct file *RtmpOSFileOpen(char *pPath, int flag, int mode)
{
struct file *filePtr;
filePtr = filp_open(pPath, flag, 0);
if (IS_ERR(filePtr)) {
DBGPRINT(RT_DEBUG_ERROR,
("%s(): Error %ld opening %s\n", __func__,
-PTR_ERR(filePtr), pPath));
}
return (struct file *)filePtr;
}
int RtmpOSFileClose(struct file *osfd)
{
filp_close(osfd, NULL);
return 0;
}
void RtmpOSFileSeek(struct file *osfd, int offset)
{
osfd->f_pos = offset;
}
int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
{
/* The object must have a read method */
if (osfd->f_op && osfd->f_op->read) {
return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
} else {
DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
return -1;
}
}
int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
{
return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen,
&osfd->f_pos);
}
/*******************************************************************************
Task create/management/kill related functions.
*******************************************************************************/
int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
{
struct rt_rtmp_adapter *pAd;
int ret = NDIS_STATUS_FAILURE;
pAd = (struct rt_rtmp_adapter *)pTask->priv;
#ifdef KTHREAD_SUPPORT
if (pTask->kthread_task) {
kthread_stop(pTask->kthread_task);
ret = NDIS_STATUS_SUCCESS;
}
#else
CHECK_PID_LEGALITY(pTask->taskPID) {
printk("Terminate the task(%s) with pid(%d)!\n",
pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
mb();
pTask->task_killed = 1;
mb();
ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
if (ret) {
printk(KERN_WARNING
"kill task(%s) with pid(%d) failed(retVal=%d)!\n",
pTask->taskName, GET_PID_NUMBER(pTask->taskPID),
ret);
} else {
wait_for_completion(&pTask->taskComplete);
pTask->taskPID = THREAD_PID_INIT_VALUE;
pTask->task_killed = 0;
ret = NDIS_STATUS_SUCCESS;
}
}
#endif
return ret;
}
int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask)
{
#ifndef KTHREAD_SUPPORT
complete_and_exit(&pTask->taskComplete, 0);
#endif
return 0;
}
void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
{
#ifndef KTHREAD_SUPPORT
daemonize((char *)& pTask->taskName[0] /*"%s",pAd->net_dev->name */ );
allow_signal(SIGTERM);
allow_signal(SIGKILL);
current->flags |= PF_NOFREEZE;
/* signal that we've started the thread */
complete(&pTask->taskComplete);
#endif
}
int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
IN int (*fn) (void *), IN void *arg)
{
int status = NDIS_STATUS_SUCCESS;
#ifdef KTHREAD_SUPPORT
pTask->task_killed = 0;
pTask->kthread_task = NULL;
pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
if (IS_ERR(pTask->kthread_task))
status = NDIS_STATUS_FAILURE;
#else
pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
if (pid_number < 0) {
DBGPRINT(RT_DEBUG_ERROR,
("Attach task(%s) failed!\n", pTask->taskName));
status = NDIS_STATUS_FAILURE;
} else {
pTask->taskPID = GET_PID(pid_number);
/* Wait for the thread to start */
wait_for_completion(&pTask->taskComplete);
status = NDIS_STATUS_SUCCESS;
}
#endif
return status;
}
int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
char *pTaskName, void * pPriv)
{
int len;
ASSERT(pTask);
#ifndef KTHREAD_SUPPORT
NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task));
#endif
len = strlen(pTaskName);
len =
len >
(RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len;
NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
pTask->priv = pPriv;
#ifndef KTHREAD_SUPPORT
RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
pTask->taskPID = THREAD_PID_INIT_VALUE;
init_completion(&pTask->taskComplete);
#endif
return NDIS_STATUS_SUCCESS;
}
void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd)
{
if (pAd->CommonCfg.bWirelessEvent) {
if (pAd->IndicateMediaState == NdisMediaStateConnected) {
RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
pAd->MacTab.Content[BSSID_WCID].
Addr, BSS0, 0);
} else {
RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
pAd->MacTab.Content[BSSID_WCID].
Addr, BSS0, 0);
}
}
}
int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
u32 eventType,
int flags,
u8 *pSrcMac,
u8 *pData, u32 dataLen)
{
union iwreq_data wrqu;
memset(&wrqu, 0, sizeof(wrqu));
if (flags > -1)
wrqu.data.flags = flags;
if (pSrcMac)
memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
if ((pData != NULL) && (dataLen > 0))
wrqu.data.length = dataLen;
wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
return 0;
}
int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
{
struct net_device *net_dev;
struct rt_rtmp_adapter *pAd;
net_dev = pNetDev;
GET_PAD_FROM_NET_DEV(pAd, net_dev);
/* work-around for the SuSE due to it has it's own interface name management system. */
{
NdisZeroMemory(pAd->StaCfg.dev_name, 16);
NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name,
strlen(net_dev->name));
}
NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
return 0;
}
/*
* Assign the network dev name for created Ralink WiFi interface.
*/
static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd,
struct net_device *dev,
char *pPrefixStr, int devIdx)
{
struct net_device *existNetDev;
char suffixName[IFNAMSIZ];
char desiredName[IFNAMSIZ];
int ifNameIdx, prefixLen, slotNameLen;
int Status;
prefixLen = strlen(pPrefixStr);
ASSERT((prefixLen < IFNAMSIZ));
for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) {
memset(suffixName, 0, IFNAMSIZ);
memset(desiredName, 0, IFNAMSIZ);
strncpy(&desiredName[0], pPrefixStr, prefixLen);
sprintf(suffixName, "%d", ifNameIdx);
slotNameLen = strlen(suffixName);
ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
strcat(desiredName, suffixName);
existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
if (existNetDev == NULL)
break;
else
RtmpOSNetDeviceRefPut(existNetDev);
}
if (ifNameIdx < 32) {
strcpy(&dev->name[0], &desiredName[0]);
Status = NDIS_STATUS_SUCCESS;
} else {
DBGPRINT(RT_DEBUG_ERROR,
("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n",
pPrefixStr));
Status = NDIS_STATUS_FAILURE;
}
return Status;
}
void RtmpOSNetDevClose(struct net_device *pNetDev)
{
dev_close(pNetDev);
}
void RtmpOSNetDevFree(struct net_device *pNetDev)
{
ASSERT(pNetDev);
free_netdev(pNetDev);
}
int RtmpOSNetDevAlloc(struct net_device ** new_dev_p, u32 privDataSize)
{
/* assign it as null first. */
*new_dev_p = NULL;
DBGPRINT(RT_DEBUG_TRACE,
("Allocate a net device with private data size=%d!\n",
privDataSize));
*new_dev_p = alloc_etherdev(privDataSize);
if (*new_dev_p)
return NDIS_STATUS_SUCCESS;
else
return NDIS_STATUS_FAILURE;
}
struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName)
{
struct net_device *pTargetNetDev = NULL;
pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
return pTargetNetDev;
}
void RtmpOSNetDeviceRefPut(struct net_device *pNetDev)
{
/*
every time dev_get_by_name is called, and it has returned a valid struct
net_device*, dev_put should be called afterwards, because otherwise the
machine hangs when the device is unregistered (since dev->refcnt > 1).
*/
if (pNetDev)
dev_put(pNetDev);
}
int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev)
{
/* TODO: Need to fix this */
printk("WARNING: This function(%s) not implement yet!\n", __func__);
return 0;
}
void RtmpOSNetDevDetach(struct net_device *pNetDev)
{
unregister_netdev(pNetDev);
}
int RtmpOSNetDevAttach(struct net_device *pNetDev,
struct rt_rtmp_os_netdev_op_hook *pDevOpHook)
{
int ret, rtnl_locked = FALSE;
DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
/* If we need hook some callback function to the net device structrue, now do it. */
if (pDevOpHook) {
struct rt_rtmp_adapter *pAd = NULL;
GET_PAD_FROM_NET_DEV(pAd, pNetDev);
pNetDev->netdev_ops = pDevOpHook->netdev_ops;
/* OS specific flags, here we used to indicate if we are virtual interface */
pNetDev->priv_flags = pDevOpHook->priv_flags;
if (pAd->OpMode == OPMODE_STA) {
pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
}
/* copy the net device mac address to the net_device structure. */
NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0],
MAC_ADDR_LEN);
rtnl_locked = pDevOpHook->needProtcted;
}
if (rtnl_locked)
ret = register_netdevice(pNetDev);
else
ret = register_netdev(pNetDev);
DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
if (ret == 0)
return NDIS_STATUS_SUCCESS;
else
return NDIS_STATUS_FAILURE;
}
struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd,
int devType,
int devNum,
int privMemSize, char *pNamePrefix)
{
struct net_device *pNetDev = NULL;
int status;
/* allocate a new network device */
status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */ );
if (status != NDIS_STATUS_SUCCESS) {
/* allocation fail, exit */
DBGPRINT(RT_DEBUG_ERROR,
("Allocate network device fail (%s)...\n",
pNamePrefix));
return NULL;
}
/* find a available interface name, max 32 interfaces */
status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
if (status != NDIS_STATUS_SUCCESS) {
/* error! no any available ra name can be used! */
DBGPRINT(RT_DEBUG_ERROR,
("Assign interface name (%s with suffix 0~32) failed...\n",
pNamePrefix));
RtmpOSNetDevFree(pNetDev);
return NULL;
} else {
DBGPRINT(RT_DEBUG_TRACE,
("The name of the new %s interface is %s...\n",
pNamePrefix, pNetDev->name));
}
return pNetDev;
}