xref: /openbmc/linux/drivers/scsi/arm/msgqueue.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/drivers/acorn/scsi/msgqueue.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (C) 1997-1998 Russell King
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  message queue handling
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds #include <linux/module.h>
101da177e4SLinus Torvalds #include <linux/kernel.h>
111da177e4SLinus Torvalds #include <linux/stddef.h>
121da177e4SLinus Torvalds #include <linux/init.h>
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include "msgqueue.h"
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds /*
171da177e4SLinus Torvalds  * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
181da177e4SLinus Torvalds  * Purpose : Allocate a message queue entry
191da177e4SLinus Torvalds  * Params  : msgq - message queue to claim entry for
201da177e4SLinus Torvalds  * Returns : message queue entry or NULL.
211da177e4SLinus Torvalds  */
mqe_alloc(MsgQueue_t * msgq)221da177e4SLinus Torvalds static struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
231da177e4SLinus Torvalds {
241da177e4SLinus Torvalds 	struct msgqueue_entry *mq;
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds 	if ((mq = msgq->free) != NULL)
271da177e4SLinus Torvalds 		msgq->free = mq->next;
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds 	return mq;
301da177e4SLinus Torvalds }
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds /*
331da177e4SLinus Torvalds  * Function: void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq)
341da177e4SLinus Torvalds  * Purpose : free a message queue entry
351da177e4SLinus Torvalds  * Params  : msgq - message queue to free entry from
361da177e4SLinus Torvalds  *	     mq   - message queue entry to free
371da177e4SLinus Torvalds  */
mqe_free(MsgQueue_t * msgq,struct msgqueue_entry * mq)381da177e4SLinus Torvalds static void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq)
391da177e4SLinus Torvalds {
401da177e4SLinus Torvalds 	if (mq) {
411da177e4SLinus Torvalds 		mq->next = msgq->free;
421da177e4SLinus Torvalds 		msgq->free = mq;
431da177e4SLinus Torvalds 	}
441da177e4SLinus Torvalds }
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds /*
471da177e4SLinus Torvalds  * Function: void msgqueue_initialise(MsgQueue_t *msgq)
481da177e4SLinus Torvalds  * Purpose : initialise a message queue
491da177e4SLinus Torvalds  * Params  : msgq - queue to initialise
501da177e4SLinus Torvalds  */
msgqueue_initialise(MsgQueue_t * msgq)511da177e4SLinus Torvalds void msgqueue_initialise(MsgQueue_t *msgq)
521da177e4SLinus Torvalds {
531da177e4SLinus Torvalds 	int i;
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds 	msgq->qe = NULL;
561da177e4SLinus Torvalds 	msgq->free = &msgq->entries[0];
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds 	for (i = 0; i < NR_MESSAGES; i++)
591da177e4SLinus Torvalds 		msgq->entries[i].next = &msgq->entries[i + 1];
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds 	msgq->entries[NR_MESSAGES - 1].next = NULL;
621da177e4SLinus Torvalds }
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds /*
661da177e4SLinus Torvalds  * Function: void msgqueue_free(MsgQueue_t *msgq)
671da177e4SLinus Torvalds  * Purpose : free a queue
681da177e4SLinus Torvalds  * Params  : msgq - queue to free
691da177e4SLinus Torvalds  */
msgqueue_free(MsgQueue_t * msgq)701da177e4SLinus Torvalds void msgqueue_free(MsgQueue_t *msgq)
711da177e4SLinus Torvalds {
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds /*
751da177e4SLinus Torvalds  * Function: int msgqueue_msglength(MsgQueue_t *msgq)
761da177e4SLinus Torvalds  * Purpose : calculate the total length of all messages on the message queue
771da177e4SLinus Torvalds  * Params  : msgq - queue to examine
781da177e4SLinus Torvalds  * Returns : number of bytes of messages in queue
791da177e4SLinus Torvalds  */
msgqueue_msglength(MsgQueue_t * msgq)801da177e4SLinus Torvalds int msgqueue_msglength(MsgQueue_t *msgq)
811da177e4SLinus Torvalds {
821da177e4SLinus Torvalds 	struct msgqueue_entry *mq = msgq->qe;
831da177e4SLinus Torvalds 	int length = 0;
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds 	for (mq = msgq->qe; mq; mq = mq->next)
861da177e4SLinus Torvalds 		length += mq->msg.length;
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	return length;
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds /*
921da177e4SLinus Torvalds  * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
931da177e4SLinus Torvalds  * Purpose : return a message
941da177e4SLinus Torvalds  * Params  : msgq   - queue to obtain message from
951da177e4SLinus Torvalds  *	   : msgno  - message number
961da177e4SLinus Torvalds  * Returns : pointer to message string, or NULL
971da177e4SLinus Torvalds  */
msgqueue_getmsg(MsgQueue_t * msgq,int msgno)981da177e4SLinus Torvalds struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
991da177e4SLinus Torvalds {
1001da177e4SLinus Torvalds 	struct msgqueue_entry *mq;
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds 	for (mq = msgq->qe; mq && msgno; mq = mq->next, msgno--);
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds 	return mq ? &mq->msg : NULL;
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds /*
1081da177e4SLinus Torvalds  * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
1091da177e4SLinus Torvalds  * Purpose : add a message onto a message queue
1101da177e4SLinus Torvalds  * Params  : msgq   - queue to add message on
1111da177e4SLinus Torvalds  *	     length - length of message
1121da177e4SLinus Torvalds  *	     ...    - message bytes
1131da177e4SLinus Torvalds  * Returns : != 0 if successful
1141da177e4SLinus Torvalds  */
msgqueue_addmsg(MsgQueue_t * msgq,int length,...)1151da177e4SLinus Torvalds int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
1161da177e4SLinus Torvalds {
1171da177e4SLinus Torvalds 	struct msgqueue_entry *mq = mqe_alloc(msgq);
1181da177e4SLinus Torvalds 	va_list ap;
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 	if (mq) {
1211da177e4SLinus Torvalds 		struct msgqueue_entry **mqp;
1221da177e4SLinus Torvalds 		int i;
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds 		va_start(ap, length);
1251da177e4SLinus Torvalds 		for (i = 0; i < length; i++)
1261da177e4SLinus Torvalds 			mq->msg.msg[i] = va_arg(ap, unsigned int);
1271da177e4SLinus Torvalds 		va_end(ap);
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 		mq->msg.length = length;
1301da177e4SLinus Torvalds 		mq->msg.fifo = 0;
1311da177e4SLinus Torvalds 		mq->next = NULL;
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 		mqp = &msgq->qe;
1341da177e4SLinus Torvalds 		while (*mqp)
1351da177e4SLinus Torvalds 			mqp = &(*mqp)->next;
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 		*mqp = mq;
1381da177e4SLinus Torvalds 	}
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds 	return mq != NULL;
1411da177e4SLinus Torvalds }
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds /*
1441da177e4SLinus Torvalds  * Function: void msgqueue_flush(MsgQueue_t *msgq)
1451da177e4SLinus Torvalds  * Purpose : flush all messages from message queue
1461da177e4SLinus Torvalds  * Params  : msgq - queue to flush
1471da177e4SLinus Torvalds  */
msgqueue_flush(MsgQueue_t * msgq)1481da177e4SLinus Torvalds void msgqueue_flush(MsgQueue_t *msgq)
1491da177e4SLinus Torvalds {
1501da177e4SLinus Torvalds 	struct msgqueue_entry *mq, *mqnext;
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds 	for (mq = msgq->qe; mq; mq = mqnext) {
1531da177e4SLinus Torvalds 		mqnext = mq->next;
1541da177e4SLinus Torvalds 		mqe_free(msgq, mq);
1551da177e4SLinus Torvalds 	}
1561da177e4SLinus Torvalds 	msgq->qe = NULL;
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds EXPORT_SYMBOL(msgqueue_initialise);
1601da177e4SLinus Torvalds EXPORT_SYMBOL(msgqueue_free);
1611da177e4SLinus Torvalds EXPORT_SYMBOL(msgqueue_msglength);
1621da177e4SLinus Torvalds EXPORT_SYMBOL(msgqueue_getmsg);
1631da177e4SLinus Torvalds EXPORT_SYMBOL(msgqueue_addmsg);
1641da177e4SLinus Torvalds EXPORT_SYMBOL(msgqueue_flush);
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds MODULE_AUTHOR("Russell King");
1671da177e4SLinus Torvalds MODULE_DESCRIPTION("SCSI message queue handling");
1681da177e4SLinus Torvalds MODULE_LICENSE("GPL");
169