Mercurial > pt1.oyama
diff driver/pt1_pci.c @ 41:51a006a8d843
imported patch ringbuf-vmalloc
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 28 Apr 2009 17:16:50 +0900 |
parents | 8f30a05cded2 |
children | 07d71b1484a8 |
line wrap: on
line diff
--- 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,