/** * 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; }
/** * 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; }
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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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); }