static int saudio_wait_common_cmd(uint32_t dst, uint32_t channel, uint32_t cmd, uint32_t subcmd,int32_t timeout) { int result = 0; struct sblock blk = { 0 }; struct cmd_common *common = NULL; ADEBUG(); result = sblock_receive(dst, channel, (struct sblock *)&blk, timeout); if (result < 0) { ETRACE("sblock_receive dst %d, channel %d result is %d \n", dst, channel, result); return result; } common = (struct cmd_common *)blk.addr; pr_debug("dst is %d, channel %d, common->command is %x ,sub cmd %x,\n", dst, channel, common->command, common->sub_cmd); if (subcmd) { if ((common->command == cmd) && (common->sub_cmd == subcmd)) { result = 0; } else { result = -1; } } else { if (common->command == cmd) { result = 0; } else { result = -1; } } sblock_release(dst, channel, &blk); return result; }
static int saudio_clear_cmd(uint32_t dst, uint32_t channel) { int result = 0; int i = 0; struct sblock blk = { 0 }; do { result = sblock_receive(dst, channel, (struct sblock *)&blk, 0); if (!result) { sblock_release(dst, channel, &blk); } } while (!result); return result; }
static int saudio_clear_ctrl_cmd(struct snd_saudio *saudio) { int result = 0; int i = 0; struct sblock blk = { 0 }; struct saudio_dev_ctrl *dev_ctrl = NULL; for (i = 0; i < SAUDIO_DEV_MAX; i++) { dev_ctrl = &saudio->dev_ctrl[i]; do { result = sblock_receive(dev_ctrl->dst, dev_ctrl->channel, (struct sblock *)&blk, 0); if (!result) { sblock_release(dev_ctrl->dst, dev_ctrl->channel, &blk); } } while (!result); } return result; }
static int sprdwl_rx_handler(struct napi_struct *napi, int budget) { struct sprdwl_priv *priv = container_of(napi, struct sprdwl_priv, napi); struct sblock blk; struct sk_buff *skb; int ret, work_done; u16 decryp_data_len = 0; struct wlan_sblock_recv_data *data; uint32_t length = 0; #ifdef CONFIG_SPRDWL_FW_ZEROCOPY u8 offset = 0; #endif for (work_done = 0; work_done < budget; work_done++) { ret = sblock_receive(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk, 0); if (ret) { dev_dbg(&priv->ndev->dev, "no more sblock to read\n"); break; } #ifdef CONFIG_SPRDWL_FW_ZEROCOPY offset = *(u8 *)blk.addr; length = blk.length - 2 - offset; #else length = blk.length; #endif /*16 bytes align */ skb = dev_alloc_skb(length + NET_IP_ALIGN); if (!skb) { dev_err(&priv->ndev->dev, "Failed to allocate skbuff!\n"); priv->ndev->stats.rx_dropped++; goto rx_failed; } #ifdef CONFIG_SPRDWL_FW_ZEROCOPY data = (struct wlan_sblock_recv_data *)(blk.addr + 2 + offset); #else data = (struct wlan_sblock_recv_data *)blk.addr; #endif if (data->is_encrypted == 1) { 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) { u8 snap_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; skb_reserve(skb, NET_IP_ALIGN); decryp_data_len = wlan_rx_wapi_decryption(priv, (u8 *)&data->u2.encrypt, data->u1.encrypt.header_len, (length - sizeof(data->is_encrypted) - sizeof(data->u1) - data->u1.encrypt.header_len), (skb->data + 12)); if (decryp_data_len == 0) { dev_err(&priv->ndev->dev, "Failed to decrypt WAPI data!\n"); priv->ndev->stats.rx_dropped++; dev_kfree_skb(skb); goto rx_failed; } if (memcmp((skb->data + 12), snap_header, sizeof(snap_header)) == 0) { skb_reserve(skb, 6); /* copy the eth address from eth header, * but not copy eth type */ memcpy(skb->data, data->u2.encrypt. mac_header.addr1, 6); memcpy(skb->data + 6, data->u2.encrypt. mac_header.addr2, 6); skb_put(skb, (decryp_data_len + 6)); } else { /* copy eth header */ memcpy(skb->data, data->u2.encrypt. mac_header.addr3, 6); memcpy(skb->data + 6, data->u2.encrypt. mac_header.addr2, 6); skb_put(skb, (decryp_data_len + 12)); } } else { dev_err(&priv->ndev->dev, "wrong encryption data!\n"); priv->ndev->stats.rx_dropped++; dev_kfree_skb(skb); goto rx_failed; } } else if (data->is_encrypted == 0) { skb_reserve(skb, NET_IP_ALIGN); /* dec the first encrypt byte */ memcpy(skb->data, (u8 *)&data->u2, (length - sizeof(data->is_encrypted) - sizeof(data->u1))); skb_put(skb, (length - sizeof(data->is_encrypted) - sizeof(data->u1))); } else { dev_err(&priv->ndev->dev, "wrong data fromat recieved!\n"); priv->ndev->stats.rx_dropped++; dev_kfree_skb(skb); goto rx_failed; } #ifdef DUMP_RECEIVE_PACKET print_hex_dump(KERN_DEBUG, "receive packet: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, 0); #endif skb->dev = priv->ndev; skb->protocol = eth_type_trans(skb, priv->ndev); /* CHECKSUM_UNNECESSARY not supported by our hardware */ /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ priv->ndev->stats.rx_packets++; priv->ndev->stats.rx_bytes += skb->len; napi_gro_receive(napi, skb); rx_failed: ret = sblock_release(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk); if (ret) dev_err(&priv->ndev->dev, "Failed to release sblock (%d)!\n", ret); } if (work_done < budget) napi_complete(napi); return work_done; }