示例#1
0
/**
 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
 * @fsf_req: request to be processed
 * @sbtype: SBALE flags
 * @sg: scatter-gather list
 * @sg_count: number of elements in scatter-gather list
 * @max_sbals: upper bound for number of SBALs to be used
 */
int
zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                        struct scatterlist *sgl, int sg_count, int max_sbals)
{
	int sg_index;
	struct scatterlist *sg_segment;
	int retval;
	volatile struct qdio_buffer_element *sbale;
	int bytes = 0;

	/* figure out last allowed SBAL */
	zfcp_qdio_sbal_limit(fsf_req, max_sbals);

	/* set storage-block type for current SBAL */
	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
	sbale->flags |= sbtype;

	/* process all segements of scatter-gather list */
	for_each_sg(sgl, sg_segment, sg_count, sg_index) {
		retval = zfcp_qdio_sbals_from_segment(
				fsf_req,
				sbtype,
				zfcp_sg_to_address(sg_segment),
				sg_segment->length);
		if (retval < 0) {
			bytes = retval;
			goto out;
		} else
                        bytes += retval;
	}
示例#2
0
/**
 * zfcp_qdio_sbal_chain - chain SBALs if more than one SBAL is needed for a
 *	request
 * @fsf_req: zfcp_fsf_req to be processed
 * @sbtype: SBAL flags which have to be set in first SBALE of new SBAL
 *
 * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req.
 */
static inline volatile struct qdio_buffer_element *
zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
{
	volatile struct qdio_buffer_element *sbale;

	/* set last entry flag in current SBALE of current SBAL */
	sbale = zfcp_qdio_sbale_curr(fsf_req);
	sbale->flags |= SBAL_FLAGS_LAST_ENTRY;

	/* don't exceed last allowed SBAL */
	if (fsf_req->sbal_curr == fsf_req->sbal_last)
		return NULL;

	/* set chaining flag in first SBALE of current SBAL */
	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
	sbale->flags |= SBAL_FLAGS0_MORE_SBALS;

	/* calculate index of next SBAL */
	fsf_req->sbal_curr++;
	fsf_req->sbal_curr %= QDIO_MAX_BUFFERS_PER_Q;

	/* keep this requests number of SBALs up-to-date */
	fsf_req->sbal_number++;

	/* start at first SBALE of new SBAL */
	fsf_req->sbale_curr = 0;

	/* set storage-block type for new SBAL */
	sbale = zfcp_qdio_sbale_curr(fsf_req);
	sbale->flags |= sbtype;

	return sbale;
}
示例#3
0
static struct qdio_buffer_element *
zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
{
	struct qdio_buffer_element *sbale;

	/* set last entry flag in current SBALE of current SBAL */
	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
	sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY;

	/* don't exceed last allowed SBAL */
	if (q_req->sbal_last == q_req->sbal_limit)
		return NULL;

	/* set chaining flag in first SBALE of current SBAL */
	sbale = zfcp_qdio_sbale_req(qdio, q_req);
	sbale->sflags |= SBAL_SFLAGS0_MORE_SBALS;

	/* calculate index of next SBAL */
	q_req->sbal_last++;
	q_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;

	/* keep this requests number of SBALs up-to-date */
	q_req->sbal_number++;
	BUG_ON(q_req->sbal_number > ZFCP_QDIO_MAX_SBALS_PER_REQ);

	/* start at first SBALE of new SBAL */
	q_req->sbale_curr = 0;

	/* set storage-block type for new SBAL */
	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
	sbale->sflags |= q_req->sbtype;

	return sbale;
}
示例#4
0
文件: zfcp_qdio.c 项目: Addision/LVS
/**
 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
 * @fsf_req: request to be processed
 * @sbtype: SBALE flags
 * @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_queue_req *q_req,
			    unsigned long sbtype, struct scatterlist *sg,
			    int max_sbals)
{
	struct qdio_buffer_element *sbale;
	int retval, bytes = 0;

	/* figure out last allowed SBAL */
	zfcp_qdio_sbal_limit(qdio, q_req, max_sbals);

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

	for (; sg; sg = sg_next(sg)) {
		retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype,
					      sg_virt(sg), sg->length);
		if (retval < 0)
			return retval;
		bytes += sg->length;
	}

	/* assume that no other SBALEs are to follow in the same SBAL */
	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
	sbale->flags |= SBAL_FLAGS_LAST_ENTRY;

	return bytes;
}
示例#5
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;
}
示例#6
0
文件: zfcp_qdio.c 项目: wxlong/Test
/**
 * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
 * @fsf_req: request to be processed
 * @sbtype: SBALE flags
 * @sg: scatter-gather list
 * @sg_count: number of elements in scatter-gather list
 * @max_sbals: upper bound for number of SBALs to be used
 */
inline int
zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                        struct scatterlist *sg,	int sg_count, int max_sbals)
{
    int sg_index;
    struct scatterlist *sg_segment;
    int retval;
    volatile struct qdio_buffer_element *sbale;
    int bytes = 0;

    /* figure out last allowed SBAL */
    zfcp_qdio_sbal_limit(fsf_req, max_sbals);

    /* set storage-block type for current SBAL */
    sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
    sbale->flags |= sbtype;

    /* process all segements of scatter-gather list */
    for (sg_index = 0, sg_segment = sg, bytes = 0;
            sg_index < sg_count;
            sg_index++, sg_segment++) {
        retval = zfcp_qdio_sbals_from_segment(
                     fsf_req,
                     sbtype,
                     zfcp_sg_to_address(sg_segment),
                     sg_segment->length);
        if (retval < 0) {
            bytes = retval;
            goto out;
        } else
            bytes += retval;
    }
    /* assume that no other SBALEs are to follow in the same SBAL */
    sbale = zfcp_qdio_sbale_curr(fsf_req);
    sbale->flags |= SBAL_FLAGS_LAST_ENTRY;

out:
#ifdef ZFCP_STAT_REQSIZES
    if (sbtype == SBAL_FLAGS0_TYPE_READ) {
        zfcp_statistics_inc(&zfcp_data.read_sguse_head, sg_count);
        zfcp_statistics_inc(&zfcp_data.read_req_head, bytes);
    } else	{
        zfcp_statistics_inc(&zfcp_data.write_sguse_head, sg_count);
        zfcp_statistics_inc(&zfcp_data.write_req_head, bytes);
    }
#endif

    return bytes;
}
示例#7
0
/**
 * zfcp_qdio_determine_pci - set PCI flag in first SBALE on qdio queue if needed
 */
int
zfcp_qdio_determine_pci(struct zfcp_qdio_queue *req_queue,
			struct zfcp_fsf_req *fsf_req)
{
	int new_distance_from_int;
	int pci_pos;
	volatile struct qdio_buffer_element *sbale;

	new_distance_from_int = req_queue->distance_from_int +
                fsf_req->sbal_number;

	if (unlikely(new_distance_from_int >= ZFCP_QDIO_PCI_INTERVAL)) {
		new_distance_from_int %= ZFCP_QDIO_PCI_INTERVAL;
                pci_pos  = fsf_req->sbal_first;
		pci_pos += fsf_req->sbal_number;
		pci_pos -= new_distance_from_int;
		pci_pos -= 1;
		pci_pos %= QDIO_MAX_BUFFERS_PER_Q;
		sbale = zfcp_qdio_sbale_req(fsf_req, pci_pos, 0);
		sbale->flags |= SBAL_FLAGS0_PCI;
	}
	return new_distance_from_int;
}
示例#8
0
/**
 * zfcp_qdio_sbale_curr - return current SBALE on request_queue for
 *	a struct zfcp_fsf_req
 */
inline volatile struct qdio_buffer_element *
zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req)
{
	return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr,
				   fsf_req->sbale_curr);
}