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

📄 qdio.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Check for aif time delay disablement fac (bit 56). If installed,	 * omit svs even under lpar (good point by rick again) */	omit_svs = css_general_characteristics.aif_tdd;	sprintf(dbf_text,"omitsvs%1x", omit_svs);	QDIO_DBF_TEXT0(0,setup,dbf_text);	return 0;}static unsigned inttiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero){	unsigned long real_addr_local_summary_bit;	unsigned long real_addr_dev_st_chg_ind;	void *ptr;	char dbf_text[15];	unsigned int resp_code;	int result;	struct {		struct chsc_header request;		u16 operation_code;		u16 reserved1;		u32 reserved2;		u32 reserved3;		u64 summary_indicator_addr;		u64 subchannel_indicator_addr;		u32 ks:4;		u32 kc:4;		u32 reserved4:21;		u32 isc:3;		u32 word_with_d_bit;		/* set to 0x10000000 to enable		 * time delay disablement facility */		u32 reserved5;		u32 subsystem_id;		u32 reserved6[1004];		struct chsc_header response;		u32 reserved7;	} *scssc_area;	if (!irq_ptr->is_thinint_irq)		return -ENODEV;	if (reset_to_zero) {		real_addr_local_summary_bit=0;		real_addr_dev_st_chg_ind=0;	} else {		real_addr_local_summary_bit=			virt_to_phys((volatile void *)indicators);		real_addr_dev_st_chg_ind=			virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);	}	scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);	if (!scssc_area) {		QDIO_PRINT_WARN("No memory for setting indicators on " \				"subchannel x%x.\n", irq_ptr->irq);		return -ENOMEM;	}	scssc_area->request = (struct chsc_header) {		.length = 0x0fe0,		.code   = 0x0021,	};	scssc_area->operation_code = 0;        scssc_area->summary_indicator_addr = real_addr_local_summary_bit;	scssc_area->subchannel_indicator_addr = real_addr_dev_st_chg_ind;	scssc_area->ks = QDIO_STORAGE_KEY;	scssc_area->kc = QDIO_STORAGE_KEY;	scssc_area->isc = TIQDIO_THININT_ISC;	scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;	/* enables the time delay disablement facility. Don't care	 * whether it is really there (i.e. we haven't checked for	 * it) */	if (css_general_characteristics.aif_tdd)		scssc_area->word_with_d_bit = 0x10000000;	else		QDIO_PRINT_WARN("Time delay disablement facility " \				"not available\n");	result = chsc(scssc_area);	if (result) {		QDIO_PRINT_WARN("could not set indicators on irq x%x, " \				"cc=%i.\n",irq_ptr->irq,result);		result = -EIO;		goto out;	}	resp_code = scssc_area->response.code;	if (resp_code!=QDIO_CHSC_RESPONSE_CODE_OK) {		QDIO_PRINT_WARN("response upon setting indicators " \				"is 0x%x.\n",resp_code);		sprintf(dbf_text,"sidR%4x",resp_code);		QDIO_DBF_TEXT1(0,trace,dbf_text);		QDIO_DBF_TEXT1(0,setup,dbf_text);		ptr=&scssc_area->response;		QDIO_DBF_HEX2(1,setup,&ptr,QDIO_DBF_SETUP_LEN);		result = -EIO;		goto out;	}	QDIO_DBF_TEXT2(0,setup,"setscind");	QDIO_DBF_HEX2(0,setup,&real_addr_local_summary_bit,		      sizeof(unsigned long));	QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));	result = 0;out:	free_page ((unsigned long) scssc_area);	return result;}static unsigned inttiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target){	unsigned int resp_code;	int result;	void *ptr;	char dbf_text[15];	struct {		struct chsc_header request;		u16 operation_code;		u16 reserved1;		u32 reserved2;		u32 reserved3;		u32 reserved4[2];		u32 delay_target;		u32 reserved5[1009];		struct chsc_header response;		u32 reserved6;	} *scsscf_area;	if (!irq_ptr->is_thinint_irq)		return -ENODEV;	scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);	if (!scsscf_area) {		QDIO_PRINT_WARN("No memory for setting delay target on " \				"subchannel x%x.\n", irq_ptr->irq);		return -ENOMEM;	}	scsscf_area->request = (struct chsc_header) {		.length = 0x0fe0,		.code   = 0x1027,	};	scsscf_area->delay_target = delay_target<<16;	result=chsc(scsscf_area);	if (result) {		QDIO_PRINT_WARN("could not set delay target on irq x%x, " \				"cc=%i. Continuing.\n",irq_ptr->irq,result);		result = -EIO;		goto out;	}	resp_code = scsscf_area->response.code;	if (resp_code!=QDIO_CHSC_RESPONSE_CODE_OK) {		QDIO_PRINT_WARN("response upon setting delay target " \				"is 0x%x. Continuing.\n",resp_code);		sprintf(dbf_text,"sdtR%4x",resp_code);		QDIO_DBF_TEXT1(0,trace,dbf_text);		QDIO_DBF_TEXT1(0,setup,dbf_text);		ptr=&scsscf_area->response;		QDIO_DBF_HEX2(1,trace,&ptr,QDIO_DBF_TRACE_LEN);	}	QDIO_DBF_TEXT2(0,trace,"delytrgt");	QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));	result = 0; /* not critical */out:	free_page ((unsigned long) scsscf_area);	return result;}intqdio_cleanup(struct ccw_device *cdev, int how){	struct qdio_irq *irq_ptr;	char dbf_text[15];	int rc;	irq_ptr = cdev->private->qdio_data;	if (!irq_ptr)		return -ENODEV;	sprintf(dbf_text,"qcln%4x",irq_ptr->irq);	QDIO_DBF_TEXT1(0,trace,dbf_text);	QDIO_DBF_TEXT0(0,setup,dbf_text);	rc = qdio_shutdown(cdev, how);	if ((rc == 0) || (rc == -EINPROGRESS))		rc = qdio_free(cdev);	return rc;}intqdio_shutdown(struct ccw_device *cdev, int how){	struct qdio_irq *irq_ptr;	int i;	int result = 0;	int rc;	unsigned long flags;	int timeout;	char dbf_text[15];	irq_ptr = cdev->private->qdio_data;	if (!irq_ptr)		return -ENODEV;	down(&irq_ptr->setting_up_sema);	sprintf(dbf_text,"qsqs%4x",irq_ptr->irq);	QDIO_DBF_TEXT1(0,trace,dbf_text);	QDIO_DBF_TEXT0(0,setup,dbf_text);	/* mark all qs as uninteresting */	for (i=0;i<irq_ptr->no_input_qs;i++)		atomic_set(&irq_ptr->input_qs[i]->is_in_shutdown,1);	for (i=0;i<irq_ptr->no_output_qs;i++)		atomic_set(&irq_ptr->output_qs[i]->is_in_shutdown,1);	tasklet_kill(&tiqdio_tasklet);	for (i=0;i<irq_ptr->no_input_qs;i++) {		qdio_unmark_q(irq_ptr->input_qs[i]);		tasklet_kill(&irq_ptr->input_qs[i]->tasklet);		wait_event_interruptible_timeout(cdev->private->wait_q,						 !atomic_read(&irq_ptr->							      input_qs[i]->							      use_count),						 QDIO_NO_USE_COUNT_TIMEOUT);		if (atomic_read(&irq_ptr->input_qs[i]->use_count))			result=-EINPROGRESS;	}	for (i=0;i<irq_ptr->no_output_qs;i++) {		tasklet_kill(&irq_ptr->output_qs[i]->tasklet);		wait_event_interruptible_timeout(cdev->private->wait_q,						 !atomic_read(&irq_ptr->							      output_qs[i]->							      use_count),						 QDIO_NO_USE_COUNT_TIMEOUT);		if (atomic_read(&irq_ptr->output_qs[i]->use_count))			result=-EINPROGRESS;	}	/* cleanup subchannel */	spin_lock_irqsave(get_ccwdev_lock(cdev),flags);	if (how&QDIO_FLAG_CLEANUP_USING_CLEAR) {		rc = ccw_device_clear(cdev, QDIO_DOING_CLEANUP);		timeout=QDIO_CLEANUP_CLEAR_TIMEOUT;	} else if (how&QDIO_FLAG_CLEANUP_USING_HALT) {		rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);		timeout=QDIO_CLEANUP_HALT_TIMEOUT;	} else { /* default behaviour */		rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);		timeout=QDIO_CLEANUP_HALT_TIMEOUT;	}	if (rc == -ENODEV) {		/* No need to wait for device no longer present. */		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);	} else if (((void *)cdev->handler != (void *)qdio_handler) && rc == 0) {		/*		 * Whoever put another handler there, has to cope with the		 * interrupt theirself. Might happen if qdio_shutdown was		 * called on already shutdown queues, but this shouldn't have		 * bad side effects.		 */		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);	} else if (rc == 0) {		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);		ccw_device_set_timeout(cdev, timeout);		spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags);		wait_event(cdev->private->wait_q,			   irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||			   irq_ptr->state == QDIO_IRQ_STATE_ERR);	} else {		QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for "				"device %s\n", result, cdev->dev.bus_id);		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);		result = rc;		goto out;	}	if (irq_ptr->is_thinint_irq) {		qdio_put_indicator((__u32*)irq_ptr->dev_st_chg_ind);		tiqdio_set_subchannel_ind(irq_ptr,1);                 /* reset adapter interrupt indicators */	} 	/* exchange int handlers, if necessary */ 	if ((void*)cdev->handler == (void*)qdio_handler) 		cdev->handler=irq_ptr->original_int_handler;	/* Ignore errors. */	qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);	ccw_device_set_timeout(cdev, 0);out:	up(&irq_ptr->setting_up_sema);	return result;}intqdio_free(struct ccw_device *cdev){	struct qdio_irq *irq_ptr;	char dbf_text[15];	irq_ptr = cdev->private->qdio_data;	if (!irq_ptr)		return -ENODEV;	down(&irq_ptr->setting_up_sema);	sprintf(dbf_text,"qfqs%4x",irq_ptr->irq);	QDIO_DBF_TEXT1(0,trace,dbf_text);	QDIO_DBF_TEXT0(0,setup,dbf_text);	cdev->private->qdio_data = 0;	up(&irq_ptr->setting_up_sema);	qdio_release_irq_memory(irq_ptr);	module_put(THIS_MODULE);	return 0;}static inline voidqdio_allocate_do_dbf(struct qdio_initialize *init_data){	char dbf_text[20]; /* if a printf printed out more than 8 chars */	sprintf(dbf_text,"qfmt:%x",init_data->q_format);	QDIO_DBF_TEXT0(0,setup,dbf_text);	QDIO_DBF_HEX0(0,setup,init_data->adapter_name,8);	sprintf(dbf_text,"qpff%4x",init_data->qib_param_field_format);	QDIO_DBF_TEXT0(0,setup,dbf_text);	QDIO_DBF_HEX0(0,setup,&init_data->qib_param_field,sizeof(char*));	QDIO_DBF_HEX0(0,setup,&init_data->input_slib_elements,sizeof(long*));	QDIO_DBF_HEX0(0,setup,&init_data->output_slib_elements,sizeof(long*));	sprintf(dbf_text,"miit%4x",init_data->min_input_threshold);	QDIO_DBF_TEXT0(0,setup,dbf_text);	sprintf(dbf_text,"mait%4x",init_data->max_input_threshold);	QDIO_DBF_TEXT0(0,setup,dbf_text);	sprintf(dbf_text,"miot%4x",init_data->min_output_threshold);	QDIO_DBF_TEXT0(0,setup,dbf_text);	sprintf(dbf_text,"maot%4x",init_data->max_output_threshold);	QDIO_DBF_TEXT0(0,setup,dbf_text);	sprintf(dbf_text,"niq:%4x",init_data->no_input_qs);	QDIO_DBF_TEXT0(0,setup,dbf_text);	sprintf(dbf_text,"noq:%4x",init_data->no_output_qs);	QDIO_DBF_TEXT0(0,setup,dbf_text);	QDIO_DBF_HEX0(0,setup,&init_data->input_handler,sizeof(void*));	QDIO_DBF_HEX0(0,setup,&init_data->output_handler,sizeof(void*));	QDIO_DBF_HEX0(0,setup,&init_data->int_parm,sizeof(long));	QDIO_DBF_HEX0(0,setup,&init_data->flags,sizeof(long));	QDIO_DBF_HEX0(0,setup,&init_data->input_sbal_addr_array,sizeof(void*));	QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*));}static inline voidqdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt){	irq_ptr->input_qs[i]->is_iqdio_q = iqfmt;	irq_ptr->input_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq;	irq_ptr->qdr->qdf0[i].sliba=(unsigned long)(irq_ptr->input_qs[i]->slib);	irq_ptr->qdr->qdf0[i].sla=(unsigned long)(irq_ptr->input_qs[i]->sl);	irq_ptr->qdr->qdf0[i].slsba=		(unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]);	irq_ptr->qdr->qdf0[i].akey=QDIO_STORAGE_KEY;	irq_ptr->qdr->qdf0[i].bkey=QDIO_STORAGE_KEY;	irq_ptr->qdr->qdf0[i].ckey=QDIO_STORAGE_KEY;	irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_KEY;}static inline voidqdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i,			       int j, int iqfmt){	irq_ptr->output_qs[i]->is_iqdio_q = iqfmt;	irq_ptr->output_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq;	irq_ptr->qdr->qdf0[i+j].sliba=(unsigned long)(irq_ptr->output_qs[i]->slib);	irq_ptr->qdr->qdf0[i+j].sla=(unsigned long)(irq_ptr->output_qs[i]->sl);	irq_ptr->qdr->qdf0[i+j].slsba=		(unsigned long)(&irq_ptr->output_qs[i]->slsb.acc.val[0]);	irq_ptr->qdr->qdf0[i+j].akey=QDIO_STORAGE_KEY;	irq_ptr->qdr->qdf0[i+j].bkey=QDIO_STORAGE_KEY;	irq_ptr->qdr->qdf0[i+j].ckey=QDIO_STORAGE_KEY;	irq_ptr->qdr->qdf0[i+j].dkey=QDIO_STORAGE_KEY;}static inline voidqdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr){	int i;	for (i=0;i<irq_ptr->no_input_qs;i++) {		irq_ptr->input_qs[i]->siga_sync=			irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY;		irq_ptr->input_qs[i]->siga_in=			irq_ptr->qdioac&CHSC_FLAG_SIGA_INPUT_NECESSARY;		irq_ptr->input_qs[i]->siga_out=			irq_ptr->qdioac&CHSC_FLAG_SIGA_OUTPUT_NECESSARY;		irq_ptr->input_qs[i]->siga_sync_done_on_thinints=			irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;		irq_ptr->input_qs[i]->hydra_gives_outbound_pcis=			irq_ptr->hydra_gives_outbound_pcis;		irq_ptr->input_qs[i]->siga_sync_done_on_outb_tis=			((irq_ptr->qdioac&			  (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|			   CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==			 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|			  CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS));	}}static inline voidqdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr){	int i;	for (i=0;i<irq_ptr->no_output_qs;i++) {		irq_ptr->output_qs[i]->siga_sync=			irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY;		irq_ptr->output_qs[i]->siga_in=			irq_ptr->qdioac&CHSC_FLAG_SIGA_INPUT_NECESSARY;		irq_ptr->output_qs[i]->siga_out=			irq_ptr->qdioac&CHSC_FLAG_SIGA_OUTPUT_NECESSARY;		irq_ptr->output_qs[i]->siga_sync_done_on_thinints=			irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;		irq_ptr->output_qs[i]->hydra_gives_outbound_pcis=			irq_ptr->hydra_gives_outbound_pcis;		irq_ptr->output_qs[i]->siga_sync_done_on_outb_tis=			((irq_ptr->qdioac&			  (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|			   CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==			 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|			  CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS));	}}static inline intqdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,				    int dstat){	char dbf_text[15];	struct qdio_irq *irq_ptr;	irq_ptr = cdev->private->qdio_data;	if (cstat || (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {		sprintf(dbf_text,"ick1%4x",irq_ptr->irq);		QDIO_DBF_TEXT2(1,trace,dbf_text);		QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));		QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));		QDIO_PRINT_ERR("received check condition on establish " \			       "queues on irq 0x%x (cs=x%x, ds=x%x).\n",			       irq_ptr->irq,cstat,dstat);		qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR);	}		if (!(dstat & DEV_STAT_DEV_END)) {		QDIO_DBF_TEXT2(1,setup,"eq:no de");		QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));		QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));		QDIO_PRINT_ERR("establish queues on irq %04x: didn't get "			       "device end: dstat=%02x, cstat=%02x\n",			       irq_ptr->irq, dstat, cstat);		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);		return 1;	}	if (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) {		QDIO_DBF_TEXT2(1,setup,"eq:badio");		QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));		QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));		QDIO_PRINT_ERR("establish queues on irq %04x: got "			       "the following devstat: dstat=%02x, "			       "cstat=%02x\n",			       irq_ptr->irq, dstat, cstat);		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);		return 1;	}	return 0;}static voidqdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat){	struct qdio_irq *irq_ptr;	char dbf_text[15];	irq_ptr = cdev->privat

⌨️ 快捷键说明

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