예제 #1
0
파일: zfcp_qdio.c 프로젝트: Addision/LVS
static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
				struct zfcp_queue_req *q_req,
				unsigned int sbtype, void *start_addr,
				unsigned int total_length)
{
	struct qdio_buffer_element *sbale;
	unsigned long remaining, length;
	void *addr;

	/* split segment up */
	for (addr = start_addr, remaining = total_length; remaining > 0;
	     addr += length, remaining -= length) {
		sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
		if (!sbale) {
			atomic_inc(&qdio->req_q_full);
			zfcp_qdio_undo_sbals(qdio, q_req);
			return -EINVAL;
		}

		/* new piece must not exceed next page boundary */
		length = min(remaining,
			     (PAGE_SIZE - ((unsigned long)addr &
					   (PAGE_SIZE - 1))));
		sbale->addr = addr;
		sbale->length = length;
	}
	return 0;
}
예제 #2
0
/**
 * zfcp_qdio_sbals_from_segment - map memory segment to SBALE(s)
 * @fsf_req: request to be processed
 * @sbtype: SBALE flags
 * @start_addr: address of memory segment
 * @total_length: length of memory segment
 *
 * Alignment and length of the segment determine how many SBALEs are needed
 * for the memory segment.
 */
static inline int
zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
			     void *start_addr, unsigned long total_length)
{
	unsigned long remaining, length;
	void *addr;

	/* split segment up heeding page boundaries */
	for (addr = start_addr, remaining = total_length; remaining > 0;
	     addr += length, remaining -= length) {
		/* get next free SBALE for new piece */
		if (NULL == zfcp_qdio_sbale_next(fsf_req, sbtype)) {
			/* no SBALE left, clean up and leave */
			zfcp_qdio_sbals_wipe(fsf_req);
			return -EINVAL;
		}
		/* calculate length of new piece */
		length = min(remaining,
			     (PAGE_SIZE - ((unsigned long) addr &
					   (PAGE_SIZE - 1))));
		/* fill current SBALE with calculated piece */
		zfcp_qdio_sbale_fill(fsf_req, sbtype, addr, length);
	}
	return total_length;
}
예제 #3
0
/**
 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
 * @qdio: pointer to struct zfcp_qdio
 * @q_req: pointer to struct zfcp_qdio_req
 * @sg: scatter-gather list
 * @max_sbals: upper bound for number of SBALs to be used
 * Returns: number of bytes, or error (negativ)
 */
int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
			    struct scatterlist *sg)
{
	struct qdio_buffer_element *sbale;
	int bytes = 0;

	/* set storage-block type for this request */
	sbale = zfcp_qdio_sbale_req(qdio, q_req);
	sbale->sflags |= q_req->sbtype;

	for (; sg; sg = sg_next(sg)) {
		sbale = zfcp_qdio_sbale_next(qdio, q_req);
		if (!sbale) {
			atomic_inc(&qdio->req_q_full);
			zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
					     q_req->sbal_number);
			return -EINVAL;
		}

		sbale->addr = sg_virt(sg);
		sbale->length = sg->length;

		bytes += sg->length;
	}

	return bytes;
}