Files @ bd21c8aa7237
Branch filter:

Location: vmkdrivers/vmkdrivers/src_9/drivers/scsi/fnic/fnic_tag_map.c - annotation

unknown
ESXi-6.0.0b
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
763922b5834e
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
763922b5834e
95e39e5412bd
763922b5834e
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
95e39e5412bd
763922b5834e
95e39e5412bd
763922b5834e
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
95e39e5412bd
763922b5834e
763922b5834e
763922b5834e
763922b5834e
763922b5834e
/*
 * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
 *
 * This file is derived from block/blk-tag.c, scsi/scsi_tcq.h, bitops.h and
 * others from Linux release 2.6.27-rc5, and shares copyright with the
 * original authors (Jens Axboe and others).
 *
 * This program is free software; you may redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * [Insert appropriate license here when releasing outside of Cisco]
 * $Id: fnic_tag_map.c 122966 2013-02-07 20:43:04Z hiralpat $
 */

#include "fnic_tag_map.h"

static int fnic_init_tag_map(struct fnic_host_tag *fht, int depth)
{
	struct scsi_cmnd **tag_index = NULL;
	unsigned long *tag_map = NULL;
	int nr_ulongs;

	tag_index = kzalloc(depth * sizeof(struct scsi_cmnd *), GFP_ATOMIC);
	if (!tag_index)
		return -ENOMEM;
		/* goto fail; */

	nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
	tag_map = kzalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
	if (!tag_map)
		goto fail;

	fht->max_depth = depth;
	fht->tag_index = tag_index;
	fht->tag_map = tag_map;
	fht->next_tag = 1;

	return 0;
fail:
	if (tag_index) {
		kfree(tag_index);
	}
	if (tag_map) {
		kfree(tag_map);
	}
	return -ENOMEM;
}

int fnic_init_shared_tag_map(struct Scsi_Host *shost, int depth)
{
	struct fnic_host_tag *fht;
	struct fc_lport *lp = shost_priv(shost);
	struct fnic *fnic = lport_priv(lp);

	fht = kmalloc(sizeof(struct fnic_host_tag), GFP_ATOMIC);
	if (!fht)
		goto fail;

	if (fnic_init_tag_map(fht, depth))
		goto fail;

	fnic->tags = fht;

	return 0;
fail:
	kfree(fht);
	return 1;
}

static inline void fnic_free_tags(struct fnic_host_tag *fht)
{

	BUG_ON(find_first_bit(fht->tag_map, fht->max_depth) <
	       fht->max_depth);

	kfree(fht->tag_index);
	fht->tag_index = NULL;

	kfree(fht->tag_map);
	fht->tag_map = NULL;

	kfree(fht);

}

void fnic_free_shared_tag_map(struct Scsi_Host *shost)
{
	struct fc_lport *lp = shost_priv(shost);
	struct fnic *fnic = lport_priv(lp);

	fnic_free_tags(fnic->tags);
}

int fnic_host_start_tag(struct Scsi_Host *shost, struct scsi_cmnd *sc)
{

	struct fc_lport *lp = shost_priv(shost);
	struct fnic *fnic = lport_priv(lp);
	struct fnic_host_tag *fht = fnic->tags;
	struct fnic_stats fnic_stats = fnic->fnic_stats;
	int tag;
	unsigned long flags;

	spin_lock_irqsave(&fnic->fnic_lock, flags);
	tag = find_next_zero_bit(fht->tag_map, fht->max_depth, fht->next_tag);
	if (((tag < 1) || (tag >= fht->max_depth)) && (fht->next_tag > 1)) {
		tag = find_next_zero_bit(fht->tag_map, fht->max_depth, 1);
	}
	if ((tag < 1) || (tag >= fht->max_depth)) {
		atomic64_inc(&fnic_stats.io_stats.tag_alloc_failures);
		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
		printk(KERN_ERR "Tag allocation failure next_tag (0x%x)\n",
		       fht->next_tag);
		return SCSI_NO_TAG;
	}
	fht->next_tag = (tag < (fht->max_depth - 1)) ? tag + 1 : 1;
	set_bit(tag, fht->tag_map);
	fht->tag_index[tag] = sc;
	CMD_TAG(sc) = tag;
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);

	return tag;
}

void fnic_host_end_tag(struct Scsi_Host *shost, struct scsi_cmnd *sc)
{
	struct fc_lport *lp = shost_priv(shost);
	struct fnic *fnic = lport_priv(lp);
	struct fnic_host_tag *fht = fnic->tags;
	int tag = CMD_TAG(sc);
	unsigned long flags;

	BUG_ON(tag == SCSI_NO_TAG);

	if (unlikely((tag < 1) || (tag >= fht->max_depth))) {
		printk(KERN_ERR "Tag 0x%x is out of range for sc 0x%p\n",
		       tag, sc);
		return;
	}

	spin_lock_irqsave(&fnic->fnic_lock, flags);
	if (unlikely(fht->tag_index[tag] == NULL)) {
		printk(KERN_ERR "Tag 0x%x is missing sc 0x%p\n",
		       tag, sc);
	}
	if (unlikely(fht->tag_index[tag] != sc)) {
		printk(KERN_ERR "Tag 0x%x does not match sc 0x%p  0x%p\n",
		      tag, sc, fht->tag_index[tag]);
		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
		return;
	}

	fht->tag_index[tag] = NULL;
	CMD_TAG(sc) = SCSI_NO_TAG;

	if (unlikely(!test_bit(tag, fht->tag_map))) {
		printk(KERN_ERR "Attempt to clear non-busy tag (0x%x)\n", tag);
		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
		return;
	}

	clear_bit(tag, fht->tag_map);
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);
}

static inline struct scsi_cmnd *fnic_find_tag(struct fnic_host_tag *fht,
					      int tag)
{
	/* Called with fnic_lock held */
	if (unlikely(fht == NULL || tag >= fht->max_depth || tag < 1))
		return NULL;
	return fht->tag_index[tag];
}

struct scsi_cmnd *fnic_host_find_tag(struct Scsi_Host *shost, int tag)
{
	struct fc_lport *lp = shost_priv(shost);
	struct fnic *fnic = lport_priv(lp);

	/* Called with fnic_lock held */
	if (tag != SCSI_NO_TAG)
		return fnic_find_tag(fnic->tags, tag);
	return NULL;
}