0001
0002
0003
0004
0005
0006
0007
0008 #include "decl.h"
0009 #include "ioctl.h"
0010 #include "util.h"
0011 #include "fw.h"
0012 #include "main.h"
0013 #include "wmm.h"
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
0033 struct sk_buff *skb)
0034 {
0035 struct mwifiex_adapter *adapter = priv->adapter;
0036 struct txpd *local_tx_pd;
0037 struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
0038 unsigned int pad;
0039 u16 pkt_type, pkt_offset;
0040 int hroom = adapter->intf_hdr_len;
0041
0042 if (!skb->len) {
0043 mwifiex_dbg(adapter, ERROR,
0044 "Tx: bad packet length: %d\n", skb->len);
0045 tx_info->status_code = -1;
0046 return skb->data;
0047 }
0048
0049 BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
0050
0051 pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
0052
0053 pad = ((uintptr_t)skb->data - (sizeof(*local_tx_pd) + hroom)) &
0054 (MWIFIEX_DMA_ALIGN_SZ - 1);
0055 skb_push(skb, sizeof(*local_tx_pd) + pad);
0056
0057 local_tx_pd = (struct txpd *) skb->data;
0058 memset(local_tx_pd, 0, sizeof(struct txpd));
0059 local_tx_pd->bss_num = priv->bss_num;
0060 local_tx_pd->bss_type = priv->bss_type;
0061 local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len -
0062 (sizeof(struct txpd) +
0063 pad)));
0064
0065 local_tx_pd->priority = (u8) skb->priority;
0066 local_tx_pd->pkt_delay_2ms =
0067 mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
0068
0069 if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
0070 tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
0071 local_tx_pd->tx_token_id = tx_info->ack_frame_id;
0072 local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
0073 }
0074
0075 if (local_tx_pd->priority <
0076 ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
0077
0078
0079
0080
0081 local_tx_pd->tx_control =
0082 cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd->
0083 priority]);
0084
0085 if (adapter->pps_uapsd_mode) {
0086 if (mwifiex_check_last_packet_indication(priv)) {
0087 adapter->tx_lock_flag = true;
0088 local_tx_pd->flags =
0089 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET;
0090 }
0091 }
0092
0093 if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
0094 local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
0095
0096
0097 pkt_offset = sizeof(struct txpd) + pad;
0098 if (pkt_type == PKT_TYPE_MGMT) {
0099
0100 local_tx_pd->tx_pkt_type = cpu_to_le16(pkt_type);
0101 pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE;
0102 }
0103
0104 local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
0105
0106
0107 skb_push(skb, hroom);
0108
0109 if (!local_tx_pd->tx_control)
0110
0111 local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
0112
0113 return skb->data;
0114 }
0115
0116
0117
0118
0119
0120
0121
0122 int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
0123 {
0124 struct mwifiex_adapter *adapter = priv->adapter;
0125 struct txpd *local_tx_pd;
0126 struct mwifiex_tx_param tx_param;
0127
0128 #define NULL_PACKET_HDR 64
0129 u32 data_len = NULL_PACKET_HDR;
0130 struct sk_buff *skb;
0131 int ret;
0132 struct mwifiex_txinfo *tx_info = NULL;
0133
0134 if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags))
0135 return -1;
0136
0137 if (!priv->media_connected)
0138 return -1;
0139
0140 if (adapter->data_sent)
0141 return -1;
0142
0143 if (adapter->if_ops.is_port_ready &&
0144 !adapter->if_ops.is_port_ready(priv))
0145 return -1;
0146
0147 skb = dev_alloc_skb(data_len);
0148 if (!skb)
0149 return -1;
0150
0151 tx_info = MWIFIEX_SKB_TXCB(skb);
0152 memset(tx_info, 0, sizeof(*tx_info));
0153 tx_info->bss_num = priv->bss_num;
0154 tx_info->bss_type = priv->bss_type;
0155 tx_info->pkt_len = data_len -
0156 (sizeof(struct txpd) + adapter->intf_hdr_len);
0157 skb_reserve(skb, sizeof(struct txpd) + adapter->intf_hdr_len);
0158 skb_push(skb, sizeof(struct txpd));
0159
0160 local_tx_pd = (struct txpd *) skb->data;
0161 local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
0162 local_tx_pd->flags = flags;
0163 local_tx_pd->priority = WMM_HIGHEST_PRIORITY;
0164 local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
0165 local_tx_pd->bss_num = priv->bss_num;
0166 local_tx_pd->bss_type = priv->bss_type;
0167
0168 skb_push(skb, adapter->intf_hdr_len);
0169 if (adapter->iface_type == MWIFIEX_USB) {
0170 ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
0171 skb, NULL);
0172 } else {
0173 tx_param.next_pkt_len = 0;
0174 ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
0175 skb, &tx_param);
0176 }
0177 switch (ret) {
0178 case -EBUSY:
0179 dev_kfree_skb_any(skb);
0180 mwifiex_dbg(adapter, ERROR,
0181 "%s: host_to_card failed: ret=%d\n",
0182 __func__, ret);
0183 adapter->dbg.num_tx_host_to_card_failure++;
0184 break;
0185 case -1:
0186 dev_kfree_skb_any(skb);
0187 mwifiex_dbg(adapter, ERROR,
0188 "%s: host_to_card failed: ret=%d\n",
0189 __func__, ret);
0190 adapter->dbg.num_tx_host_to_card_failure++;
0191 break;
0192 case 0:
0193 dev_kfree_skb_any(skb);
0194 mwifiex_dbg(adapter, DATA,
0195 "data: %s: host_to_card succeeded\n",
0196 __func__);
0197 adapter->tx_lock_flag = true;
0198 break;
0199 case -EINPROGRESS:
0200 adapter->tx_lock_flag = true;
0201 break;
0202 default:
0203 break;
0204 }
0205
0206 return ret;
0207 }
0208
0209
0210
0211
0212 u8
0213 mwifiex_check_last_packet_indication(struct mwifiex_private *priv)
0214 {
0215 struct mwifiex_adapter *adapter = priv->adapter;
0216 u8 ret = false;
0217
0218 if (!adapter->sleep_period.period)
0219 return ret;
0220 if (mwifiex_wmm_lists_empty(adapter))
0221 ret = true;
0222
0223 if (ret && !adapter->cmd_sent && !adapter->curr_cmd &&
0224 !is_command_pending(adapter)) {
0225 adapter->delay_null_pkt = false;
0226 ret = true;
0227 } else {
0228 ret = false;
0229 adapter->delay_null_pkt = true;
0230 }
0231 return ret;
0232 }