xref: /openbmc/linux/include/linux/mhi_ep.h (revision ad671dfc)
1d434743eSManivannan Sadhasivam /* SPDX-License-Identifier: GPL-2.0 */
2d434743eSManivannan Sadhasivam /*
3d434743eSManivannan Sadhasivam  * Copyright (c) 2022, Linaro Ltd.
4d434743eSManivannan Sadhasivam  *
5d434743eSManivannan Sadhasivam  */
6d434743eSManivannan Sadhasivam #ifndef _MHI_EP_H_
7d434743eSManivannan Sadhasivam #define _MHI_EP_H_
8d434743eSManivannan Sadhasivam 
9d434743eSManivannan Sadhasivam #include <linux/dma-direction.h>
10d434743eSManivannan Sadhasivam #include <linux/mhi.h>
11d434743eSManivannan Sadhasivam 
12d434743eSManivannan Sadhasivam #define MHI_EP_DEFAULT_MTU 0x8000
13d434743eSManivannan Sadhasivam 
14d434743eSManivannan Sadhasivam /**
15d434743eSManivannan Sadhasivam  * struct mhi_ep_channel_config - Channel configuration structure for controller
16d434743eSManivannan Sadhasivam  * @name: The name of this channel
17d434743eSManivannan Sadhasivam  * @num: The number assigned to this channel
18d434743eSManivannan Sadhasivam  * @num_elements: The number of elements that can be queued to this channel
19d434743eSManivannan Sadhasivam  * @dir: Direction that data may flow on this channel
20d434743eSManivannan Sadhasivam  */
21d434743eSManivannan Sadhasivam struct mhi_ep_channel_config {
22d434743eSManivannan Sadhasivam 	char *name;
23d434743eSManivannan Sadhasivam 	u32 num;
24d434743eSManivannan Sadhasivam 	u32 num_elements;
25d434743eSManivannan Sadhasivam 	enum dma_data_direction dir;
26d434743eSManivannan Sadhasivam };
27d434743eSManivannan Sadhasivam 
28d434743eSManivannan Sadhasivam /**
29d434743eSManivannan Sadhasivam  * struct mhi_ep_cntrl_config - MHI Endpoint controller configuration
30d434743eSManivannan Sadhasivam  * @mhi_version: MHI spec version supported by the controller
31d434743eSManivannan Sadhasivam  * @max_channels: Maximum number of channels supported
32d434743eSManivannan Sadhasivam  * @num_channels: Number of channels defined in @ch_cfg
33d434743eSManivannan Sadhasivam  * @ch_cfg: Array of defined channels
34d434743eSManivannan Sadhasivam  */
35d434743eSManivannan Sadhasivam struct mhi_ep_cntrl_config {
36d434743eSManivannan Sadhasivam 	u32 mhi_version;
37d434743eSManivannan Sadhasivam 	u32 max_channels;
38d434743eSManivannan Sadhasivam 	u32 num_channels;
39d434743eSManivannan Sadhasivam 	const struct mhi_ep_channel_config *ch_cfg;
40d434743eSManivannan Sadhasivam };
41d434743eSManivannan Sadhasivam 
42d434743eSManivannan Sadhasivam /**
43d434743eSManivannan Sadhasivam  * struct mhi_ep_db_info - MHI Endpoint doorbell info
44d434743eSManivannan Sadhasivam  * @mask: Mask of the doorbell interrupt
45d434743eSManivannan Sadhasivam  * @status: Status of the doorbell interrupt
46d434743eSManivannan Sadhasivam  */
47d434743eSManivannan Sadhasivam struct mhi_ep_db_info {
48d434743eSManivannan Sadhasivam 	u32 mask;
49d434743eSManivannan Sadhasivam 	u32 status;
50d434743eSManivannan Sadhasivam };
51d434743eSManivannan Sadhasivam 
52d434743eSManivannan Sadhasivam /**
53*ad671dfcSManivannan Sadhasivam  * struct mhi_ep_buf_info - MHI Endpoint transfer buffer info
54*ad671dfcSManivannan Sadhasivam  * @dev_addr: Address of the buffer in endpoint
55*ad671dfcSManivannan Sadhasivam  * @host_addr: Address of the bufffer in host
56*ad671dfcSManivannan Sadhasivam  * @size: Size of the buffer
57*ad671dfcSManivannan Sadhasivam  */
58*ad671dfcSManivannan Sadhasivam struct mhi_ep_buf_info {
59*ad671dfcSManivannan Sadhasivam 	void *dev_addr;
60*ad671dfcSManivannan Sadhasivam 	u64 host_addr;
61*ad671dfcSManivannan Sadhasivam 	size_t size;
62*ad671dfcSManivannan Sadhasivam };
63*ad671dfcSManivannan Sadhasivam 
64*ad671dfcSManivannan Sadhasivam /**
65d434743eSManivannan Sadhasivam  * struct mhi_ep_cntrl - MHI Endpoint controller structure
66d434743eSManivannan Sadhasivam  * @cntrl_dev: Pointer to the struct device of physical bus acting as the MHI
67d434743eSManivannan Sadhasivam  *             Endpoint controller
68d434743eSManivannan Sadhasivam  * @mhi_dev: MHI Endpoint device instance for the controller
69d434743eSManivannan Sadhasivam  * @mmio: MMIO region containing the MHI registers
70d434743eSManivannan Sadhasivam  * @mhi_chan: Points to the channel configuration table
71d434743eSManivannan Sadhasivam  * @mhi_event: Points to the event ring configurations table
72d434743eSManivannan Sadhasivam  * @mhi_cmd: Points to the command ring configurations table
73d434743eSManivannan Sadhasivam  * @sm: MHI Endpoint state machine
74961aeb68SManivannan Sadhasivam  * @ch_ctx_cache: Cache of host channel context data structure
75961aeb68SManivannan Sadhasivam  * @ev_ctx_cache: Cache of host event context data structure
76961aeb68SManivannan Sadhasivam  * @cmd_ctx_cache: Cache of host command context data structure
77e9e4da23SManivannan Sadhasivam  * @ch_ctx_host_pa: Physical address of host channel context data structure
78e9e4da23SManivannan Sadhasivam  * @ev_ctx_host_pa: Physical address of host event context data structure
79e9e4da23SManivannan Sadhasivam  * @cmd_ctx_host_pa: Physical address of host command context data structure
80fb3a26b7SManivannan Sadhasivam  * @ch_ctx_cache_phys: Physical address of the host channel context cache
81fb3a26b7SManivannan Sadhasivam  * @ev_ctx_cache_phys: Physical address of the host event context cache
82fb3a26b7SManivannan Sadhasivam  * @cmd_ctx_cache_phys: Physical address of the host command context cache
83e9e4da23SManivannan Sadhasivam  * @chdb: Array of channel doorbell interrupt info
84961aeb68SManivannan Sadhasivam  * @event_lock: Lock for protecting event rings
85f9baa4f7SManivannan Sadhasivam  * @state_lock: Lock for protecting state transitions
861ddc7618SManivannan Sadhasivam  * @list_lock: Lock for protecting state transition and channel doorbell lists
87f9baa4f7SManivannan Sadhasivam  * @st_transition_list: List of state transitions
884799e71bSManivannan Sadhasivam  * @ch_db_list: List of queued channel doorbells
89f9baa4f7SManivannan Sadhasivam  * @wq: Dedicated workqueue for handling rings and state changes
90f9baa4f7SManivannan Sadhasivam  * @state_work: State transition worker
917a97b6b4SManivannan Sadhasivam  * @reset_work: Worker for MHI Endpoint reset
92e8275690SManivannan Sadhasivam  * @cmd_ring_work: Worker for processing command rings
9303c0bb8eSManivannan Sadhasivam  * @ch_ring_work: Worker for processing channel rings
94d434743eSManivannan Sadhasivam  * @raise_irq: CB function for raising IRQ to the host
95d434743eSManivannan Sadhasivam  * @alloc_map: CB function for allocating memory in endpoint for storing host context and mapping it
96d434743eSManivannan Sadhasivam  * @unmap_free: CB function to unmap and free the allocated memory in endpoint for storing host context
97d434743eSManivannan Sadhasivam  * @read_from_host: CB function for reading from host memory from endpoint
98d434743eSManivannan Sadhasivam  * @write_to_host: CB function for writing to host memory from endpoint
99d434743eSManivannan Sadhasivam  * @mhi_state: MHI Endpoint state
100d434743eSManivannan Sadhasivam  * @max_chan: Maximum channels supported by the endpoint controller
101d434743eSManivannan Sadhasivam  * @mru: MRU (Maximum Receive Unit) value of the endpoint controller
102e9e4da23SManivannan Sadhasivam  * @event_rings: Number of event rings supported by the endpoint controller
103e9e4da23SManivannan Sadhasivam  * @hw_event_rings: Number of hardware event rings supported by the endpoint controller
104e9e4da23SManivannan Sadhasivam  * @chdb_offset: Channel doorbell offset set by the host
105e9e4da23SManivannan Sadhasivam  * @erdb_offset: Event ring doorbell offset set by the host
106d434743eSManivannan Sadhasivam  * @index: MHI Endpoint controller index
1074799e71bSManivannan Sadhasivam  * @irq: IRQ used by the endpoint controller
108fb3a26b7SManivannan Sadhasivam  * @enabled: Check if the endpoint controller is enabled or not
109d434743eSManivannan Sadhasivam  */
110d434743eSManivannan Sadhasivam struct mhi_ep_cntrl {
111d434743eSManivannan Sadhasivam 	struct device *cntrl_dev;
112d434743eSManivannan Sadhasivam 	struct mhi_ep_device *mhi_dev;
113d434743eSManivannan Sadhasivam 	void __iomem *mmio;
114d434743eSManivannan Sadhasivam 
115d434743eSManivannan Sadhasivam 	struct mhi_ep_chan *mhi_chan;
116d434743eSManivannan Sadhasivam 	struct mhi_ep_event *mhi_event;
117d434743eSManivannan Sadhasivam 	struct mhi_ep_cmd *mhi_cmd;
118d434743eSManivannan Sadhasivam 	struct mhi_ep_sm *sm;
119d434743eSManivannan Sadhasivam 
120961aeb68SManivannan Sadhasivam 	struct mhi_chan_ctxt *ch_ctx_cache;
121961aeb68SManivannan Sadhasivam 	struct mhi_event_ctxt *ev_ctx_cache;
122961aeb68SManivannan Sadhasivam 	struct mhi_cmd_ctxt *cmd_ctx_cache;
123e9e4da23SManivannan Sadhasivam 	u64 ch_ctx_host_pa;
124e9e4da23SManivannan Sadhasivam 	u64 ev_ctx_host_pa;
125e9e4da23SManivannan Sadhasivam 	u64 cmd_ctx_host_pa;
126fb3a26b7SManivannan Sadhasivam 	phys_addr_t ch_ctx_cache_phys;
127fb3a26b7SManivannan Sadhasivam 	phys_addr_t ev_ctx_cache_phys;
128fb3a26b7SManivannan Sadhasivam 	phys_addr_t cmd_ctx_cache_phys;
129e9e4da23SManivannan Sadhasivam 
130e9e4da23SManivannan Sadhasivam 	struct mhi_ep_db_info chdb[4];
131961aeb68SManivannan Sadhasivam 	struct mutex event_lock;
1321ddc7618SManivannan Sadhasivam 	struct mutex state_lock;
133f9baa4f7SManivannan Sadhasivam 	spinlock_t list_lock;
134f9baa4f7SManivannan Sadhasivam 
135f9baa4f7SManivannan Sadhasivam 	struct list_head st_transition_list;
1364799e71bSManivannan Sadhasivam 	struct list_head ch_db_list;
137f9baa4f7SManivannan Sadhasivam 
138f9baa4f7SManivannan Sadhasivam 	struct workqueue_struct *wq;
139f9baa4f7SManivannan Sadhasivam 	struct work_struct state_work;
1407a97b6b4SManivannan Sadhasivam 	struct work_struct reset_work;
141e8275690SManivannan Sadhasivam 	struct work_struct cmd_ring_work;
14203c0bb8eSManivannan Sadhasivam 	struct work_struct ch_ring_work;
143bd4f6f1fSManivannan Sadhasivam 	struct kmem_cache *ring_item_cache;
144bd4f6f1fSManivannan Sadhasivam 	struct kmem_cache *ev_ring_el_cache;
145bd4f6f1fSManivannan Sadhasivam 	struct kmem_cache *tre_buf_cache;
146e9e4da23SManivannan Sadhasivam 
147d434743eSManivannan Sadhasivam 	void (*raise_irq)(struct mhi_ep_cntrl *mhi_cntrl, u32 vector);
148d434743eSManivannan Sadhasivam 	int (*alloc_map)(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, phys_addr_t *phys_ptr,
149d434743eSManivannan Sadhasivam 			 void __iomem **virt, size_t size);
150d434743eSManivannan Sadhasivam 	void (*unmap_free)(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, phys_addr_t phys,
151d434743eSManivannan Sadhasivam 			   void __iomem *virt, size_t size);
152*ad671dfcSManivannan Sadhasivam 	int (*read_from_host)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info);
153*ad671dfcSManivannan Sadhasivam 	int (*write_to_host)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info);
154d434743eSManivannan Sadhasivam 
155d434743eSManivannan Sadhasivam 	enum mhi_state mhi_state;
156d434743eSManivannan Sadhasivam 
157d434743eSManivannan Sadhasivam 	u32 max_chan;
158d434743eSManivannan Sadhasivam 	u32 mru;
159e9e4da23SManivannan Sadhasivam 	u32 event_rings;
160e9e4da23SManivannan Sadhasivam 	u32 hw_event_rings;
161e9e4da23SManivannan Sadhasivam 	u32 chdb_offset;
162e9e4da23SManivannan Sadhasivam 	u32 erdb_offset;
163d434743eSManivannan Sadhasivam 	u32 index;
1644799e71bSManivannan Sadhasivam 	int irq;
165fb3a26b7SManivannan Sadhasivam 	bool enabled;
166d434743eSManivannan Sadhasivam };
167d434743eSManivannan Sadhasivam 
168d434743eSManivannan Sadhasivam /**
169d434743eSManivannan Sadhasivam  * struct mhi_ep_device - Structure representing an MHI Endpoint device that binds
170d434743eSManivannan Sadhasivam  *                     to channels or is associated with controllers
171d434743eSManivannan Sadhasivam  * @dev: Driver model device node for the MHI Endpoint device
172d434743eSManivannan Sadhasivam  * @mhi_cntrl: Controller the device belongs to
173d434743eSManivannan Sadhasivam  * @id: Pointer to MHI Endpoint device ID struct
174d434743eSManivannan Sadhasivam  * @name: Name of the associated MHI Endpoint device
175ee0360b2SManivannan Sadhasivam  * @ul_chan: UL (from host to endpoint) channel for the device
176ee0360b2SManivannan Sadhasivam  * @dl_chan: DL (from endpoint to host) channel for the device
177d434743eSManivannan Sadhasivam  * @dev_type: MHI device type
178d434743eSManivannan Sadhasivam  */
179d434743eSManivannan Sadhasivam struct mhi_ep_device {
180d434743eSManivannan Sadhasivam 	struct device dev;
181d434743eSManivannan Sadhasivam 	struct mhi_ep_cntrl *mhi_cntrl;
182d434743eSManivannan Sadhasivam 	const struct mhi_device_id *id;
183d434743eSManivannan Sadhasivam 	const char *name;
184d434743eSManivannan Sadhasivam 	struct mhi_ep_chan *ul_chan;
185d434743eSManivannan Sadhasivam 	struct mhi_ep_chan *dl_chan;
186d434743eSManivannan Sadhasivam 	enum mhi_device_type dev_type;
187d434743eSManivannan Sadhasivam };
188d434743eSManivannan Sadhasivam 
189ee0360b2SManivannan Sadhasivam /**
190ee0360b2SManivannan Sadhasivam  * struct mhi_ep_driver - Structure representing a MHI Endpoint client driver
191ee0360b2SManivannan Sadhasivam  * @id_table: Pointer to MHI Endpoint device ID table
192ee0360b2SManivannan Sadhasivam  * @driver: Device driver model driver
193ee0360b2SManivannan Sadhasivam  * @probe: CB function for client driver probe function
194ee0360b2SManivannan Sadhasivam  * @remove: CB function for client driver remove function
195ee0360b2SManivannan Sadhasivam  * @ul_xfer_cb: CB function for UL (from host to endpoint) data transfer
196ee0360b2SManivannan Sadhasivam  * @dl_xfer_cb: CB function for DL (from endpoint to host) data transfer
197ee0360b2SManivannan Sadhasivam  */
198ee0360b2SManivannan Sadhasivam struct mhi_ep_driver {
199ee0360b2SManivannan Sadhasivam 	const struct mhi_device_id *id_table;
200ee0360b2SManivannan Sadhasivam 	struct device_driver driver;
201ee0360b2SManivannan Sadhasivam 	int (*probe)(struct mhi_ep_device *mhi_ep,
202ee0360b2SManivannan Sadhasivam 		     const struct mhi_device_id *id);
203ee0360b2SManivannan Sadhasivam 	void (*remove)(struct mhi_ep_device *mhi_ep);
204ee0360b2SManivannan Sadhasivam 	void (*ul_xfer_cb)(struct mhi_ep_device *mhi_dev,
205ee0360b2SManivannan Sadhasivam 			   struct mhi_result *result);
206ee0360b2SManivannan Sadhasivam 	void (*dl_xfer_cb)(struct mhi_ep_device *mhi_dev,
207ee0360b2SManivannan Sadhasivam 			   struct mhi_result *result);
208ee0360b2SManivannan Sadhasivam };
209ee0360b2SManivannan Sadhasivam 
210d434743eSManivannan Sadhasivam #define to_mhi_ep_device(dev) container_of(dev, struct mhi_ep_device, dev)
211ee0360b2SManivannan Sadhasivam #define to_mhi_ep_driver(drv) container_of(drv, struct mhi_ep_driver, driver)
212ee0360b2SManivannan Sadhasivam 
213ee0360b2SManivannan Sadhasivam /*
214ee0360b2SManivannan Sadhasivam  * module_mhi_ep_driver() - Helper macro for drivers that don't do
215ee0360b2SManivannan Sadhasivam  * anything special other than using default mhi_ep_driver_register() and
216ee0360b2SManivannan Sadhasivam  * mhi_ep_driver_unregister().  This eliminates a lot of boilerplate.
217ee0360b2SManivannan Sadhasivam  * Each module may only use this macro once.
218ee0360b2SManivannan Sadhasivam  */
219ee0360b2SManivannan Sadhasivam #define module_mhi_ep_driver(mhi_drv) \
220ee0360b2SManivannan Sadhasivam 	module_driver(mhi_drv, mhi_ep_driver_register, \
221ee0360b2SManivannan Sadhasivam 		      mhi_ep_driver_unregister)
222ee0360b2SManivannan Sadhasivam 
223ee0360b2SManivannan Sadhasivam /*
224ee0360b2SManivannan Sadhasivam  * Macro to avoid include chaining to get THIS_MODULE
225ee0360b2SManivannan Sadhasivam  */
226ee0360b2SManivannan Sadhasivam #define mhi_ep_driver_register(mhi_drv) \
227ee0360b2SManivannan Sadhasivam 	__mhi_ep_driver_register(mhi_drv, THIS_MODULE)
228ee0360b2SManivannan Sadhasivam 
229ee0360b2SManivannan Sadhasivam /**
230ee0360b2SManivannan Sadhasivam  * __mhi_ep_driver_register - Register a driver with MHI Endpoint bus
231ee0360b2SManivannan Sadhasivam  * @mhi_drv: Driver to be associated with the device
232ee0360b2SManivannan Sadhasivam  * @owner: The module owner
233ee0360b2SManivannan Sadhasivam  *
234ee0360b2SManivannan Sadhasivam  * Return: 0 if driver registrations succeeds, a negative error code otherwise.
235ee0360b2SManivannan Sadhasivam  */
236ee0360b2SManivannan Sadhasivam int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner);
237ee0360b2SManivannan Sadhasivam 
238ee0360b2SManivannan Sadhasivam /**
239ee0360b2SManivannan Sadhasivam  * mhi_ep_driver_unregister - Unregister a driver from MHI Endpoint bus
240ee0360b2SManivannan Sadhasivam  * @mhi_drv: Driver associated with the device
241ee0360b2SManivannan Sadhasivam  */
242ee0360b2SManivannan Sadhasivam void mhi_ep_driver_unregister(struct mhi_ep_driver *mhi_drv);
243d434743eSManivannan Sadhasivam 
244d434743eSManivannan Sadhasivam /**
245d434743eSManivannan Sadhasivam  * mhi_ep_register_controller - Register MHI Endpoint controller
246d434743eSManivannan Sadhasivam  * @mhi_cntrl: MHI Endpoint controller to register
247d434743eSManivannan Sadhasivam  * @config: Configuration to use for the controller
248d434743eSManivannan Sadhasivam  *
249d434743eSManivannan Sadhasivam  * Return: 0 if controller registrations succeeds, a negative error code otherwise.
250d434743eSManivannan Sadhasivam  */
251d434743eSManivannan Sadhasivam int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
252d434743eSManivannan Sadhasivam 			       const struct mhi_ep_cntrl_config *config);
253d434743eSManivannan Sadhasivam 
254d434743eSManivannan Sadhasivam /**
255d434743eSManivannan Sadhasivam  * mhi_ep_unregister_controller - Unregister MHI Endpoint controller
256d434743eSManivannan Sadhasivam  * @mhi_cntrl: MHI Endpoint controller to unregister
257d434743eSManivannan Sadhasivam  */
258d434743eSManivannan Sadhasivam void mhi_ep_unregister_controller(struct mhi_ep_cntrl *mhi_cntrl);
259d434743eSManivannan Sadhasivam 
260fb3a26b7SManivannan Sadhasivam /**
261fb3a26b7SManivannan Sadhasivam  * mhi_ep_power_up - Power up the MHI endpoint stack
262fb3a26b7SManivannan Sadhasivam  * @mhi_cntrl: MHI Endpoint controller
263fb3a26b7SManivannan Sadhasivam  *
264fb3a26b7SManivannan Sadhasivam  * Return: 0 if power up succeeds, a negative error code otherwise.
265fb3a26b7SManivannan Sadhasivam  */
266fb3a26b7SManivannan Sadhasivam int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl);
267fb3a26b7SManivannan Sadhasivam 
2685d507ee0SManivannan Sadhasivam /**
2695d507ee0SManivannan Sadhasivam  * mhi_ep_power_down - Power down the MHI endpoint stack
2705d507ee0SManivannan Sadhasivam  * @mhi_cntrl: MHI controller
2715d507ee0SManivannan Sadhasivam  */
2725d507ee0SManivannan Sadhasivam void mhi_ep_power_down(struct mhi_ep_cntrl *mhi_cntrl);
2735d507ee0SManivannan Sadhasivam 
27453012588SManivannan Sadhasivam /**
27553012588SManivannan Sadhasivam  * mhi_ep_queue_is_empty - Determine whether the transfer queue is empty
27653012588SManivannan Sadhasivam  * @mhi_dev: Device associated with the channels
27753012588SManivannan Sadhasivam  * @dir: DMA direction for the channel
27853012588SManivannan Sadhasivam  *
27953012588SManivannan Sadhasivam  * Return: true if the queue is empty, false otherwise.
28053012588SManivannan Sadhasivam  */
28153012588SManivannan Sadhasivam bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_dev, enum dma_data_direction dir);
28253012588SManivannan Sadhasivam 
2832d945a39SManivannan Sadhasivam /**
2842d945a39SManivannan Sadhasivam  * mhi_ep_queue_skb - Send SKBs to host over MHI Endpoint
2852d945a39SManivannan Sadhasivam  * @mhi_dev: Device associated with the DL channel
2862d945a39SManivannan Sadhasivam  * @skb: SKBs to be queued
2872d945a39SManivannan Sadhasivam  *
2882d945a39SManivannan Sadhasivam  * Return: 0 if the SKBs has been sent successfully, a negative error code otherwise.
2892d945a39SManivannan Sadhasivam  */
2902d945a39SManivannan Sadhasivam int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb);
2912d945a39SManivannan Sadhasivam 
292d434743eSManivannan Sadhasivam #endif
293