2 * SCSI target kernel/user interface functions
4 * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
5 * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu>
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.
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.
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
22 #include <linux/miscdevice.h>
23 #include <linux/file.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>
32 #include <asm/cacheflush.h>
34 #include "scsi_tgt_priv.h"
38 unsigned long tr_pages
[TGT_RING_PAGES
];
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
);
46 static inline void tgt_ring_idx_inc(struct tgt_ring
*ring
)
48 if (ring
->tr_idx
== TGT_MAX_EVENTS
- 1)
54 static struct tgt_event
*tgt_head_event(struct tgt_ring
*ring
, u32 idx
)
58 pidx
= idx
/ TGT_EVENT_PER_PAGE
;
59 off
= idx
% TGT_EVENT_PER_PAGE
;
61 return (struct tgt_event
*)
62 (ring
->tr_pages
[pidx
] + sizeof(struct tgt_event
) * off
);
65 static int tgt_uspace_send_event(u32 type
, struct tgt_event
*p
)
68 struct tgt_ring
*ring
= &tx_ring
;
72 spin_lock_irqsave(&ring
->tr_lock
, flags
);
74 ev
= tgt_head_event(ring
, ring
->tr_idx
);
76 tgt_ring_idx_inc(ring
);
80 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
85 memcpy(ev
, p
, sizeof(*ev
));
90 flush_dcache_page(virt_to_page(ev
));
92 wake_up_interruptible(&tgt_poll_wait
);
97 int scsi_tgt_uspace_send_cmd(struct scsi_cmnd
*cmd
, struct scsi_lun
*lun
, u64 tag
)
99 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
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
;
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
);
115 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_REQ
, &ev
);
117 eprintk("tx buf is full, could not send\n");
122 int scsi_tgt_uspace_send_status(struct scsi_cmnd
*cmd
, u64 tag
)
124 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
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
;
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
);
137 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_DONE
, &ev
);
139 eprintk("tx buf is full, could not send\n");
144 int scsi_tgt_uspace_send_tsk_mgmt(int host_no
, int function
, u64 tag
,
145 struct scsi_lun
*scsilun
, void *data
)
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
;
157 dprintk("%d %x %llx %llx\n", host_no
, function
, (unsigned long long) tag
,
158 (unsigned long long) ev
.p
.tsk_mgmt_req
.mid
);
160 err
= tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ
, &ev
);
162 eprintk("tx buf is full, could not send\n");
167 static int event_recv_msg(struct tgt_event
*ev
)
171 switch (ev
->hdr
.type
) {
172 case TGT_UEVENT_CMD_RSP
:
173 err
= scsi_tgt_kspace_exec(ev
->p
.cmd_rsp
.host_no
,
175 ev
->p
.cmd_rsp
.result
,
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
);
186 eprintk("unknown type %d\n", ev
->hdr
.type
);
193 static ssize_t
tgt_write(struct file
*file
, const char __user
* buffer
,
194 size_t count
, loff_t
* ppos
)
196 struct tgt_event
*ev
;
197 struct tgt_ring
*ring
= &rx_ring
;
200 ev
= tgt_head_event(ring
, ring
->tr_idx
);
201 /* do we need this? */
202 flush_dcache_page(virt_to_page(ev
));
207 tgt_ring_idx_inc(ring
);
215 static unsigned int tgt_poll(struct file
* file
, struct poll_table_struct
*wait
)
217 struct tgt_event
*ev
;
218 struct tgt_ring
*ring
= &tx_ring
;
220 unsigned int mask
= 0;
223 poll_wait(file
, &tgt_poll_wait
, wait
);
225 spin_lock_irqsave(&ring
->tr_lock
, flags
);
227 idx
= ring
->tr_idx
? ring
->tr_idx
- 1 : TGT_MAX_EVENTS
- 1;
228 ev
= tgt_head_event(ring
, idx
);
230 mask
|= POLLIN
| POLLRDNORM
;
232 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
237 static int uspace_ring_map(struct vm_area_struct
*vma
, unsigned long addr
,
238 struct tgt_ring
*ring
)
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
);
253 static int tgt_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
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
);
267 addr
= vma
->vm_start
;
268 err
= uspace_ring_map(vma
, addr
, &tx_ring
);
271 err
= uspace_ring_map(vma
, addr
+ TGT_RING_SIZE
, &rx_ring
);
276 static int tgt_open(struct inode
*inode
, struct file
*file
)
278 tx_ring
.tr_idx
= rx_ring
.tr_idx
= 0;
283 static struct file_operations tgt_fops
= {
284 .owner
= THIS_MODULE
,
291 static struct miscdevice tgt_miscdev
= {
292 .minor
= MISC_DYNAMIC_MINOR
,
297 static void tgt_ring_exit(struct tgt_ring
*ring
)
301 for (i
= 0; i
< TGT_RING_PAGES
; i
++)
302 free_page(ring
->tr_pages
[i
]);
305 static int tgt_ring_init(struct tgt_ring
*ring
)
309 spin_lock_init(&ring
->tr_lock
);
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");
322 void scsi_tgt_if_exit(void)
324 tgt_ring_exit(&tx_ring
);
325 tgt_ring_exit(&rx_ring
);
326 misc_deregister(&tgt_miscdev
);
329 int scsi_tgt_if_init(void)
333 err
= tgt_ring_init(&tx_ring
);
337 err
= tgt_ring_init(&rx_ring
);
341 err
= misc_register(&tgt_miscdev
);
347 tgt_ring_exit(&rx_ring
);
349 tgt_ring_exit(&tx_ring
);