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

📄 qdio.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	count=0; 	while (1) { 		count++; 		if (i==end)			break; 		i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1); 	}#ifdef CONFIG_QDIO_DEBUG	sprintf(dbf_text,"s=%2xc=%2x",start,count);	QDIO_DBF_TEXT4(0,trace,dbf_text);#endif /* CONFIG_QDIO_DEBUG */	if (likely(q->state==QDIO_IRQ_STATE_ACTIVE))		q->handler(q->cdev,			   QDIO_STATUS_INBOUND_INT|q->error_status_flags,			   q->qdio_error,q->siga_error,q->q_no,start,count,			   q->int_parm);	/* for the next time: */	q->first_element_to_kick=real_end;	q->qdio_error=0;	q->siga_error=0;	q->error_status_flags=0;#ifdef QDIO_PERFORMANCE_STATS	perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;	perf_stats.inbound_cnt++;#endif /* QDIO_PERFORMANCE_STATS */}static inline void__tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set){	struct qdio_irq *irq_ptr;	struct qdio_q *oq;	int i;	QDIO_DBF_TEXT4(0,trace,"iqinproc");	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));	/* 	 * we first want to reserve the q, so that we know, that we don't	 * interrupt ourselves and call qdio_unmark_q, as is_in_shutdown might	 * be set 	 */	if (unlikely(qdio_reserve_q(q))) {		qdio_release_q(q);#ifdef QDIO_PERFORMANCE_STATS		ii_p_c++;#endif /* QDIO_PERFORMANCE_STATS */		/* 		 * as we might just be about to stop polling, we make		 * sure that we check again at least once more 		 */		tiqdio_sched_tl();		return;	}#ifdef QDIO_PERFORMANCE_STATS	ii_p_nc++;#endif /* QDIO_PERFORMANCE_STATS */	if (unlikely(atomic_read(&q->is_in_shutdown))) {		qdio_unmark_q(q);		goto out;	}	/* 	 * we reset spare_ind_was_set, when the queue does not use the	 * spare indicator	 */	if (spare_ind_was_set)		spare_ind_was_set = (q->dev_st_chg_ind == &spare_indicator);	if (!(*(q->dev_st_chg_ind)) && !spare_ind_was_set)		goto out;	/*	 * q->dev_st_chg_ind is the indicator, be it shared or not.	 * only clear it, if indicator is non-shared	 */	if (!spare_ind_was_set)		tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);	if (q->hydra_gives_outbound_pcis) {		if (!q->siga_sync_done_on_thinints) {			SYNC_MEMORY_ALL;		} else if ((!q->siga_sync_done_on_outb_tis)&&			 (q->hydra_gives_outbound_pcis)) {			SYNC_MEMORY_ALL_OUTB;		}	} else {		SYNC_MEMORY;	}	/*	 * maybe we have to do work on our outbound queues... at least	 * we have to check the outbound-int-capable thinint-capable	 * queues	 */	if (q->hydra_gives_outbound_pcis) {		irq_ptr = (struct qdio_irq*)q->irq_ptr;		for (i=0;i<irq_ptr->no_output_qs;i++) {			oq = irq_ptr->output_qs[i];#ifdef QDIO_PERFORMANCE_STATS			perf_stats.tl_runs--;#endif /* QDIO_PERFORMANCE_STATS */			if (!qdio_is_outbound_q_done(oq))				__qdio_outbound_processing(oq);		}	}	if (!qdio_has_inbound_q_moved(q))		goto out;	qdio_kick_inbound_handler(q);	if (tiqdio_is_inbound_q_done(q))		if (!qdio_stop_polling(q)) {			/* 			 * we set the flags to get into the stuff next time,			 * see also comment in qdio_stop_polling 			 */			tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);			tiqdio_sched_tl();		}out:	qdio_release_q(q);}static voidtiqdio_inbound_processing(struct qdio_q *q){	__tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount));}static inline void__qdio_inbound_processing(struct qdio_q *q){	int q_laps=0;	QDIO_DBF_TEXT4(0,trace,"qinproc");	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));	if (unlikely(qdio_reserve_q(q))) {		qdio_release_q(q);#ifdef QDIO_PERFORMANCE_STATS		i_p_c++;#endif /* QDIO_PERFORMANCE_STATS */		/* as we're sissies, we'll check next time */		if (likely(!atomic_read(&q->is_in_shutdown))) {			qdio_mark_q(q);			QDIO_DBF_TEXT4(0,trace,"busy,agn");		}		return;	}#ifdef QDIO_PERFORMANCE_STATS	i_p_nc++;	perf_stats.tl_runs++;#endif /* QDIO_PERFORMANCE_STATS */again:	if (qdio_has_inbound_q_moved(q)) {		qdio_kick_inbound_handler(q);		if (!qdio_stop_polling(q)) {			q_laps++;			if (q_laps<QDIO_Q_LAPS) 				goto again;		}		qdio_mark_q(q);	} else {		if (!qdio_is_inbound_q_done(q))                         /* means poll time is not yet over */			qdio_mark_q(q);	}	qdio_release_q(q);}static voidqdio_inbound_processing(struct qdio_q *q){	__qdio_inbound_processing(q);}/************************* MAIN ROUTINES *******************************/#ifdef QDIO_USE_PROCESSING_STATEstatic inline inttiqdio_reset_processing_state(struct qdio_q *q, int q_laps){	if (!q) {		tiqdio_sched_tl();		return 0;	}	/* 	 * under VM, we have not used the PROCESSING state, so no	 * need to stop polling 	 */	if (q->siga_sync)		return 2;	if (unlikely(qdio_reserve_q(q))) {		qdio_release_q(q);#ifdef QDIO_PERFORMANCE_STATS		ii_p_c++;#endif /* QDIO_PERFORMANCE_STATS */		/* 		 * as we might just be about to stop polling, we make		 * sure that we check again at least once more 		 */				/* 		 * sanity -- we'd get here without setting the		 * dev st chg ind 		 */		tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);		tiqdio_sched_tl();		return 0;	}	if (qdio_stop_polling(q)) {		qdio_release_q(q);		return 2;	}			if (q_laps<QDIO_Q_LAPS-1) {		qdio_release_q(q);		return 3;	}	/* 	 * we set the flags to get into the stuff	 * next time, see also comment in qdio_stop_polling 	 */	tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);	tiqdio_sched_tl();	qdio_release_q(q);	return 1;	}#endif /* QDIO_USE_PROCESSING_STATE */static inline voidtiqdio_inbound_checks(void){	struct qdio_q *q;	int spare_ind_was_set=0;#ifdef QDIO_USE_PROCESSING_STATE	int q_laps=0;#endif /* QDIO_USE_PROCESSING_STATE */	QDIO_DBF_TEXT4(0,trace,"iqdinbck");	QDIO_DBF_TEXT5(0,trace,"iqlocsum");#ifdef QDIO_USE_PROCESSING_STATEagain:#endif /* QDIO_USE_PROCESSING_STATE */	/* when the spare indicator is used and set, save that and clear it */	if ((atomic_read(&spare_indicator_usecount)) && spare_indicator) {		spare_ind_was_set = 1;		tiqdio_clear_summary_bit((__u32*)&spare_indicator);	}	q=(struct qdio_q*)tiq_list;	do {		if (!q)			break;		__tiqdio_inbound_processing(q, spare_ind_was_set);		q=(struct qdio_q*)q->list_next;	} while (q!=(struct qdio_q*)tiq_list);#ifdef QDIO_USE_PROCESSING_STATE	q=(struct qdio_q*)tiq_list;	do {		int ret;		ret = tiqdio_reset_processing_state(q, q_laps);		switch (ret) {		case 0:			return;		case 1:			q_laps++;		case 2:			q = (struct qdio_q*)q->list_next;			break;		default:			q_laps++;			goto again;		}	} while (q!=(struct qdio_q*)tiq_list);#endif /* QDIO_USE_PROCESSING_STATE */}static voidtiqdio_tl(unsigned long data){	QDIO_DBF_TEXT4(0,trace,"iqdio_tl");#ifdef QDIO_PERFORMANCE_STATS	perf_stats.tl_runs++;#endif /* QDIO_PERFORMANCE_STATS */	tiqdio_inbound_checks();}/********************* GENERAL HELPER_ROUTINES ***********************/static voidqdio_release_irq_memory(struct qdio_irq *irq_ptr){	int i;	for (i=0;i<QDIO_MAX_QUEUES_PER_IRQ;i++) {		if (!irq_ptr->input_qs[i])			goto next;		kfree(irq_ptr->input_qs[i]->slib);		kfree(irq_ptr->input_qs[i]);next:		if (!irq_ptr->output_qs[i])			continue;		kfree(irq_ptr->output_qs[i]->slib);		kfree(irq_ptr->output_qs[i]);	}	kfree(irq_ptr->qdr);	kfree(irq_ptr);}static voidqdio_set_impl_params(struct qdio_irq *irq_ptr,		     unsigned int qib_param_field_format,		     /* pointer to 128 bytes or NULL, if no param field */		     unsigned char *qib_param_field,		     /* pointer to no_queues*128 words of data or NULL */		     unsigned int no_input_qs,		     unsigned int no_output_qs,		     unsigned long *input_slib_elements,		     unsigned long *output_slib_elements){	int i,j;	if (!irq_ptr)		return;	irq_ptr->qib.pfmt=qib_param_field_format;	if (qib_param_field)		memcpy(irq_ptr->qib.parm,qib_param_field,		       QDIO_MAX_BUFFERS_PER_Q);	if (input_slib_elements)		for (i=0;i<no_input_qs;i++) {			for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)				irq_ptr->input_qs[i]->slib->slibe[j].parms=					input_slib_elements[						i*QDIO_MAX_BUFFERS_PER_Q+j];		}	if (output_slib_elements)		for (i=0;i<no_output_qs;i++) {			for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)				irq_ptr->output_qs[i]->slib->slibe[j].parms=					output_slib_elements[						i*QDIO_MAX_BUFFERS_PER_Q+j];		}}static intqdio_alloc_qs(struct qdio_irq *irq_ptr,	      int no_input_qs, int no_output_qs){	int i;	struct qdio_q *q;	int result=-ENOMEM;	for (i=0;i<no_input_qs;i++) {		q=kmalloc(sizeof(struct qdio_q),GFP_KERNEL);		if (!q) {			QDIO_PRINT_ERR("kmalloc of q failed!\n");			goto out;		}		memset(q,0,sizeof(struct qdio_q));		q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);		if (!q->slib) {			QDIO_PRINT_ERR("kmalloc of slib failed!\n");			goto out;		}		irq_ptr->input_qs[i]=q;	}	for (i=0;i<no_output_qs;i++) {		q=kmalloc(sizeof(struct qdio_q),GFP_KERNEL);		if (!q) {			goto out;		}		memset(q,0,sizeof(struct qdio_q));		q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);		if (!q->slib) {			QDIO_PRINT_ERR("kmalloc of slib failed!\n");			goto out;		}		irq_ptr->output_qs[i]=q;	}	result=0;out:	return result;}static voidqdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,       	     int no_input_qs, int no_output_qs,	     qdio_handler_t *input_handler,	     qdio_handler_t *output_handler,	     unsigned long int_parm,int q_format,	     unsigned long flags,	     void **inbound_sbals_array,	     void **outbound_sbals_array){	struct qdio_q *q;	int i,j;	char dbf_text[20]; /* see qdio_initialize */	void *ptr;	int available;	sprintf(dbf_text,"qfqs%4x",cdev->private->irq);	QDIO_DBF_TEXT0(0,setup,dbf_text);	for (i=0;i<no_input_qs;i++) {		q=irq_ptr->input_qs[i];		memset(q,0,((char*)&q->slib)-((char*)q));		sprintf(dbf_text,"in-q%4x",i);		QDIO_DBF_TEXT0(0,setup,dbf_text);		QDIO_DBF_HEX0(0,setup,&q,sizeof(void*));		memset(q->slib,0,PAGE_SIZE);		q->sl=(struct sl*)(((char*)q->slib)+PAGE_SIZE/2);		available=0;		for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)			q->sbal[j]=*(inbound_sbals_array++);                q->queue_type=q_format;		q->int_parm=int_parm;		q->irq=irq_ptr->irq;		q->irq_ptr = irq_ptr;		q->cdev = cdev;		q->mask=1<<(31-i);		q->q_no=i;		q->is_input_q=1;		q->first_to_check=0;		q->last_move_ftc=0;		q->handler=input_handler;		q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind;		q->tasklet.data=(unsigned long)q;		/* q->is_thinint_q isn't valid at this time, but		 * irq_ptr->is_thinint_irq is */		q->tasklet.func=(void(*)(unsigned long))			((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:			 &qdio_inbound_processing);		/* actually this is not used for inbound queues. yet. */		atomic_set(&q->busy_siga_counter,0);		q->timing.busy_start=0;/*		for (j=0;j<QDIO_STATS_NUMBER;j++)			q->timing.last_transfer_times[j]=(qdio_get_micros()/							  QDIO_STATS_NUMBER)*j;		q->timing.last_transfer_index=QDIO_STATS_NUMBER-1;*/		/* fill in slib */		if (i>0) irq_ptr->input_qs[i-1]->slib->nsliba=				 (unsigned long)(q->slib);		q->slib->sla=(unsigned long)(q->sl);		q->slib->slsba=(unsigned long)(&q->slsb.acc.val[0]);		/* fill in sl */		for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++)			q->sl->element[j].sbal=(unsigned long)(q->sbal[j]);		QDIO_DBF_TEXT2(0,setup,"sl-sb-b0");		ptr=(void*)q->sl;		QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));		ptr=(void*)&q->slsb;		QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));		ptr=(void*)q->sbal[0];		QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));		/* fill in slsb */		for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {			set_slsb(&q->slsb.acc.val[j],		   		 SLSB_P_INPUT_NOT_INIT);/*			q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/		}	}	for (i=0;i<no_output_qs;i++) {		q=irq_ptr->output_qs[i];		memset(q,0,((char*)&q->slib)-((char*)q));		sprintf(dbf_text,"outq%4x",i);		QDIO_DBF_TEXT0(0,setup,dbf_text);		QDIO_DBF_HEX0(0,setup,&q,sizeof(void*));		memset(q->slib,0,PAGE_SIZE);		q->sl=(struct sl*)(((char*)q->slib)+PAGE_SIZE/2);

⌨️ 快捷键说明

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