]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/open-iscsi-offloading-support
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / open-iscsi-offloading-support
1 Subject: support for iscsi pdu digest offload and payload DDP.
2 From: Karen Xie <kxie@chelsio.com>
3 References: FATE#304154,bnc#433500
4
5 Added PDU digest offload and payload direct-placement support in open-iscsi.
6
7 Signed-off-by: Karen Xie <kxie@chelsio.com>
8 Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
9 Signed-off-by: Hannes Reinecke <hare@suse.de>
10 ---
11
12 ---
13 drivers/scsi/iscsi_tcp.c | 55 ++++++++++++-----
14 drivers/scsi/iscsi_tcp.h | 16 +++++
15 drivers/scsi/libiscsi.c | 111 ++++++++++++++++++++++++++++--------
16 drivers/scsi/scsi_transport_iscsi.c | 8 +-
17 include/scsi/iscsi_if.h | 1
18 include/scsi/libiscsi.h | 12 +++
19 include/scsi/scsi_transport_iscsi.h | 9 ++
20 7 files changed, 166 insertions(+), 46 deletions(-)
21
22 --- a/drivers/scsi/iscsi_tcp.c
23 +++ b/drivers/scsi/iscsi_tcp.c
24 @@ -97,7 +97,7 @@ static int iscsi_tcp_hdr_recv_done(struc
25 * data is copied to the indicated sg entry, at the given
26 * offset.
27 */
28 -static inline void
29 +void
30 iscsi_tcp_segment_init_sg(struct iscsi_segment *segment,
31 struct scatterlist *sg, unsigned int offset)
32 {
33 @@ -107,6 +107,7 @@ iscsi_tcp_segment_init_sg(struct iscsi_s
34 segment->total_size - segment->total_copied);
35 segment->data = NULL;
36 }
37 +EXPORT_SYMBOL_GPL(iscsi_tcp_segment_init_sg);
38
39 /**
40 * iscsi_tcp_segment_map - map the current S/G page
41 @@ -117,7 +118,7 @@ iscsi_tcp_segment_init_sg(struct iscsi_s
42 * because the iscsi passthrough and internal IO paths will never use high
43 * mem pages.
44 */
45 -static inline void
46 +void
47 iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
48 {
49 struct scatterlist *sg;
50 @@ -143,8 +144,9 @@ iscsi_tcp_segment_map(struct iscsi_segme
51 segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
52 segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
53 }
54 +EXPORT_SYMBOL_GPL(iscsi_tcp_segment_map);
55
56 -static inline void
57 +void
58 iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
59 {
60 debug_tcp("iscsi_tcp_segment_unmap %p\n", segment);
61 @@ -156,6 +158,7 @@ iscsi_tcp_segment_unmap(struct iscsi_seg
62 segment->data = NULL;
63 }
64 }
65 +EXPORT_SYMBOL_GPL(iscsi_tcp_segment_unmap);
66
67 /*
68 * Splice the digest buffer into the buffer
69 @@ -376,6 +379,9 @@ static inline int
70 iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn,
71 struct iscsi_segment *segment)
72 {
73 + if (tcp_conn->iscsi_conn->session->tt->caps & CAP_DIGEST_OFFLOAD)
74 + return (segment->status & ISCSI_SEGMENT_DGST_ERR) ? 0 : 1;
75 +
76 if (!segment->digest_len)
77 return 1;
78
79 @@ -448,7 +454,7 @@ iscsi_segment_seek_sg(struct iscsi_segme
80 * function is called we do not yet know the final size of the header and want
81 * to delay the digest processing until we know that.
82 */
83 -static void
84 +void
85 iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn)
86 {
87 debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn,
88 @@ -457,6 +463,7 @@ iscsi_tcp_hdr_recv_prep(struct iscsi_tcp
89 tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr),
90 iscsi_tcp_hdr_recv_done, NULL);
91 }
92 +EXPORT_SYMBOL_GPL(iscsi_tcp_hdr_recv_prep);
93
94 /*
95 * Handle incoming reply to any other type of command
96 @@ -486,7 +493,8 @@ iscsi_tcp_data_recv_prep(struct iscsi_tc
97 struct iscsi_conn *conn = tcp_conn->iscsi_conn;
98 struct hash_desc *rx_hash = NULL;
99
100 - if (conn->datadgst_en)
101 + if (conn->datadgst_en &&
102 + !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
103 rx_hash = &tcp_conn->rx_hash;
104
105 iscsi_segment_init_linear(&tcp_conn->in.segment,
106 @@ -497,7 +505,7 @@ iscsi_tcp_data_recv_prep(struct iscsi_tc
107 /*
108 * must be called with session lock
109 */
110 -static void
111 +void
112 iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
113 {
114 struct iscsi_tcp_task *tcp_task = task->dd_data;
115 @@ -521,6 +529,7 @@ iscsi_tcp_cleanup_task(struct iscsi_conn
116 tcp_task->r2t = NULL;
117 }
118 }
119 +EXPORT_SYMBOL_GPL(iscsi_tcp_cleanup_task);
120
121 /**
122 * iscsi_data_rsp - SCSI Data-In Response processing
123 @@ -737,7 +746,7 @@ iscsi_tcp_process_data_in(struct iscsi_t
124 * by data, the receive buffer is set up to copy the incoming data
125 * to the correct location.
126 */
127 -static int
128 +int
129 iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
130 {
131 int rc = 0, opcode, ahslen;
132 @@ -793,7 +802,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn
133 * we move on to the next scatterlist entry and
134 * update the digest per-entry.
135 */
136 - if (conn->datadgst_en)
137 + if (conn->datadgst_en &&
138 + !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
139 rx_hash = &tcp_conn->rx_hash;
140
141 debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
142 @@ -881,6 +891,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn
143
144 return rc;
145 }
146 +EXPORT_SYMBOL_GPL(iscsi_tcp_hdr_dissect);
147
148 /**
149 * iscsi_tcp_hdr_recv_done - process PDU header
150 @@ -919,7 +930,8 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp
151 /* We're done processing the header. See if we're doing
152 * header digests; if so, set up the recv_digest buffer
153 * and go back for more. */
154 - if (conn->hdrdgst_en) {
155 + if (conn->hdrdgst_en &&
156 + !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
157 if (segment->digest_len == 0) {
158 iscsi_tcp_segment_splice_digest(segment,
159 segment->recv_digest);
160 @@ -1161,10 +1173,11 @@ iscsi_tcp_xmit_qlen(struct iscsi_conn *c
161 static inline int
162 iscsi_tcp_flush(struct iscsi_conn *conn)
163 {
164 + struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
165 int rc;
166
167 while (iscsi_tcp_xmit_qlen(conn)) {
168 - rc = iscsi_xmit(conn);
169 + rc = tcp_conn->xmit_segment(conn);
170 if (rc == 0)
171 return -EAGAIN;
172 if (rc < 0)
173 @@ -1205,7 +1218,8 @@ iscsi_tcp_send_hdr_prep(struct iscsi_con
174 * sure that both iscsi_tcp_task and mtask have
175 * sufficient room.
176 */
177 - if (conn->hdrdgst_en) {
178 + if (conn->hdrdgst_en &&
179 + !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
180 iscsi_tcp_dgst_header(&tcp_conn->tx_hash, hdr, hdrlen,
181 hdr + hdrlen);
182 hdrlen += ISCSI_DIGEST_SIZE;
183 @@ -1243,7 +1257,8 @@ iscsi_tcp_send_data_prep(struct iscsi_co
184 hdr_spec_len = ntoh24(tcp_conn->out.hdr->dlength);
185 WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len));
186
187 - if (conn->datadgst_en)
188 + if (conn->datadgst_en &&
189 + !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
190 tx_hash = &tcp_conn->tx_hash;
191
192 return iscsi_segment_seek_sg(&tcp_conn->out.data_segment,
193 @@ -1267,7 +1282,8 @@ iscsi_tcp_send_linear_data_prepare(struc
194 hdr_spec_len = ntoh24(tcp_conn->out.hdr->dlength);
195 WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len));
196
197 - if (conn->datadgst_en)
198 + if (conn->datadgst_en &&
199 + !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
200 tx_hash = &tcp_conn->tx_hash;
201
202 iscsi_segment_init_linear(&tcp_conn->out.data_segment,
203 @@ -1329,7 +1345,7 @@ iscsi_solicit_data_cont(struct iscsi_con
204 * @task: scsi command task
205 * @sc: scsi command
206 **/
207 -static int
208 +int
209 iscsi_tcp_task_init(struct iscsi_task *task)
210 {
211 struct iscsi_tcp_task *tcp_task = task->dd_data;
212 @@ -1378,6 +1394,7 @@ iscsi_tcp_task_init(struct iscsi_task *t
213 task->imm_count = 0;
214 return 0;
215 }
216 +EXPORT_SYMBOL_GPL(iscsi_tcp_task_init);
217
218 /*
219 * iscsi_tcp_task_xmit - xmit normal PDU task
220 @@ -1387,7 +1404,7 @@ iscsi_tcp_task_init(struct iscsi_task *t
221 * -EAGAIN if there's still data in the queue, or != 0 for any other kind
222 * of error.
223 */
224 -static int
225 +int
226 iscsi_tcp_task_xmit(struct iscsi_task *task)
227 {
228 struct iscsi_conn *conn = task->conn;
229 @@ -1490,6 +1507,7 @@ fail:
230 iscsi_conn_failure(conn, rc);
231 return -EIO;
232 }
233 +EXPORT_SYMBOL_GPL(iscsi_tcp_task_xmit);
234
235 static struct iscsi_cls_conn *
236 iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
237 @@ -1685,6 +1703,7 @@ iscsi_tcp_conn_bind(struct iscsi_cls_ses
238
239 iscsi_conn_set_callbacks(conn);
240 tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
241 + tcp_conn->xmit_segment = iscsi_xmit;
242 /*
243 * set receive state machine into initial state
244 */
245 @@ -1696,7 +1715,7 @@ free_socket:
246 return err;
247 }
248
249 -static int
250 +int
251 iscsi_r2tpool_alloc(struct iscsi_session *session)
252 {
253 int i;
254 @@ -1742,8 +1761,9 @@ r2t_alloc_fail:
255 }
256 return -ENOMEM;
257 }
258 +EXPORT_SYMBOL_GPL(iscsi_r2tpool_alloc);
259
260 -static void
261 +void
262 iscsi_r2tpool_free(struct iscsi_session *session)
263 {
264 int i;
265 @@ -1756,6 +1776,7 @@ iscsi_r2tpool_free(struct iscsi_session
266 iscsi_pool_free(&tcp_task->r2tpool);
267 }
268 }
269 +EXPORT_SYMBOL_GPL(iscsi_r2tpool_free);
270
271 static int
272 iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
273 --- a/drivers/scsi/iscsi_tcp.h
274 +++ b/drivers/scsi/iscsi_tcp.h
275 @@ -32,7 +32,9 @@ struct iscsi_segment;
276 typedef int iscsi_segment_done_fn_t(struct iscsi_tcp_conn *,
277 struct iscsi_segment *);
278
279 +#define ISCSI_SEGMENT_DGST_ERR 0x1
280 struct iscsi_segment {
281 + unsigned int status;
282 unsigned char *data;
283 unsigned int size;
284 unsigned int copied;
285 @@ -95,6 +97,8 @@ struct iscsi_tcp_conn {
286
287 int error;
288
289 + /* segment transmit */
290 + int (*xmit_segment)(struct iscsi_conn *);
291 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
292 };
293
294 @@ -130,4 +134,16 @@ struct iscsi_tcp_task {
295 struct iscsi_data_task unsol_dtask; /* Data-Out header buf */
296 };
297
298 +void iscsi_tcp_segment_init_sg(struct iscsi_segment *, struct scatterlist *,
299 + unsigned int);
300 +void iscsi_tcp_segment_map(struct iscsi_segment *, int);
301 +void iscsi_tcp_segment_unmap(struct iscsi_segment *);
302 +void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *);
303 +void iscsi_tcp_cleanup_task(struct iscsi_conn *, struct iscsi_task *);
304 +int iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *);
305 +int iscsi_tcp_task_init(struct iscsi_task *);
306 +int iscsi_tcp_task_xmit(struct iscsi_task *);
307 +int iscsi_r2tpool_alloc(struct iscsi_session *);
308 +void iscsi_r2tpool_free(struct iscsi_session *);
309 +
310 #endif /* ISCSI_H */
311 --- a/drivers/scsi/libiscsi.c
312 +++ b/drivers/scsi/libiscsi.c
313 @@ -218,7 +218,12 @@ static int iscsi_prep_scsi_cmd_pdu(struc
314 hdr->opcode = ISCSI_OP_SCSI_CMD;
315 hdr->flags = ISCSI_ATTR_SIMPLE;
316 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
317 - hdr->itt = build_itt(task->itt, session->age);
318 + if (session->tt->reserve_itt) {
319 + rc = session->tt->reserve_itt(task, &hdr->itt);
320 + if (rc)
321 + return rc;
322 + } else
323 + hdr->itt = build_itt(task->itt, session->age);
324 hdr->cmdsn = cpu_to_be32(session->cmdsn);
325 session->cmdsn++;
326 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
327 @@ -332,6 +337,9 @@ static void iscsi_complete_command(struc
328 struct iscsi_session *session = conn->session;
329 struct scsi_cmnd *sc = task->sc;
330
331 + if (session->tt->release_itt)
332 + session->tt->release_itt(task, task->hdr->itt);
333 +
334 list_del_init(&task->running);
335 task->state = ISCSI_TASK_COMPLETED;
336 task->sc = NULL;
337 @@ -443,7 +451,12 @@ static int iscsi_prep_mgmt_task(struct i
338 */
339 nop->cmdsn = cpu_to_be32(session->cmdsn);
340 if (hdr->itt != RESERVED_ITT) {
341 - hdr->itt = build_itt(task->itt, session->age);
342 + if (session->tt->reserve_itt) {
343 + int rc = session->tt->reserve_itt(task, &hdr->itt);
344 + if (rc)
345 + return rc;
346 + } else
347 + hdr->itt = build_itt(task->itt, session->age);
348 /*
349 * TODO: We always use immediate, so we never hit this.
350 * If we start to send tmfs or nops as non-immediate then
351 @@ -692,7 +705,13 @@ static int iscsi_handle_reject(struct is
352
353 if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
354 memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
355 - itt = get_itt(rejected_pdu.itt);
356 + if (conn->session->tt->parse_itt)
357 + conn->session->tt->parse_itt(conn,
358 + rejected_pdu.itt,
359 + &itt,
360 + NULL);
361 + else
362 + itt = get_itt(rejected_pdu.itt);
363 iscsi_conn_printk(KERN_ERR, conn,
364 "itt 0x%x had pdu (op 0x%x) rejected "
365 "due to DataDigest error.\n", itt,
366 @@ -720,7 +739,10 @@ struct iscsi_task *iscsi_itt_to_task(str
367 if (itt == RESERVED_ITT)
368 return NULL;
369
370 - i = get_itt(itt);
371 + if (conn->session->tt->parse_itt)
372 + conn->session->tt->parse_itt(conn, itt, &i, NULL);
373 + else
374 + i = get_itt(itt);
375 if (i >= session->cmds_max)
376 return NULL;
377
378 @@ -752,9 +774,13 @@ int __iscsi_complete_pdu(struct iscsi_co
379 if (rc)
380 return rc;
381
382 - if (hdr->itt != RESERVED_ITT)
383 - itt = get_itt(hdr->itt);
384 - else
385 + if (hdr->itt != RESERVED_ITT) {
386 + if (conn->session->tt->parse_itt)
387 + conn->session->tt->parse_itt(conn, hdr->itt,
388 + &itt, NULL);
389 + else
390 + itt = get_itt(hdr->itt);
391 + } else
392 itt = ~0U;
393
394 debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n",
395 @@ -901,20 +927,25 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
396 int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
397 {
398 struct iscsi_session *session = conn->session;
399 - uint32_t i;
400 + uint32_t i, age;
401
402 if (itt == RESERVED_ITT)
403 return 0;
404
405 - if (((__force u32)itt & ISCSI_AGE_MASK) !=
406 - (session->age << ISCSI_AGE_SHIFT)) {
407 + if (conn->session->tt->parse_itt)
408 + conn->session->tt->parse_itt(conn, itt, &i, &age);
409 + else {
410 + i = get_itt(itt);
411 + age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK;
412 + }
413 +
414 + if (age != session->age) {
415 iscsi_conn_printk(KERN_ERR, conn,
416 "received itt %x expected session age (%x)\n",
417 (__force u32)itt, session->age);
418 return ISCSI_ERR_BAD_ITT;
419 }
420
421 - i = get_itt(itt);
422 if (i >= session->cmds_max) {
423 iscsi_conn_printk(KERN_ERR, conn,
424 "received invalid itt index %u (max cmds "
425 @@ -1930,13 +1961,15 @@ struct Scsi_Host *iscsi_host_alloc(struc
426 shost->cmd_per_lun = qdepth;
427
428 ihost = shost_priv(shost);
429 - atomic_set(&ihost->num_sessions, 0);
430 + spin_lock_init(&ihost->lock);
431 + ihost->state = ISCSI_HOST_SETUP;
432 + ihost->num_sessions = 0;
433 init_waitqueue_head(&ihost->session_removal_wq);
434 return shost;
435 }
436 EXPORT_SYMBOL_GPL(iscsi_host_alloc);
437
438 -static void iscsi_kill_session(struct iscsi_cls_session *cls_session)
439 +static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
440 {
441 iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
442 }
443 @@ -1951,10 +1984,15 @@ static void iscsi_kill_session(struct is
444 void iscsi_host_remove(struct Scsi_Host *shost)
445 {
446 struct iscsi_host *ihost = shost_priv(shost);
447 + unsigned long flags;
448
449 - iscsi_host_for_each_session(shost, iscsi_kill_session);
450 + spin_lock_irqsave(&ihost->lock, flags);
451 + ihost->state = ISCSI_HOST_REMOVED;
452 + spin_unlock_irqrestore(&ihost->lock, flags);
453 +
454 + iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
455 wait_event_interruptible(ihost->session_removal_wq,
456 - atomic_read(&ihost->num_sessions) == 0);
457 + ihost->num_sessions == 0);
458 if (signal_pending(current))
459 flush_signals(current);
460
461 @@ -1973,6 +2011,27 @@ void iscsi_host_free(struct Scsi_Host *s
462 }
463 EXPORT_SYMBOL_GPL(iscsi_host_free);
464
465 +static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost)
466 +{
467 + struct iscsi_host *ihost = shost_priv(shost);
468 + unsigned long flags;
469 +
470 + shost = scsi_host_get(shost);
471 + if (!shost) {
472 + printk(KERN_ERR "Invalid state. Cannot notify host removal "
473 + "of session teardown event because host already "
474 + "removed.\n");
475 + return;
476 + }
477 +
478 + spin_lock_irqsave(&ihost->lock, flags);
479 + ihost->num_sessions--;
480 + if (ihost->num_sessions == 0)
481 + wake_up(&ihost->session_removal_wq);
482 + spin_unlock_irqrestore(&ihost->lock, flags);
483 + scsi_host_put(shost);
484 +}
485 +
486 /**
487 * iscsi_session_setup - create iscsi cls session and host and session
488 * @iscsit: iscsi transport template
489 @@ -1997,6 +2056,15 @@ iscsi_session_setup(struct iscsi_transpo
490 struct iscsi_session *session;
491 struct iscsi_cls_session *cls_session;
492 int cmd_i, scsi_cmds, total_cmds = cmds_max;
493 + unsigned long flags;
494 +
495 + spin_lock_irqsave(&ihost->lock, flags);
496 + if (ihost->state == ISCSI_HOST_REMOVED) {
497 + spin_unlock_irqrestore(&ihost->lock, flags);
498 + return NULL;
499 + }
500 + ihost->num_sessions++;
501 + spin_unlock_irqrestore(&ihost->lock, flags);
502
503 if (!total_cmds)
504 total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
505 @@ -2009,7 +2077,7 @@ iscsi_session_setup(struct iscsi_transpo
506 printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
507 "must be a power of two that is at least %d.\n",
508 total_cmds, ISCSI_TOTAL_CMDS_MIN);
509 - return NULL;
510 + goto dec_session_count;
511 }
512
513 if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
514 @@ -2033,7 +2101,7 @@ iscsi_session_setup(struct iscsi_transpo
515 cls_session = iscsi_alloc_session(shost, iscsit,
516 sizeof(struct iscsi_session));
517 if (!cls_session)
518 - return NULL;
519 + goto dec_session_count;
520 session = cls_session->dd_data;
521 session->cls_session = cls_session;
522 session->host = shost;
523 @@ -2073,7 +2141,6 @@ iscsi_session_setup(struct iscsi_transpo
524 if (iscsi_add_session(cls_session, id))
525 goto cls_session_fail;
526
527 - atomic_inc(&ihost->num_sessions);
528 return cls_session;
529
530 cls_session_fail:
531 @@ -2082,6 +2149,8 @@ module_get_fail:
532 iscsi_pool_free(&session->cmdpool);
533 cmdpool_alloc_fail:
534 iscsi_free_session(cls_session);
535 +dec_session_count:
536 + iscsi_host_dec_session_cnt(shost);
537 return NULL;
538 }
539 EXPORT_SYMBOL_GPL(iscsi_session_setup);
540 @@ -2096,8 +2165,8 @@ EXPORT_SYMBOL_GPL(iscsi_session_setup);
541 void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
542 {
543 struct iscsi_session *session = cls_session->dd_data;
544 - struct iscsi_host *ihost = shost_priv(session->host);
545 struct module *owner = cls_session->transport->owner;
546 + struct Scsi_Host *shost = session->host;
547
548 iscsi_pool_free(&session->cmdpool);
549
550 @@ -2111,9 +2180,7 @@ void iscsi_session_teardown(struct iscsi
551
552 iscsi_destroy_session(cls_session);
553
554 - atomic_dec(&ihost->num_sessions);
555 - wake_up(&ihost->session_removal_wq);
556 -
557 + iscsi_host_dec_session_cnt(shost);
558 module_put(owner);
559 }
560 EXPORT_SYMBOL_GPL(iscsi_session_teardown);
561 --- a/drivers/scsi/scsi_transport_iscsi.c
562 +++ b/drivers/scsi/scsi_transport_iscsi.c
563 @@ -138,7 +138,7 @@ static ssize_t
564 show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
565 {
566 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
567 - return sprintf(buf, "%u\n", ep->id);
568 + return sprintf(buf, "%llu\n", (unsigned long long)ep->id);
569 }
570 static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
571
572 @@ -156,7 +156,7 @@ static struct attribute_group iscsi_endp
573 static int iscsi_match_epid(struct device *dev, void *data)
574 {
575 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
576 - unsigned int *epid = (unsigned int *) data;
577 + uint64_t *epid = (uint64_t *) data;
578
579 return *epid == ep->id;
580 }
581 @@ -166,7 +166,7 @@ iscsi_create_endpoint(int dd_size)
582 {
583 struct device *dev;
584 struct iscsi_endpoint *ep;
585 - unsigned int id;
586 + uint64_t id;
587 int err;
588
589 for (id = 1; id < ISCSI_MAX_EPID; id++) {
590 @@ -187,7 +187,7 @@ iscsi_create_endpoint(int dd_size)
591
592 ep->id = id;
593 ep->dev.class = &iscsi_endpoint_class;
594 - snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id);
595 + snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%llu", id);
596 err = device_register(&ep->dev);
597 if (err)
598 goto free_ep;
599 --- a/include/scsi/iscsi_if.h
600 +++ b/include/scsi/iscsi_if.h
601 @@ -334,6 +334,7 @@ enum iscsi_host_param {
602 #define CAP_FW_DB 0x200
603 #define CAP_SENDTARGETS_OFFLOAD 0x400
604 #define CAP_DATA_PATH_OFFLOAD 0x800
605 +#define CAP_DIGEST_OFFLOAD 0x1000
606
607 /*
608 * These flags describes reason of stop_conn() call
609 --- a/include/scsi/libiscsi.h
610 +++ b/include/scsi/libiscsi.h
611 @@ -75,7 +75,7 @@ enum {
612 /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
613 #define ISCSI_TOTAL_CMDS_MIN 16
614 #define ISCSI_AGE_SHIFT 28
615 -#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT)
616 +#define ISCSI_AGE_MASK 0xf
617
618 #define ISCSI_ADDRESS_BUF_LEN 64
619
620 @@ -287,6 +287,10 @@ struct iscsi_session {
621 struct iscsi_pool cmdpool; /* PDU's pool */
622 };
623
624 +enum {
625 + ISCSI_HOST_SETUP,
626 + ISCSI_HOST_REMOVED,
627 +};
628 struct iscsi_host {
629 char *initiatorname;
630 /* hw address or netdev iscsi connection is bound to */
631 @@ -297,7 +301,11 @@ struct iscsi_host {
632 char local_address[ISCSI_ADDRESS_BUF_LEN];
633
634 wait_queue_head_t session_removal_wq;
635 - atomic_t num_sessions;
636 +
637 + /* protects sessions and state */
638 + spinlock_t lock;
639 + int num_sessions;
640 + int state;
641 };
642
643 /*
644 --- a/include/scsi/scsi_transport_iscsi.h
645 +++ b/include/scsi/scsi_transport_iscsi.h
646 @@ -56,6 +56,9 @@ struct sockaddr;
647 * is not supported, and a -Exx value on other error
648 * @start_conn: set connection to be operational
649 * @stop_conn: suspend/recover/terminate connection
650 + * @parse_itt: parse the itt rcv'ed in BHS
651 + * @reserve_itt: construct a task itt to be sent in BHS
652 + * @release_itt: release a itt (constructed by reserve_itt)
653 * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
654 * @session_recovery_timedout: notify LLD a block during recovery timed out
655 * @init_task: Initialize a iscsi_task and any internal structs.
656 @@ -109,6 +112,10 @@ struct iscsi_transport {
657 int (*set_host_param) (struct Scsi_Host *shost,
658 enum iscsi_host_param param, char *buf,
659 int buflen);
660 + void (*parse_itt)(struct iscsi_conn *conn, itt_t hdr_itt,
661 + int *idx, int *age);
662 + int (*reserve_itt)(struct iscsi_task *task, itt_t *hdr_itt);
663 + void (*release_itt)(struct iscsi_task *task, itt_t hdr_itt);
664 int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
665 char *data, uint32_t data_size);
666 void (*get_stats) (struct iscsi_cls_conn *conn,
667 @@ -207,7 +214,7 @@ extern void iscsi_host_for_each_session(
668 struct iscsi_endpoint {
669 void *dd_data; /* LLD private data */
670 struct device dev;
671 - unsigned int id;
672 + uint64_t id;
673 };
674
675 /*