37bbfbdb870f7adbffb9f688d02898db14c8f2ef
[safe/jmp/linux-2.6] / drivers / scsi / scsi_tgt_if.c
1 /*
2  * SCSI target kernel/user interface functions
3  *
4  * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
5  * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  */
22 #include <linux/miscdevice.h>
23 #include <linux/file.h>
24 #include <net/tcp.h>
25 #include <scsi/scsi.h>
26 #include <scsi/scsi_cmnd.h>
27 #include <scsi/scsi_device.h>
28 #include <scsi/scsi_host.h>
29 #include <scsi/scsi_tgt.h>
30 #include <scsi/scsi_tgt_if.h>
31
32 #include <asm/cacheflush.h>
33
34 #include "scsi_tgt_priv.h"
35
36 struct tgt_ring {
37         u32 tr_idx;
38         unsigned long tr_pages[TGT_RING_PAGES];
39         spinlock_t tr_lock;
40 };
41
42 /* tx_ring : kernel->user, rx_ring : user->kernel */
43 static struct tgt_ring tx_ring, rx_ring;
44 static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait);
45
46 static inline void tgt_ring_idx_inc(struct tgt_ring *ring)
47 {
48         if (ring->tr_idx == TGT_MAX_EVENTS - 1)
49                 ring->tr_idx = 0;
50         else
51                 ring->tr_idx++;
52 }
53
54 static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx)
55 {
56         u32 pidx, off;
57
58         pidx = idx / TGT_EVENT_PER_PAGE;
59         off = idx % TGT_EVENT_PER_PAGE;
60
61         return (struct tgt_event *)
62                 (ring->tr_pages[pidx] + sizeof(struct tgt_event) * off);
63 }
64
65 static int tgt_uspace_send_event(u32 type, struct tgt_event *p)
66 {
67         struct tgt_event *ev;
68         struct tgt_ring *ring = &tx_ring;
69         unsigned long flags;
70         int err = 0;
71
72         spin_lock_irqsave(&ring->tr_lock, flags);
73
74         ev = tgt_head_event(ring, ring->tr_idx);
75         if (!ev->hdr.status)
76                 tgt_ring_idx_inc(ring);
77         else
78                 err = -BUSY;
79
80         spin_unlock_irqrestore(&ring->tr_lock, flags);
81
82         if (err)
83                 return err;
84
85         memcpy(ev, p, sizeof(*ev));
86         ev->hdr.type = type;
87         mb();
88         ev->hdr.status = 1;
89
90         flush_dcache_page(virt_to_page(ev));
91
92         wake_up_interruptible(&tgt_poll_wait);
93
94         return 0;
95 }
96
97 int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag)
98 {
99         struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
100         struct tgt_event ev;
101         int err;
102
103         memset(&ev, 0, sizeof(ev));
104         ev.p.cmd_req.host_no = shost->host_no;
105         ev.p.cmd_req.data_len = cmd->request_bufflen;
106         memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb));
107         memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun));
108         ev.p.cmd_req.attribute = cmd->tag;
109         ev.p.cmd_req.tag = tag;
110
111         dprintk("%p %d %u %x %llx\n", cmd, shost->host_no,
112                 ev.p.cmd_req.data_len, cmd->tag,
113                 (unsigned long long) ev.p.cmd_req.tag);
114
115         err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev);
116         if (err)
117                 eprintk("tx buf is full, could not send\n");
118
119         return err;
120 }
121
122 int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
123 {
124         struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
125         struct tgt_event ev;
126         int err;
127
128         memset(&ev, 0, sizeof(ev));
129         ev.p.cmd_done.host_no = shost->host_no;
130         ev.p.cmd_done.tag = tag;
131         ev.p.cmd_done.result = cmd->result;
132
133         dprintk("%p %d %llu %u %x\n", cmd, shost->host_no,
134                 (unsigned long long) ev.p.cmd_req.tag,
135                 ev.p.cmd_req.data_len, cmd->tag);
136
137         err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev);
138         if (err)
139                 eprintk("tx buf is full, could not send\n");
140
141         return err;
142 }
143
144 int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
145                                   struct scsi_lun *scsilun, void *data)
146 {
147         struct tgt_event ev;
148         int err;
149
150         memset(&ev, 0, sizeof(ev));
151         ev.p.tsk_mgmt_req.host_no = host_no;
152         ev.p.tsk_mgmt_req.function = function;
153         ev.p.tsk_mgmt_req.tag = tag;
154         memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun));
155         ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data;
156
157         dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag,
158                 (unsigned long long) ev.p.tsk_mgmt_req.mid);
159
160         err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev);
161         if (err)
162                 eprintk("tx buf is full, could not send\n");
163
164         return err;
165 }
166
167 static int event_recv_msg(struct tgt_event *ev)
168 {
169         int err = 0;
170
171         switch (ev->hdr.type) {
172         case TGT_UEVENT_CMD_RSP:
173                 err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
174                                            ev->p.cmd_rsp.tag,
175                                            ev->p.cmd_rsp.result,
176                                            ev->p.cmd_rsp.len,
177                                            ev->p.cmd_rsp.uaddr,
178                                            ev->p.cmd_rsp.rw);
179                 break;
180         case TGT_UEVENT_TSK_MGMT_RSP:
181                 err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no,
182                                                ev->p.tsk_mgmt_rsp.mid,
183                                                ev->p.tsk_mgmt_rsp.result);
184                 break;
185         default:
186                 eprintk("unknown type %d\n", ev->hdr.type);
187                 err = -EINVAL;
188         }
189
190         return err;
191 }
192
193 static ssize_t tgt_write(struct file *file, const char __user * buffer,
194                          size_t count, loff_t * ppos)
195 {
196         struct tgt_event *ev;
197         struct tgt_ring *ring = &rx_ring;
198
199         while (1) {
200                 ev = tgt_head_event(ring, ring->tr_idx);
201                 /* do we need this? */
202                 flush_dcache_page(virt_to_page(ev));
203
204                 if (!ev->hdr.status)
205                         break;
206
207                 tgt_ring_idx_inc(ring);
208                 event_recv_msg(ev);
209                 ev->hdr.status = 0;
210         };
211
212         return count;
213 }
214
215 static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait)
216 {
217         struct tgt_event *ev;
218         struct tgt_ring *ring = &tx_ring;
219         unsigned long flags;
220         unsigned int mask = 0;
221         u32 idx;
222
223         poll_wait(file, &tgt_poll_wait, wait);
224
225         spin_lock_irqsave(&ring->tr_lock, flags);
226
227         idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1;
228         ev = tgt_head_event(ring, idx);
229         if (ev->hdr.status)
230                 mask |= POLLIN | POLLRDNORM;
231
232         spin_unlock_irqrestore(&ring->tr_lock, flags);
233
234         return mask;
235 }
236
237 static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr,
238                            struct tgt_ring *ring)
239 {
240         int i, err;
241
242         for (i = 0; i < TGT_RING_PAGES; i++) {
243                 struct page *page = virt_to_page(ring->tr_pages[i]);
244                 err = vm_insert_page(vma, addr, page);
245                 if (err)
246                         return err;
247                 addr += PAGE_SIZE;
248         }
249
250         return 0;
251 }
252
253 static int tgt_mmap(struct file *filp, struct vm_area_struct *vma)
254 {
255         unsigned long addr;
256         int err;
257
258         if (vma->vm_pgoff)
259                 return -EINVAL;
260
261         if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) {
262                 eprintk("mmap size must be %lu, not %lu \n",
263                         TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start);
264                 return -EINVAL;
265         }
266
267         addr = vma->vm_start;
268         err = uspace_ring_map(vma, addr, &tx_ring);
269         if (err)
270                 return err;
271         err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring);
272
273         return err;
274 }
275
276 static int tgt_open(struct inode *inode, struct file *file)
277 {
278         tx_ring.tr_idx = rx_ring.tr_idx = 0;
279
280         return 0;
281 }
282
283 static struct file_operations tgt_fops = {
284         .owner          = THIS_MODULE,
285         .open           = tgt_open,
286         .poll           = tgt_poll,
287         .write          = tgt_write,
288         .mmap           = tgt_mmap,
289 };
290
291 static struct miscdevice tgt_miscdev = {
292         .minor = MISC_DYNAMIC_MINOR,
293         .name = "tgt",
294         .fops = &tgt_fops,
295 };
296
297 static void tgt_ring_exit(struct tgt_ring *ring)
298 {
299         int i;
300
301         for (i = 0; i < TGT_RING_PAGES; i++)
302                 free_page(ring->tr_pages[i]);
303 }
304
305 static int tgt_ring_init(struct tgt_ring *ring)
306 {
307         int i;
308
309         spin_lock_init(&ring->tr_lock);
310
311         for (i = 0; i < TGT_RING_PAGES; i++) {
312                 ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL);
313                 if (!ring->tr_pages[i]) {
314                         eprintk("out of memory\n");
315                         return -ENOMEM;
316                 }
317         }
318
319         return 0;
320 }
321
322 void scsi_tgt_if_exit(void)
323 {
324         tgt_ring_exit(&tx_ring);
325         tgt_ring_exit(&rx_ring);
326         misc_deregister(&tgt_miscdev);
327 }
328
329 int scsi_tgt_if_init(void)
330 {
331         int err;
332
333         err = tgt_ring_init(&tx_ring);
334         if (err)
335                 return err;
336
337         err = tgt_ring_init(&rx_ring);
338         if (err)
339                 goto free_tx_ring;
340
341         err = misc_register(&tgt_miscdev);
342         if (err)
343                 goto free_rx_ring;
344
345         return 0;
346 free_rx_ring:
347         tgt_ring_exit(&rx_ring);
348 free_tx_ring:
349         tgt_ring_exit(&tx_ring);
350
351         return err;
352 }