diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-06-07 18:50:55 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 04:04:51 -0700 |
commit | ac668c69709c7d927015c5cf3d9e87bf4eaaf57d (patch) | |
tree | 16a42117d260a86b8217d266ab65b25438c48e06 /drivers/scsi/isci/host.c | |
parent | 9b917987fd16d0687afe550a02f68099419f5d43 (diff) | |
download | lwn-ac668c69709c7d927015c5cf3d9e87bf4eaaf57d.tar.gz lwn-ac668c69709c7d927015c5cf3d9e87bf4eaaf57d.zip |
isci: cleanup/optimize pool implementation
The circ_buf macros are ~6% faster, as measured by perf, because they take
advantage of power-of-two math assumptions i.e. no test and branch for
rollover. Their semantics are clearer than the hidden side effects in pool.h
(like sci_pool_get() which hides an assignment).
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/host.c')
-rw-r--r-- | drivers/scsi/isci/host.c | 75 |
1 files changed, 51 insertions, 24 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 41a7c5099dea..343655bd1a6a 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -52,6 +52,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <linux/circ_buf.h> #include <linux/device.h> #include <scsi/sas.h> #include "host.h" @@ -1054,6 +1055,33 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } +static void isci_tci_free(struct isci_host *ihost, u16 tci) +{ + u16 tail = ihost->tci_tail & (SCI_MAX_IO_REQUESTS-1); + + ihost->tci_pool[tail] = tci; + ihost->tci_tail = tail + 1; +} + +static u16 isci_tci_alloc(struct isci_host *ihost) +{ + u16 head = ihost->tci_head & (SCI_MAX_IO_REQUESTS-1); + u16 tci = ihost->tci_pool[head]; + + ihost->tci_head = head + 1; + return tci; +} + +static u16 isci_tci_active(struct isci_host *ihost) +{ + return CIRC_CNT(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); +} + +static u16 isci_tci_space(struct isci_host *ihost) +{ + return CIRC_SPACE(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); +} + static enum sci_status scic_controller_start(struct scic_sds_controller *scic, u32 timeout) { @@ -1069,9 +1097,11 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, } /* Build the TCi free pool */ - sci_pool_initialize(scic->tci_pool); + BUILD_BUG_ON(SCI_MAX_IO_REQUESTS > 1 << sizeof(ihost->tci_pool[0]) * 8); + ihost->tci_head = 0; + ihost->tci_tail = 0; for (index = 0; index < scic->task_context_entries; index++) - sci_pool_put(scic->tci_pool, index); + isci_tci_free(ihost, index); /* Build the RNi free pool */ scic_sds_remote_node_table_initialize( @@ -3063,18 +3093,17 @@ enum sci_task_status scic_controller_start_task( * currently available tags to be allocated. All return other values indicate a * legitimate tag. */ -u16 scic_controller_allocate_io_tag( - struct scic_sds_controller *scic) +u16 scic_controller_allocate_io_tag(struct scic_sds_controller *scic) { - u16 task_context; - u16 sequence_count; - - if (!sci_pool_empty(scic->tci_pool)) { - sci_pool_get(scic->tci_pool, task_context); + struct isci_host *ihost = scic_to_ihost(scic); + u16 tci; + u16 seq; - sequence_count = scic->io_request_sequence[task_context]; + if (isci_tci_space(ihost)) { + tci = isci_tci_alloc(ihost); + seq = scic->io_request_sequence[tci]; - return scic_sds_io_tag_construct(sequence_count, task_context); + return scic_sds_io_tag_construct(seq, tci); } return SCI_CONTROLLER_INVALID_IO_TAG; @@ -3105,10 +3134,10 @@ u16 scic_controller_allocate_io_tag( * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag * is not a valid IO tag value. */ -enum sci_status scic_controller_free_io_tag( - struct scic_sds_controller *scic, - u16 io_tag) +enum sci_status scic_controller_free_io_tag(struct scic_sds_controller *scic, + u16 io_tag) { + struct isci_host *ihost = scic_to_ihost(scic); u16 sequence; u16 index; @@ -3117,18 +3146,16 @@ enum sci_status scic_controller_free_io_tag( sequence = scic_sds_io_tag_get_sequence(io_tag); index = scic_sds_io_tag_get_index(io_tag); - if (!sci_pool_full(scic->tci_pool)) { - if (sequence == scic->io_request_sequence[index]) { - scic_sds_io_sequence_increment( - scic->io_request_sequence[index]); + /* prevent tail from passing head */ + if (isci_tci_active(ihost) == 0) + return SCI_FAILURE_INVALID_IO_TAG; - sci_pool_put(scic->tci_pool, index); + if (sequence == scic->io_request_sequence[index]) { + scic_sds_io_sequence_increment(scic->io_request_sequence[index]); - return SCI_SUCCESS; - } - } + isci_tci_free(ihost, index); + return SCI_SUCCESS; + } return SCI_FAILURE_INVALID_IO_TAG; } - - |