2 * Copyright (c) 2014 Redpine Signals Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * rsi_send_data_pkt() - This function sends the recieved data packet from
22 * @common: Pointer to the driver private structure.
23 * @skb: Pointer to the socket buffer structure.
25 * Return: status: 0 on success, -1 on failure.
27 int rsi_send_data_pkt(struct rsi_common
*common
, struct sk_buff
*skb
)
29 struct rsi_hw
*adapter
= common
->priv
;
30 struct ieee80211_hdr
*tmp_hdr
= NULL
;
31 struct ieee80211_tx_info
*info
;
32 struct skb_info
*tx_params
;
33 struct ieee80211_bss_conf
*bss
= NULL
;
35 u8 ieee80211_size
= MIN_802_11_HDR_LEN
;
40 info
= IEEE80211_SKB_CB(skb
);
41 bss
= &info
->control
.vif
->bss_conf
;
42 tx_params
= (struct skb_info
*)info
->driver_data
;
47 tmp_hdr
= (struct ieee80211_hdr
*)&skb
->data
[0];
48 seq_num
= (le16_to_cpu(tmp_hdr
->seq_ctrl
) >> 4);
50 extnd_size
= ((uintptr_t)skb
->data
& 0x3);
52 if ((FRAME_DESC_SZ
+ extnd_size
) > skb_headroom(skb
)) {
53 rsi_dbg(ERR_ZONE
, "%s: Unable to send pkt\n", __func__
);
58 skb_push(skb
, (FRAME_DESC_SZ
+ extnd_size
));
59 frame_desc
= (__le16
*)&skb
->data
[0];
60 memset((u8
*)frame_desc
, 0, FRAME_DESC_SZ
);
62 if (ieee80211_is_data_qos(tmp_hdr
->frame_control
)) {
64 frame_desc
[6] |= cpu_to_le16(BIT(12));
67 if ((!(info
->flags
& IEEE80211_TX_INTFL_DONT_ENCRYPT
)) &&
68 (common
->secinfo
.security_enable
)) {
69 if (rsi_is_cipher_wep(common
))
73 frame_desc
[6] |= cpu_to_le16(BIT(15));
76 frame_desc
[0] = cpu_to_le16((skb
->len
- FRAME_DESC_SZ
) |
77 (RSI_WIFI_DATA_Q
<< 12));
78 frame_desc
[2] = cpu_to_le16((extnd_size
) | (ieee80211_size
) << 8);
80 if (common
->min_rate
!= 0xffff) {
82 frame_desc
[3] = cpu_to_le16(RATE_INFO_ENABLE
);
83 frame_desc
[4] = cpu_to_le16(common
->min_rate
);
86 frame_desc
[6] |= cpu_to_le16(seq_num
& 0xfff);
87 frame_desc
[7] = cpu_to_le16(((tx_params
->tid
& 0xf) << 4) |
88 (skb
->priority
& 0xf) |
89 (tx_params
->sta_id
<< 8));
91 status
= adapter
->host_intf_write_pkt(common
->priv
,
95 rsi_dbg(ERR_ZONE
, "%s: Failed to write pkt\n",
99 ++common
->tx_stats
.total_tx_pkt_freed
[skb
->priority
];
100 rsi_indicate_tx_status(common
->priv
, skb
, status
);
105 * rsi_send_mgmt_pkt() - This functions sends the received management packet
106 * from driver to device.
107 * @common: Pointer to the driver private structure.
108 * @skb: Pointer to the socket buffer structure.
110 * Return: status: 0 on success, -1 on failure.
112 int rsi_send_mgmt_pkt(struct rsi_common
*common
,
115 struct rsi_hw
*adapter
= common
->priv
;
116 struct ieee80211_hdr
*wh
= NULL
;
117 struct ieee80211_tx_info
*info
;
118 struct ieee80211_bss_conf
*bss
= NULL
;
119 struct skb_info
*tx_params
;
125 info
= IEEE80211_SKB_CB(skb
);
126 tx_params
= (struct skb_info
*)info
->driver_data
;
127 extnd_size
= ((uintptr_t)skb
->data
& 0x3);
129 if (tx_params
->flags
& INTERNAL_MGMT_PKT
) {
130 if ((extnd_size
) > skb_headroom(skb
)) {
131 rsi_dbg(ERR_ZONE
, "%s: Unable to send pkt\n", __func__
);
135 skb_push(skb
, extnd_size
);
136 skb
->data
[extnd_size
+ 4] = extnd_size
;
137 status
= adapter
->host_intf_write_pkt(common
->priv
,
142 "%s: Failed to write the packet\n", __func__
);
148 bss
= &info
->control
.vif
->bss_conf
;
149 wh
= (struct ieee80211_hdr
*)&skb
->data
[0];
151 if (FRAME_DESC_SZ
> skb_headroom(skb
))
154 skb_push(skb
, FRAME_DESC_SZ
);
155 memset(skb
->data
, 0, FRAME_DESC_SZ
);
156 msg
= (__le16
*)skb
->data
;
158 if (skb
->len
> MAX_MGMT_PKT_SIZE
) {
159 rsi_dbg(INFO_ZONE
, "%s: Dropping mgmt pkt > 512\n", __func__
);
163 msg
[0] = cpu_to_le16((skb
->len
- FRAME_DESC_SZ
) |
164 (RSI_WIFI_MGMT_Q
<< 12));
165 msg
[1] = cpu_to_le16(TX_DOT11_MGMT
);
166 msg
[2] = cpu_to_le16(MIN_802_11_HDR_LEN
<< 8);
167 msg
[3] = cpu_to_le16(RATE_INFO_ENABLE
);
168 msg
[6] = cpu_to_le16(le16_to_cpu(wh
->seq_ctrl
) >> 4);
170 if (wh
->addr1
[0] & BIT(0))
171 msg
[3] |= cpu_to_le16(RSI_BROADCAST_PKT
);
173 if (common
->band
== IEEE80211_BAND_2GHZ
)
174 msg
[4] = cpu_to_le16(RSI_11B_MODE
);
176 msg
[4] = cpu_to_le16((RSI_RATE_6
& 0x0f) | RSI_11G_MODE
);
178 /* Indicate to firmware to give cfm */
179 if ((skb
->data
[16] == IEEE80211_STYPE_PROBE_REQ
) && (!bss
->assoc
)) {
180 msg
[1] |= cpu_to_le16(BIT(10));
181 msg
[7] = cpu_to_le16(PROBEREQ_CONFIRM
);
182 common
->mgmt_q_block
= true;
185 msg
[7] |= cpu_to_le16(vap_id
<< 8);
187 status
= adapter
->host_intf_write_pkt(common
->priv
,
191 rsi_dbg(ERR_ZONE
, "%s: Failed to write the packet\n", __func__
);
194 rsi_indicate_tx_status(common
->priv
, skb
, status
);