1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. |
4 | * |
5 | * Contact Information: wlanfae <wlanfae@realtek.com> |
6 | */ |
7 | #include "rtl_core.h" |
8 | #include "r8192E_hw.h" |
9 | #include "r8192E_cmdpkt.h" |
10 | |
11 | bool rtl92e_send_cmd_pkt(struct net_device *dev, u32 type, const void *data, |
12 | u32 len) |
13 | { |
14 | bool rt_status = true; |
15 | struct r8192_priv *priv = rtllib_priv(dev); |
16 | u16 frag_length = 0, frag_offset = 0; |
17 | struct sk_buff *skb; |
18 | unsigned char *seg_ptr; |
19 | struct cb_desc *tcb_desc; |
20 | u8 bLastIniPkt; |
21 | |
22 | struct tx_fwinfo_8190pci *pTxFwInfo = NULL; |
23 | |
24 | do { |
25 | if ((len - frag_offset) > CMDPACKET_FRAG_SIZE) { |
26 | frag_length = CMDPACKET_FRAG_SIZE; |
27 | bLastIniPkt = 0; |
28 | |
29 | } else { |
30 | frag_length = (u16)(len - frag_offset); |
31 | bLastIniPkt = 1; |
32 | } |
33 | |
34 | if (type == DESC_PACKET_TYPE_NORMAL) |
35 | skb = dev_alloc_skb(length: frag_length + |
36 | priv->rtllib->tx_headroom + 4); |
37 | else |
38 | skb = dev_alloc_skb(length: frag_length + 4); |
39 | |
40 | if (!skb) { |
41 | rt_status = false; |
42 | goto Failed; |
43 | } |
44 | |
45 | memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); |
46 | tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); |
47 | tcb_desc->queue_index = TXCMD_QUEUE; |
48 | tcb_desc->bCmdOrInit = type; |
49 | tcb_desc->bLastIniPkt = bLastIniPkt; |
50 | |
51 | if (type == DESC_PACKET_TYPE_NORMAL) { |
52 | tcb_desc->pkt_size = frag_length; |
53 | |
54 | seg_ptr = skb_put(skb, len: priv->rtllib->tx_headroom); |
55 | pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr; |
56 | memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci)); |
57 | memset(pTxFwInfo, 0x12, 8); |
58 | } else { |
59 | tcb_desc->txbuf_size = frag_length; |
60 | } |
61 | |
62 | skb_put_data(skb, data, len: frag_length); |
63 | |
64 | if (type == DESC_PACKET_TYPE_INIT && |
65 | (!priv->rtllib->check_nic_enough_desc(dev, TXCMD_QUEUE) || |
66 | (!skb_queue_empty(list: &priv->rtllib->skb_waitq[TXCMD_QUEUE])) || |
67 | (priv->rtllib->queue_stop))) { |
68 | skb_queue_tail(list: &priv->rtllib->skb_waitq[TXCMD_QUEUE], |
69 | newsk: skb); |
70 | } else { |
71 | priv->rtllib->softmac_hard_start_xmit(skb, dev); |
72 | } |
73 | |
74 | data += frag_length; |
75 | frag_offset += frag_length; |
76 | |
77 | } while (frag_offset < len); |
78 | |
79 | rtl92e_writeb(dev, x: TP_POLL, TP_POLL_CQ); |
80 | Failed: |
81 | return rt_status; |
82 | } |
83 | |