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

📄 dasd.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* SECTION: Managing the device queues etc. *//* * DASD_TERM_IO * * attempts to terminate the the current IO and set it to failed if termination * was successful. * returns an appropriate return code */intdasd_term_IO (ccw_req_t * cqr){	int rc = 0;	dasd_device_t *device = cqr->device;	int irq;        int retries = 0;	if (!cqr) {		BUG ();	}	irq = device->devinfo.irq;	if (strncmp ((char *) &cqr->magic, device->discipline->ebcname, 4)) {		DASD_MESSAGE (KERN_WARNING, device,			      " ccw_req_t 0x%08x magic doesn't match"			      " discipline 0x%08x\n",			      cqr->magic,			      *(unsigned int *) device->discipline->name);		return -EINVAL;	}                while ((retries < 5                    ) &&               (cqr->status == CQR_STATUS_IN_IO)   ) {                if ( retries < 2 )                        rc = halt_IO(irq, (long)cqr,                                      cqr->options | DOIO_WAIT_FOR_INTERRUPT);                else                        rc = clear_IO(irq, (long)cqr,                                       cqr->options | DOIO_WAIT_FOR_INTERRUPT);                switch (rc) {                case 0:         /* termination successful */                        check_then_set (&cqr->status,                                        CQR_STATUS_IN_IO,                                         CQR_STATUS_FAILED);                                                asm volatile ("STCK %0":"=m" (cqr->stopclk));                        break;                case -ENODEV:                        DASD_MESSAGE (KERN_WARNING, device, "%s",                                      "device gone, retry\n");                        break;                case -EIO:                        DASD_MESSAGE (KERN_WARNING, device, "%s",                                      "I/O error, retry\n");                        break;                case -EBUSY:                        DASD_MESSAGE (KERN_WARNING, device, "%s",                                      "device busy, retry later\n");                        break;                default:                        DASD_MESSAGE (KERN_ERR, device,                                      "line %d unknown RC=%d, please report"                                      " to linux390@de.ibm.com\n",                                       __LINE__,                                       rc);                        BUG ();                        break;                }                retries ++;        }	return rc;}/* * function dasd_start_IO * attempts to start the IO and returns an appropriate return code */intdasd_start_IO (ccw_req_t * cqr){	int rc = 0;	dasd_device_t *device = cqr->device;	int irq;	unsigned long long now;	if (!cqr) {		BUG ();	}	irq = device->devinfo.irq;	if (strncmp ((char *) &cqr->magic, device->discipline->ebcname, 4)) {		DASD_MESSAGE (KERN_WARNING, device,			      " ccw_req_t 0x%08x magic doesn't match"			      " discipline 0x%08x\n",			      cqr->magic,			      *(unsigned int *) device->discipline->name);		return -EINVAL;	}	asm volatile ("STCK %0":"=m" (now));        cqr->startclk = now;	rc = do_IO (irq, cqr->cpaddr, (long) cqr, cqr->lpm, cqr->options);	switch (rc) {	case 0:                if (cqr->options & DOIO_WAIT_FOR_INTERRUPT) {                        /* request already finished (synchronous IO) */                        DASD_MESSAGE (KERN_ERR, device, "%s",                                      " do_IO finished request... "                                      "DOIO_WAIT_FOR_INTERRUPT was set");                        check_then_set (&cqr->status,                                        CQR_STATUS_QUEUED,                                         CQR_STATUS_DONE);                        cqr->stopclk = now;                        dasd_schedule_bh (device);                                        } else {                        check_then_set (&cqr->status,                                        CQR_STATUS_QUEUED,                                         CQR_STATUS_IN_IO);                }		break;	case -EBUSY:		DASD_MESSAGE (KERN_WARNING, device, "%s",			      "device busy, retry later\n");		break;	case -ETIMEDOUT: 		DASD_MESSAGE (KERN_WARNING, device, "%s",			      "request timeout - terminated\n");	case -ENODEV:	case -EIO:		check_then_set (&cqr->status,				CQR_STATUS_QUEUED,                                 CQR_STATUS_FAILED);                cqr->stopclk = now;                dasd_schedule_bh (device);		break;	default:		DASD_MESSAGE (KERN_ERR, device,			      "line %d unknown RC=%d, please report"			      " to linux390@de.ibm.com\n", __LINE__, rc);		BUG ();		break;	}	return rc;}/* * function dasd_sleep_on_req * attempts to start the IO and waits for completion * FIXME: replace handmade sleeping by wait_event */intdasd_sleep_on_req (ccw_req_t * req){	unsigned long flags;	int cs;	int rc = 0;	dasd_device_t *device = (dasd_device_t *) req->device;        if ( signal_pending(current) ) {                return -ERESTARTSYS;        }	s390irq_spin_lock_irqsave (device->devinfo.irq, flags);	dasd_chanq_enq (&device->queue, req);	/* let the bh start the request to keep them in order */	dasd_schedule_bh (device);	do {		s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);		wait_event ( device->wait_q,			     (((cs = req->status) == CQR_STATUS_DONE) ||			     (cs == CQR_STATUS_FAILED) ||                             signal_pending(current)));		s390irq_spin_lock_irqsave (device->devinfo.irq, flags);                if ( signal_pending(current) ) {                        rc = -ERESTARTSYS;		     	if (req->status == CQR_STATUS_IN_IO )                         	device->discipline->term_IO(req);                        break;                } else if ( req->status == CQR_STATUS_FAILED) {                        rc = -EIO;                        break;                }	} while (cs != CQR_STATUS_DONE && cs != CQR_STATUS_FAILED);	s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);	return rc;}				/* end dasd_sleep_on_req *//* * function dasd_end_request * posts the buffer_cache about a finalized request * FIXME: for requests splitted to serveral cqrs */static inline voiddasd_end_request (struct request *req, int uptodate){	while (end_that_request_first (req, uptodate, DASD_NAME)) {	}#ifndef DEVICE_NO_RANDOM	add_blkdev_randomness (MAJOR (req->rq_dev));#endif	end_that_request_last (req);	return;}/* * function dasd_get_queue * returns the queue corresponding to a device behind a kdev */static request_queue_t *dasd_get_queue (kdev_t kdev){	dasd_device_t *device = dasd_device_from_kdev (kdev);	if (!device) {		return NULL;	}	return device->request_queue;}/* * function dasd_check_expire_time * check the request given as argument for expiration * and returns 0 if not yet expired, EIO else */static inline intdasd_check_expire_time (ccw_req_t * cqr){	unsigned long long now;	int rc = 0;	asm volatile ("STCK %0":"=m" (now));	if (cqr->expires && cqr->expires + cqr->startclk < now) {		DASD_MESSAGE (KERN_ERR, ((dasd_device_t *) cqr->device),			      "IO timeout 0x%08lx%08lx usecs in req %p\n",			      (long) (cqr->expires >> 44),			      (long) (cqr->expires >> 12), cqr);		cqr->expires <<= 1;                rc = -EIO;	}	return rc;}/* * function dasd_finalize_request * implemets the actions to perform, when a request is finally finished * namely in status CQR_STATUS_DONE || CQR_STATUS_FAILED */static inline voiddasd_finalize_request (ccw_req_t * cqr){	dasd_device_t *device = cqr->device;	asm volatile ("STCK %0":"=m" (cqr->endclk));	if (cqr->req) {#ifdef DASD_PROFILE		dasd_profile_add (cqr);#endif		dasd_end_request (cqr->req, (cqr->status == CQR_STATUS_DONE));		/* free request if nobody is waiting on it */		dasd_free_request (cqr, cqr->device);	} else {                if ( cqr == device->init_cqr && /* bring late devices online */                     device->level <= DASD_STATE_ONLINE ) {                         device->timer.function = dasd_enable_single_device;                         device->timer.data     = (unsigned long) device;                        device->timer.expires  = jiffies;                        add_timer(&device->timer);                }		/* notify sleeping task about finished postprocessing */		wake_up (&device->wait_q);                	}	return;}/* * function dasd_process_queues * transfers the requests on the queue given as argument to the chanq * if possible, the request ist started on a fastpath */static voiddasd_process_queues (dasd_device_t * device){	unsigned long flags;	struct request *req;	request_queue_t *queue = device->request_queue;	dasd_chanq_t *qp = &device->queue;	int irq = device->devinfo.irq;	ccw_req_t *final_requests = NULL;	static int chanq_min_size = DASD_MIN_SIZE_FOR_QUEUE;	int chanq_max_size = DASD_CHANQ_MAX_SIZE;	ccw_req_t *cqr = NULL, *temp;	dasd_erp_postaction_fn_t erp_postaction;	s390irq_spin_lock_irqsave (irq, flags);	/* First we dechain the requests, processed with completed status */	while (qp->head &&	       ((qp->head->status == CQR_STATUS_DONE  ) ||		(qp->head->status == CQR_STATUS_FAILED) ||		(qp->head->status == CQR_STATUS_ERROR )   )) {		dasd_erp_action_fn_t erp_action;		ccw_req_t            *erp_cqr = NULL;		/*  preprocess requests with CQR_STATUS_ERROR */		if (qp->head->status == CQR_STATUS_ERROR) {                        qp->head->retries--; 			if (qp->head->dstat->flag & DEVSTAT_HALT_FUNCTION) {                                check_then_set (&qp->head->status,                                                CQR_STATUS_ERROR,                                                CQR_STATUS_FAILED);                                asm volatile ("STCK %0":"=m" (qp->head->stopclk));                        } else if ((device->discipline->erp_action == NULL                          ) ||                                   ((erp_action = device->discipline->erp_action (qp->head)) == NULL)   ) {                                				erp_cqr = dasd_default_erp_action (qp->head);			} else { /* call discipline ERP action */                                erp_cqr = erp_action (qp->head);                        }                        continue;		} else if (qp->head->refers) {	/* we deal with a finished ERP */			if (qp->head->status == CQR_STATUS_DONE) {                                DASD_MESSAGE (KERN_DEBUG, device, "%s",                                              "ERP successful");			} else {                                DASD_MESSAGE (KERN_ERR, device, "%s",                                              "ERP unsuccessful");			}			if ((device->discipline->erp_postaction == NULL                              )||			    ((erp_postaction = device->discipline->erp_postaction (qp->head)) == NULL)  ) {                                dasd_default_erp_postaction (qp->head);			} else {  /* call ERP postaction of discipline */                                erp_postaction (qp->head);                        }			continue;		}		/* dechain request now */		if (final_requests == NULL)			final_requests = qp->head;		cqr      = qp->head;		qp->head = qp->head->next;		if (qp->head == NULL)			qp->tail = NULL;	} /* end while over completed requests */	if (cqr)		cqr->next = NULL;	/* Now clean the requests with final status */	while (final_requests) { 		temp = final_requests;		final_requests = temp->next;		dasd_finalize_request (temp);	}	/* Now we try to fetch requests from the request queue */	for (temp = cqr; temp != NULL; temp = temp->next)		if (temp->status == CQR_STATUS_QUEUED)			chanq_max_size--;	while ((atomic_read(&device->plugged) == 0) &&               (!queue->plugged) &&	       (!list_empty (&queue->queue_head)) &&	       (req = dasd_next_request (queue)) != NULL) {		/* queue empty or certain critera fulfilled -> transfer */		if (qp->head == NULL ||		    chanq_max_size > 0 || (req->nr_sectors >= chanq_min_size)) {			ccw_req_t *cqr = NULL;                        if (is_read_only(device->kdev) && req->cmd == WRITE) {                                DASD_DRIVER_DEBUG_EVENT (3, dasd_int_handler,                                                         "(%04x) Rejecting write request %p\n",                                                         device->devinfo.devno,                                                         req);                                dasd_end_request (req, 0);                                dasd_dequeue_request (queue,req);                        } else {                            /* relocate request according to partition table */                            req->sector +=                                device->major_info->gendisk.                                part[MINOR (req->rq_dev)].start_sect;                            cqr = device->discipline->build_cp_from_req (device, req);                            if (cqr == NULL) {                                    DASD_DRIVER_DEBUG_EVENT (3, dasd_int_handler,                                                             "(%04x) CCW creation failed "                                                             "on request %p\n",                                                             device->devinfo.devno,                                                             req);                                    /* revert relocation of request */                                    req->sector -=                                        device->major_info->gendisk.                                        part[MINOR (req->rq_dev)].start_sect;                                    break;	/* terminate request queue loop */                                                                }#ifdef CONFIG_DYNAMIC_QUEUE_MIN_SIZE                            chanq_min_size =                                (chanq_min_size + req->nr_sectors) >> 1;#endif				/* CONFIG_DYNAMIC_QUEUE_MIN_SIZE */                            dasd_dequeue_request (queue, req);                            dasd_chanq_enq (qp, cqr);                        }		} else {	/* queue not empty OR criteria not met */			break;	/* terminate request queue loop */		}	}	/* we process the requests with non-final status */	if (qp->head) {

⌨️ 快捷键说明

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