⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_merge.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *              if it is not OK. * * Lock status: io_request_lock is assumed to be held here. * * Notes:       Some drivers have limited scatter-gather table sizes, and *              thus they cannot queue an infinitely large command.  This *              function is called from ll_rw_blk before it attempts to merge *              a new block into a request to make sure that the request will *              not become too large. * *              This function is not designed to be directly called.  Instead *              it should be referenced from other functions where the *              use_clustering and dma_host parameters should be integer *              constants.  The compiler should thus be able to properly *              optimize the code, eliminating stuff that is irrelevant. *              It is more maintainable to do this way with a single function *              than to have 4 separate functions all doing roughly the *              same thing. */__inline static int __scsi_back_merge_fn(request_queue_t * q,					 struct request *req,					 struct buffer_head *bh,					 int max_segments,					 int use_clustering,					 int dma_host){	unsigned int count;	unsigned int segment_size = 0;	Scsi_Device *SDpnt;	struct Scsi_Host *SHpnt;	SDpnt = (Scsi_Device *) q->queuedata;	SHpnt = SDpnt->host;	if (max_segments > 64)		max_segments = 64;	if (use_clustering) {		/* 		 * See if we can do this without creating another		 * scatter-gather segment.  In the event that this is a		 * DMA capable host, make sure that a segment doesn't span		 * the DMA threshold boundary.  		 */		if (dma_host &&		    virt_to_phys(req->bhtail->b_data) - 1 == ISA_DMA_THRESHOLD) {			goto new_end_segment;		}		if (CONTIGUOUS_BUFFERS(req->bhtail, bh)) {#ifdef DMA_SEGMENT_SIZE_LIMITED			if( dma_host			    && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD ) {				segment_size = 0;				count = __count_segments(req, use_clustering, dma_host, &segment_size);				if( segment_size + bh->b_size > PAGE_SIZE ) {					goto new_end_segment;				}			}#endif			/*			 * This one is OK.  Let it go.			 */			return 1;		}	} new_end_segment:#ifdef DMA_CHUNK_SIZE	if (MERGEABLE_BUFFERS(req->bhtail, bh))		return scsi_new_mergeable(q, req, SHpnt, max_segments);#endif	return scsi_new_segment(q, req, SHpnt, max_segments);}__inline static int __scsi_front_merge_fn(request_queue_t * q,					  struct request *req,					  struct buffer_head *bh,					  int max_segments,					  int use_clustering,					  int dma_host){	unsigned int count;	unsigned int segment_size = 0;	Scsi_Device *SDpnt;	struct Scsi_Host *SHpnt;	SDpnt = (Scsi_Device *) q->queuedata;	SHpnt = SDpnt->host;	if (max_segments > 64)		max_segments = 64;	if (use_clustering) {		/* 		 * See if we can do this without creating another		 * scatter-gather segment.  In the event that this is a		 * DMA capable host, make sure that a segment doesn't span		 * the DMA threshold boundary. 		 */		if (dma_host &&		    virt_to_phys(bh->b_data) - 1 == ISA_DMA_THRESHOLD) {			goto new_start_segment;		}		if (CONTIGUOUS_BUFFERS(bh, req->bh)) {#ifdef DMA_SEGMENT_SIZE_LIMITED			if( dma_host			    && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD ) {				segment_size = bh->b_size;				count = __count_segments(req, use_clustering, dma_host, &segment_size);				if( count != req->nr_segments ) {					goto new_start_segment;				}			}#endif			/*			 * This one is OK.  Let it go.			 */			return 1;		}	} new_start_segment:#ifdef DMA_CHUNK_SIZE	if (MERGEABLE_BUFFERS(bh, req->bh))		return scsi_new_mergeable(q, req, SHpnt, max_segments);#endif	return scsi_new_segment(q, req, SHpnt, max_segments);}/* * Function:    scsi_merge_fn_() * * Purpose:     queue merge function. * * Arguments:   q       - Queue for which we are merging request. *              req     - request into which we wish to merge. *              bh      - Block which we may wish to merge into request * * Returns:     1 if it is OK to merge the block into the request.  0 *              if it is not OK. * * Lock status: io_request_lock is assumed to be held here. * * Notes:       Optimized for different cases depending upon whether *              ISA DMA is in use and whether clustering should be used. */#define MERGEFCT(_FUNCTION, _BACK_FRONT, _CLUSTER, _DMA)		\static int _FUNCTION(request_queue_t * q,				\		     struct request * req,				\		     struct buffer_head * bh,				\		     int max_segments)					\{									\    int ret;								\    SANITY_CHECK(req, _CLUSTER, _DMA);					\    ret =  __scsi_ ## _BACK_FRONT ## _merge_fn(q,			\					       req,			\					       bh,			\					       max_segments,		\					       _CLUSTER,		\					       _DMA);			\    return ret;								\}/* Version with use_clustering 0 and dma_host 1 is not necessary, * since the only use of dma_host above is protected by use_clustering. */MERGEFCT(scsi_back_merge_fn_, back, 0, 0)MERGEFCT(scsi_back_merge_fn_c, back, 1, 0)MERGEFCT(scsi_back_merge_fn_dc, back, 1, 1)MERGEFCT(scsi_front_merge_fn_, front, 0, 0)MERGEFCT(scsi_front_merge_fn_c, front, 1, 0)MERGEFCT(scsi_front_merge_fn_dc, front, 1, 1)/* * Function:    __scsi_merge_requests_fn() * * Purpose:     Prototype for queue merge function. * * Arguments:   q       - Queue for which we are merging request. *              req     - request into which we wish to merge. *              next    - 2nd request that we might want to combine with req *              use_clustering - 1 if this host wishes to use clustering *              dma_host - 1 if this host has ISA DMA issues (bus doesn't *                      expose all of the address lines, so that DMA cannot *                      be done from an arbitrary address). * * Returns:     1 if it is OK to merge the two requests.  0 *              if it is not OK. * * Lock status: io_request_lock is assumed to be held here. * * Notes:       Some drivers have limited scatter-gather table sizes, and *              thus they cannot queue an infinitely large command.  This *              function is called from ll_rw_blk before it attempts to merge *              a new block into a request to make sure that the request will *              not become too large. * *              This function is not designed to be directly called.  Instead *              it should be referenced from other functions where the *              use_clustering and dma_host parameters should be integer *              constants.  The compiler should thus be able to properly *              optimize the code, eliminating stuff that is irrelevant. *              It is more maintainable to do this way with a single function *              than to have 4 separate functions all doing roughly the *              same thing. */__inline static int __scsi_merge_requests_fn(request_queue_t * q,					     struct request *req,					     struct request *next,					     int max_segments,					     int use_clustering,					     int dma_host){	Scsi_Device *SDpnt;	struct Scsi_Host *SHpnt;	SDpnt = (Scsi_Device *) q->queuedata;	SHpnt = SDpnt->host;	if (max_segments > 64)		max_segments = 64;#ifdef DMA_CHUNK_SIZE	/* If it would not fit into prepared memory space for sg chain,	 * then don't allow the merge.	 */	if (req->nr_segments + next->nr_segments - 1 > max_segments ||	    req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) {		return 0;	}	if (req->nr_hw_segments + next->nr_hw_segments - 1 > SHpnt->sg_tablesize) {		return 0;	}#else	/*	 * If the two requests together are too large (even assuming that we	 * can merge the boundary requests into one segment, then don't	 * allow the merge.	 */	if (req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) {		return 0;	}#endif	/*	 * The main question is whether the two segments at the boundaries	 * would be considered one or two.	 */	if (use_clustering) {		/* 		 * See if we can do this without creating another		 * scatter-gather segment.  In the event that this is a		 * DMA capable host, make sure that a segment doesn't span		 * the DMA threshold boundary.  		 */		if (dma_host &&		    virt_to_phys(req->bhtail->b_data) - 1 == ISA_DMA_THRESHOLD) {			goto dont_combine;		}#ifdef DMA_SEGMENT_SIZE_LIMITED		/*		 * We currently can only allocate scatter-gather bounce		 * buffers in chunks of PAGE_SIZE or less.		 */		if (dma_host		    && CONTIGUOUS_BUFFERS(req->bhtail, next->bh)		    && virt_to_phys(req->bhtail->b_data) - 1 >= ISA_DMA_THRESHOLD )		{			int segment_size = 0;			int count = 0;			count = __count_segments(req, use_clustering, dma_host, &segment_size);			count += __count_segments(next, use_clustering, dma_host, &segment_size);			if( count != req->nr_segments + next->nr_segments ) {				goto dont_combine;			}		}#endif		if (CONTIGUOUS_BUFFERS(req->bhtail, next->bh)) {			/*			 * This one is OK.  Let it go.			 */			req->nr_segments += next->nr_segments - 1;			q->elevator.nr_segments--;#ifdef DMA_CHUNK_SIZE			req->nr_hw_segments += next->nr_hw_segments - 1;#endif			return 1;		}	}      dont_combine:#ifdef DMA_CHUNK_SIZE	if (req->nr_segments + next->nr_segments > max_segments ||	    req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) {		return 0;	}	/* If dynamic DMA mapping can merge last segment in req with	 * first segment in next, then the check for hw segments was	 * done above already, so we can always merge.	 */	if (MERGEABLE_BUFFERS (req->bhtail, next->bh)) {		req->nr_hw_segments += next->nr_hw_segments - 1;	} else if (req->nr_hw_segments + next->nr_hw_segments > SHpnt->sg_tablesize) {		return 0;	} else {		req->nr_hw_segments += next->nr_hw_segments;	}	req->nr_segments += next->nr_segments;	return 1;#else	/*	 * We know that the two requests at the boundary should not be combined.	 * Make sure we can fix something that is the sum of the two.	 * A slightly stricter test than we had above.	 */	if (req->nr_segments + next->nr_segments > max_segments ||	    req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) {		return 0;	} else {		/*		 * This will form the start of a new segment.  Bump the 		 * counter.		 */		req->nr_segments += next->nr_segments;		return 1;	}#endif}/* * Function:    scsi_merge_requests_fn_() * * Purpose:     queue merge function. * * Arguments:   q       - Queue for which we are merging request. *              req     - request into which we wish to merge. *              bh      - Block which we may wish to merge into request * * Returns:     1 if it is OK to merge the block into the request.  0 *              if it is not OK. * * Lock status: io_request_lock is assumed to be held here. * * Notes:       Optimized for different cases depending upon whether *              ISA DMA is in use and whether clustering should be used. */#define MERGEREQFCT(_FUNCTION, _CLUSTER, _DMA)		\static int _FUNCTION(request_queue_t * q,		\		     struct request * req,		\		     struct request * next,		\		     int max_segments)			\{							\    int ret;						\    SANITY_CHECK(req, _CLUSTER, _DMA);			\    ret =  __scsi_merge_requests_fn(q, req, next, max_segments, _CLUSTER, _DMA); \    return ret;						\}/* Version with use_clustering 0 and dma_host 1 is not necessary, * since the only use of dma_host above is protected by use_clustering. */MERGEREQFCT(scsi_merge_requests_fn_, 0, 0)MERGEREQFCT(scsi_merge_requests_fn_c, 1, 0)MERGEREQFCT(scsi_merge_requests_fn_dc, 1, 1)/* * Function:    __init_io() * * Purpose:     Prototype for io initialize function. * * Arguments:   SCpnt   - Command descriptor we wish to initialize *              sg_count_valid  - 1 if the sg count in the req is valid. *              use_clustering - 1 if this host wishes to use clustering *              dma_host - 1 if this host has ISA DMA issues (bus doesn't *                      expose all of the address lines, so that DMA cannot *                      be done from an arbitrary address). * * Returns:     1 on success. * * Lock status:  * * Notes:       Only the SCpnt argument should be a non-constant variable. *              This function is designed in such a way that it will be *              invoked from a series of small stubs, each of which would *              be optimized for specific circumstances. * *              The advantage of this is that hosts that don't do DMA *              get versions of the function that essentially don't have

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -