Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9933135 authored by Stephen M. Cameron's avatar Stephen M. Cameron Committed by Jens Axboe
Browse files

cciss: factor out cciss_enter_performant_mode



cciss: factor out cciss_enter_performant_mode

Signed-off-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJens Axboe <jaxboe@fusionio.com>
parent 0f8a6a1e
Loading
Loading
Loading
Loading
+59 −39
Original line number Diff line number Diff line
@@ -3830,54 +3830,36 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h)
	}
}

static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
{
	__u32 trans_support;
static __devinit void cciss_enter_performant_mode(ctlr_info_t *h)
{
	/* This is a bit complicated.  There are 8 registers on
	 * the controller which we write to to tell it 8 different
	 * sizes of commands which there may be.  It's a way of
	 * reducing the DMA done to fetch each command.  Encoded into
	 * each command's tag are 3 bits which communicate to the controller
	 * which of the eight sizes that command fits within.  The size of
	 * each command depends on how many scatter gather entries there are.
	 * Each SG entry requires 16 bytes.  The eight registers are programmed
	 * with the number of 16-byte blocks a command of that size requires.
	 * The smallest command possible requires 5 such 16 byte blocks.
	 * the largest command possible requires MAXSGENTRIES + 4 16-byte
	 * blocks.  Note, this only extends to the SG entries contained
	 * within the command block, and does not extend to chained blocks
	 * of SG elements.   bft[] contains the eight values we write to
	 * the registers.  They are not evenly distributed, but have more
	 * sizes for small commands, and fewer sizes for larger commands.
	 */
	__u32 trans_offset;
	int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4};
			/*
			 *  5 = 1 s/g entry or 4k
			 *  6 = 2 s/g entry or 8k
			 *  8 = 4 s/g entry or 16k
			 * 10 = 6 s/g entry or 24k
			 */
	int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4};
	unsigned long register_value;

	BUILD_BUG_ON(28 > MAXSGENTRIES + 4);

	dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
	/* Attempt to put controller into performant mode if supported */
	/* Does board support performant mode? */
	trans_support = readl(&(h->cfgtable->TransportSupport));
	if (!(trans_support & PERFORMANT_MODE))
		return;

	printk(KERN_WARNING "cciss%d: Placing controller into "
				"performant mode\n", h->ctlr);
	/* Performant mode demands commands on a 32 byte boundary
	 * pci_alloc_consistent aligns on page boundarys already.
	 * Just need to check if divisible by 32
	 */
	if ((sizeof(CommandList_struct) % 32) != 0) {
		printk(KERN_WARNING "%s %d %s\n",
			"cciss info: command size[",
			(int)sizeof(CommandList_struct),
			"] not divisible by 32, no performant mode..\n");
		return;
	}

	/* Performant mode ring buffer and supporting data structures */
	h->reply_pool = (__u64 *)pci_alloc_consistent(
		h->pdev, h->max_commands * sizeof(__u64),
		&(h->reply_pool_dhandle));

	/* Need a block fetch table for performant mode */
	h->blockFetchTable = kmalloc(((h->maxsgentries+1) *
		sizeof(__u32)), GFP_KERNEL);

	if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
		goto clean_up;

	h->reply_pool_wraparound = 1; /* spec: init to 1 */

	/* Controller spec: zero out this buffer. */
@@ -3906,18 +3888,56 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
	writel(CFGTBL_Trans_Performant,
			&(h->cfgtable->HostWrite.TransportRequest));

	h->transMethod = CFGTBL_Trans_Performant;
	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
	cciss_wait_for_mode_change_ack(h);
	register_value = readl(&(h->cfgtable->TransportActive));
	if (!(register_value & CFGTBL_Trans_Performant)) {
	if (!(register_value & CFGTBL_Trans_Performant))
		printk(KERN_WARNING "cciss: unable to get board into"
					" performant mode\n");
}

static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
{
	__u32 trans_support;

	dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
	/* Attempt to put controller into performant mode if supported */
	/* Does board support performant mode? */
	trans_support = readl(&(h->cfgtable->TransportSupport));
	if (!(trans_support & PERFORMANT_MODE))
		return;

	printk(KERN_WARNING "cciss%d: Placing controller into "
				"performant mode\n", h->ctlr);
	/* Performant mode demands commands on a 32 byte boundary
	 * pci_alloc_consistent aligns on page boundarys already.
	 * Just need to check if divisible by 32
	 */
	if ((sizeof(CommandList_struct) % 32) != 0) {
		printk(KERN_WARNING "%s %d %s\n",
			"cciss info: command size[",
			(int)sizeof(CommandList_struct),
			"] not divisible by 32, no performant mode..\n");
		return;
	}

	/* Performant mode ring buffer and supporting data structures */
	h->reply_pool = (__u64 *)pci_alloc_consistent(
		h->pdev, h->max_commands * sizeof(__u64),
		&(h->reply_pool_dhandle));

	/* Need a block fetch table for performant mode */
	h->blockFetchTable = kmalloc(((h->maxsgentries+1) *
		sizeof(__u32)), GFP_KERNEL);

	if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
		goto clean_up;

	cciss_enter_performant_mode(h);

	/* Change the access methods to the performant access methods */
	h->access = SA5_performant_access;
	h->transMethod = CFGTBL_Trans_Performant;

	return;
clean_up: