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>
24 #include <linux/smp_lock.h>
26 #include <scsi/scsi.h>
27 #include <scsi/scsi_cmnd.h>
28 #include <scsi/scsi_device.h>
29 #include <scsi/scsi_host.h>
30 #include <scsi/scsi_tgt.h>
31 #include <scsi/scsi_tgt_if.h>
33 #include <asm/cacheflush.h>
35 #include "scsi_tgt_priv.h"
37 #if TGT_RING_SIZE < PAGE_SIZE
38 # define TGT_RING_SIZE PAGE_SIZE
41 #define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
42 #define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
43 #define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
47 unsigned long tr_pages
[TGT_RING_PAGES
];
51 /* tx_ring : kernel->user, rx_ring : user->kernel */
52 static struct tgt_ring tx_ring
, rx_ring
;
53 static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait
);
55 static inline void tgt_ring_idx_inc(struct tgt_ring
*ring
)
57 if (ring
->tr_idx
== TGT_MAX_EVENTS
- 1)
63 static struct tgt_event
*tgt_head_event(struct tgt_ring
*ring
, u32 idx
)
67 pidx
= idx
/ TGT_EVENT_PER_PAGE
;
68 off
= idx
% TGT_EVENT_PER_PAGE
;
70 return (struct tgt_event
*)
71 (ring
->tr_pages
[pidx
] + sizeof(struct tgt_event
) * off
);
74 static int tgt_uspace_send_event(u32 type
, struct tgt_event
*p
)
77 struct tgt_ring
*ring
= &tx_ring
;
81 spin_lock_irqsave(&ring
->tr_lock
, flags
);
83 ev
= tgt_head_event(ring
, ring
->tr_idx
);
85 tgt_ring_idx_inc(ring
);
89 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
94 memcpy(ev
, p
, sizeof(*ev
));
99 flush_dcache_page(virt_to_page(ev
));
101 wake_up_interruptible(&tgt_poll_wait
);
106 int scsi_tgt_uspace_send_cmd(struct scsi_cmnd
*cmd
, u64 itn_id
,
107 struct scsi_lun
*lun
, u64 tag
)
109 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
113 memset(&ev
, 0, sizeof(ev
));
114 ev
.p
.cmd_req
.host_no
= shost
->host_no
;
115 ev
.p
.cmd_req
.itn_id
= itn_id
;
116 ev
.p
.cmd_req
.data_len
= scsi_bufflen(cmd
);
117 memcpy(ev
.p
.cmd_req
.scb
, cmd
->cmnd
, sizeof(ev
.p
.cmd_req
.scb
));
118 memcpy(ev
.p
.cmd_req
.lun
, lun
, sizeof(ev
.p
.cmd_req
.lun
));
119 ev
.p
.cmd_req
.attribute
= cmd
->tag
;
120 ev
.p
.cmd_req
.tag
= tag
;
122 dprintk("%p %d %u %x %llx\n", cmd
, shost
->host_no
,
123 ev
.p
.cmd_req
.data_len
, cmd
->tag
,
124 (unsigned long long) ev
.p
.cmd_req
.tag
);
126 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_REQ
, &ev
);
128 eprintk("tx buf is full, could not send\n");
133 int scsi_tgt_uspace_send_status(struct scsi_cmnd
*cmd
, u64 itn_id
, u64 tag
)
135 struct Scsi_Host
*shost
= scsi_tgt_cmd_to_host(cmd
);
139 memset(&ev
, 0, sizeof(ev
));
140 ev
.p
.cmd_done
.host_no
= shost
->host_no
;
141 ev
.p
.cmd_done
.itn_id
= itn_id
;
142 ev
.p
.cmd_done
.tag
= tag
;
143 ev
.p
.cmd_done
.result
= cmd
->result
;
145 dprintk("%p %d %llu %u %x\n", cmd
, shost
->host_no
,
146 (unsigned long long) ev
.p
.cmd_req
.tag
,
147 ev
.p
.cmd_req
.data_len
, cmd
->tag
);
149 err
= tgt_uspace_send_event(TGT_KEVENT_CMD_DONE
, &ev
);
151 eprintk("tx buf is full, could not send\n");
156 int scsi_tgt_uspace_send_tsk_mgmt(int host_no
, u64 itn_id
, int function
,
157 u64 tag
, struct scsi_lun
*scsilun
, void *data
)
162 memset(&ev
, 0, sizeof(ev
));
163 ev
.p
.tsk_mgmt_req
.host_no
= host_no
;
164 ev
.p
.tsk_mgmt_req
.itn_id
= itn_id
;
165 ev
.p
.tsk_mgmt_req
.function
= function
;
166 ev
.p
.tsk_mgmt_req
.tag
= tag
;
167 memcpy(ev
.p
.tsk_mgmt_req
.lun
, scsilun
, sizeof(ev
.p
.tsk_mgmt_req
.lun
));
168 ev
.p
.tsk_mgmt_req
.mid
= (u64
) (unsigned long) data
;
170 dprintk("%d %x %llx %llx\n", host_no
, function
, (unsigned long long) tag
,
171 (unsigned long long) ev
.p
.tsk_mgmt_req
.mid
);
173 err
= tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ
, &ev
);
175 eprintk("tx buf is full, could not send\n");
180 int scsi_tgt_uspace_send_it_nexus_request(int host_no
, u64 itn_id
,
181 int function
, char *initiator_id
)
186 memset(&ev
, 0, sizeof(ev
));
187 ev
.p
.it_nexus_req
.host_no
= host_no
;
188 ev
.p
.it_nexus_req
.function
= function
;
189 ev
.p
.it_nexus_req
.itn_id
= itn_id
;
191 strncpy(ev
.p
.it_nexus_req
.initiator_id
, initiator_id
,
192 sizeof(ev
.p
.it_nexus_req
.initiator_id
));
194 dprintk("%d %x %llx\n", host_no
, function
, (unsigned long long)itn_id
);
196 err
= tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ
, &ev
);
198 eprintk("tx buf is full, could not send\n");
203 static int event_recv_msg(struct tgt_event
*ev
)
207 switch (ev
->hdr
.type
) {
208 case TGT_UEVENT_CMD_RSP
:
209 err
= scsi_tgt_kspace_exec(ev
->p
.cmd_rsp
.host_no
,
210 ev
->p
.cmd_rsp
.itn_id
,
211 ev
->p
.cmd_rsp
.result
,
215 ev
->p
.cmd_rsp
.sense_uaddr
,
216 ev
->p
.cmd_rsp
.sense_len
,
219 case TGT_UEVENT_TSK_MGMT_RSP
:
220 err
= scsi_tgt_kspace_tsk_mgmt(ev
->p
.tsk_mgmt_rsp
.host_no
,
221 ev
->p
.tsk_mgmt_rsp
.itn_id
,
222 ev
->p
.tsk_mgmt_rsp
.mid
,
223 ev
->p
.tsk_mgmt_rsp
.result
);
225 case TGT_UEVENT_IT_NEXUS_RSP
:
226 err
= scsi_tgt_kspace_it_nexus_rsp(ev
->p
.it_nexus_rsp
.host_no
,
227 ev
->p
.it_nexus_rsp
.itn_id
,
228 ev
->p
.it_nexus_rsp
.result
);
231 eprintk("unknown type %d\n", ev
->hdr
.type
);
238 static ssize_t
tgt_write(struct file
*file
, const char __user
* buffer
,
239 size_t count
, loff_t
* ppos
)
241 struct tgt_event
*ev
;
242 struct tgt_ring
*ring
= &rx_ring
;
245 ev
= tgt_head_event(ring
, ring
->tr_idx
);
246 /* do we need this? */
247 flush_dcache_page(virt_to_page(ev
));
252 tgt_ring_idx_inc(ring
);
260 static unsigned int tgt_poll(struct file
* file
, struct poll_table_struct
*wait
)
262 struct tgt_event
*ev
;
263 struct tgt_ring
*ring
= &tx_ring
;
265 unsigned int mask
= 0;
268 poll_wait(file
, &tgt_poll_wait
, wait
);
270 spin_lock_irqsave(&ring
->tr_lock
, flags
);
272 idx
= ring
->tr_idx
? ring
->tr_idx
- 1 : TGT_MAX_EVENTS
- 1;
273 ev
= tgt_head_event(ring
, idx
);
275 mask
|= POLLIN
| POLLRDNORM
;
277 spin_unlock_irqrestore(&ring
->tr_lock
, flags
);
282 static int uspace_ring_map(struct vm_area_struct
*vma
, unsigned long addr
,
283 struct tgt_ring
*ring
)
287 for (i
= 0; i
< TGT_RING_PAGES
; i
++) {
288 struct page
*page
= virt_to_page(ring
->tr_pages
[i
]);
289 err
= vm_insert_page(vma
, addr
, page
);
298 static int tgt_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
306 if (vma
->vm_end
- vma
->vm_start
!= TGT_RING_SIZE
* 2) {
307 eprintk("mmap size must be %lu, not %lu \n",
308 TGT_RING_SIZE
* 2, vma
->vm_end
- vma
->vm_start
);
312 addr
= vma
->vm_start
;
313 err
= uspace_ring_map(vma
, addr
, &tx_ring
);
316 err
= uspace_ring_map(vma
, addr
+ TGT_RING_SIZE
, &rx_ring
);
321 static int tgt_open(struct inode
*inode
, struct file
*file
)
323 tx_ring
.tr_idx
= rx_ring
.tr_idx
= 0;
329 static const struct file_operations tgt_fops
= {
330 .owner
= THIS_MODULE
,
337 static struct miscdevice tgt_miscdev
= {
338 .minor
= MISC_DYNAMIC_MINOR
,
343 static void tgt_ring_exit(struct tgt_ring
*ring
)
347 for (i
= 0; i
< TGT_RING_PAGES
; i
++)
348 free_page(ring
->tr_pages
[i
]);
351 static int tgt_ring_init(struct tgt_ring
*ring
)
355 spin_lock_init(&ring
->tr_lock
);
357 for (i
= 0; i
< TGT_RING_PAGES
; i
++) {
358 ring
->tr_pages
[i
] = get_zeroed_page(GFP_KERNEL
);
359 if (!ring
->tr_pages
[i
]) {
360 eprintk("out of memory\n");
368 void scsi_tgt_if_exit(void)
370 tgt_ring_exit(&tx_ring
);
371 tgt_ring_exit(&rx_ring
);
372 misc_deregister(&tgt_miscdev
);
375 int scsi_tgt_if_init(void)
379 err
= tgt_ring_init(&tx_ring
);
383 err
= tgt_ring_init(&rx_ring
);
387 err
= misc_register(&tgt_miscdev
);
393 tgt_ring_exit(&rx_ring
);
395 tgt_ring_exit(&tx_ring
);
This page took 0.039129 seconds and 5 git commands to generate.