// SPDX-License-Identifier: GPL-2.0-only/* * IBM Accelerator Family 'GenWQE' * * (C) Copyright IBM Corp. 2013 * * Author: Frank Haverkamp <haver@linux.vnet.ibm.com> * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com> * Author: Michael Jung <mijung@gmx.net> * Author: Michael Ruettger <michael@ibmra.de> *//* * Device Driver Control Block (DDCB) queue support. Definition of * interrupt handlers for queue support as well as triggering the * health monitor code in case of problems. The current hardware uses * an MSI interrupt which is shared between error handling and * functional code. */#include<linux/types.h>#include<linux/sched.h>#include<linux/wait.h>#include<linux/pci.h>#include<linux/string.h>#include<linux/dma-mapping.h>#include<linux/delay.h>#include<linux/module.h>#include<linux/interrupt.h>#include<linux/crc-itu-t.h>#include"card_base.h"#include"card_ddcb.h"/* * N: next DDCB, this is where the next DDCB will be put. * A: active DDCB, this is where the code will look for the next completion. * x: DDCB is enqueued, we are waiting for its completion. * Situation (1): Empty queue * +---+---+---+---+---+---+---+---+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | | | | | | | | | * +---+---+---+---+---+---+---+---+ * A/N * enqueued_ddcbs = A - N = 2 - 2 = 0 * * Situation (2): Wrapped, N > A * +---+---+---+---+---+---+---+---+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | | | x | x | | | | | * +---+---+---+---+---+---+---+---+ * A N * enqueued_ddcbs = N - A = 4 - 2 = 2 * * Situation (3): Queue wrapped, A > N * +---+---+---+---+---+---+---+---+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | x | x | | | x | x | x | x | * +---+---+---+---+---+---+---+---+ * N A * enqueued_ddcbs = queue_max - (A - N) = 8 - (4 - 2) = 6 * * Situation (4a): Queue full N > A * +---+---+---+---+---+---+---+---+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | x | x | x | x | x | x | x | | * +---+---+---+---+---+---+---+---+ * A N * * enqueued_ddcbs = N - A = 7 - 0 = 7 * * Situation (4a): Queue full A > N * +---+---+---+---+---+---+---+---+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | x | x | x | | x | x | x | x | * +---+---+---+---+---+---+---+---+ * N A * enqueued_ddcbs = queue_max - (A - N) = 8 - (4 - 3) = 7 */staticintqueue_empty(structddcb_queue*queue){returnqueue->ddcb_next==queue->ddcb_act;}staticintqueue_enqueued_ddcbs(structddcb_queue*queue){if(queue->ddcb_next>=queue->ddcb_act)returnqueue->ddcb_next-queue->ddcb_act;returnqueue->ddcb_max-(queue->ddcb_act-queue->ddcb_next);}staticintqueue_free_ddcbs(structddcb_queue*que