static int saudio_send_common_cmd(uint32_t dst, uint32_t channel, uint32_t cmd, uint32_t subcmd,int32_t timeout) { int result = 0; struct sblock blk = { 0 }; ADEBUG(); pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x\n", dst, channel, cmd, subcmd); result = sblock_get(dst, channel, (struct sblock *)&blk, timeout); if (result >= 0) { struct cmd_common *common = (struct cmd_common *)blk.addr; int retry = 0; common->command = cmd; common->sub_cmd = subcmd; blk.length = sizeof(struct cmd_common); pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x send ok\n", dst, channel, cmd, subcmd); while ((result = sblock_send(dst, channel, (struct sblock *)&blk)) == -EBUSY) { if (retry++ < 20*1000) udelay(100); else { printk(KERN_WARNING "%s retry %d timeout\n", __func__, retry); break; } } } return result; }
/* Establish the file system and write it to disk */ int fs_format(mem_sblock_t sbp) { blocknum_t inode_bitmap_size; blocknum_t block_bitmap_size; blocknum_t i; sbp->filesys_lock = semaphore_new(1); if (NULL == sbp->filesys_lock) { return -1; } fs_lock(sbp); /* Format super block */ sblock_get(maindisk, sbp); sblock_format(sbp, disk_size); sblock_update(sbp); /* Format inode and block bitmaps */ inode_bitmap_size = sbp->inode_bitmap_last - sbp->inode_bitmap_first + 1; sbp->inode_bitmap = malloc(inode_bitmap_size * DISK_BLOCK_SIZE); block_bitmap_size = sbp->block_bitmap_last - sbp->block_bitmap_first + 1; sbp->block_bitmap = malloc(block_bitmap_size * DISK_BLOCK_SIZE); if (NULL == sbp->block_bitmap || NULL == sbp->inode_bitmap) { semaphore_V(sbp->filesys_lock); return -1; } /* Clear bitmaps */ bitmap_zeroall(sbp->inode_bitmap, inode_bitmap_size * BITS_PER_BLOCK); bitmap_zeroall(sbp->block_bitmap, block_bitmap_size * BITS_PER_BLOCK); /* Set file system blocks to be occupied */ for (i = 0; i <= sbp->block_bitmap_last; ++i) { bitmap_set(sbp->block_bitmap, i); } /* Set inode 0 to be occupied */ bitmap_set(sbp->inode_bitmap, 0); /* Push updates to disk */ for (i = sbp->inode_bitmap_first; i <= sbp->inode_bitmap_last; ++i) { bpush(i, (char*) sbp->inode_bitmap + (i - sbp->inode_bitmap_first) * DISK_BLOCK_SIZE); } for (i = sbp->block_bitmap_first; i <= sbp->block_bitmap_last; ++i) { bpush(i, (char*) sbp->block_bitmap + (i - sbp->block_bitmap_first) * DISK_BLOCK_SIZE); } /* Count free inodes and free blocks */ mainsb->free_inodes = bitmap_count_zero(mainsb->inode_bitmap, mainsb->total_inodes); mainsb->free_blocks = bitmap_count_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); fs_unlock(sbp); return 0; }
static int saudio_data_trigger_process(struct saudio_stream *stream, struct saudio_msg *msg) { int32_t result = 0; struct sblock blk = { 0 }; struct cmd_common *common = NULL; struct snd_pcm_runtime *runtime = stream->substream->runtime; ADEBUG(); if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) { stream->periods_avail = snd_pcm_playback_avail(runtime) / runtime->period_size; } else { stream->periods_avail = snd_pcm_capture_avail(runtime) / runtime->period_size; } pr_debug("saudio.c:stream->periods_avail is %d,block count is %d", stream->periods_avail, sblock_get_free_count(stream->dst, stream->channel)); stream->periods_tosend = runtime->periods - stream->periods_avail; ADEBUG(); while (stream->periods_tosend) { result = sblock_get(stream->dst, stream->channel, &blk, 0); if (result) { break; } stream->last_getblk_count++; common = (struct cmd_common *)blk.addr; blk.length = frames_to_bytes(runtime, runtime->period_size); common->command = SAUDIO_DATA_PCM; common->sub_cmd = stream->stream_id; common->reserved1 = stream->substream->dma_buffer.addr + stream->period * blk.length; sblock_send(stream->dst, stream->channel, &blk); stream->period++; stream->period = stream->period % runtime->periods; stream->periods_tosend--; } pr_debug(":sblock_getblock_count trigger is %d \n", stream->last_getblk_count); return result; }
/* Initialize the file system structure from disk */ int fs_init(mem_sblock_t sbp) { blocknum_t inode_bitmap_size; blocknum_t block_bitmap_size; blocknum_t i; sbp->filesys_lock = semaphore_new(1); if (NULL == sbp->filesys_lock) { return -1; } fs_lock(sbp); sblock_get(maindisk, sbp); sblock_put(sbp); if (sblock_isvalid(sbp) != 1) { sblock_print(sbp); kprintf("File system is not recognized. "); kprintf("Recommend running './mkfs <blocks>'.\n"); return -2; } inode_bitmap_size = sbp->inode_bitmap_last - sbp->inode_bitmap_first + 1; sbp->inode_bitmap = malloc(inode_bitmap_size * DISK_BLOCK_SIZE); block_bitmap_size = sbp->block_bitmap_last - sbp->block_bitmap_first + 1; sbp->block_bitmap = malloc(block_bitmap_size * DISK_BLOCK_SIZE); if (NULL == sbp->block_bitmap || NULL == sbp->inode_bitmap) { semaphore_V(sbp->filesys_lock); return -1; } /* Get disk bitmap */ for (i = sbp->inode_bitmap_first; i <= sbp->inode_bitmap_last; ++i) { bpull(i, (char*) sbp->inode_bitmap + (i - sbp->inode_bitmap_first) * DISK_BLOCK_SIZE); } for (i = sbp->block_bitmap_first; i <= sbp->block_bitmap_last; ++i) { bpull(i, (char*) sbp->block_bitmap + (i - sbp->block_bitmap_first) * DISK_BLOCK_SIZE); } /* Count free inodes and free blocks */ mainsb->free_inodes = bitmap_count_zero(mainsb->inode_bitmap, mainsb->total_inodes); mainsb->free_blocks = bitmap_count_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); fs_unlock(sbp); return 0; }
static int saudio_cmd_prepare_process(struct saudio_dev_ctrl *dev_ctrl, struct saudio_msg *msg) { struct sblock blk; struct snd_saudio *saudio=NULL; int32_t result = 0; struct snd_pcm_runtime *runtime = dev_ctrl->stream[msg->stream_id].substream->runtime; ADEBUG(); saudio = dev_ctrl->stream[msg->stream_id].saudio; result = sblock_get(dev_ctrl->dst, dev_ctrl->channel, (struct sblock *)&blk, CMD_TIMEOUT); if (!result) { struct cmd_prepare *prepare = (struct cmd_prepare *)blk.addr; prepare->common.command = SAUDIO_CMD_PREPARE; prepare->common.sub_cmd=msg->stream_id; prepare->rate = runtime->rate; prepare->channels = runtime->channels; prepare->format = runtime->format; prepare->period = frames_to_bytes(runtime, runtime->period_size); prepare->periods = runtime->periods; blk.length = sizeof(struct cmd_prepare); mutex_lock(&dev_ctrl->mutex); sblock_send(dev_ctrl->dst, dev_ctrl->channel, (struct sblock *)&blk); result = saudio_wait_common_cmd(dev_ctrl->dst, dev_ctrl->channel, SAUDIO_CMD_PREPARE_RET, 0,CMD_TIMEOUT); if(result) saudio_snd_card_free(saudio); mutex_unlock(&dev_ctrl->mutex); } pr_debug("saudio_cmd_prepare_process result is %d", result); return result; }
static int saudio_send_common_cmd(uint32_t dst, uint32_t channel, uint32_t cmd, uint32_t subcmd, int32_t timeout) { int result = 0; struct sblock blk = { 0 }; ADEBUG(); pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x\n", dst, channel, cmd, subcmd); saudio_clear_cmd( dst, channel); result = sblock_get(dst, channel, (struct sblock *)&blk, timeout); if (result >= 0) { struct cmd_common *common = (struct cmd_common *)blk.addr; common->command = cmd; common->sub_cmd = subcmd; blk.length = sizeof(struct cmd_common); pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x send ok\n", dst, channel, cmd, subcmd); result = sblock_send(dst, channel, (struct sblock *)&blk); } return result; }
static int saudio_data_transfer_process(struct saudio_stream *stream, struct saudio_msg *msg) { struct snd_pcm_runtime *runtime = stream->substream->runtime; struct sblock blk = { 0 }; int32_t result = 0; struct cmd_common *common = NULL; int32_t elapsed_blks = 0; int32_t periods_avail; int32_t periods_tosend; int32_t cur_blk_count = 0; cur_blk_count = sblock_get_free_count(stream->dst, stream->channel); elapsed_blks = (cur_blk_count + stream->last_getblk_count - stream->blk_count) - stream->last_elapsed_count; if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) { periods_avail = snd_pcm_playback_avail(runtime) / runtime->period_size; } else { periods_avail = snd_pcm_capture_avail(runtime) / runtime->period_size; } periods_tosend = stream->periods_avail - periods_avail; if (periods_tosend > 0) { stream->periods_tosend += periods_tosend; } if (stream->periods_tosend) { while (stream->periods_tosend) { result = sblock_get(stream->dst, stream->channel, &blk, 0); if (result) { break; } stream->last_getblk_count++; common = (struct cmd_common *)blk.addr; blk.length = frames_to_bytes(runtime, runtime->period_size); common->command = SAUDIO_DATA_PCM; common->sub_cmd = stream->stream_id; common->reserved1 = stream->substream->dma_buffer.addr + stream->period * blk.length; sblock_send(stream->dst, stream->channel, &blk); stream->periods_tosend--; stream->period++; stream->period = stream->period % runtime->periods; } } else { pr_debug("saudio.c: saudio no data to send "); if (sblock_get_free_count(stream->dst, stream->channel) == SAUDIO_STREAM_BLOCK_COUNT) { pr_debug ("saudio.c: saudio no data to send and is empty "); result = sblock_get(stream->dst, stream->channel, &blk, 0); if (result) { ETRACE("saudio.c: no data and no blk\n"); } else { stream->last_getblk_count++; common = (struct cmd_common *)blk.addr; common->command = SAUDIO_DATA_SILENCE; common->sub_cmd = stream->stream_id; sblock_send(stream->dst, stream->channel, &blk); stream->last_elapsed_count++; schedule_timeout(msecs_to_jiffies(1)); } } } while (elapsed_blks) { elapsed_blks--; stream->hwptr_done++; stream->hwptr_done %= runtime->periods; snd_pcm_period_elapsed(stream->substream); stream->periods_avail++; stream->last_elapsed_count++; } return 0; }
/*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; }