1*1a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 2b2fb06fcSJack Steiner 3b2fb06fcSJack Steiner /* 4b2fb06fcSJack Steiner * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 5b2fb06fcSJack Steiner */ 6b2fb06fcSJack Steiner #ifndef __GRU_KSERVICES_H_ 7b2fb06fcSJack Steiner #define __GRU_KSERVICES_H_ 8b2fb06fcSJack Steiner 9b2fb06fcSJack Steiner 10b2fb06fcSJack Steiner /* 11b2fb06fcSJack Steiner * Message queues using the GRU to send/receive messages. 12b2fb06fcSJack Steiner * 13b2fb06fcSJack Steiner * These function allow the user to create a message queue for 14b2fb06fcSJack Steiner * sending/receiving 1 or 2 cacheline messages using the GRU. 15b2fb06fcSJack Steiner * 16b2fb06fcSJack Steiner * Processes SENDING messages will use a kernel CBR/DSR to send 17b2fb06fcSJack Steiner * the message. This is transparent to the caller. 18b2fb06fcSJack Steiner * 19b2fb06fcSJack Steiner * The receiver does not use any GRU resources. 20b2fb06fcSJack Steiner * 21b2fb06fcSJack Steiner * The functions support: 22b2fb06fcSJack Steiner * - single receiver 23b2fb06fcSJack Steiner * - multiple senders 24b2fb06fcSJack Steiner * - cross partition message 25b2fb06fcSJack Steiner * 26b2fb06fcSJack Steiner * Missing features ZZZ: 27b2fb06fcSJack Steiner * - user options for dealing with timeouts, queue full, etc. 28b2fb06fcSJack Steiner * - gru_create_message_queue() needs interrupt vector info 29b2fb06fcSJack Steiner */ 30b2fb06fcSJack Steiner 316f2584f4SJack Steiner struct gru_message_queue_desc { 326f2584f4SJack Steiner void *mq; /* message queue vaddress */ 336f2584f4SJack Steiner unsigned long mq_gpa; /* global address of mq */ 346f2584f4SJack Steiner int qlines; /* queue size in CL */ 356f2584f4SJack Steiner int interrupt_vector; /* interrupt vector */ 366f2584f4SJack Steiner int interrupt_pnode; /* pnode for interrupt */ 376f2584f4SJack Steiner int interrupt_apicid; /* lapicid for interrupt */ 386f2584f4SJack Steiner }; 396f2584f4SJack Steiner 40b2fb06fcSJack Steiner /* 41b2fb06fcSJack Steiner * Initialize a user allocated chunk of memory to be used as 42b2fb06fcSJack Steiner * a message queue. The caller must ensure that the queue is 43b2fb06fcSJack Steiner * in contiguous physical memory and is cacheline aligned. 44b2fb06fcSJack Steiner * 45b2fb06fcSJack Steiner * Message queue size is the total number of bytes allocated 46b2fb06fcSJack Steiner * to the queue including a 2 cacheline header that is used 47b2fb06fcSJack Steiner * to manage the queue. 48b2fb06fcSJack Steiner * 49b2fb06fcSJack Steiner * Input: 506f2584f4SJack Steiner * mqd pointer to message queue descriptor 516f2584f4SJack Steiner * p pointer to user allocated mesq memory. 52b2fb06fcSJack Steiner * bytes size of message queue in bytes 536f2584f4SJack Steiner * vector interrupt vector (zero if no interrupts) 546f2584f4SJack Steiner * nasid nasid of blade where interrupt is delivered 556f2584f4SJack Steiner * apicid apicid of cpu for interrupt 56b2fb06fcSJack Steiner * 57b2fb06fcSJack Steiner * Errors: 58b2fb06fcSJack Steiner * 0 OK 59b2fb06fcSJack Steiner * >0 error 60b2fb06fcSJack Steiner */ 616f2584f4SJack Steiner extern int gru_create_message_queue(struct gru_message_queue_desc *mqd, 626f2584f4SJack Steiner void *p, unsigned int bytes, int nasid, int vector, int apicid); 63b2fb06fcSJack Steiner 64b2fb06fcSJack Steiner /* 65b2fb06fcSJack Steiner * Send a message to a message queue. 66b2fb06fcSJack Steiner * 67b2fb06fcSJack Steiner * Note: The message queue transport mechanism uses the first 32 68b2fb06fcSJack Steiner * bits of the message. Users should avoid using these bits. 69b2fb06fcSJack Steiner * 70b2fb06fcSJack Steiner * 71b2fb06fcSJack Steiner * Input: 726f2584f4SJack Steiner * mqd pointer to message queue descriptor 73b2fb06fcSJack Steiner * mesg pointer to message. Must be 64-bit aligned 74b2fb06fcSJack Steiner * bytes size of message in bytes 75b2fb06fcSJack Steiner * 76b2fb06fcSJack Steiner * Output: 77b2fb06fcSJack Steiner * 0 message sent 78b2fb06fcSJack Steiner * >0 Send failure - see error codes below 79b2fb06fcSJack Steiner * 80b2fb06fcSJack Steiner */ 816f2584f4SJack Steiner extern int gru_send_message_gpa(struct gru_message_queue_desc *mqd, 826f2584f4SJack Steiner void *mesg, unsigned int bytes); 83b2fb06fcSJack Steiner 84b2fb06fcSJack Steiner /* Status values for gru_send_message() */ 85b2fb06fcSJack Steiner #define MQE_OK 0 /* message sent successfully */ 86b2fb06fcSJack Steiner #define MQE_CONGESTION 1 /* temporary congestion, try again */ 87b2fb06fcSJack Steiner #define MQE_QUEUE_FULL 2 /* queue is full */ 88b2fb06fcSJack Steiner #define MQE_UNEXPECTED_CB_ERR 3 /* unexpected CB error */ 89b2fb06fcSJack Steiner #define MQE_PAGE_OVERFLOW 10 /* BUG - queue overflowed a page */ 90b2fb06fcSJack Steiner #define MQE_BUG_NO_RESOURCES 11 /* BUG - could not alloc GRU cb/dsr */ 91b2fb06fcSJack Steiner 92b2fb06fcSJack Steiner /* 93b2fb06fcSJack Steiner * Advance the receive pointer for the message queue to the next message. 94b2fb06fcSJack Steiner * Note: current API requires messages to be gotten & freed in order. Future 95b2fb06fcSJack Steiner * API extensions may allow for out-of-order freeing. 96b2fb06fcSJack Steiner * 97b2fb06fcSJack Steiner * Input 986f2584f4SJack Steiner * mqd pointer to message queue descriptor 99b2fb06fcSJack Steiner * mesq message being freed 100b2fb06fcSJack Steiner */ 1016f2584f4SJack Steiner extern void gru_free_message(struct gru_message_queue_desc *mqd, 1026f2584f4SJack Steiner void *mesq); 103b2fb06fcSJack Steiner 104b2fb06fcSJack Steiner /* 105b2fb06fcSJack Steiner * Get next message from message queue. Returns pointer to 106b2fb06fcSJack Steiner * message OR NULL if no message present. 107b2fb06fcSJack Steiner * User must call gru_free_message() after message is processed 108b2fb06fcSJack Steiner * in order to move the queue pointers to next message. 109b2fb06fcSJack Steiner * 110b2fb06fcSJack Steiner * Input 1116f2584f4SJack Steiner * mqd pointer to message queue descriptor 112b2fb06fcSJack Steiner * 113b2fb06fcSJack Steiner * Output: 114b2fb06fcSJack Steiner * p pointer to message 115b2fb06fcSJack Steiner * NULL no message available 116b2fb06fcSJack Steiner */ 1176f2584f4SJack Steiner extern void *gru_get_next_message(struct gru_message_queue_desc *mqd); 118b2fb06fcSJack Steiner 119b2fb06fcSJack Steiner 120b2fb06fcSJack Steiner /* 121289750d1SRobin Holt * Read a GRU global GPA. Source can be located in a remote partition. 122289750d1SRobin Holt * 123289750d1SRobin Holt * Input: 124289750d1SRobin Holt * value memory address where MMR value is returned 125289750d1SRobin Holt * gpa source numalink physical address of GPA 126289750d1SRobin Holt * 127289750d1SRobin Holt * Output: 128289750d1SRobin Holt * 0 OK 129289750d1SRobin Holt * >0 error 130289750d1SRobin Holt */ 131289750d1SRobin Holt int gru_read_gpa(unsigned long *value, unsigned long gpa); 132289750d1SRobin Holt 133289750d1SRobin Holt 134289750d1SRobin Holt /* 135b2fb06fcSJack Steiner * Copy data using the GRU. Source or destination can be located in a remote 136b2fb06fcSJack Steiner * partition. 137b2fb06fcSJack Steiner * 138b2fb06fcSJack Steiner * Input: 139b2fb06fcSJack Steiner * dest_gpa destination global physical address 140b2fb06fcSJack Steiner * src_gpa source global physical address 141b2fb06fcSJack Steiner * bytes number of bytes to copy 142b2fb06fcSJack Steiner * 143b2fb06fcSJack Steiner * Output: 144b2fb06fcSJack Steiner * 0 OK 145b2fb06fcSJack Steiner * >0 error 146b2fb06fcSJack Steiner */ 147b2fb06fcSJack Steiner extern int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa, 148b2fb06fcSJack Steiner unsigned int bytes); 149b2fb06fcSJack Steiner 1509120dec4SJack Steiner /* 1519120dec4SJack Steiner * Reserve GRU resources to be used asynchronously. 1529120dec4SJack Steiner * 1539120dec4SJack Steiner * input: 1549120dec4SJack Steiner * blade_id - blade on which resources should be reserved 1559120dec4SJack Steiner * cbrs - number of CBRs 1569120dec4SJack Steiner * dsr_bytes - number of DSR bytes needed 1579120dec4SJack Steiner * cmp - completion structure for waiting for 1589120dec4SJack Steiner * async completions 1599120dec4SJack Steiner * output: 1609120dec4SJack Steiner * handle to identify resource 1619120dec4SJack Steiner * (0 = no resources) 1629120dec4SJack Steiner */ 1639120dec4SJack Steiner extern unsigned long gru_reserve_async_resources(int blade_id, int cbrs, int dsr_bytes, 1649120dec4SJack Steiner struct completion *cmp); 1659120dec4SJack Steiner 1669120dec4SJack Steiner /* 1679120dec4SJack Steiner * Release async resources previously reserved. 1689120dec4SJack Steiner * 1699120dec4SJack Steiner * input: 1709120dec4SJack Steiner * han - handle to identify resources 1719120dec4SJack Steiner */ 1729120dec4SJack Steiner extern void gru_release_async_resources(unsigned long han); 1739120dec4SJack Steiner 1749120dec4SJack Steiner /* 1759120dec4SJack Steiner * Wait for async GRU instructions to complete. 1769120dec4SJack Steiner * 1779120dec4SJack Steiner * input: 1789120dec4SJack Steiner * han - handle to identify resources 1799120dec4SJack Steiner */ 1809120dec4SJack Steiner extern void gru_wait_async_cbr(unsigned long han); 1819120dec4SJack Steiner 1829120dec4SJack Steiner /* 1839120dec4SJack Steiner * Lock previous reserved async GRU resources 1849120dec4SJack Steiner * 1859120dec4SJack Steiner * input: 1869120dec4SJack Steiner * han - handle to identify resources 1879120dec4SJack Steiner * output: 1889120dec4SJack Steiner * cb - pointer to first CBR 1899120dec4SJack Steiner * dsr - pointer to first DSR 1909120dec4SJack Steiner */ 1919120dec4SJack Steiner extern void gru_lock_async_resource(unsigned long han, void **cb, void **dsr); 1929120dec4SJack Steiner 1939120dec4SJack Steiner /* 1949120dec4SJack Steiner * Unlock previous reserved async GRU resources 1959120dec4SJack Steiner * 1969120dec4SJack Steiner * input: 1979120dec4SJack Steiner * han - handle to identify resources 1989120dec4SJack Steiner */ 1999120dec4SJack Steiner extern void gru_unlock_async_resource(unsigned long han); 2009120dec4SJack Steiner 201b2fb06fcSJack Steiner #endif /* __GRU_KSERVICES_H_ */ 202