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/gfp.h>
24 #include <linux/file.h>
25 #include <linux/export.h>
27 #include <scsi/scsi.h>
28 #include <scsi/scsi_cmnd.h>
29 #include <scsi/scsi_device.h>
30 #include <scsi/scsi_host.h>
31 #include <scsi/scsi_tgt.h>
32 #include <scsi/scsi_tgt_if.h>
34 #include <asm/cacheflush.h>
36 #include "scsi_tgt_priv.h"
38 #if TGT_RING_SIZE < PAGE_SIZE
39 # define TGT_RING_SIZE PAGE_SIZE
42 #define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
43 #define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
44 #define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
48 unsigned long tr_pages
[TGT_RING_PAGES
];
52 /* tx_ring : kernel->user, rx_ring : user->kernel */
53 static struct tgt_ring tx_ring
, rx_ring
;
54 static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait
);
56 static inline void tgt_ring_idx_inc(struct tgt_ring
*ring
)
58 if (ring
->tr_idx
== TGT_MAX_EVENTS
- 1)
64 static struct tgt_event
*tgt_head_event(struct tgt_ring
*ring
, u32 idx
)
68 pidx
= idx
/ TGT_EVENT_PER_PAGE
;
69 off
= idx
% TGT_EVENT_PER_PAGE
;
71 return (struct tgt_event
*)
72 (ring
->tr_pages
[pidx
] + sizeof(struct tgt_event
) * off
);
75 static int tgt_uspace_send_event(u32 type
, struct tgt_event
*p
)
78 struct tgt_ring
*ring
= &tx_ring
;
82 spin_lock_irqsave(&ring
->tr_lock
, flags
);
84 ev
= tgt_head_event(ring
, ring
->tr_idx
);
86 tgt_ring_idx_inc(ring
);
90 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
95 memcpy(ev
, p
, sizeof(*ev
));
100 flush_dcache_page(virt_to_page(ev
));
102 wake_up_interruptible(&tgt_poll_wait
);
107 int scsi_tgt_uspace_send_cmd(struct scsi_cmnd
*cmd
, u64 itn_id
,
108 struct scsi_lun
*lun
, u64 tag
)
110 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
114 memset(&ev
, 0, sizeof(ev
));
115 ev
.p
.cmd_req
.host_no
= shost
->host_no
;
116 ev
.p
.cmd_req
.itn_id
= itn_id
;
117 ev
.p
.cmd_req
.data_len
= scsi_bufflen(cmd
);
118 memcpy(ev
.p
.cmd_req
.scb
, cmd
->cmnd
, sizeof(ev
.p
.cmd_req
.scb
));
119 memcpy(ev
.p
.cmd_req
.lun
, lun
, sizeof(ev
.p
.cmd_req
.lun
));
120 ev
.p
.cmd_req
.attribute
= cmd
->tag
;
121 ev
.p
.cmd_req
.tag
= tag
;
123 dprintk("%p %d %u %x %llx\n", cmd
, shost
->host_no
,
124 ev
.p
.cmd_req
.data_len
, cmd
->tag
,
125 (unsigned long long) ev
.p
.cmd_req
.tag
);
127 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_REQ
, &ev
);
129 eprintk("tx buf is full, could not send\n");
134 int scsi_tgt_uspace_send_status(struct scsi_cmnd
*cmd
, u64 itn_id
, u64 tag
)
136 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
140 memset(&ev
, 0, sizeof(ev
));
141 ev
.p
.cmd_done
.host_no
= shost
->host_no
;
142 ev
.p
.cmd_done
.itn_id
= itn_id
;
143 ev
.p
.cmd_done
.tag
= tag
;
144 ev
.p
.cmd_done
.result
= cmd
->result
;
146 dprintk("%p %d %llu %u %x\n", cmd
, shost
->host_no
,
147 (unsigned long long) ev
.p
.cmd_req
.tag
,
148 ev
.p
.cmd_req
.data_len
, cmd
->tag
);
150 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_DONE
, &ev
);
152 eprintk("tx buf is full, could not send\n");
157 int scsi_tgt_uspace_send_tsk_mgmt(int host_no
, u64 itn_id
, int function
,
158 u64 tag
, struct scsi_lun
*scsilun
, void *data
)
163 memset(&ev
, 0, sizeof(ev
));
164 ev
.p
.tsk_mgmt_req
.host_no
= host_no
;
165 ev
.p
.tsk_mgmt_req
.itn_id
= itn_id
;
166 ev
.p
.tsk_mgmt_req
.function
= function
;
167 ev
.p
.tsk_mgmt_req
.tag
= tag
;
168 memcpy(ev
.p
.tsk_mgmt_req
.lun
, scsilun
, sizeof(ev
.p
.tsk_mgmt_req
.lun
));
169 ev
.p
.tsk_mgmt_req
.mid
= (u64
) (unsigned long) data
;
171 dprintk("%d %x %llx %llx\n", host_no
, function
, (unsigned long long) tag
,
172 (unsigned long long) ev
.p
.tsk_mgmt_req
.mid
);
174 err
= tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ
, &ev
);
176 eprintk("tx buf is full, could not send\n");
181 int scsi_tgt_uspace_send_it_nexus_request(int host_no
, u64 itn_id
,
182 int function
, char *initiator_id
)
187 memset(&ev
, 0, sizeof(ev
));
188 ev
.p
.it_nexus_req
.host_no
= host_no
;
189 ev
.p
.it_nexus_req
.function
= function
;
190 ev
.p
.it_nexus_req
.itn_id
= itn_id
;
192 strncpy(ev
.p
.it_nexus_req
.initiator_id
, initiator_id
,
193 sizeof(ev
.p
.it_nexus_req
.initiator_id
));
195 dprintk("%d %x %llx\n", host_no
, function
, (unsigned long long)itn_id
);
197 err
= tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ
, &ev
);
199 eprintk("tx buf is full, could not send\n");
204 static int event_recv_msg(struct tgt_event
*ev
)
208 switch (ev
->hdr
.type
) {
209 case TGT_UEVENT_CMD_RSP
:
210 err
= scsi_tgt_kspace_exec(ev
->p
.cmd_rsp
.host_no
,
211 ev
->p
.cmd_rsp
.itn_id
,
212 ev
->p
.cmd_rsp
.result
,
216 ev
->p
.cmd_rsp
.sense_uaddr
,
217 ev
->p
.cmd_rsp
.sense_len
,
220 case TGT_UEVENT_TSK_MGMT_RSP
:
221 err
= scsi_tgt_kspace_tsk_mgmt(ev
->p
.tsk_mgmt_rsp
.host_no
,
222 ev
->p
.tsk_mgmt_rsp
.itn_id
,
223 ev
->p
.tsk_mgmt_rsp
.mid
,
224 ev
->p
.tsk_mgmt_rsp
.result
);
226 case TGT_UEVENT_IT_NEXUS_RSP
:
227 err
= scsi_tgt_kspace_it_nexus_rsp(ev
->p
.it_nexus_rsp
.host_no
,
228 ev
->p
.it_nexus_rsp
.itn_id
,
229 ev
->p
.it_nexus_rsp
.result
);
232 eprintk("unknown type %d\n", ev
->hdr
.type
);
239 static ssize_t
tgt_write(struct file
*file
, const char __user
* buffer
,
240 size_t count
, loff_t
* ppos
)
242 struct tgt_event
*ev
;
243 struct tgt_ring
*ring
= &rx_ring
;
246 ev
= tgt_head_event(ring
, ring
->tr_idx
);
247 /* do we need this? */
248 flush_dcache_page(virt_to_page(ev
));
253 tgt_ring_idx_inc(ring
);
261 static unsigned int tgt_poll(struct file
* file
, struct poll_table_struct
*wait
)
263 struct tgt_event
*ev
;
264 struct tgt_ring
*ring
= &tx_ring
;
266 unsigned int mask
= 0;
269 poll_wait(file
, &tgt_poll_wait
, wait
);
271 spin_lock_irqsave(&ring
->tr_lock
, flags
);
273 idx
= ring
->tr_idx
? ring
->tr_idx
- 1 : TGT_MAX_EVENTS
- 1;
274 ev
= tgt_head_event(ring
, idx
);
276 mask
|= POLLIN
| POLLRDNORM
;
278 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
283 static int uspace_ring_map(struct vm_area_struct
*vma
, unsigned long addr
,
284 struct tgt_ring
*ring
)
288 for (i
= 0; i
< TGT_RING_PAGES
; i
++) {
289 struct page
*page
= virt_to_page(ring
->tr_pages
[i
]);
290 err
= vm_insert_page(vma
, addr
, page
);
299 static int tgt_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
307 if (vma
->vm_end
- vma
->vm_start
!= TGT_RING_SIZE
* 2) {
308 eprintk("mmap size must be %lu, not %lu \n",
309 TGT_RING_SIZE
* 2, vma
->vm_end
- vma
->vm_start
);
313 addr
= vma
->vm_start
;
314 err
= uspace_ring_map(vma
, addr
, &tx_ring
);
317 err
= uspace_ring_map(vma
, addr
+ TGT_RING_SIZE
, &rx_ring
);
322 static int tgt_open(struct inode
*inode
, struct file
*file
)
324 tx_ring
.tr_idx
= rx_ring
.tr_idx
= 0;
329 static const struct file_operations tgt_fops
= {
330 .owner
= THIS_MODULE
,
335 .llseek
= noop_llseek
,
338 static struct miscdevice tgt_miscdev
= {
339 .minor
= MISC_DYNAMIC_MINOR
,
344 static void tgt_ring_exit(struct tgt_ring
*ring
)
348 for (i
= 0; i
< TGT_RING_PAGES
; i
++)
349 free_page(ring
->tr_pages
[i
]);
352 static int tgt_ring_init(struct tgt_ring
*ring
)
356 spin_lock_init(&ring
->tr_lock
);
358 for (i
= 0; i
< TGT_RING_PAGES
; i
++) {
359 ring
->tr_pages
[i
] = get_zeroed_page(GFP_KERNEL
);
360 if (!ring
->tr_pages
[i
]) {
361 eprintk("out of memory\n");
369 void scsi_tgt_if_exit(void)
371 tgt_ring_exit(&tx_ring
);
372 tgt_ring_exit(&rx_ring
);
373 misc_deregister(&tgt_miscdev
);
376 int scsi_tgt_if_init(void)
380 err
= tgt_ring_init(&tx_ring
);
384 err
= tgt_ring_init(&rx_ring
);
388 err
= misc_register(&tgt_miscdev
);
394 tgt_ring_exit(&rx_ring
);
396 tgt_ring_exit(&tx_ring
);
This page took 0.040891 seconds and 5 git commands to generate.