aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <tomof@acm.org>2007-07-11 02:08:17 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:37:50 -0400
commit2c47f9efbedbe5749b6bb16e59bc11d6e460855f (patch)
treebfc1a2154f67c3aa45f92e586678ffc37e5f80eb
parentaebd5e476ecc8ceb53577b20f2a352ff4ceffd8d (diff)
[SCSI] tgt: add I_T nexus support
tgt uses scsi_host as I_T nexus. This works for ibmvstgt because it creates one scsi_host for one initiator. However, other target drivers don't work like that. This adds I_T nexus support, which enable one scsi_host to handle multiple initiators. New scsi_tgt_it_nexus_create/destroy functions are expected be called transport classes. For example, ibmvstgt creates an initiator remote port, then the srp transport calls tgt_it_nexus_create. tgt doesn't manages I_T nexus, instead it tells tgtd, user-space daemon, to create a new I_T nexus. On the receiving the response from tgtd, tgt calls shost->transportt->it_nexus_response. transports should notify a lld. The srp transport uses it_nexus_response callback in srp_function_template to do that. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/scsi_tgt_if.c42
-rw-r--r--drivers/scsi/scsi_tgt_lib.c83
-rw-r--r--drivers/scsi/scsi_tgt_priv.h22
-rw-r--r--include/scsi/scsi_host.h2
-rw-r--r--include/scsi/scsi_tgt.h8
-rw-r--r--include/scsi/scsi_tgt_if.h35
-rw-r--r--include/scsi/scsi_transport.h6
7 files changed, 161 insertions, 37 deletions
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index ca22ddf81746..9815a1a2db24 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -102,7 +102,8 @@ static int tgt_uspace_send_event(u32 type, struct tgt_event *p)
102 return 0; 102 return 0;
103} 103}
104 104
105int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) 105int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id,
106 struct scsi_lun *lun, u64 tag)
106{ 107{
107 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); 108 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
108 struct tgt_event ev; 109 struct tgt_event ev;
@@ -110,6 +111,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta
110 111
111 memset(&ev, 0, sizeof(ev)); 112 memset(&ev, 0, sizeof(ev));
112 ev.p.cmd_req.host_no = shost->host_no; 113 ev.p.cmd_req.host_no = shost->host_no;
114 ev.p.cmd_req.itn_id = itn_id;
113 ev.p.cmd_req.data_len = cmd->request_bufflen; 115 ev.p.cmd_req.data_len = cmd->request_bufflen;
114 memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); 116 memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb));
115 memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); 117 memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun));
@@ -127,7 +129,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta
127 return err; 129 return err;
128} 130}
129 131
130int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) 132int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag)
131{ 133{
132 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); 134 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
133 struct tgt_event ev; 135 struct tgt_event ev;
@@ -135,6 +137,7 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
135 137
136 memset(&ev, 0, sizeof(ev)); 138 memset(&ev, 0, sizeof(ev));
137 ev.p.cmd_done.host_no = shost->host_no; 139 ev.p.cmd_done.host_no = shost->host_no;
140 ev.p.cmd_done.itn_id = itn_id;
138 ev.p.cmd_done.tag = tag; 141 ev.p.cmd_done.tag = tag;
139 ev.p.cmd_done.result = cmd->result; 142 ev.p.cmd_done.result = cmd->result;
140 143
@@ -149,14 +152,15 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
149 return err; 152 return err;
150} 153}
151 154
152int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, 155int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function,
153 struct scsi_lun *scsilun, void *data) 156 u64 tag, struct scsi_lun *scsilun, void *data)
154{ 157{
155 struct tgt_event ev; 158 struct tgt_event ev;
156 int err; 159 int err;
157 160
158 memset(&ev, 0, sizeof(ev)); 161 memset(&ev, 0, sizeof(ev));
159 ev.p.tsk_mgmt_req.host_no = host_no; 162 ev.p.tsk_mgmt_req.host_no = host_no;
163 ev.p.tsk_mgmt_req.itn_id = itn_id;
160 ev.p.tsk_mgmt_req.function = function; 164 ev.p.tsk_mgmt_req.function = function;
161 ev.p.tsk_mgmt_req.tag = tag; 165 ev.p.tsk_mgmt_req.tag = tag;
162 memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); 166 memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun));
@@ -172,6 +176,29 @@ int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
172 return err; 176 return err;
173} 177}
174 178
179int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id,
180 int function, char *initiator_id)
181{
182 struct tgt_event ev;
183 int err;
184
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;
189 if (initiator_id)
190 strncpy(ev.p.it_nexus_req.initiator_id, initiator_id,
191 sizeof(ev.p.it_nexus_req.initiator_id));
192
193 dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id);
194
195 err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev);
196 if (err)
197 eprintk("tx buf is full, could not send\n");
198
199 return err;
200}
201
175static int event_recv_msg(struct tgt_event *ev) 202static int event_recv_msg(struct tgt_event *ev)
176{ 203{
177 int err = 0; 204 int err = 0;
@@ -179,6 +206,7 @@ static int event_recv_msg(struct tgt_event *ev)
179 switch (ev->hdr.type) { 206 switch (ev->hdr.type) {
180 case TGT_UEVENT_CMD_RSP: 207 case TGT_UEVENT_CMD_RSP:
181 err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, 208 err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
209 ev->p.cmd_rsp.itn_id,
182 ev->p.cmd_rsp.result, 210 ev->p.cmd_rsp.result,
183 ev->p.cmd_rsp.tag, 211 ev->p.cmd_rsp.tag,
184 ev->p.cmd_rsp.uaddr, 212 ev->p.cmd_rsp.uaddr,
@@ -189,9 +217,15 @@ static int event_recv_msg(struct tgt_event *ev)
189 break; 217 break;
190 case TGT_UEVENT_TSK_MGMT_RSP: 218 case TGT_UEVENT_TSK_MGMT_RSP:
191 err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, 219 err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no,
220 ev->p.tsk_mgmt_rsp.itn_id,
192 ev->p.tsk_mgmt_rsp.mid, 221 ev->p.tsk_mgmt_rsp.mid,
193 ev->p.tsk_mgmt_rsp.result); 222 ev->p.tsk_mgmt_rsp.result);
194 break; 223 break;
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);
228 break;
195 default: 229 default:
196 eprintk("unknown type %d\n", ev->hdr.type); 230 eprintk("unknown type %d\n", ev->hdr.type);
197 err = -EINVAL; 231 err = -EINVAL;
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index 371b69c110bc..fa79e54722db 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -27,6 +27,7 @@
27#include <scsi/scsi_cmnd.h> 27#include <scsi/scsi_cmnd.h>
28#include <scsi/scsi_device.h> 28#include <scsi/scsi_device.h>
29#include <scsi/scsi_host.h> 29#include <scsi/scsi_host.h>
30#include <scsi/scsi_transport.h>
30#include <scsi/scsi_tgt.h> 31#include <scsi/scsi_tgt.h>
31 32
32#include "scsi_tgt_priv.h" 33#include "scsi_tgt_priv.h"
@@ -46,6 +47,7 @@ struct scsi_tgt_cmd {
46 47
47 struct list_head hash_list; 48 struct list_head hash_list;
48 struct request *rq; 49 struct request *rq;
50 u64 itn_id;
49 u64 tag; 51 u64 tag;
50}; 52};
51 53
@@ -185,12 +187,13 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work)
185} 187}
186 188
187static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, 189static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
188 u64 tag) 190 u64 itn_id, u64 tag)
189{ 191{
190 struct scsi_tgt_queuedata *qdata = rq->q->queuedata; 192 struct scsi_tgt_queuedata *qdata = rq->q->queuedata;
191 unsigned long flags; 193 unsigned long flags;
192 struct list_head *head; 194 struct list_head *head;
193 195
196 tcmd->itn_id = itn_id;
194 tcmd->tag = tag; 197 tcmd->tag = tag;
195 tcmd->bio = NULL; 198 tcmd->bio = NULL;
196 INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); 199 INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
@@ -301,14 +304,14 @@ EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host);
301 * @scsilun: scsi lun 304 * @scsilun: scsi lun
302 * @tag: unique value to identify this command for tmf 305 * @tag: unique value to identify this command for tmf
303 */ 306 */
304int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, 307int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id,
305 u64 tag) 308 struct scsi_lun *scsilun, u64 tag)
306{ 309{
307 struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; 310 struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
308 int err; 311 int err;
309 312
310 init_scsi_tgt_cmd(cmd->request, tcmd, tag); 313 init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag);
311 err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); 314 err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag);
312 if (err) 315 if (err)
313 cmd_hashlist_del(cmd); 316 cmd_hashlist_del(cmd);
314 317
@@ -326,7 +329,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
326 329
327 dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); 330 dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
328 331
329 scsi_tgt_uspace_send_status(cmd, tcmd->tag); 332 scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag);
330 333
331 if (cmd->request_buffer) 334 if (cmd->request_buffer)
332 scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); 335 scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
@@ -459,7 +462,7 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag)
459 return rq; 462 return rq;
460} 463}
461 464
462int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, 465int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag,
463 unsigned long uaddr, u32 len, unsigned long sense_uaddr, 466 unsigned long uaddr, u32 len, unsigned long sense_uaddr,
464 u32 sense_len, u8 rw) 467 u32 sense_len, u8 rw)
465{ 468{
@@ -541,21 +544,22 @@ done:
541 return err; 544 return err;
542} 545}
543 546
544int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, 547int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id,
545 struct scsi_lun *scsilun, void *data) 548 int function, u64 tag, struct scsi_lun *scsilun,
549 void *data)
546{ 550{
547 int err; 551 int err;
548 552
549 /* TODO: need to retry if this fails. */ 553 /* TODO: need to retry if this fails. */
550 err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, 554 err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id,
551 tag, scsilun, data); 555 function, tag, scsilun, data);
552 if (err < 0) 556 if (err < 0)
553 eprintk("The task management request lost!\n"); 557 eprintk("The task management request lost!\n");
554 return err; 558 return err;
555} 559}
556EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); 560EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request);
557 561
558int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) 562int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result)
559{ 563{
560 struct Scsi_Host *shost; 564 struct Scsi_Host *shost;
561 int err = -EINVAL; 565 int err = -EINVAL;
@@ -573,7 +577,60 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result)
573 goto done; 577 goto done;
574 } 578 }
575 579
576 err = shost->hostt->tsk_mgmt_response(mid, result); 580 err = shost->hostt->tsk_mgmt_response(shost, itn_id, mid, result);
581done:
582 scsi_host_put(shost);
583 return err;
584}
585
586int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id,
587 char *initiator)
588{
589 int err;
590
591 /* TODO: need to retry if this fails. */
592 err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0,
593 initiator);
594 if (err < 0)
595 eprintk("The i_t_neuxs request lost, %d %llx!\n",
596 shost->host_no, (unsigned long long)itn_id);
597 return err;
598}
599EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create);
600
601int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id)
602{
603 int err;
604
605 /* TODO: need to retry if this fails. */
606 err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no,
607 itn_id, 1, NULL);
608 if (err < 0)
609 eprintk("The i_t_neuxs request lost, %d %llx!\n",
610 shost->host_no, (unsigned long long)itn_id);
611 return err;
612}
613EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy);
614
615int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result)
616{
617 struct Scsi_Host *shost;
618 int err = -EINVAL;
619
620 dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
621
622 shost = scsi_host_lookup(host_no);
623 if (IS_ERR(shost)) {
624 printk(KERN_ERR "Could not find host no %d\n", host_no);
625 return err;
626 }
627
628 if (!shost->uspace_req_q) {
629 printk(KERN_ERR "Not target scsi host %d\n", host_no);
630 goto done;
631 }
632
633 err = shost->transportt->it_nexus_response(shost, itn_id, result);
577done: 634done:
578 scsi_host_put(shost); 635 scsi_host_put(shost);
579 return err; 636 return err;
diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h
index e9e6db1c417f..cb92888948f9 100644
--- a/drivers/scsi/scsi_tgt_priv.h
+++ b/drivers/scsi/scsi_tgt_priv.h
@@ -15,12 +15,18 @@ do { \
15extern void scsi_tgt_if_exit(void); 15extern void scsi_tgt_if_exit(void);
16extern int scsi_tgt_if_init(void); 16extern int scsi_tgt_if_init(void);
17 17
18extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, 18extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id,
19 u64 tag); 19 struct scsi_lun *lun, u64 tag);
20extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); 20extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id,
21extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, 21 u64 tag);
22 unsigned long uaddr, u32 len, unsigned long sense_uaddr, 22extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag,
23 u32 sense_len, u8 rw); 23 unsigned long uaddr, u32 len,
24extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, 24 unsigned long sense_uaddr, u32 sense_len, u8 rw);
25extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id,
26 int function, u64 tag,
25 struct scsi_lun *scsilun, void *data); 27 struct scsi_lun *scsilun, void *data);
26extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); 28extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id,
29 u64 mid, int result);
30extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id,
31 int function, char *initiator);
32extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 3b8a6a85c2f8..89c40c4bd5c4 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -146,7 +146,7 @@ struct scsi_host_template {
146 void (*done)(struct scsi_cmnd *)); 146 void (*done)(struct scsi_cmnd *));
147 147
148 /* Used as callback for the completion of task management request. */ 148 /* Used as callback for the completion of task management request. */
149 int (* tsk_mgmt_response)(u64 mid, int result); 149 int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64 mid, int result);
150 150
151 /* 151 /*
152 * This is an error handling strategy routine. You don't need to 152 * This is an error handling strategy routine. You don't need to
diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h
index 4f4427937af2..d0fefb96158f 100644
--- a/include/scsi/scsi_tgt.h
+++ b/include/scsi/scsi_tgt.h
@@ -11,9 +11,11 @@ struct scsi_lun;
11extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); 11extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *);
12extern int scsi_tgt_alloc_queue(struct Scsi_Host *); 12extern int scsi_tgt_alloc_queue(struct Scsi_Host *);
13extern void scsi_tgt_free_queue(struct Scsi_Host *); 13extern void scsi_tgt_free_queue(struct Scsi_Host *);
14extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64); 14extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64);
15extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *, 15extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64,
16 void *); 16 struct scsi_lun *, void *);
17extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, 17extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *,
18 enum dma_data_direction, gfp_t); 18 enum dma_data_direction, gfp_t);
19extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); 19extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *);
20extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *);
21extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64);
diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h
index 4cf9dff29a2f..f2ee7c238a45 100644
--- a/include/scsi/scsi_tgt_if.h
+++ b/include/scsi/scsi_tgt_if.h
@@ -23,13 +23,15 @@
23#define __SCSI_TARGET_IF_H 23#define __SCSI_TARGET_IF_H
24 24
25/* user -> kernel */ 25/* user -> kernel */
26#define TGT_UEVENT_CMD_RSP 0x0001 26#define TGT_UEVENT_CMD_RSP 0x0001
27#define TGT_UEVENT_TSK_MGMT_RSP 0x0002 27#define TGT_UEVENT_IT_NEXUS_RSP 0x0002
28#define TGT_UEVENT_TSK_MGMT_RSP 0x0003
28 29
29/* kernel -> user */ 30/* kernel -> user */
30#define TGT_KEVENT_CMD_REQ 0x1001 31#define TGT_KEVENT_CMD_REQ 0x1001
31#define TGT_KEVENT_CMD_DONE 0x1002 32#define TGT_KEVENT_CMD_DONE 0x1002
32#define TGT_KEVENT_TSK_MGMT_REQ 0x1003 33#define TGT_KEVENT_IT_NEXUS_REQ 0x1003
34#define TGT_KEVENT_TSK_MGMT_REQ 0x1004
33 35
34struct tgt_event_hdr { 36struct tgt_event_hdr {
35 uint16_t version; 37 uint16_t version;
@@ -46,6 +48,7 @@ struct tgt_event {
46 struct { 48 struct {
47 int host_no; 49 int host_no;
48 int result; 50 int result;
51 aligned_u64 itn_id;
49 aligned_u64 tag; 52 aligned_u64 tag;
50 aligned_u64 uaddr; 53 aligned_u64 uaddr;
51 aligned_u64 sense_uaddr; 54 aligned_u64 sense_uaddr;
@@ -55,15 +58,22 @@ struct tgt_event {
55 } cmd_rsp; 58 } cmd_rsp;
56 struct { 59 struct {
57 int host_no; 60 int host_no;
58 aligned_u64 mid;
59 int result; 61 int result;
62 aligned_u64 itn_id;
63 aligned_u64 mid;
60 } tsk_mgmt_rsp; 64 } tsk_mgmt_rsp;
61 65 struct {
66 __s32 host_no;
67 __s32 result;
68 aligned_u64 itn_id;
69 __u32 function;
70 } it_nexus_rsp;
62 71
63 /* kernel -> user */ 72 /* kernel -> user */
64 struct { 73 struct {
65 int host_no; 74 int host_no;
66 uint32_t data_len; 75 uint32_t data_len;
76 aligned_u64 itn_id;
67 uint8_t scb[16]; 77 uint8_t scb[16];
68 uint8_t lun[8]; 78 uint8_t lun[8];
69 int attribute; 79 int attribute;
@@ -71,16 +81,25 @@ struct tgt_event {
71 } cmd_req; 81 } cmd_req;
72 struct { 82 struct {
73 int host_no; 83 int host_no;
74 aligned_u64 tag;
75 int result; 84 int result;
85 aligned_u64 itn_id;
86 aligned_u64 tag;
76 } cmd_done; 87 } cmd_done;
77 struct { 88 struct {
78 int host_no; 89 int host_no;
79 int function; 90 int function;
91 aligned_u64 itn_id;
80 aligned_u64 tag; 92 aligned_u64 tag;
81 uint8_t lun[8]; 93 uint8_t lun[8];
82 aligned_u64 mid; 94 aligned_u64 mid;
83 } tsk_mgmt_req; 95 } tsk_mgmt_req;
96 struct {
97 __s32 host_no;
98 __u32 function;
99 aligned_u64 itn_id;
100 __u32 max_cmds;
101 __u8 initiator_id[16];
102 } it_nexus_req;
84 } p; 103 } p;
85} __attribute__ ((aligned (sizeof(uint64_t)))); 104} __attribute__ ((aligned (sizeof(uint64_t))));
86 105
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index 3c18baa65a72..af5b3e15e64e 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -65,6 +65,12 @@ struct scsi_transport_template {
65 * EH_NOT_HANDLED Begin normal error recovery 65 * EH_NOT_HANDLED Begin normal error recovery
66 */ 66 */
67 enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); 67 enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
68
69 /*
70 * Used as callback for the completion of i_t_nexus request
71 * for target drivers.
72 */
73 int (* it_nexus_response)(struct Scsi_Host *, u64, int);
68}; 74};
69 75
70#define transport_class_to_shost(tc) \ 76#define transport_class_to_shost(tc) \