# HG changeset patch # User Yoshiki Yazawa # Date 1240906610 -32400 # Node ID 51a006a8d8438a7e52a45aeba20c8cb7885b5a10 # Parent 8f30a05cded27272e65306fd1c5dcd2a9d9fa8a2 imported patch ringbuf-vmalloc diff -r 8f30a05cded2 -r 51a006a8d843 driver/pt1_pci.c --- a/driver/pt1_pci.c Tue Apr 28 17:16:48 2009 +0900 +++ b/driver/pt1_pci.c Tue Apr 28 17:16:50 2009 +0900 @@ -72,13 +72,8 @@ #define DMA_SIZE 4096 // DMAバッファサイズ #define DMA_RING_SIZE 128 // RINGサイズ #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) #define CHANEL_DMA_SIZE (2*1024*1024) // 地デジ用(16Mbps) #define BS_CHANEL_DMA_SIZE (4*1024*1024) // BS用(32Mbps) -#else -#define CHANEL_DMA_SIZE (1*128*1024) // 地デジ用(1Mbps) -#define BS_CHANEL_DMA_SIZE (1*128*1024) // BS用(1Mbps) -#endif typedef struct _DMA_CONTROL{ dma_addr_t ring_dma[DMA_RING_MAX] ; // DMA情報 @@ -125,6 +120,7 @@ __u32 transerr ; // 転送エラー __u32 minor ; // マイナー番号 __u8 *buf; // CH別受信メモリ + __u32 pointer; __u8 req_dma ; // 溢れたチャネル __u8 packet_buf[PACKET_SIZE] ; // 溢れたチャネル PT1_DEVICE *ptr ; // カード別情報 @@ -246,7 +242,7 @@ mutex_lock(&channel->lock); // あふれたら読み出すまで待つ while(1){ - if(channel->size >= (channel->maxsize - 4)){ + if(channel->size >= (channel->maxsize - PACKET_SIZE - 4)){ // 該当チャンネルのDMA読みだし待ちにする wake_up(&channel->wait_q); channel->req_dma = TRUE ; @@ -272,8 +268,22 @@ // パケットが出来たらコピーする if(channel->packet_size >= PACKET_SIZE){ - memcpy(&channel->buf[channel->size], - channel->packet_buf, PACKET_SIZE); + if (channel->pointer + channel->size >= channel->maxsize) { + // リングバッファの境界を越えていてリングバッファの先頭に戻っている場合 + // channel->pointer + channel->size - channel->maxsize でリングバッファ先頭からのアドレスになる + memcpy(&channel->buf[channel->pointer + channel->size - channel->maxsize], channel->packet_buf, PACKET_SIZE); + } else if (channel->pointer + channel->size + PACKET_SIZE > channel->maxsize) { + // リングバッファの境界をまたぐように書き込まれる場合 + // リングバッファの境界まで書き込み + __u32 tmp_size = channel->maxsize - (channel->pointer + channel->size); + memcpy(&channel->buf[channel->pointer + channel->size], channel->packet_buf, tmp_size); + // 先頭に戻って書き込み + memcpy(channel->buf, &channel->packet_buf[tmp_size], PACKET_SIZE - tmp_size); + } else { + // リングバッファ内で収まる場合 + // 通常の書き込み + memcpy(&channel->buf[channel->pointer + channel->size], channel->packet_buf, PACKET_SIZE); + } channel->size += PACKET_SIZE ; channel->packet_size = 0 ; } @@ -385,17 +395,28 @@ if(!channel->size){ size = 0 ; }else{ - if(cnt < channel->size){ - // バッファが足りない場合は残りを移動する - size = cnt ; - dummy = copy_to_user(buf, channel->buf, cnt); - memmove(channel->buf, &channel->buf[cnt], (channel->size - cnt)); - channel->size -= cnt ; - }else{ - size = channel->size ; - dummy = copy_to_user(buf, channel->buf, size); - channel->size = 0 ; + __u32 tmp_size = 0; + if (cnt < channel->size) { + // バッファにあるデータより小さい読み込みの場合 + size = cnt; + } else { + // バッファにあるデータ以上の読み込みの場合 + size = channel->size; } + if (channel->maxsize <= size + channel->pointer) { + // リングバッファの境界を越える場合 + tmp_size = channel->maxsize - channel->pointer; + // 境界までコピー + copy_to_user(buf, &channel->buf[channel->pointer], tmp_size); + // 残りをコピー + copy_to_user(&buf[tmp_size], channel->buf, size - tmp_size); + channel->pointer = size - tmp_size; + } else { + // 普通にコピー + copy_to_user(buf, &channel->buf[channel->pointer], size); + channel->pointer += size; + } + channel->size -= size; } // 読み終わったかつ使用しているのがが4K以下 if(channel->req_dma == TRUE){ @@ -733,11 +754,13 @@ switch(channel->type){ case CHANNEL_TYPE_ISDB_T: channel->maxsize = CHANEL_DMA_SIZE ; - channel->buf = kzalloc(CHANEL_DMA_SIZE, GFP_KERNEL); + channel->buf = vmalloc(CHANEL_DMA_SIZE); + channel->pointer = 0; break ; case CHANNEL_TYPE_ISDB_S: channel->maxsize = BS_CHANEL_DMA_SIZE ; - channel->buf = kzalloc(BS_CHANEL_DMA_SIZE, GFP_KERNEL); + channel->buf = vmalloc(BS_CHANEL_DMA_SIZE); + channel->pointer = 0; break ; } if(channel->buf == NULL){ @@ -785,7 +808,7 @@ for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ if(dev_conf->channel[lp] != NULL){ if(dev_conf->channel[lp]->buf != NULL){ - kfree(dev_conf->channel[lp]->buf); + vfree(dev_conf->channel[lp]->buf); } kfree(dev_conf->channel[lp]); } @@ -831,7 +854,7 @@ for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ if(dev_conf->channel[lp] != NULL){ cdev_del(&dev_conf->cdev[lp]); - kfree(dev_conf->channel[lp]->buf); + vfree(dev_conf->channel[lp]->buf); kfree(dev_conf->channel[lp]); } device_destroy(pt1video_class,