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

Commit 113156bc authored by Raghava Aditya Renukunta's avatar Raghava Aditya Renukunta Committed by Martin K. Petersen
Browse files

scsi: aacraid: Reworked aac_command_thread



Reworked aac_command_thread into aac_process_events

Signed-off-by: default avatarRaghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: default avatarDave Carroll <David.Carroll@microsemi.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f956a669
Loading
Loading
Loading
Loading
+274 −194
Original line number Diff line number Diff line
@@ -1729,96 +1729,11 @@ int aac_check_health(struct aac_dev * aac)
	return BlinkLED;
}


/**
 *	aac_command_thread	-	command processing thread
 *	@dev: Adapter to monitor
 *
 *	Waits on the commandready event in it's queue. When the event gets set
 *	it will pull FIBs off it's queue. It will continue to pull FIBs off
 *	until the queue is empty. When the queue is empty it will wait for
 *	more FIBs.
 */

int aac_command_thread(void *data)
static int get_fib_count(struct aac_dev *dev)
{
	struct aac_dev *dev = data;
	struct hw_fib *hw_fib, *hw_newfib;
	struct fib *fib, *newfib;
	struct aac_fib_context *fibctx;
	unsigned long flags;
	DECLARE_WAITQUEUE(wait, current);
	unsigned long next_jiffies = jiffies + HZ;
	unsigned long next_check_jiffies = next_jiffies;
	long difference = HZ;

	/*
	 *	We can only have one thread per adapter for AIF's.
	 */
	if (dev->aif_thread)
		return -EINVAL;

	/*
	 *	Let the DPC know it has a place to send the AIF's to.
	 */
	dev->aif_thread = 1;
	add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
	set_current_state(TASK_INTERRUPTIBLE);
	dprintk ((KERN_INFO "aac_command_thread start\n"));
	while (1) {
		spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
		while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) {
	unsigned int num = 0;
	struct list_head *entry;
			struct aac_aifcmd * aifcmd;

			set_current_state(TASK_RUNNING);

			entry = dev->queues->queue[HostNormCmdQueue].cmdq.next;
			list_del(entry);

			spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
			fib = list_entry(entry, struct fib, fiblink);
			/*
			 *	We will process the FIB here or pass it to a
			 *	worker thread that is TBD. We Really can't
			 *	do anything at this point since we don't have
			 *	anything defined for this thread to do.
			 */
			hw_fib = fib->hw_fib_va;
			memset(fib, 0, sizeof(struct fib));
			fib->type = FSAFS_NTC_FIB_CONTEXT;
			fib->size = sizeof(struct fib);
			fib->hw_fib_va = hw_fib;
			fib->data = hw_fib->data;
			fib->dev = dev;
			/*
			 *	We only handle AifRequest fibs from the adapter.
			 */
			aifcmd = (struct aac_aifcmd *) hw_fib->data;
			if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
				/* Handle Driver Notify Events */
				aac_handle_aif(dev, fib);
				*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
				aac_fib_adapter_complete(fib, (u16)sizeof(u32));
			} else {
				/* The u32 here is important and intended. We are using
				   32bit wrapping time to fit the adapter field */

				u32 time_now, time_last;
	unsigned long flagv;
				unsigned num;
				struct hw_fib ** hw_fib_pool, ** hw_fib_p;
				struct fib ** fib_pool, ** fib_p;

				/* Sniff events */
				if ((aifcmd->command ==
				     cpu_to_le32(AifCmdEventNotify)) ||
				    (aifcmd->command ==
				     cpu_to_le32(AifCmdJobProgress))) {
					aac_handle_aif(dev, fib);
				}

				time_now = jiffies/HZ;

	/*
	 * Warning: no sleep allowed while
@@ -1826,8 +1741,7 @@ int aac_command_thread(void *data)
	 * and pre-allocate a set of fibs outside the
	 * lock.
	 */
				num = le32_to_cpu(dev->init->
							r7.adapter_fibs_size)
	num = le32_to_cpu(dev->init->r7.adapter_fibs_size)
			/ sizeof(struct hw_fib); /* some extra */
	spin_lock_irqsave(&dev->fib_lock, flagv);
	entry = dev->fib_list.next;
@@ -1836,33 +1750,58 @@ int aac_command_thread(void *data)
		++num;
	}
	spin_unlock_irqrestore(&dev->fib_lock, flagv);
				hw_fib_pool = NULL;
				fib_pool = NULL;
				if (num
				 && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL)))
				 && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) {

	return num;
}

static int fillup_pools(struct aac_dev *dev, struct hw_fib **hw_fib_pool,
						struct fib **fib_pool,
						unsigned int num)
{
	struct hw_fib **hw_fib_p;
	struct fib **fib_p;
	int rcode = 1;

	hw_fib_p = hw_fib_pool;
	fib_p = fib_pool;
	while (hw_fib_p < &hw_fib_pool[num]) {
						if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) {
		*(hw_fib_p) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL);
		if (!(*(hw_fib_p++))) {
			--hw_fib_p;
			break;
		}
						if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) {

		*(fib_p) = kmalloc(sizeof(struct fib), GFP_KERNEL);
		if (!(*(fib_p++))) {
			kfree(*(--hw_fib_p));
			break;
		}
	}
					if ((num = hw_fib_p - hw_fib_pool) == 0) {
						kfree(fib_pool);
						fib_pool = NULL;
						kfree(hw_fib_pool);
						hw_fib_pool = NULL;
					}
				} else {
					kfree(hw_fib_pool);
					hw_fib_pool = NULL;

	num = hw_fib_p - hw_fib_pool;
	if (!num)
		rcode = 0;

	return rcode;
}

static void wakeup_fibctx_threads(struct aac_dev *dev,
						struct hw_fib **hw_fib_pool,
						struct fib **fib_pool,
						struct fib *fib,
						struct hw_fib *hw_fib,
						unsigned int num)
{
	unsigned long flagv;
	struct list_head *entry;
	struct hw_fib **hw_fib_p;
	struct fib **fib_p;
	u32 time_now, time_last;
	struct hw_fib *hw_newfib;
	struct fib *newfib;
	struct aac_fib_context *fibctx;

	time_now = jiffies/HZ;
	spin_lock_irqsave(&dev->fib_lock, flagv);
	entry = dev->fib_list.next;
	/*
@@ -1871,19 +1810,20 @@ int aac_command_thread(void *data)
	 * fib, and then set the event to wake up the
	 * thread that is waiting for it.
	 */

	hw_fib_p = hw_fib_pool;
	fib_p = fib_pool;
	while (entry != &dev->fib_list) {
		/*
		 * Extract the fibctx
		 */
					fibctx = list_entry(entry, struct aac_fib_context, next);
		fibctx = list_entry(entry, struct aac_fib_context,
				next);
		/*
		 * Check if the queue is getting
		 * backlogged
		 */
					if (fibctx->count > 20)
					{
		if (fibctx->count > 20) {
			/*
			 * It's *not* jiffies folks,
			 * but jiffies / HZ so do not
@@ -1905,7 +1845,12 @@ int aac_command_thread(void *data)
		 * Warning: no sleep allowed while
		 * holding spinlock
		 */
					if (hw_fib_p < &hw_fib_pool[num]) {
		if (hw_fib_p >= &hw_fib_pool[num]) {
			pr_warn("aifd: didn't allocate NewFib\n");
			entry = entry->next;
			continue;
		}

		hw_newfib = *hw_fib_p;
		*(hw_fib_p++) = NULL;
		newfib = *fib_p;
@@ -1927,9 +1872,7 @@ int aac_command_thread(void *data)
		 * thread that is waiting.
		 */
		up(&fibctx->wait_sem);
					} else {
						printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
					}

		entry = entry->next;
	}
	/*
@@ -1938,6 +1881,104 @@ int aac_command_thread(void *data)
	*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
	aac_fib_adapter_complete(fib, sizeof(u32));
	spin_unlock_irqrestore(&dev->fib_lock, flagv);

}

static void aac_process_events(struct aac_dev *dev)
{
	struct hw_fib *hw_fib;
	struct fib *fib;
	unsigned long flags;
	spinlock_t *t_lock;
	unsigned int rcode;

	t_lock = dev->queues->queue[HostNormCmdQueue].lock;
	spin_lock_irqsave(t_lock, flags);

	while (!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) {
		struct list_head *entry;
		struct aac_aifcmd *aifcmd;
		unsigned int  num;
		struct hw_fib **hw_fib_pool, **hw_fib_p;
		struct fib **fib_pool, **fib_p;

		set_current_state(TASK_RUNNING);

		entry = dev->queues->queue[HostNormCmdQueue].cmdq.next;
		list_del(entry);

		t_lock = dev->queues->queue[HostNormCmdQueue].lock;
		spin_unlock_irqrestore(t_lock, flags);

		fib = list_entry(entry, struct fib, fiblink);
		hw_fib = fib->hw_fib_va;
		/*
		 *	We will process the FIB here or pass it to a
		 *	worker thread that is TBD. We Really can't
		 *	do anything at this point since we don't have
		 *	anything defined for this thread to do.
		 */
		memset(fib, 0, sizeof(struct fib));
		fib->type = FSAFS_NTC_FIB_CONTEXT;
		fib->size = sizeof(struct fib);
		fib->hw_fib_va = hw_fib;
		fib->data = hw_fib->data;
		fib->dev = dev;
		/*
		 *	We only handle AifRequest fibs from the adapter.
		 */

		aifcmd = (struct aac_aifcmd *) hw_fib->data;
		if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
			/* Handle Driver Notify Events */
			aac_handle_aif(dev, fib);
			*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
			aac_fib_adapter_complete(fib, (u16)sizeof(u32));
			goto free_fib;
		}
		/*
		 * The u32 here is important and intended. We are using
		 * 32bit wrapping time to fit the adapter field
		 */

		/* Sniff events */
		if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)
		 || aifcmd->command == cpu_to_le32(AifCmdJobProgress)) {
			aac_handle_aif(dev, fib);
		}

		/*
		 * get number of fibs to process
		 */
		num = get_fib_count(dev);
		if (!num)
			goto free_fib;

		hw_fib_pool = kmalloc_array(num, sizeof(struct hw_fib *),
						GFP_KERNEL);
		if (!hw_fib_pool)
			goto free_fib;

		fib_pool = kmalloc_array(num, sizeof(struct fib *), GFP_KERNEL);
		if (!fib_pool)
			goto free_hw_fib_pool;

		/*
		 * Fill up fib pointer pools with actual fibs
		 * and hw_fibs
		 */
		rcode = fillup_pools(dev, hw_fib_pool, fib_pool, num);
		if (!rcode)
			goto free_mem;

		/*
		 * wakeup the thread that is waiting for
		 * the response from fw (ioctl)
		 */
		wakeup_fibctx_threads(dev, hw_fib_pool, fib_pool,
							    fib, hw_fib, num);

free_mem:
		/* Free up the remaining resources */
		hw_fib_p = hw_fib_pool;
		fib_p = fib_pool;
@@ -1947,16 +1988,55 @@ int aac_command_thread(void *data)
			++fib_p;
			++hw_fib_p;
		}
				kfree(hw_fib_pool);
		kfree(fib_pool);
			}
free_hw_fib_pool:
		kfree(hw_fib_pool);
free_fib:
		kfree(fib);
			spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
		t_lock = dev->queues->queue[HostNormCmdQueue].lock;
		spin_lock_irqsave(t_lock, flags);
	}
	/*
	 *	There are no more AIF's
	 */
		spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
	t_lock = dev->queues->queue[HostNormCmdQueue].lock;
	spin_unlock_irqrestore(t_lock, flags);
}

/**
 *	aac_command_thread	-	command processing thread
 *	@dev: Adapter to monitor
 *
 *	Waits on the commandready event in it's queue. When the event gets set
 *	it will pull FIBs off it's queue. It will continue to pull FIBs off
 *	until the queue is empty. When the queue is empty it will wait for
 *	more FIBs.
 */

int aac_command_thread(void *data)
{
	struct aac_dev *dev = data;
	DECLARE_WAITQUEUE(wait, current);
	unsigned long next_jiffies = jiffies + HZ;
	unsigned long next_check_jiffies = next_jiffies;
	long difference = HZ;

	/*
	 *	We can only have one thread per adapter for AIF's.
	 */
	if (dev->aif_thread)
		return -EINVAL;

	/*
	 *	Let the DPC know it has a place to send the AIF's to.
	 */
	dev->aif_thread = 1;
	add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
	set_current_state(TASK_INTERRUPTIBLE);
	dprintk ((KERN_INFO "aac_command_thread start\n"));
	while (1) {

		aac_process_events(dev);

		/*
		 *	Background activity