167207b96SArnd Bergmann /* 267207b96SArnd Bergmann * SPU file system 367207b96SArnd Bergmann * 467207b96SArnd Bergmann * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 567207b96SArnd Bergmann * 667207b96SArnd Bergmann * Author: Arnd Bergmann <arndb@de.ibm.com> 767207b96SArnd Bergmann * 867207b96SArnd Bergmann * This program is free software; you can redistribute it and/or modify 967207b96SArnd Bergmann * it under the terms of the GNU General Public License as published by 1067207b96SArnd Bergmann * the Free Software Foundation; either version 2, or (at your option) 1167207b96SArnd Bergmann * any later version. 1267207b96SArnd Bergmann * 1367207b96SArnd Bergmann * This program is distributed in the hope that it will be useful, 1467207b96SArnd Bergmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 1567207b96SArnd Bergmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1667207b96SArnd Bergmann * GNU General Public License for more details. 1767207b96SArnd Bergmann * 1867207b96SArnd Bergmann * You should have received a copy of the GNU General Public License 1967207b96SArnd Bergmann * along with this program; if not, write to the Free Software 2067207b96SArnd Bergmann * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2167207b96SArnd Bergmann */ 2267207b96SArnd Bergmann #ifndef SPUFS_H 2367207b96SArnd Bergmann #define SPUFS_H 2467207b96SArnd Bergmann 2567207b96SArnd Bergmann #include <linux/kref.h> 2667207b96SArnd Bergmann #include <linux/rwsem.h> 2767207b96SArnd Bergmann #include <linux/spinlock.h> 2867207b96SArnd Bergmann #include <linux/fs.h> 2967207b96SArnd Bergmann 3067207b96SArnd Bergmann #include <asm/spu.h> 315473af04SMark Nutter #include <asm/spu_csa.h> 3267207b96SArnd Bergmann 3367207b96SArnd Bergmann /* The magic number for our file system */ 3467207b96SArnd Bergmann enum { 3567207b96SArnd Bergmann SPUFS_MAGIC = 0x23c9b64e, 3667207b96SArnd Bergmann }; 3767207b96SArnd Bergmann 388b3d6663SArnd Bergmann struct spu_context_ops; 398b3d6663SArnd Bergmann 408837d921SArnd Bergmann #define SPU_CONTEXT_PREEMPT 0UL 412a911f0bSArnd Bergmann 4267207b96SArnd Bergmann struct spu_context { 4367207b96SArnd Bergmann struct spu *spu; /* pointer to a physical SPU */ 445473af04SMark Nutter struct spu_state csa; /* SPU context save area. */ 4567207b96SArnd Bergmann spinlock_t mmio_lock; /* protects mmio access */ 468b3d6663SArnd Bergmann struct address_space *local_store;/* local store backing store */ 478b3d6663SArnd Bergmann 488b3d6663SArnd Bergmann enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 498b3d6663SArnd Bergmann struct rw_semaphore state_sema; 505ef8224aSArnd Bergmann struct semaphore run_sema; 518b3d6663SArnd Bergmann 528b3d6663SArnd Bergmann struct mm_struct *owner; 5367207b96SArnd Bergmann 5467207b96SArnd Bergmann struct kref kref; 558b3d6663SArnd Bergmann wait_queue_head_t ibox_wq; 568b3d6663SArnd Bergmann wait_queue_head_t wbox_wq; 575110459fSArnd Bergmann wait_queue_head_t stop_wq; 58a33a7d73SArnd Bergmann wait_queue_head_t mfc_wq; 598b3d6663SArnd Bergmann struct fasync_struct *ibox_fasync; 608b3d6663SArnd Bergmann struct fasync_struct *wbox_fasync; 61a33a7d73SArnd Bergmann struct fasync_struct *mfc_fasync; 62a33a7d73SArnd Bergmann u32 tagwait; 638b3d6663SArnd Bergmann struct spu_context_ops *ops; 642a911f0bSArnd Bergmann struct work_struct reap_work; 652a911f0bSArnd Bergmann u64 flags; 6667207b96SArnd Bergmann }; 6767207b96SArnd Bergmann 68a33a7d73SArnd Bergmann struct mfc_dma_command { 69a33a7d73SArnd Bergmann int32_t pad; /* reserved */ 70a33a7d73SArnd Bergmann uint32_t lsa; /* local storage address */ 71a33a7d73SArnd Bergmann uint64_t ea; /* effective address */ 72a33a7d73SArnd Bergmann uint16_t size; /* transfer size */ 73a33a7d73SArnd Bergmann uint16_t tag; /* command tag */ 74a33a7d73SArnd Bergmann uint16_t class; /* class ID */ 75a33a7d73SArnd Bergmann uint16_t cmd; /* command opcode */ 76a33a7d73SArnd Bergmann }; 77a33a7d73SArnd Bergmann 78a33a7d73SArnd Bergmann 798b3d6663SArnd Bergmann /* SPU context query/set operations. */ 808b3d6663SArnd Bergmann struct spu_context_ops { 818b3d6663SArnd Bergmann int (*mbox_read) (struct spu_context * ctx, u32 * data); 828b3d6663SArnd Bergmann u32(*mbox_stat_read) (struct spu_context * ctx); 833a843d7cSArnd Bergmann unsigned int (*mbox_stat_poll)(struct spu_context *ctx, 843a843d7cSArnd Bergmann unsigned int events); 858b3d6663SArnd Bergmann int (*ibox_read) (struct spu_context * ctx, u32 * data); 868b3d6663SArnd Bergmann int (*wbox_write) (struct spu_context * ctx, u32 data); 878b3d6663SArnd Bergmann u32(*signal1_read) (struct spu_context * ctx); 888b3d6663SArnd Bergmann void (*signal1_write) (struct spu_context * ctx, u32 data); 898b3d6663SArnd Bergmann u32(*signal2_read) (struct spu_context * ctx); 908b3d6663SArnd Bergmann void (*signal2_write) (struct spu_context * ctx, u32 data); 918b3d6663SArnd Bergmann void (*signal1_type_set) (struct spu_context * ctx, u64 val); 928b3d6663SArnd Bergmann u64(*signal1_type_get) (struct spu_context * ctx); 938b3d6663SArnd Bergmann void (*signal2_type_set) (struct spu_context * ctx, u64 val); 948b3d6663SArnd Bergmann u64(*signal2_type_get) (struct spu_context * ctx); 958b3d6663SArnd Bergmann u32(*npc_read) (struct spu_context * ctx); 968b3d6663SArnd Bergmann void (*npc_write) (struct spu_context * ctx, u32 data); 978b3d6663SArnd Bergmann u32(*status_read) (struct spu_context * ctx); 988b3d6663SArnd Bergmann char*(*get_ls) (struct spu_context * ctx); 995110459fSArnd Bergmann void (*runcntl_write) (struct spu_context * ctx, u32 data); 1005110459fSArnd Bergmann void (*runcntl_stop) (struct spu_context * ctx); 101a33a7d73SArnd Bergmann int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); 102a33a7d73SArnd Bergmann u32 (*read_mfc_tagstatus)(struct spu_context * ctx); 103a33a7d73SArnd Bergmann u32 (*get_mfc_free_elements)(struct spu_context *ctx); 104a33a7d73SArnd Bergmann int (*send_mfc_command)(struct spu_context *ctx, 105a33a7d73SArnd Bergmann struct mfc_dma_command *cmd); 1068b3d6663SArnd Bergmann }; 1078b3d6663SArnd Bergmann 1088b3d6663SArnd Bergmann extern struct spu_context_ops spu_hw_ops; 1098b3d6663SArnd Bergmann extern struct spu_context_ops spu_backing_ops; 1108b3d6663SArnd Bergmann 11167207b96SArnd Bergmann struct spufs_inode_info { 11267207b96SArnd Bergmann struct spu_context *i_ctx; 11367207b96SArnd Bergmann struct inode vfs_inode; 11467207b96SArnd Bergmann }; 11567207b96SArnd Bergmann #define SPUFS_I(inode) \ 11667207b96SArnd Bergmann container_of(inode, struct spufs_inode_info, vfs_inode) 11767207b96SArnd Bergmann 11867207b96SArnd Bergmann extern struct tree_descr spufs_dir_contents[]; 11967207b96SArnd Bergmann 12067207b96SArnd Bergmann /* system call implementation */ 12167207b96SArnd Bergmann long spufs_run_spu(struct file *file, 12267207b96SArnd Bergmann struct spu_context *ctx, u32 *npc, u32 *status); 1236ff730c3SArnd Bergmann long spufs_create_thread(struct nameidata *nd, 12467207b96SArnd Bergmann unsigned int flags, mode_t mode); 125e80358adSArnd Bergmann extern struct file_operations spufs_context_fops; 12667207b96SArnd Bergmann 12767207b96SArnd Bergmann /* context management */ 1288b3d6663SArnd Bergmann struct spu_context * alloc_spu_context(struct address_space *local_store); 12967207b96SArnd Bergmann void destroy_spu_context(struct kref *kref); 13067207b96SArnd Bergmann struct spu_context * get_spu_context(struct spu_context *ctx); 13167207b96SArnd Bergmann int put_spu_context(struct spu_context *ctx); 1325110459fSArnd Bergmann void spu_unmap_mappings(struct spu_context *ctx); 13367207b96SArnd Bergmann 1348b3d6663SArnd Bergmann void spu_forget(struct spu_context *ctx); 13567207b96SArnd Bergmann void spu_acquire(struct spu_context *ctx); 13667207b96SArnd Bergmann void spu_release(struct spu_context *ctx); 1378b3d6663SArnd Bergmann int spu_acquire_runnable(struct spu_context *ctx); 13867207b96SArnd Bergmann void spu_acquire_saved(struct spu_context *ctx); 13967207b96SArnd Bergmann 1408b3d6663SArnd Bergmann int spu_activate(struct spu_context *ctx, u64 flags); 1418b3d6663SArnd Bergmann void spu_deactivate(struct spu_context *ctx); 1428b3d6663SArnd Bergmann void spu_yield(struct spu_context *ctx); 1438b3d6663SArnd Bergmann int __init spu_sched_init(void); 1448b3d6663SArnd Bergmann void __exit spu_sched_exit(void); 1458b3d6663SArnd Bergmann 146ce8ab854SArnd Bergmann /* 147ce8ab854SArnd Bergmann * spufs_wait 148ce8ab854SArnd Bergmann * Same as wait_event_interruptible(), except that here 149ce8ab854SArnd Bergmann * we need to call spu_release(ctx) before sleeping, and 150ce8ab854SArnd Bergmann * then spu_acquire(ctx) when awoken. 151ce8ab854SArnd Bergmann */ 152ce8ab854SArnd Bergmann 153ce8ab854SArnd Bergmann #define spufs_wait(wq, condition) \ 154ce8ab854SArnd Bergmann ({ \ 155ce8ab854SArnd Bergmann int __ret = 0; \ 156ce8ab854SArnd Bergmann DEFINE_WAIT(__wait); \ 157ce8ab854SArnd Bergmann for (;;) { \ 158ce8ab854SArnd Bergmann prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ 159ce8ab854SArnd Bergmann if (condition) \ 160ce8ab854SArnd Bergmann break; \ 161ce8ab854SArnd Bergmann if (!signal_pending(current)) { \ 162ce8ab854SArnd Bergmann spu_release(ctx); \ 163ce8ab854SArnd Bergmann schedule(); \ 164ce8ab854SArnd Bergmann spu_acquire(ctx); \ 165ce8ab854SArnd Bergmann continue; \ 166ce8ab854SArnd Bergmann } \ 167ce8ab854SArnd Bergmann __ret = -ERESTARTSYS; \ 168ce8ab854SArnd Bergmann break; \ 169ce8ab854SArnd Bergmann } \ 170ce8ab854SArnd Bergmann finish_wait(&(wq), &__wait); \ 171ce8ab854SArnd Bergmann __ret; \ 172ce8ab854SArnd Bergmann }) 173ce8ab854SArnd Bergmann 1748b3d6663SArnd Bergmann size_t spu_wbox_write(struct spu_context *ctx, u32 data); 1758b3d6663SArnd Bergmann size_t spu_ibox_read(struct spu_context *ctx, u32 *data); 1768b3d6663SArnd Bergmann 1778b3d6663SArnd Bergmann /* irq callback funcs. */ 1788b3d6663SArnd Bergmann void spufs_ibox_callback(struct spu *spu); 1798b3d6663SArnd Bergmann void spufs_wbox_callback(struct spu *spu); 1805110459fSArnd Bergmann void spufs_stop_callback(struct spu *spu); 181a33a7d73SArnd Bergmann void spufs_mfc_callback(struct spu *spu); 1828b3d6663SArnd Bergmann 18367207b96SArnd Bergmann #endif 184