]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/cxgbe/cxgbei/cxgbei.c
cxgbe(4): Update T5 and T4 firmwares to 1.15.37.0.
[FreeBSD/FreeBSD.git] / sys / dev / cxgbe / cxgbei / cxgbei.c
1 /*-
2  * Copyright (c) 2012 Chelsio Communications, Inc.
3  * All rights reserved.
4  *
5  * Chelsio T5xx iSCSI driver
6  *
7  * Written by: Sreenivasa Honnur <shonnur@chelsio.com>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_inet.h"
35 #include "opt_inet6.h"
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/systm.h>
42
43 #ifdef TCP_OFFLOAD
44 #include <sys/errno.h>
45 #include <sys/kthread.h>
46 #include <sys/smp.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/mbuf.h>
50 #include <sys/lock.h>
51 #include <sys/mutex.h>
52 #include <sys/condvar.h>
53
54 #include <netinet/in.h>
55 #include <netinet/in_pcb.h>
56 #include <netinet/toecore.h>
57 #include <netinet/tcp_var.h>
58 #include <netinet/tcp_fsm.h>
59
60 #include <cam/scsi/scsi_all.h>
61 #include <cam/scsi/scsi_da.h>
62 #include <cam/ctl/ctl_io.h>
63 #include <cam/ctl/ctl.h>
64 #include <cam/ctl/ctl_backend.h>
65 #include <cam/ctl/ctl_error.h>
66 #include <cam/ctl/ctl_frontend.h>
67 #include <cam/ctl/ctl_debug.h>
68 #include <cam/ctl/ctl_ha.h>
69 #include <cam/ctl/ctl_ioctl.h>
70
71 #include <dev/iscsi/icl.h>
72 #include <dev/iscsi/iscsi_proto.h>
73 #include <dev/iscsi/iscsi_ioctl.h>
74 #include <dev/iscsi/iscsi.h>
75 #include <cam/ctl/ctl_frontend_iscsi.h>
76
77 #include <cam/cam.h>
78 #include <cam/cam_ccb.h>
79 #include <cam/cam_xpt.h>
80 #include <cam/cam_debug.h>
81 #include <cam/cam_sim.h>
82 #include <cam/cam_xpt_sim.h>
83 #include <cam/cam_xpt_periph.h>
84 #include <cam/cam_periph.h>
85 #include <cam/cam_compat.h>
86 #include <cam/scsi/scsi_message.h>
87
88 #include "common/common.h"
89 #include "common/t4_msg.h"
90 #include "common/t4_regs.h"     /* for PCIE_MEM_ACCESS */
91 #include "tom/t4_tom.h"
92 #include "cxgbei.h"
93 #include "cxgbei_ulp2_ddp.h"
94
95 static int worker_thread_count;
96 static struct cxgbei_worker_thread_softc *cwt_softc;
97 static struct proc *cxgbei_proc;
98
99 /* XXXNP some header instead. */
100 struct icl_pdu *icl_cxgbei_new_pdu(int);
101 void icl_cxgbei_new_pdu_set_conn(struct icl_pdu *, struct icl_conn *);
102 void icl_cxgbei_conn_pdu_free(struct icl_conn *, struct icl_pdu *);
103
104 /*
105  * Direct Data Placement -
106  * Directly place the iSCSI Data-In or Data-Out PDU's payload into pre-posted
107  * final destination host-memory buffers based on the Initiator Task Tag (ITT)
108  * in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
109  * The host memory address is programmed into h/w in the format of pagepod
110  * entries.
111  * The location of the pagepod entry is encoded into ddp tag which is used as
112  * the base for ITT/TTT.
113  */
114
115 /*
116  * functions to program the pagepod in h/w
117  */
118 static void inline
119 ppod_set(struct pagepod *ppod,
120         struct cxgbei_ulp2_pagepod_hdr *hdr,
121         struct cxgbei_ulp2_gather_list *gl,
122         unsigned int pidx)
123 {
124         int i;
125
126         memcpy(ppod, hdr, sizeof(*hdr));
127
128         for (i = 0; i < (PPOD_PAGES + 1); i++, pidx++) {
129                 ppod->addr[i] = pidx < gl->nelem ?
130                         cpu_to_be64(gl->dma_sg[pidx].phys_addr) : 0ULL;
131         }
132 }
133
134 static void inline
135 ppod_clear(struct pagepod *ppod)
136 {
137         memset(ppod, 0, sizeof(*ppod));
138 }
139
140 static inline void
141 ulp_mem_io_set_hdr(struct adapter *sc, int tid, struct ulp_mem_io *req,
142                 unsigned int wr_len, unsigned int dlen,
143                 unsigned int pm_addr)
144 {
145         struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1);
146
147         INIT_ULPTX_WR(req, wr_len, 0, 0);
148         req->cmd = cpu_to_be32(V_ULPTX_CMD(ULP_TX_MEM_WRITE) |
149                                 V_ULP_MEMIO_ORDER(is_t4(sc)) |
150                                 V_T5_ULP_MEMIO_IMM(is_t5(sc)));
151         req->dlen = htonl(V_ULP_MEMIO_DATA_LEN(dlen >> 5));
152         req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16)
153                                 | V_FW_WR_FLOWID(tid));
154         req->lock_addr = htonl(V_ULP_MEMIO_ADDR(pm_addr >> 5));
155
156         idata->cmd_more = htonl(V_ULPTX_CMD(ULP_TX_SC_IMM));
157         idata->len = htonl(dlen);
158 }
159
160 #define PPOD_SIZE               sizeof(struct pagepod)
161 #define ULPMEM_IDATA_MAX_NPPODS 1       /* 256/PPOD_SIZE */
162 #define PCIE_MEMWIN_MAX_NPPODS 16       /* 1024/PPOD_SIZE */
163
164 static int
165 ppod_write_idata(struct cxgbei_data *ci,
166                         struct cxgbei_ulp2_pagepod_hdr *hdr,
167                         unsigned int idx, unsigned int npods,
168                         struct cxgbei_ulp2_gather_list *gl,
169                         unsigned int gl_pidx, struct toepcb *toep)
170 {
171         u_int dlen = PPOD_SIZE * npods;
172         u_int pm_addr = idx * PPOD_SIZE + ci->llimit;
173         u_int wr_len = roundup(sizeof(struct ulp_mem_io) +
174             sizeof(struct ulptx_idata) + dlen, 16);
175         struct ulp_mem_io *req;
176         struct ulptx_idata *idata;
177         struct pagepod *ppod;
178         u_int i;
179         struct wrqe *wr;
180         struct adapter *sc = toep->vi->pi->adapter;
181
182         wr = alloc_wrqe(wr_len, toep->ctrlq);
183         if (wr == NULL) {
184                 CXGBE_UNIMPLEMENTED("ppod_write_idata: alloc_wrqe failure");
185                 return (ENOMEM);
186         }
187
188         req = wrtod(wr);
189         memset(req, 0, wr_len);
190         ulp_mem_io_set_hdr(sc, toep->tid, req, wr_len, dlen, pm_addr);
191         idata = (struct ulptx_idata *)(req + 1);
192
193         ppod = (struct pagepod *)(idata + 1);
194         for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES) {
195                 if (!hdr) /* clear the pagepod */
196                         ppod_clear(ppod);
197                 else /* set the pagepod */
198                         ppod_set(ppod, hdr, gl, gl_pidx);
199         }
200
201         t4_wrq_tx(sc, wr);
202         return 0;
203 }
204
205 int
206 t4_ddp_set_map(struct cxgbei_data *ci, void *iccp,
207     struct cxgbei_ulp2_pagepod_hdr *hdr, u_int idx, u_int npods,
208     struct cxgbei_ulp2_gather_list *gl, int reply)
209 {
210         struct icl_cxgbei_conn *icc = (struct icl_cxgbei_conn *)iccp;
211         struct toepcb *toep = icc->toep;
212         int err;
213         unsigned int pidx = 0, w_npods = 0, cnt;
214
215         /*
216          * on T4, if we use a mix of IMMD and DSGL with ULP_MEM_WRITE,
217          * the order would not be guaranteed, so we will stick with IMMD
218          */
219         gl->tid = toep->tid;
220         gl->port_id = toep->vi->pi->port_id;
221         gl->egress_dev = (void *)toep->vi->ifp;
222
223         /* send via immediate data */
224         for (; w_npods < npods; idx += cnt, w_npods += cnt,
225                 pidx += PPOD_PAGES) {
226                 cnt = npods - w_npods;
227                 if (cnt > ULPMEM_IDATA_MAX_NPPODS)
228                         cnt = ULPMEM_IDATA_MAX_NPPODS;
229                 err = ppod_write_idata(ci, hdr, idx, cnt, gl, pidx, toep);
230                 if (err) {
231                         printf("%s: ppod_write_idata failed\n", __func__);
232                         break;
233                 }
234         }
235         return err;
236 }
237
238 void
239 t4_ddp_clear_map(struct cxgbei_data *ci, struct cxgbei_ulp2_gather_list *gl,
240     u_int tag, u_int idx, u_int npods, struct icl_cxgbei_conn *icc)
241 {
242         struct toepcb *toep = icc->toep;
243         int err = -1;
244         u_int pidx = 0;
245         u_int w_npods = 0;
246         u_int cnt;
247
248         for (; w_npods < npods; idx += cnt, w_npods += cnt,
249                 pidx += PPOD_PAGES) {
250                 cnt = npods - w_npods;
251                 if (cnt > ULPMEM_IDATA_MAX_NPPODS)
252                         cnt = ULPMEM_IDATA_MAX_NPPODS;
253                 err = ppod_write_idata(ci, NULL, idx, cnt, gl, 0, toep);
254                 if (err)
255                         break;
256         }
257 }
258
259 static int
260 cxgbei_map_sg(struct cxgbei_sgl *sgl, struct ccb_scsiio *csio)
261 {
262         unsigned int data_len = csio->dxfer_len;
263         unsigned int sgoffset = (uint64_t)csio->data_ptr & PAGE_MASK;
264         unsigned int nsge;
265         unsigned char *sgaddr = csio->data_ptr;
266         unsigned int len = 0;
267
268         nsge = (csio->dxfer_len + sgoffset + PAGE_SIZE - 1) >> PAGE_SHIFT;
269         sgl->sg_addr = sgaddr;
270         sgl->sg_offset = sgoffset;
271         if (data_len <  (PAGE_SIZE - sgoffset))
272                 len = data_len;
273         else
274                 len = PAGE_SIZE - sgoffset;
275
276         sgl->sg_length = len;
277
278         data_len -= len;
279         sgaddr += len;
280         sgl = sgl+1;
281
282         while (data_len > 0) {
283                 sgl->sg_addr = sgaddr;
284                 len = (data_len < PAGE_SIZE)? data_len: PAGE_SIZE;
285                 sgl->sg_length = len;
286                 sgaddr += len;
287                 data_len -= len;
288                 sgl = sgl + 1;
289         }
290
291         return nsge;
292 }
293
294 static int
295 cxgbei_map_sg_tgt(struct cxgbei_sgl *sgl, union ctl_io *io)
296 {
297         unsigned int data_len, sgoffset, nsge;
298         unsigned char *sgaddr;
299         unsigned int len = 0, index = 0, ctl_sg_count, i;
300         struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
301
302         if (io->scsiio.kern_sg_entries > 0) {
303                 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
304                 ctl_sg_count = io->scsiio.kern_sg_entries;
305         } else {
306                 ctl_sglist = &ctl_sg_entry;
307                 ctl_sglist->addr = io->scsiio.kern_data_ptr;
308                 ctl_sglist->len = io->scsiio.kern_data_len;
309                 ctl_sg_count = 1;
310         }
311
312         sgaddr = sgl->sg_addr = ctl_sglist[index].addr;
313         sgoffset = sgl->sg_offset = (uint64_t)sgl->sg_addr & PAGE_MASK;
314         data_len = ctl_sglist[index].len;
315
316         if (data_len <  (PAGE_SIZE - sgoffset))
317                 len = data_len;
318         else
319                 len = PAGE_SIZE - sgoffset;
320
321         sgl->sg_length = len;
322
323         data_len -= len;
324         sgaddr += len;
325         sgl = sgl+1;
326
327         len = 0;
328         for (i = 0;  i< ctl_sg_count; i++)
329                 len += ctl_sglist[i].len;
330         nsge = (len + sgoffset + PAGE_SIZE -1) >> PAGE_SHIFT;
331         while (data_len > 0) {
332                 sgl->sg_addr = sgaddr;
333                 len = (data_len < PAGE_SIZE)? data_len: PAGE_SIZE;
334                 sgl->sg_length = len;
335                 sgaddr += len;
336                 data_len -= len;
337                 sgl = sgl + 1;
338                 if (data_len == 0) {
339                         if (index == ctl_sg_count - 1)
340                                 break;
341                         index++;
342                         sgaddr = ctl_sglist[index].addr;
343                         data_len = ctl_sglist[index].len;
344                 }
345         }
346
347         return nsge;
348 }
349
350 static int
351 t4_sk_ddp_tag_reserve(struct cxgbei_data *ci, struct icl_cxgbei_conn *icc,
352     u_int xferlen, struct cxgbei_sgl *sgl, u_int sgcnt, u_int *ddp_tag)
353 {
354         struct cxgbei_ulp2_gather_list *gl;
355         int err = -EINVAL;
356         struct toepcb *toep = icc->toep;
357
358         gl = cxgbei_ulp2_ddp_make_gl_from_iscsi_sgvec(xferlen, sgl, sgcnt, ci, 0);
359         if (gl) {
360                 err = cxgbei_ulp2_ddp_tag_reserve(ci, icc, toep->tid,
361                     &ci->tag_format, ddp_tag, gl, 0, 0);
362                 if (err) {
363                         cxgbei_ulp2_ddp_release_gl(ci, gl);
364                 }
365         }
366
367         return err;
368 }
369
370 static unsigned int
371 cxgbei_task_reserve_itt(struct icl_conn *ic, void **prv,
372                         struct ccb_scsiio *scmd, unsigned int *itt)
373 {
374         struct icl_cxgbei_conn *icc = ic_to_icc(ic);
375         int xferlen = scmd->dxfer_len;
376         struct cxgbei_task_data *tdata = NULL;
377         struct cxgbei_sgl *sge = NULL;
378         struct toepcb *toep = icc->toep;
379         struct adapter *sc = td_adapter(toep->td);
380         struct cxgbei_data *ci = sc->iscsi_ulp_softc;
381         int err = -1;
382
383         MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
384
385         tdata = (struct cxgbei_task_data *)*prv;
386         if (xferlen == 0 || tdata == NULL)
387                 goto out;
388         if (xferlen < DDP_THRESHOLD)
389                 goto out;
390
391         if ((scmd->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
392                 tdata->nsge = cxgbei_map_sg(tdata->sgl, scmd);
393                 if (tdata->nsge == 0) {
394                         CTR1(KTR_CXGBE, "%s: map_sg failed", __func__);
395                         return 0;
396                 }
397                 sge = tdata->sgl;
398
399                 tdata->sc_ddp_tag = *itt;
400
401                 CTR3(KTR_CXGBE, "%s: *itt:0x%x sc_ddp_tag:0x%x",
402                                 __func__, *itt, tdata->sc_ddp_tag);
403                 if (cxgbei_ulp2_sw_tag_usable(&ci->tag_format,
404                                                         tdata->sc_ddp_tag)) {
405                         err = t4_sk_ddp_tag_reserve(ci, icc, scmd->dxfer_len,
406                             sge, tdata->nsge, &tdata->sc_ddp_tag);
407                 } else {
408                         CTR3(KTR_CXGBE,
409                                 "%s: itt:0x%x sc_ddp_tag:0x%x not usable",
410                                 __func__, *itt, tdata->sc_ddp_tag);
411                 }
412         }
413 out:
414         if (err < 0)
415                 tdata->sc_ddp_tag =
416                         cxgbei_ulp2_set_non_ddp_tag(&ci->tag_format, *itt);
417
418         return tdata->sc_ddp_tag;
419 }
420
421 static unsigned int
422 cxgbei_task_reserve_ttt(struct icl_conn *ic, void **prv, union ctl_io *io,
423                                 unsigned int *ttt)
424 {
425         struct icl_cxgbei_conn *icc = ic_to_icc(ic);
426         struct toepcb *toep = icc->toep;
427         struct adapter *sc = td_adapter(toep->td);
428         struct cxgbei_data *ci = sc->iscsi_ulp_softc;
429         struct cxgbei_task_data *tdata = NULL;
430         int xferlen, err = -1;
431         struct cxgbei_sgl *sge = NULL;
432
433         MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
434
435         xferlen = (io->scsiio.kern_data_len - io->scsiio.ext_data_filled);
436         tdata = (struct cxgbei_task_data *)*prv;
437         if ((xferlen == 0) || (tdata == NULL))
438                 goto out;
439         if (xferlen < DDP_THRESHOLD)
440                 goto out;
441         tdata->nsge = cxgbei_map_sg_tgt(tdata->sgl, io);
442         if (tdata->nsge == 0) {
443                 CTR1(KTR_CXGBE, "%s: map_sg failed", __func__);
444                 return 0;
445         }
446         sge = tdata->sgl;
447
448         tdata->sc_ddp_tag = *ttt;
449         if (cxgbei_ulp2_sw_tag_usable(&ci->tag_format, tdata->sc_ddp_tag)) {
450                 err = t4_sk_ddp_tag_reserve(ci, icc, xferlen, sge,
451                     tdata->nsge, &tdata->sc_ddp_tag);
452         } else {
453                 CTR2(KTR_CXGBE, "%s: sc_ddp_tag:0x%x not usable",
454                                 __func__, tdata->sc_ddp_tag);
455         }
456 out:
457         if (err < 0)
458                 tdata->sc_ddp_tag =
459                         cxgbei_ulp2_set_non_ddp_tag(&ci->tag_format, *ttt);
460         return tdata->sc_ddp_tag;
461 }
462
463 static int
464 t4_sk_ddp_tag_release(struct icl_cxgbei_conn *icc, unsigned int ddp_tag)
465 {
466         struct toepcb *toep = icc->toep;
467         struct adapter *sc = td_adapter(toep->td);
468         struct cxgbei_data *ci = sc->iscsi_ulp_softc;
469
470         cxgbei_ulp2_ddp_tag_release(ci, ddp_tag, icc);
471
472         return (0);
473 }
474
475 static int
476 cxgbei_ddp_init(struct adapter *sc, struct cxgbei_data *ci)
477 {
478         int nppods, bits, max_sz, rc;
479         static const u_int pgsz_order[] = {0, 1, 2, 3};
480
481         MPASS(sc->vres.iscsi.size > 0);
482
483         ci->llimit = sc->vres.iscsi.start;
484         ci->ulimit = sc->vres.iscsi.start + sc->vres.iscsi.size - 1;
485         max_sz = G_MAXRXDATA(t4_read_reg(sc, A_TP_PARA_REG2));
486
487         nppods = sc->vres.iscsi.size >> IPPOD_SIZE_SHIFT;
488         if (nppods <= 1024)
489                 return (ENXIO);
490
491         bits = fls(nppods);
492         if (bits > IPPOD_IDX_MAX_SIZE)
493                 bits = IPPOD_IDX_MAX_SIZE;
494         nppods = (1 << (bits - 1)) - 1;
495
496         rc = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR,
497             BUS_SPACE_MAXADDR, NULL, NULL, UINT32_MAX , 8, BUS_SPACE_MAXSIZE,
498             BUS_DMA_ALLOCNOW, NULL, NULL, &ci->ulp_ddp_tag);
499         if (rc != 0) {
500                 device_printf(sc->dev, "%s: failed to create DMA tag: %u.\n",
501                     __func__, rc);
502                 return (rc);
503         }
504
505         ci->colors = malloc(nppods * sizeof(char), M_CXGBE, M_NOWAIT | M_ZERO);
506         ci->gl_map = malloc(nppods * sizeof(struct cxgbei_ulp2_gather_list *),
507             M_CXGBE, M_NOWAIT | M_ZERO);
508         if (ci->colors == NULL || ci->gl_map == NULL) {
509                 bus_dma_tag_destroy(ci->ulp_ddp_tag);
510                 free(ci->colors, M_CXGBE);
511                 free(ci->gl_map, M_CXGBE);
512                 return (ENOMEM);
513         }
514
515         mtx_init(&ci->map_lock, "ddp lock", NULL, MTX_DEF | MTX_DUPOK);
516         ci->max_txsz = ci->max_rxsz = min(max_sz, ULP2_MAX_PKT_SIZE);
517         ci->nppods = nppods;
518         ci->idx_last = nppods;
519         ci->idx_bits = bits;
520         ci->idx_mask = (1 << bits) - 1;
521         ci->rsvd_tag_mask = (1 << (bits + IPPOD_IDX_SHIFT)) - 1;
522
523         ci->tag_format.sw_bits = bits;
524         ci->tag_format.rsvd_bits = bits;
525         ci->tag_format.rsvd_shift = IPPOD_IDX_SHIFT;
526         ci->tag_format.rsvd_mask = ci->idx_mask;
527
528         t4_iscsi_init(sc, ci->idx_mask << IPPOD_IDX_SHIFT, pgsz_order);
529
530         return (rc);
531 }
532
533 static int
534 do_rx_iscsi_hdr(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
535 {
536         struct adapter *sc = iq->adapter;
537         struct cpl_iscsi_hdr *cpl = mtod(m, struct cpl_iscsi_hdr *);
538         u_int tid = GET_TID(cpl);
539         struct toepcb *toep = lookup_tid(sc, tid);
540         struct icl_pdu *ip;
541         struct icl_cxgbei_pdu *icp;
542
543         M_ASSERTPKTHDR(m);
544
545         ip = icl_cxgbei_new_pdu(M_NOWAIT);
546         if (ip == NULL)
547                 CXGBE_UNIMPLEMENTED("PDU allocation failure");
548         icp = ip_to_icp(ip);
549         bcopy(mtod(m, caddr_t) + sizeof(*cpl), icp->ip.ip_bhs, sizeof(struct
550             iscsi_bhs));
551         icp->pdu_seq = ntohl(cpl->seq);
552         icp->pdu_flags = SBUF_ULP_FLAG_HDR_RCVD;
553
554         /* This is the start of a new PDU.  There should be no old state. */
555         MPASS(toep->ulpcb2 == NULL);
556         toep->ulpcb2 = icp;
557
558 #if 0
559         CTR4(KTR_CXGBE, "%s: tid %u, cpl->len hlen %u, m->m_len hlen %u",
560             __func__, tid, ntohs(cpl->len), m->m_len);
561 #endif
562
563         m_freem(m);
564         return (0);
565 }
566
567 static int
568 do_rx_iscsi_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
569 {
570         struct adapter *sc = iq->adapter;
571         struct cpl_iscsi_data *cpl =  mtod(m, struct cpl_iscsi_data *);
572         u_int tid = GET_TID(cpl);
573         struct toepcb *toep = lookup_tid(sc, tid);
574         struct icl_cxgbei_pdu *icp = toep->ulpcb2;
575
576         M_ASSERTPKTHDR(m);
577
578         /* Must already have received the header (but not the data). */
579         MPASS(icp != NULL);
580         MPASS(icp->pdu_flags == SBUF_ULP_FLAG_HDR_RCVD);
581         MPASS(icp->ip.ip_data_mbuf == NULL);
582         MPASS(icp->ip.ip_data_len == 0);
583
584         m_adj(m, sizeof(*cpl));
585
586         icp->pdu_flags |= SBUF_ULP_FLAG_DATA_RCVD;
587         icp->ip.ip_data_mbuf = m;
588         icp->ip.ip_data_len = m->m_pkthdr.len;
589
590 #if 0
591         CTR4(KTR_CXGBE, "%s: tid %u, cpl->len dlen %u, m->m_len dlen %u",
592             __func__, tid, ntohs(cpl->len), m->m_len);
593 #endif
594
595         return (0);
596 }
597
598 static int
599 do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
600 {
601         struct adapter *sc = iq->adapter;
602         const struct cpl_rx_data_ddp *cpl = (const void *)(rss + 1);
603         u_int tid = GET_TID(cpl);
604         struct toepcb *toep = lookup_tid(sc, tid);
605         struct inpcb *inp = toep->inp;
606         struct socket *so;
607         struct sockbuf *sb;
608         struct tcpcb *tp;
609         struct icl_cxgbei_conn *icc;
610         struct icl_conn *ic;
611         struct icl_cxgbei_pdu *icp = toep->ulpcb2;
612         struct icl_pdu *ip;
613         u_int pdu_len, val;
614
615         MPASS(m == NULL);
616
617         /* Must already be assembling a PDU. */
618         MPASS(icp != NULL);
619         MPASS(icp->pdu_flags & SBUF_ULP_FLAG_HDR_RCVD); /* Data is optional. */
620         ip = &icp->ip;
621         icp->pdu_flags |= SBUF_ULP_FLAG_STATUS_RCVD;
622         val = ntohl(cpl->ddpvld);
623         if (val & F_DDP_PADDING_ERR)
624                 icp->pdu_flags |= SBUF_ULP_FLAG_PAD_ERROR;
625         if (val & F_DDP_HDRCRC_ERR)
626                 icp->pdu_flags |= SBUF_ULP_FLAG_HCRC_ERROR;
627         if (val & F_DDP_DATACRC_ERR)
628                 icp->pdu_flags |= SBUF_ULP_FLAG_DCRC_ERROR;
629         if (ip->ip_data_mbuf == NULL) {
630                 /* XXXNP: what should ip->ip_data_len be, and why? */
631                 icp->pdu_flags |= SBUF_ULP_FLAG_DATA_DDPED;
632         }
633         pdu_len = ntohs(cpl->len);      /* includes everything. */
634
635         INP_WLOCK(inp);
636         if (__predict_false(inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT))) {
637                 CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x",
638                     __func__, tid, pdu_len, inp->inp_flags);
639                 INP_WUNLOCK(inp);
640                 icl_cxgbei_conn_pdu_free(NULL, ip);
641 #ifdef INVARIANTS
642                 toep->ulpcb2 = NULL;
643 #endif
644                 return (0);
645         }
646
647         tp = intotcpcb(inp);
648         MPASS(icp->pdu_seq == tp->rcv_nxt);
649         MPASS(tp->rcv_wnd >= pdu_len);
650         tp->rcv_nxt += pdu_len;
651         tp->rcv_wnd -= pdu_len;
652         tp->t_rcvtime = ticks;
653
654         /* update rx credits */
655         toep->rx_credits += pdu_len;
656         t4_rcvd(&toep->td->tod, tp);    /* XXX: sc->tom_softc.tod */
657
658         so = inp->inp_socket;
659         sb = &so->so_rcv;
660         SOCKBUF_LOCK(sb);
661
662         icc = toep->ulpcb;
663         if (__predict_false(icc == NULL || sb->sb_state & SBS_CANTRCVMORE)) {
664                 CTR5(KTR_CXGBE,
665                     "%s: tid %u, excess rx (%d bytes), icc %p, sb_state 0x%x",
666                     __func__, tid, pdu_len, icc, sb->sb_state);
667                 SOCKBUF_UNLOCK(sb);
668                 INP_WUNLOCK(inp);
669
670                 INP_INFO_RLOCK(&V_tcbinfo);
671                 INP_WLOCK(inp);
672                 tp = tcp_drop(tp, ECONNRESET);
673                 if (tp)
674                         INP_WUNLOCK(inp);
675                 INP_INFO_RUNLOCK(&V_tcbinfo);
676
677                 icl_cxgbei_conn_pdu_free(NULL, ip);
678 #ifdef INVARIANTS
679                 toep->ulpcb2 = NULL;
680 #endif
681                 return (0);
682         }
683         MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
684         ic = &icc->ic;
685         icl_cxgbei_new_pdu_set_conn(ip, ic);
686
687         MPASS(m == NULL); /* was unused, we'll use it now. */
688         m = sbcut_locked(sb, sbused(sb)); /* XXXNP: toep->sb_cc accounting? */
689         if (__predict_false(m != NULL)) {
690                 int len = m_length(m, NULL);
691
692                 /*
693                  * PDUs were received before the tid transitioned to ULP mode.
694                  * Convert them to icl_cxgbei_pdus and send them to ICL before
695                  * the PDU in icp/ip.
696                  */
697                 CTR3(KTR_CXGBE, "%s: tid %u, %u bytes in so_rcv", __func__, tid,
698                     len);
699
700                 /* XXXNP: needs to be rewritten. */
701                 if (len == sizeof(struct iscsi_bhs) || len == 4 + sizeof(struct
702                     iscsi_bhs)) {
703                         struct icl_cxgbei_pdu *icp0;
704                         struct icl_pdu *ip0;
705
706                         ip0 = icl_cxgbei_new_pdu(M_NOWAIT);
707                         icl_cxgbei_new_pdu_set_conn(ip0, ic);
708                         if (ip0 == NULL)
709                                 CXGBE_UNIMPLEMENTED("PDU allocation failure");
710                         icp0 = ip_to_icp(ip0);
711                         icp0->pdu_seq = 0; /* XXX */
712                         icp0->pdu_flags = SBUF_ULP_FLAG_HDR_RCVD |
713                             SBUF_ULP_FLAG_STATUS_RCVD;
714                         m_copydata(m, 0, sizeof(struct iscsi_bhs), (void *)ip0->ip_bhs);
715                         STAILQ_INSERT_TAIL(&icc->rcvd_pdus, ip0, ip_next);
716                 }
717                 m_freem(m);
718         }
719
720 #if 0
721         CTR4(KTR_CXGBE, "%s: tid %u, pdu_len %u, pdu_flags 0x%x",
722             __func__, tid, pdu_len, icp->pdu_flags);
723 #endif
724
725         STAILQ_INSERT_TAIL(&icc->rcvd_pdus, ip, ip_next);
726         if ((icc->rx_flags & RXF_ACTIVE) == 0) {
727                 struct cxgbei_worker_thread_softc *cwt = &cwt_softc[icc->cwt];
728
729                 mtx_lock(&cwt->cwt_lock);
730                 icc->rx_flags |= RXF_ACTIVE;
731                 TAILQ_INSERT_TAIL(&cwt->rx_head, icc, rx_link);
732                 if (cwt->cwt_state == CWT_SLEEPING) {
733                         cwt->cwt_state = CWT_RUNNING;
734                         cv_signal(&cwt->cwt_cv);
735                 }
736                 mtx_unlock(&cwt->cwt_lock);
737         }
738         SOCKBUF_UNLOCK(sb);
739         INP_WUNLOCK(inp);
740
741 #ifdef INVARIANTS
742         toep->ulpcb2 = NULL;
743 #endif
744
745         return (0);
746 }
747
748 static void
749 t4_register_cpl_handler_with_tom(struct adapter *sc)
750 {
751
752         t4_register_cpl_handler(sc, CPL_ISCSI_HDR, do_rx_iscsi_hdr);
753         t4_register_cpl_handler(sc, CPL_ISCSI_DATA, do_rx_iscsi_data);
754         t4_register_cpl_handler(sc, CPL_RX_ISCSI_DDP, do_rx_iscsi_ddp);
755 }
756
757 static void
758 t4_unregister_cpl_handler_with_tom(struct adapter *sc)
759 {
760
761         t4_register_cpl_handler(sc, CPL_ISCSI_HDR, NULL);
762         t4_register_cpl_handler(sc, CPL_ISCSI_DATA, NULL);
763         t4_register_cpl_handler(sc, CPL_RX_ISCSI_DDP, NULL);
764 }
765
766 /* initiator */
767 void
768 cxgbei_conn_task_reserve_itt(void *conn, void **prv,
769                                 void *scmd, unsigned int *itt)
770 {
771         unsigned int tag;
772         tag = cxgbei_task_reserve_itt(conn, prv, scmd, itt);
773         if (tag)
774                 *itt = htonl(tag);
775         return;
776 }
777
778 /* target */
779 void
780 cxgbei_conn_transfer_reserve_ttt(void *conn, void **prv,
781                                 void *scmd, unsigned int *ttt)
782 {
783         unsigned int tag;
784         tag = cxgbei_task_reserve_ttt(conn, prv, scmd, ttt);
785         if (tag)
786                 *ttt = htonl(tag);
787         return;
788 }
789
790 void
791 cxgbei_cleanup_task(void *conn, void *ofld_priv)
792 {
793         struct icl_conn *ic = (struct icl_conn *)conn;
794         struct icl_cxgbei_conn *icc = ic_to_icc(ic);
795         struct cxgbei_task_data *tdata = ofld_priv;
796         struct adapter *sc = icc->sc;
797         struct cxgbei_data *ci = sc->iscsi_ulp_softc;
798
799         MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
800         MPASS(tdata != NULL);
801
802         if (cxgbei_ulp2_is_ddp_tag(&ci->tag_format, tdata->sc_ddp_tag))
803                 t4_sk_ddp_tag_release(icc, tdata->sc_ddp_tag);
804         memset(tdata, 0, sizeof(*tdata));
805 }
806
807 static int
808 cxgbei_activate(struct adapter *sc)
809 {
810         struct cxgbei_data *ci;
811         int rc;
812
813         ASSERT_SYNCHRONIZED_OP(sc);
814
815         if (uld_active(sc, ULD_ISCSI)) {
816                 KASSERT(0, ("%s: iSCSI offload already enabled on adapter %p",
817                     __func__, sc));
818                 return (0);
819         }
820
821         if (sc->iscsicaps == 0 || sc->vres.iscsi.size == 0) {
822                 device_printf(sc->dev,
823                     "not iSCSI offload capable, or capability disabled.\n");
824                 return (ENOSYS);
825         }
826
827         /* per-adapter softc for iSCSI */
828         ci = malloc(sizeof(*ci), M_CXGBE, M_ZERO | M_NOWAIT);
829         if (ci == NULL)
830                 return (ENOMEM);
831
832         rc = cxgbei_ddp_init(sc, ci);
833         if (rc != 0) {
834                 free(ci, M_CXGBE);
835                 return (rc);
836         }
837
838         t4_register_cpl_handler_with_tom(sc);
839         sc->iscsi_ulp_softc = ci;
840
841         return (0);
842 }
843
844 static int
845 cxgbei_deactivate(struct adapter *sc)
846 {
847
848         ASSERT_SYNCHRONIZED_OP(sc);
849
850         if (sc->iscsi_ulp_softc != NULL) {
851                 cxgbei_ddp_cleanup(sc->iscsi_ulp_softc);
852                 t4_unregister_cpl_handler_with_tom(sc);
853                 free(sc->iscsi_ulp_softc, M_CXGBE);
854                 sc->iscsi_ulp_softc = NULL;
855         }
856
857         return (0);
858 }
859
860 static void
861 cxgbei_activate_all(struct adapter *sc, void *arg __unused)
862 {
863
864         if (begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4isact") != 0)
865                 return;
866
867         /* Activate iSCSI if any port on this adapter has IFCAP_TOE enabled. */
868         if (sc->offload_map && !uld_active(sc, ULD_ISCSI))
869                 (void) t4_activate_uld(sc, ULD_ISCSI);
870
871         end_synchronized_op(sc, 0);
872 }
873
874 static void
875 cxgbei_deactivate_all(struct adapter *sc, void *arg __unused)
876 {
877
878         if (begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4isdea") != 0)
879                 return;
880
881         if (uld_active(sc, ULD_ISCSI))
882             (void) t4_deactivate_uld(sc, ULD_ISCSI);
883
884         end_synchronized_op(sc, 0);
885 }
886
887 static struct uld_info cxgbei_uld_info = {
888         .uld_id = ULD_ISCSI,
889         .activate = cxgbei_activate,
890         .deactivate = cxgbei_deactivate,
891 };
892
893 static void
894 cwt_main(void *arg)
895 {
896         struct cxgbei_worker_thread_softc *cwt = arg;
897         struct icl_cxgbei_conn *icc = NULL;
898         struct icl_conn *ic;
899         struct icl_pdu *ip;
900         struct sockbuf *sb;
901         STAILQ_HEAD(, icl_pdu) rx_pdus = STAILQ_HEAD_INITIALIZER(rx_pdus);
902
903         MPASS(cwt != NULL);
904
905         mtx_lock(&cwt->cwt_lock);
906         MPASS(cwt->cwt_state == 0);
907         cwt->cwt_state = CWT_RUNNING;
908         cv_signal(&cwt->cwt_cv);
909
910         while (__predict_true(cwt->cwt_state != CWT_STOP)) {
911                 cwt->cwt_state = CWT_RUNNING;
912                 while ((icc = TAILQ_FIRST(&cwt->rx_head)) != NULL) {
913                         TAILQ_REMOVE(&cwt->rx_head, icc, rx_link);
914                         mtx_unlock(&cwt->cwt_lock);
915
916                         ic = &icc->ic;
917                         sb = &ic->ic_socket->so_rcv;
918
919                         SOCKBUF_LOCK(sb);
920                         MPASS(icc->rx_flags & RXF_ACTIVE);
921                         if (__predict_true(!(sb->sb_state & SBS_CANTRCVMORE))) {
922                                 MPASS(STAILQ_EMPTY(&rx_pdus));
923                                 STAILQ_SWAP(&icc->rcvd_pdus, &rx_pdus, icl_pdu);
924                                 SOCKBUF_UNLOCK(sb);
925
926                                 /* Hand over PDUs to ICL. */
927                                 while ((ip = STAILQ_FIRST(&rx_pdus)) != NULL) {
928                                         STAILQ_REMOVE_HEAD(&rx_pdus, ip_next);
929                                         ic->ic_receive(ip);
930                                 }
931
932                                 SOCKBUF_LOCK(sb);
933                                 MPASS(STAILQ_EMPTY(&rx_pdus));
934                         }
935                         MPASS(icc->rx_flags & RXF_ACTIVE);
936                         if (STAILQ_EMPTY(&icc->rcvd_pdus) ||
937                             __predict_false(sb->sb_state & SBS_CANTRCVMORE)) {
938                                 icc->rx_flags &= ~RXF_ACTIVE;
939                         } else {
940                                 /*
941                                  * More PDUs were received while we were busy
942                                  * handing over the previous batch to ICL.
943                                  * Re-add this connection to the end of the
944                                  * queue.
945                                  */
946                                 mtx_lock(&cwt->cwt_lock);
947                                 TAILQ_INSERT_TAIL(&cwt->rx_head, icc,
948                                     rx_link);
949                                 mtx_unlock(&cwt->cwt_lock);
950                         }
951                         SOCKBUF_UNLOCK(sb);
952
953                         mtx_lock(&cwt->cwt_lock);
954                 }
955
956                 /* Inner loop doesn't check for CWT_STOP, do that first. */
957                 if (__predict_false(cwt->cwt_state == CWT_STOP))
958                         break;
959                 cwt->cwt_state = CWT_SLEEPING;
960                 cv_wait(&cwt->cwt_cv, &cwt->cwt_lock);
961         }
962
963         MPASS(TAILQ_FIRST(&cwt->rx_head) == NULL);
964         mtx_assert(&cwt->cwt_lock, MA_OWNED);
965         cwt->cwt_state = CWT_STOPPED;
966         cv_signal(&cwt->cwt_cv);
967         mtx_unlock(&cwt->cwt_lock);
968         kthread_exit();
969 }
970
971 static int
972 start_worker_threads(void)
973 {
974         int i, rc;
975         struct cxgbei_worker_thread_softc *cwt;
976
977         worker_thread_count = min(mp_ncpus, 32);
978         cwt_softc = malloc(worker_thread_count * sizeof(*cwt), M_CXGBE,
979             M_WAITOK | M_ZERO);
980
981         MPASS(cxgbei_proc == NULL);
982         for (i = 0, cwt = &cwt_softc[0]; i < worker_thread_count; i++, cwt++) {
983                 mtx_init(&cwt->cwt_lock, "cwt lock", NULL, MTX_DEF);
984                 cv_init(&cwt->cwt_cv, "cwt cv");
985                 TAILQ_INIT(&cwt->rx_head);
986                 rc = kproc_kthread_add(cwt_main, cwt, &cxgbei_proc, NULL, 0, 0,
987                     "cxgbei", "%d", i);
988                 if (rc != 0) {
989                         printf("cxgbei: failed to start thread #%d/%d (%d)\n",
990                             i + 1, worker_thread_count, rc);
991                         mtx_destroy(&cwt->cwt_lock);
992                         cv_destroy(&cwt->cwt_cv);
993                         bzero(&cwt, sizeof(*cwt));
994                         if (i == 0) {
995                                 free(cwt_softc, M_CXGBE);
996                                 worker_thread_count = 0;
997
998                                 return (rc);
999                         }
1000
1001                         /* Not fatal, carry on with fewer threads. */
1002                         worker_thread_count = i;
1003                         rc = 0;
1004                         break;
1005                 }
1006
1007                 /* Wait for thread to start before moving on to the next one. */
1008                 mtx_lock(&cwt->cwt_lock);
1009                 while (cwt->cwt_state == 0)
1010                         cv_wait(&cwt->cwt_cv, &cwt->cwt_lock);
1011                 mtx_unlock(&cwt->cwt_lock);
1012         }
1013
1014         MPASS(cwt_softc != NULL);
1015         MPASS(worker_thread_count > 0);
1016         return (0);
1017 }
1018
1019 static void
1020 stop_worker_threads(void)
1021 {
1022         int i;
1023         struct cxgbei_worker_thread_softc *cwt = &cwt_softc[0];
1024
1025         MPASS(worker_thread_count >= 0);
1026
1027         for (i = 0, cwt = &cwt_softc[0]; i < worker_thread_count; i++, cwt++) {
1028                 mtx_lock(&cwt->cwt_lock);
1029                 MPASS(cwt->cwt_state == CWT_RUNNING ||
1030                     cwt->cwt_state == CWT_SLEEPING);
1031                 cwt->cwt_state = CWT_STOP;
1032                 cv_signal(&cwt->cwt_cv);
1033                 do {
1034                         cv_wait(&cwt->cwt_cv, &cwt->cwt_lock);
1035                 } while (cwt->cwt_state != CWT_STOPPED);
1036                 mtx_unlock(&cwt->cwt_lock);
1037         }
1038         free(cwt_softc, M_CXGBE);
1039 }
1040
1041 /* Select a worker thread for a connection. */
1042 u_int
1043 cxgbei_select_worker_thread(struct icl_cxgbei_conn *icc)
1044 {
1045         struct adapter *sc = icc->sc;
1046         struct toepcb *toep = icc->toep;
1047         u_int i, n;
1048
1049         n = worker_thread_count / sc->sge.nofldrxq;
1050         if (n > 0)
1051                 i = toep->vi->pi->port_id * n + arc4random() % n;
1052         else
1053                 i = arc4random() % worker_thread_count;
1054
1055         CTR3(KTR_CXGBE, "%s: tid %u, cwt %u", __func__, toep->tid, i);
1056
1057         return (i);
1058 }
1059
1060 static int
1061 cxgbei_mod_load(void)
1062 {
1063         int rc;
1064
1065         rc = start_worker_threads();
1066         if (rc != 0)
1067                 return (rc);
1068
1069         rc = t4_register_uld(&cxgbei_uld_info);
1070         if (rc != 0) {
1071                 stop_worker_threads();
1072                 return (rc);
1073         }
1074
1075         t4_iterate(cxgbei_activate_all, NULL);
1076
1077         return (rc);
1078 }
1079
1080 static int
1081 cxgbei_mod_unload(void)
1082 {
1083
1084         t4_iterate(cxgbei_deactivate_all, NULL);
1085
1086         if (t4_unregister_uld(&cxgbei_uld_info) == EBUSY)
1087                 return (EBUSY);
1088
1089         stop_worker_threads();
1090
1091         return (0);
1092 }
1093 #endif
1094
1095 static int
1096 cxgbei_modevent(module_t mod, int cmd, void *arg)
1097 {
1098         int rc = 0;
1099
1100 #ifdef TCP_OFFLOAD
1101         switch (cmd) {
1102         case MOD_LOAD:
1103                 rc = cxgbei_mod_load();
1104                 break;
1105
1106         case MOD_UNLOAD:
1107                 rc = cxgbei_mod_unload();
1108                 break;
1109
1110         default:
1111                 rc = EINVAL;
1112         }
1113 #else
1114         printf("cxgbei: compiled without TCP_OFFLOAD support.\n");
1115         rc = EOPNOTSUPP;
1116 #endif
1117
1118         return (rc);
1119 }
1120
1121 static moduledata_t cxgbei_mod = {
1122         "cxgbei",
1123         cxgbei_modevent,
1124         NULL,
1125 };
1126
1127 MODULE_VERSION(cxgbei, 1);
1128 DECLARE_MODULE(cxgbei, cxgbei_mod, SI_SUB_EXEC, SI_ORDER_ANY);
1129 MODULE_DEPEND(cxgbei, t4_tom, 1, 1, 1);
1130 MODULE_DEPEND(cxgbei, cxgbe, 1, 1, 1);
1131 MODULE_DEPEND(cxgbei, icl, 1, 1, 1);