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,