static int wlan_xmit(struct sk_buff *skb, struct net_device *dev) { wlan_vif_t *vif; tx_msg_t msg = { 0 }; msg_q_t *msg_q; int ret, addr_len = 0; struct sk_buff *wapi_skb; vif = ndev_to_vif(dev); msg_q = wlan_tcpack_q(vif, skb->data, skb->len); if (vif->cfg80211.cipher_type == WAPI && vif->cfg80211.connect_status == ITM_CONNECTED && vif->cfg80211.key_len[PAIRWISE][vif->cfg80211. key_index[PAIRWISE]] != 0 && (*(u16 *) ((u8 *) skb->data + ETH_PKT_TYPE_OFFSET) != 0xb488)) { wapi_skb = dev_alloc_skb(skb->len + 100 + NET_IP_ALIGN); skb_reserve(wapi_skb, NET_IP_ALIGN); memcpy(wapi_skb->data, skb->data, ETHERNET_HDR_LEN); addr_len = wlan_tx_wapi_encryption(vif, skb->data, (skb->len - ETHERNET_HDR_LEN), ((unsigned char *)(wapi_skb->data) + ETHERNET_HDR_LEN)); addr_len = addr_len + ETHERNET_HDR_LEN; skb_put(wapi_skb, addr_len); dev_kfree_skb(skb); skb = wapi_skb; } msg.p = (void *)skb; msg.slice[0].data = skb->data; msg.slice[0].len = skb->len; msg.hdr.mode = vif->id; msg.hdr.type = HOST_SC2331_PKT; msg.hdr.subtype = 0; msg.hdr.len = skb->len; ret = msg_q_in(msg_q, &msg); if (OK != ret) { printkd("L-PKT\n"); dev_kfree_skb(skb); return NETDEV_TX_OK; } vif->ndev->stats.tx_bytes += skb->len; vif->ndev->stats.tx_packets++; dev->trans_start = jiffies; g_wlan.wlan_core.need_tx++; core_up(); return NETDEV_TX_OK; }
/*Transmit interface*/ static int sprdwl_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sprdwl_priv *priv = netdev_priv(dev); struct sblock blk; int ret; u8 *addr = NULL; #ifdef CONFIG_SPRDWL_FW_ZEROCOPY if (priv->tx_free < TX_FLOW_LOW) { dev_err(&dev->dev, "tx flow control full\n"); netif_stop_queue(dev); priv->ndev->stats.tx_fifo_errors++; return NETDEV_TX_BUSY; } #endif /*Get a free sblock.*/ ret = sblock_get(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk, 0); if (ret) { dev_err(&dev->dev, "Failed to get free sblock (%d)!\n", ret); netif_stop_queue(dev); priv->ndev->stats.tx_fifo_errors++; return NETDEV_TX_BUSY; } if (blk.length < skb->len) { dev_err(&dev->dev, "The size of sblock is so tiny!\n"); priv->ndev->stats.tx_fifo_errors++; sblock_put(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk); dev_kfree_skb_any(skb); priv->txrcnt = 0; return NETDEV_TX_OK; } #ifdef CONFIG_SPRDWL_FW_ZEROCOPY addr = blk.addr + SIPC_TRANS_OFFSET; #else addr = blk.addr; #endif priv->tx_free--; if (priv->connect_status == SPRDWL_CONNECTED && priv->cipher_type == SPRDWL_CIPHER_WAPI && /* priv->key_len[GROUP][priv->key_index[GROUP]] != 0 &&*/ priv->key_len[PAIRWISE][priv->key_index[PAIRWISE]] != 0 && (*(u16 *)((u8 *)skb->data + ETH_PKT_TYPE_OFFSET) != 0xb488)) { memcpy(((u8 *)addr), skb->data, ETHERNET_HDR_LEN); blk.length = wlan_tx_wapi_encryption(priv, skb->data, (skb->len - ETHERNET_HDR_LEN), ((u8 *)addr + ETHERNET_HDR_LEN)) + ETHERNET_HDR_LEN; } else { blk.length = skb->len; memcpy(((u8 *)addr), skb->data, skb->len); } #ifdef DUMP_TRANSMIT_PACKET print_hex_dump(KERN_DEBUG, "transmit packet: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, 0); #endif ret = sblock_send(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk); if (ret) { dev_err(&dev->dev, "Failed to send sblock (%d)!\n", ret); sblock_put(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk); priv->tx_free++; priv->ndev->stats.tx_fifo_errors++; if (priv->txrcnt > SETH_RESEND_MAX_NUM) netif_stop_queue(dev); priv->txrcnt++; return NETDEV_TX_BUSY; } /*Statistics*/ priv->ndev->stats.tx_bytes += skb->len; priv->ndev->stats.tx_packets++; dev->trans_start = jiffies; priv->txrcnt = 0; dev_kfree_skb_any(skb); return NETDEV_TX_OK; }