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"
36 #if TGT_RING_SIZE < PAGE_SIZE
37 # define TGT_RING_SIZE PAGE_SIZE
40 #define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
41 #define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
42 #define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
46 unsigned long tr_pages
[TGT_RING_PAGES
];
50 /* tx_ring : kernel->user, rx_ring : user->kernel */
51 static struct tgt_ring tx_ring
, rx_ring
;
52 static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait
);
54 static inline void tgt_ring_idx_inc(struct tgt_ring
*ring
)
56 if (ring
->tr_idx
== TGT_MAX_EVENTS
- 1)
62 static struct tgt_event
*tgt_head_event(struct tgt_ring
*ring
, u32 idx
)
66 pidx
= idx
/ TGT_EVENT_PER_PAGE
;
67 off
= idx
% TGT_EVENT_PER_PAGE
;
69 return (struct tgt_event
*)
70 (ring
->tr_pages
[pidx
] + sizeof(struct tgt_event
) * off
);
73 static int tgt_uspace_send_event(u32 type
, struct tgt_event
*p
)
76 struct tgt_ring
*ring
= &tx_ring
;
80 spin_lock_irqsave(&ring
->tr_lock
, flags
);
82 ev
= tgt_head_event(ring
, ring
->tr_idx
);
84 tgt_ring_idx_inc(ring
);
88 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
93 memcpy(ev
, p
, sizeof(*ev
));
98 flush_dcache_page(virt_to_page(ev
));
100 wake_up_interruptible(&tgt_poll_wait
);
105 int scsi_tgt_uspace_send_cmd(struct scsi_cmnd
*cmd
, u64 itn_id
,
106 struct scsi_lun
*lun
, u64 tag
)
108 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
112 memset(&ev
, 0, sizeof(ev
));
113 ev
.p
.cmd_req
.host_no
= shost
->host_no
;
114 ev
.p
.cmd_req
.itn_id
= itn_id
;
115 ev
.p
.cmd_req
.data_len
= scsi_bufflen(cmd
);
116 memcpy(ev
.p
.cmd_req
.scb
, cmd
->cmnd
, sizeof(ev
.p
.cmd_req
.scb
));
117 memcpy(ev
.p
.cmd_req
.lun
, lun
, sizeof(ev
.p
.cmd_req
.lun
));
118 ev
.p
.cmd_req
.attribute
= cmd
->tag
;
119 ev
.p
.cmd_req
.tag
= tag
;
121 dprintk("%p %d %u %x %llx\n", cmd
, shost
->host_no
,
122 ev
.p
.cmd_req
.data_len
, cmd
->tag
,
123 (unsigned long long) ev
.p
.cmd_req
.tag
);
125 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_REQ
, &ev
);
127 eprintk("tx buf is full, could not send\n");
132 int scsi_tgt_uspace_send_status(struct scsi_cmnd
*cmd
, u64 itn_id
, u64 tag
)
134 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
138 memset(&ev
, 0, sizeof(ev
));
139 ev
.p
.cmd_done
.host_no
= shost
->host_no
;
140 ev
.p
.cmd_done
.itn_id
= itn_id
;
141 ev
.p
.cmd_done
.tag
= tag
;
142 ev
.p
.cmd_done
.result
= cmd
->result
;
144 dprintk("%p %d %llu %u %x\n", cmd
, shost
->host_no
,
145 (unsigned long long) ev
.p
.cmd_req
.tag
,
146 ev
.p
.cmd_req
.data_len
, cmd
->tag
);
148 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_DONE
, &ev
);
150 eprintk("tx buf is full, could not send\n");
155 int scsi_tgt_uspace_send_tsk_mgmt(int host_no
, u64 itn_id
, int function
,
156 u64 tag
, struct scsi_lun
*scsilun
, void *data
)
161 memset(&ev
, 0, sizeof(ev
));
162 ev
.p
.tsk_mgmt_req
.host_no
= host_no
;
163 ev
.p
.tsk_mgmt_req
.itn_id
= itn_id
;
164 ev
.p
.tsk_mgmt_req
.function
= function
;
165 ev
.p
.tsk_mgmt_req
.tag
= tag
;
166 memcpy(ev
.p
.tsk_mgmt_req
.lun
, scsilun
, sizeof(ev
.p
.tsk_mgmt_req
.lun
));
167 ev
.p
.tsk_mgmt_req
.mid
= (u64
) (unsigned long) data
;
169 dprintk("%d %x %llx %llx\n", host_no
, function
, (unsigned long long) tag
,
170 (unsigned long long) ev
.p
.tsk_mgmt_req
.mid
);
172 err
= tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ
, &ev
);
174 eprintk("tx buf is full, could not send\n");
179 int scsi_tgt_uspace_send_it_nexus_request(int host_no
, u64 itn_id
,
180 int function
, char *initiator_id
)
185 memset(&ev
, 0, sizeof(ev
));
186 ev
.p
.it_nexus_req
.host_no
= host_no
;
187 ev
.p
.it_nexus_req
.function
= function
;
188 ev
.p
.it_nexus_req
.itn_id
= itn_id
;
190 strncpy(ev
.p
.it_nexus_req
.initiator_id
, initiator_id
,
191 sizeof(ev
.p
.it_nexus_req
.initiator_id
));
193 dprintk("%d %x %llx\n", host_no
, function
, (unsigned long long)itn_id
);
195 err
= tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ
, &ev
);
197 eprintk("tx buf is full, could not send\n");
202 static int event_recv_msg(struct tgt_event
*ev
)
206 switch (ev
->hdr
.type
) {
207 case TGT_UEVENT_CMD_RSP
:
208 err
= scsi_tgt_kspace_exec(ev
->p
.cmd_rsp
.host_no
,
209 ev
->p
.cmd_rsp
.itn_id
,
210 ev
->p
.cmd_rsp
.result
,
214 ev
->p
.cmd_rsp
.sense_uaddr
,
215 ev
->p
.cmd_rsp
.sense_len
,
218 case TGT_UEVENT_TSK_MGMT_RSP
:
219 err
= scsi_tgt_kspace_tsk_mgmt(ev
->p
.tsk_mgmt_rsp
.host_no
,
220 ev
->p
.tsk_mgmt_rsp
.itn_id
,
221 ev
->p
.tsk_mgmt_rsp
.mid
,
222 ev
->p
.tsk_mgmt_rsp
.result
);
224 case TGT_UEVENT_IT_NEXUS_RSP
:
225 err
= scsi_tgt_kspace_it_nexus_rsp(ev
->p
.it_nexus_rsp
.host_no
,
226 ev
->p
.it_nexus_rsp
.itn_id
,
227 ev
->p
.it_nexus_rsp
.result
);
230 eprintk("unknown type %d\n", ev
->hdr
.type
);
237 static ssize_t
tgt_write(struct file
*file
, const char __user
* buffer
,
238 size_t count
, loff_t
* ppos
)
240 struct tgt_event
*ev
;
241 struct tgt_ring
*ring
= &rx_ring
;
244 ev
= tgt_head_event(ring
, ring
->tr_idx
);
245 /* do we need this? */
246 flush_dcache_page(virt_to_page(ev
));
251 tgt_ring_idx_inc(ring
);
259 static unsigned int tgt_poll(struct file
* file
, struct poll_table_struct
*wait
)
261 struct tgt_event
*ev
;
262 struct tgt_ring
*ring
= &tx_ring
;
264 unsigned int mask
= 0;
267 poll_wait(file
, &tgt_poll_wait
, wait
);
269 spin_lock_irqsave(&ring
->tr_lock
, flags
);
271 idx
= ring
->tr_idx
? ring
->tr_idx
- 1 : TGT_MAX_EVENTS
- 1;
272 ev
= tgt_head_event(ring
, idx
);
274 mask
|= POLLIN
| POLLRDNORM
;
276 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
281 static int uspace_ring_map(struct vm_area_struct
*vma
, unsigned long addr
,
282 struct tgt_ring
*ring
)
286 for (i
= 0; i
< TGT_RING_PAGES
; i
++) {
287 struct page
*page
= virt_to_page(ring
->tr_pages
[i
]);
288 err
= vm_insert_page(vma
, addr
, page
);
297 static int tgt_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
305 if (vma
->vm_end
- vma
->vm_start
!= TGT_RING_SIZE
* 2) {
306 eprintk("mmap size must be %lu, not %lu \n",
307 TGT_RING_SIZE
* 2, vma
->vm_end
- vma
->vm_start
);
311 addr
= vma
->vm_start
;
312 err
= uspace_ring_map(vma
, addr
, &tx_ring
);
315 err
= uspace_ring_map(vma
, addr
+ TGT_RING_SIZE
, &rx_ring
);
320 static int tgt_open(struct inode
*inode
, struct file
*file
)
322 tx_ring
.tr_idx
= rx_ring
.tr_idx
= 0;
327 static const struct file_operations tgt_fops
= {
328 .owner
= THIS_MODULE
,
335 static struct miscdevice tgt_miscdev
= {
336 .minor
= MISC_DYNAMIC_MINOR
,
341 static void tgt_ring_exit(struct tgt_ring
*ring
)
345 for (i
= 0; i
< TGT_RING_PAGES
; i
++)
346 free_page(ring
->tr_pages
[i
]);
349 static int tgt_ring_init(struct tgt_ring
*ring
)
353 spin_lock_init(&ring
->tr_lock
);
355 for (i
= 0; i
< TGT_RING_PAGES
; i
++) {
356 ring
->tr_pages
[i
] = get_zeroed_page(GFP_KERNEL
);
357 if (!ring
->tr_pages
[i
]) {
358 eprintk("out of memory\n");
366 void scsi_tgt_if_exit(void)
368 tgt_ring_exit(&tx_ring
);
369 tgt_ring_exit(&rx_ring
);
370 misc_deregister(&tgt_miscdev
);
373 int scsi_tgt_if_init(void)
377 err
= tgt_ring_init(&tx_ring
);
381 err
= tgt_ring_init(&rx_ring
);
385 err
= misc_register(&tgt_miscdev
);
391 tgt_ring_exit(&rx_ring
);
393 tgt_ring_exit(&tx_ring
);