14814a0a4SEdward Tomasz Napierala /*-
24814a0a4SEdward Tomasz Napierala * Copyright (c) 2015, Mellanox Technologies, Inc. All rights reserved.
34814a0a4SEdward Tomasz Napierala *
44814a0a4SEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without
54814a0a4SEdward Tomasz Napierala * modification, are permitted provided that the following conditions
64814a0a4SEdward Tomasz Napierala * are met:
74814a0a4SEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright
84814a0a4SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer.
94814a0a4SEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright
104814a0a4SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the
114814a0a4SEdward Tomasz Napierala * documentation and/or other materials provided with the distribution.
124814a0a4SEdward Tomasz Napierala *
134814a0a4SEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
144814a0a4SEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
154814a0a4SEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
164814a0a4SEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
174814a0a4SEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
184814a0a4SEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
194814a0a4SEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
204814a0a4SEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
214814a0a4SEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
224814a0a4SEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
234814a0a4SEdward Tomasz Napierala * SUCH DAMAGE.
244814a0a4SEdward Tomasz Napierala */
254814a0a4SEdward Tomasz Napierala
264814a0a4SEdward Tomasz Napierala #include "icl_iser.h"
274814a0a4SEdward Tomasz Napierala
287029da5cSPawel Biernacki SYSCTL_NODE(_kern, OID_AUTO, iser, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
297029da5cSPawel Biernacki "iSER module");
304814a0a4SEdward Tomasz Napierala int iser_debug = 0;
314814a0a4SEdward Tomasz Napierala SYSCTL_INT(_kern_iser, OID_AUTO, debug, CTLFLAG_RWTUN,
324814a0a4SEdward Tomasz Napierala &iser_debug, 0, "Enable iser debug messages");
334814a0a4SEdward Tomasz Napierala
344814a0a4SEdward Tomasz Napierala static MALLOC_DEFINE(M_ICL_ISER, "icl_iser", "iSCSI iser backend");
354814a0a4SEdward Tomasz Napierala static uma_zone_t icl_pdu_zone;
364814a0a4SEdward Tomasz Napierala
374814a0a4SEdward Tomasz Napierala static volatile u_int icl_iser_ncons;
384814a0a4SEdward Tomasz Napierala struct iser_global ig;
394814a0a4SEdward Tomasz Napierala
4095c4a392SEdward Tomasz Napierala static void iser_conn_release(struct icl_conn *ic);
4195c4a392SEdward Tomasz Napierala
424814a0a4SEdward Tomasz Napierala static icl_conn_new_pdu_t iser_conn_new_pdu;
434814a0a4SEdward Tomasz Napierala static icl_conn_pdu_free_t iser_conn_pdu_free;
444814a0a4SEdward Tomasz Napierala static icl_conn_pdu_data_segment_length_t iser_conn_pdu_data_segment_length;
457aab9c14SJohn Baldwin static icl_conn_pdu_append_bio_t iser_conn_pdu_append_bio;
464814a0a4SEdward Tomasz Napierala static icl_conn_pdu_append_data_t iser_conn_pdu_append_data;
474814a0a4SEdward Tomasz Napierala static icl_conn_pdu_queue_t iser_conn_pdu_queue;
484814a0a4SEdward Tomasz Napierala static icl_conn_handoff_t iser_conn_handoff;
494814a0a4SEdward Tomasz Napierala static icl_conn_free_t iser_conn_free;
504814a0a4SEdward Tomasz Napierala static icl_conn_close_t iser_conn_close;
514814a0a4SEdward Tomasz Napierala static icl_conn_connect_t iser_conn_connect;
524814a0a4SEdward Tomasz Napierala static icl_conn_task_setup_t iser_conn_task_setup;
534814a0a4SEdward Tomasz Napierala static icl_conn_task_done_t iser_conn_task_done;
547aab9c14SJohn Baldwin static icl_conn_pdu_get_bio_t iser_conn_pdu_get_bio;
554814a0a4SEdward Tomasz Napierala static icl_conn_pdu_get_data_t iser_conn_pdu_get_data;
564814a0a4SEdward Tomasz Napierala
574814a0a4SEdward Tomasz Napierala static kobj_method_t icl_iser_methods[] = {
584814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_new_pdu, iser_conn_new_pdu),
594814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_pdu_free, iser_conn_pdu_free),
604814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_pdu_data_segment_length, iser_conn_pdu_data_segment_length),
617aab9c14SJohn Baldwin KOBJMETHOD(icl_conn_pdu_append_bio, iser_conn_pdu_append_bio),
624814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_pdu_append_data, iser_conn_pdu_append_data),
634814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_pdu_queue, iser_conn_pdu_queue),
644814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_handoff, iser_conn_handoff),
654814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_free, iser_conn_free),
664814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_close, iser_conn_close),
674814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_connect, iser_conn_connect),
684814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_task_setup, iser_conn_task_setup),
694814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_task_done, iser_conn_task_done),
707aab9c14SJohn Baldwin KOBJMETHOD(icl_conn_pdu_get_bio, iser_conn_pdu_get_bio),
714814a0a4SEdward Tomasz Napierala KOBJMETHOD(icl_conn_pdu_get_data, iser_conn_pdu_get_data),
724814a0a4SEdward Tomasz Napierala { 0, 0 }
734814a0a4SEdward Tomasz Napierala };
744814a0a4SEdward Tomasz Napierala
754814a0a4SEdward Tomasz Napierala DEFINE_CLASS(icl_iser, icl_iser_methods, sizeof(struct iser_conn));
764814a0a4SEdward Tomasz Napierala
774814a0a4SEdward Tomasz Napierala /**
784814a0a4SEdward Tomasz Napierala * iser_initialize_headers() - Initialize task headers
794814a0a4SEdward Tomasz Napierala * @pdu: iser pdu
804814a0a4SEdward Tomasz Napierala * @iser_conn: iser connection
814814a0a4SEdward Tomasz Napierala *
824814a0a4SEdward Tomasz Napierala * Notes:
834814a0a4SEdward Tomasz Napierala * This routine may race with iser teardown flow for scsi
844814a0a4SEdward Tomasz Napierala * error handling TMFs. So for TMF we should acquire the
854814a0a4SEdward Tomasz Napierala * state mutex to avoid dereferencing the IB device which
864814a0a4SEdward Tomasz Napierala * may have already been terminated (racing teardown sequence).
874814a0a4SEdward Tomasz Napierala */
884814a0a4SEdward Tomasz Napierala int
iser_initialize_headers(struct icl_iser_pdu * pdu,struct iser_conn * iser_conn)894814a0a4SEdward Tomasz Napierala iser_initialize_headers(struct icl_iser_pdu *pdu, struct iser_conn *iser_conn)
904814a0a4SEdward Tomasz Napierala {
914814a0a4SEdward Tomasz Napierala struct iser_tx_desc *tx_desc = &pdu->desc;
924814a0a4SEdward Tomasz Napierala struct iser_device *device = iser_conn->ib_conn.device;
934814a0a4SEdward Tomasz Napierala u64 dma_addr;
944814a0a4SEdward Tomasz Napierala int ret = 0;
954814a0a4SEdward Tomasz Napierala
964814a0a4SEdward Tomasz Napierala dma_addr = ib_dma_map_single(device->ib_device, (void *)tx_desc,
974814a0a4SEdward Tomasz Napierala ISER_HEADERS_LEN, DMA_TO_DEVICE);
984814a0a4SEdward Tomasz Napierala if (ib_dma_mapping_error(device->ib_device, dma_addr)) {
994814a0a4SEdward Tomasz Napierala ret = -ENOMEM;
1004814a0a4SEdward Tomasz Napierala goto out;
1014814a0a4SEdward Tomasz Napierala }
1024814a0a4SEdward Tomasz Napierala
1034814a0a4SEdward Tomasz Napierala tx_desc->mapped = true;
1044814a0a4SEdward Tomasz Napierala tx_desc->dma_addr = dma_addr;
1054814a0a4SEdward Tomasz Napierala tx_desc->tx_sg[0].addr = tx_desc->dma_addr;
1064814a0a4SEdward Tomasz Napierala tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
1074814a0a4SEdward Tomasz Napierala tx_desc->tx_sg[0].lkey = device->mr->lkey;
1084814a0a4SEdward Tomasz Napierala
1094814a0a4SEdward Tomasz Napierala out:
1104814a0a4SEdward Tomasz Napierala
1114814a0a4SEdward Tomasz Napierala return (ret);
1124814a0a4SEdward Tomasz Napierala }
1134814a0a4SEdward Tomasz Napierala
1144814a0a4SEdward Tomasz Napierala int
iser_conn_pdu_append_bio(struct icl_conn * ic,struct icl_pdu * request,struct bio * bp,size_t offset,size_t len,int flags)1157aab9c14SJohn Baldwin iser_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *request,
1167aab9c14SJohn Baldwin struct bio *bp, size_t offset, size_t len, int flags)
1177aab9c14SJohn Baldwin {
1187aab9c14SJohn Baldwin MPASS(!((request->ip_bhs->bhs_opcode & ISCSI_OPCODE_MASK) ==
1197aab9c14SJohn Baldwin ISCSI_BHS_OPCODE_LOGIN_REQUEST ||
1207aab9c14SJohn Baldwin (request->ip_bhs->bhs_opcode & ISCSI_OPCODE_MASK) ==
1217aab9c14SJohn Baldwin ISCSI_BHS_OPCODE_TEXT_REQUEST));
1227aab9c14SJohn Baldwin
1237aab9c14SJohn Baldwin return (0);
1247aab9c14SJohn Baldwin }
1257aab9c14SJohn Baldwin
1267aab9c14SJohn Baldwin int
iser_conn_pdu_append_data(struct icl_conn * ic,struct icl_pdu * request,const void * addr,size_t len,int flags)1274814a0a4SEdward Tomasz Napierala iser_conn_pdu_append_data(struct icl_conn *ic, struct icl_pdu *request,
1284814a0a4SEdward Tomasz Napierala const void *addr, size_t len, int flags)
1294814a0a4SEdward Tomasz Napierala {
1304814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
1314814a0a4SEdward Tomasz Napierala
132c6a43f7fSJohn Baldwin switch (request->ip_bhs->bhs_opcode & ISCSI_OPCODE_MASK) {
133c6a43f7fSJohn Baldwin case ISCSI_BHS_OPCODE_LOGIN_REQUEST:
134c6a43f7fSJohn Baldwin case ISCSI_BHS_OPCODE_TEXT_REQUEST:
1354814a0a4SEdward Tomasz Napierala ISER_DBG("copy to login buff");
1364814a0a4SEdward Tomasz Napierala memcpy(iser_conn->login_req_buf, addr, len);
1374814a0a4SEdward Tomasz Napierala request->ip_data_len = len;
138c6a43f7fSJohn Baldwin break;
1394814a0a4SEdward Tomasz Napierala }
1404814a0a4SEdward Tomasz Napierala
1414814a0a4SEdward Tomasz Napierala return (0);
1424814a0a4SEdward Tomasz Napierala }
1434814a0a4SEdward Tomasz Napierala
1444814a0a4SEdward Tomasz Napierala void
iser_conn_pdu_get_bio(struct icl_conn * ic,struct icl_pdu * ip,size_t pdu_off,struct bio * bp,size_t bio_off,size_t len)1457aab9c14SJohn Baldwin iser_conn_pdu_get_bio(struct icl_conn *ic, struct icl_pdu *ip,
1467aab9c14SJohn Baldwin size_t pdu_off, struct bio *bp, size_t bio_off,
1477aab9c14SJohn Baldwin size_t len)
1487aab9c14SJohn Baldwin {
1497aab9c14SJohn Baldwin MPASS(ip->ip_data_mbuf == NULL);
1507aab9c14SJohn Baldwin }
1517aab9c14SJohn Baldwin
1527aab9c14SJohn Baldwin void
iser_conn_pdu_get_data(struct icl_conn * ic,struct icl_pdu * ip,size_t off,void * addr,size_t len)1534814a0a4SEdward Tomasz Napierala iser_conn_pdu_get_data(struct icl_conn *ic, struct icl_pdu *ip,
1544814a0a4SEdward Tomasz Napierala size_t off, void *addr, size_t len)
1554814a0a4SEdward Tomasz Napierala {
1564814a0a4SEdward Tomasz Napierala /* If we have a receive data, copy it to upper layer buffer */
1574814a0a4SEdward Tomasz Napierala if (ip->ip_data_mbuf)
1584814a0a4SEdward Tomasz Napierala memcpy(addr, ip->ip_data_mbuf + off, len);
1594814a0a4SEdward Tomasz Napierala }
1604814a0a4SEdward Tomasz Napierala
1614814a0a4SEdward Tomasz Napierala /*
1624814a0a4SEdward Tomasz Napierala * Allocate icl_pdu with empty BHS to fill up by the caller.
1634814a0a4SEdward Tomasz Napierala */
1644814a0a4SEdward Tomasz Napierala struct icl_pdu *
iser_new_pdu(struct icl_conn * ic,int flags)1654814a0a4SEdward Tomasz Napierala iser_new_pdu(struct icl_conn *ic, int flags)
1664814a0a4SEdward Tomasz Napierala {
1674814a0a4SEdward Tomasz Napierala struct icl_iser_pdu *iser_pdu;
1684814a0a4SEdward Tomasz Napierala struct icl_pdu *ip;
1694814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
1704814a0a4SEdward Tomasz Napierala
1714814a0a4SEdward Tomasz Napierala iser_pdu = uma_zalloc(icl_pdu_zone, flags | M_ZERO);
1724814a0a4SEdward Tomasz Napierala if (iser_pdu == NULL) {
1734814a0a4SEdward Tomasz Napierala ISER_WARN("failed to allocate %zd bytes", sizeof(*iser_pdu));
1744814a0a4SEdward Tomasz Napierala return (NULL);
1754814a0a4SEdward Tomasz Napierala }
1764814a0a4SEdward Tomasz Napierala
1774814a0a4SEdward Tomasz Napierala iser_pdu->iser_conn = iser_conn;
1784814a0a4SEdward Tomasz Napierala ip = &iser_pdu->icl_pdu;
1794814a0a4SEdward Tomasz Napierala ip->ip_conn = ic;
1804814a0a4SEdward Tomasz Napierala ip->ip_bhs = &iser_pdu->desc.iscsi_header;
1814814a0a4SEdward Tomasz Napierala
1824814a0a4SEdward Tomasz Napierala return (ip);
1834814a0a4SEdward Tomasz Napierala }
1844814a0a4SEdward Tomasz Napierala
1854814a0a4SEdward Tomasz Napierala struct icl_pdu *
iser_conn_new_pdu(struct icl_conn * ic,int flags)1864814a0a4SEdward Tomasz Napierala iser_conn_new_pdu(struct icl_conn *ic, int flags)
1874814a0a4SEdward Tomasz Napierala {
1884814a0a4SEdward Tomasz Napierala return (iser_new_pdu(ic, flags));
1894814a0a4SEdward Tomasz Napierala }
1904814a0a4SEdward Tomasz Napierala
1914814a0a4SEdward Tomasz Napierala void
iser_pdu_free(struct icl_conn * ic,struct icl_pdu * ip)1924814a0a4SEdward Tomasz Napierala iser_pdu_free(struct icl_conn *ic, struct icl_pdu *ip)
1934814a0a4SEdward Tomasz Napierala {
1944814a0a4SEdward Tomasz Napierala struct icl_iser_pdu *iser_pdu = icl_to_iser_pdu(ip);
1954814a0a4SEdward Tomasz Napierala
1964814a0a4SEdward Tomasz Napierala uma_zfree(icl_pdu_zone, iser_pdu);
1974814a0a4SEdward Tomasz Napierala }
1984814a0a4SEdward Tomasz Napierala
1994814a0a4SEdward Tomasz Napierala size_t
iser_conn_pdu_data_segment_length(struct icl_conn * ic,const struct icl_pdu * request)2004814a0a4SEdward Tomasz Napierala iser_conn_pdu_data_segment_length(struct icl_conn *ic,
2014814a0a4SEdward Tomasz Napierala const struct icl_pdu *request)
2024814a0a4SEdward Tomasz Napierala {
2034814a0a4SEdward Tomasz Napierala uint32_t len = 0;
2044814a0a4SEdward Tomasz Napierala
2054814a0a4SEdward Tomasz Napierala len += request->ip_bhs->bhs_data_segment_len[0];
2064814a0a4SEdward Tomasz Napierala len <<= 8;
2074814a0a4SEdward Tomasz Napierala len += request->ip_bhs->bhs_data_segment_len[1];
2084814a0a4SEdward Tomasz Napierala len <<= 8;
2094814a0a4SEdward Tomasz Napierala len += request->ip_bhs->bhs_data_segment_len[2];
2104814a0a4SEdward Tomasz Napierala
2114814a0a4SEdward Tomasz Napierala return (len);
2124814a0a4SEdward Tomasz Napierala }
2134814a0a4SEdward Tomasz Napierala
2144814a0a4SEdward Tomasz Napierala void
iser_conn_pdu_free(struct icl_conn * ic,struct icl_pdu * ip)2154814a0a4SEdward Tomasz Napierala iser_conn_pdu_free(struct icl_conn *ic, struct icl_pdu *ip)
2164814a0a4SEdward Tomasz Napierala {
2174814a0a4SEdward Tomasz Napierala iser_pdu_free(ic, ip);
2184814a0a4SEdward Tomasz Napierala }
2194814a0a4SEdward Tomasz Napierala
2204814a0a4SEdward Tomasz Napierala static bool
is_control_opcode(uint8_t opcode)2214814a0a4SEdward Tomasz Napierala is_control_opcode(uint8_t opcode)
2224814a0a4SEdward Tomasz Napierala {
2234814a0a4SEdward Tomasz Napierala bool is_control = false;
2244814a0a4SEdward Tomasz Napierala
2254814a0a4SEdward Tomasz Napierala switch (opcode & ISCSI_OPCODE_MASK) {
2264814a0a4SEdward Tomasz Napierala case ISCSI_BHS_OPCODE_NOP_OUT:
2274814a0a4SEdward Tomasz Napierala case ISCSI_BHS_OPCODE_LOGIN_REQUEST:
2284814a0a4SEdward Tomasz Napierala case ISCSI_BHS_OPCODE_LOGOUT_REQUEST:
2294814a0a4SEdward Tomasz Napierala case ISCSI_BHS_OPCODE_TEXT_REQUEST:
2304814a0a4SEdward Tomasz Napierala is_control = true;
2314814a0a4SEdward Tomasz Napierala break;
2324814a0a4SEdward Tomasz Napierala case ISCSI_BHS_OPCODE_SCSI_COMMAND:
2334814a0a4SEdward Tomasz Napierala is_control = false;
2344814a0a4SEdward Tomasz Napierala break;
2354814a0a4SEdward Tomasz Napierala default:
2364814a0a4SEdward Tomasz Napierala ISER_ERR("unknown opcode %d", opcode);
2374814a0a4SEdward Tomasz Napierala }
2384814a0a4SEdward Tomasz Napierala
2394814a0a4SEdward Tomasz Napierala return (is_control);
2404814a0a4SEdward Tomasz Napierala }
2414814a0a4SEdward Tomasz Napierala
2424814a0a4SEdward Tomasz Napierala void
iser_conn_pdu_queue(struct icl_conn * ic,struct icl_pdu * ip)2434814a0a4SEdward Tomasz Napierala iser_conn_pdu_queue(struct icl_conn *ic, struct icl_pdu *ip)
2444814a0a4SEdward Tomasz Napierala {
2454814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
2464814a0a4SEdward Tomasz Napierala struct icl_iser_pdu *iser_pdu = icl_to_iser_pdu(ip);
2474814a0a4SEdward Tomasz Napierala int ret;
2484814a0a4SEdward Tomasz Napierala
2494686f1a6SEdward Tomasz Napierala if (iser_conn->state != ISER_CONN_UP)
2504686f1a6SEdward Tomasz Napierala return;
2514686f1a6SEdward Tomasz Napierala
2524814a0a4SEdward Tomasz Napierala ret = iser_initialize_headers(iser_pdu, iser_conn);
2534814a0a4SEdward Tomasz Napierala if (ret) {
2544814a0a4SEdward Tomasz Napierala ISER_ERR("Failed to map TX descriptor pdu %p", iser_pdu);
2554814a0a4SEdward Tomasz Napierala return;
2564814a0a4SEdward Tomasz Napierala }
2574814a0a4SEdward Tomasz Napierala
2584814a0a4SEdward Tomasz Napierala if (is_control_opcode(ip->ip_bhs->bhs_opcode)) {
2594814a0a4SEdward Tomasz Napierala ret = iser_send_control(iser_conn, iser_pdu);
2604814a0a4SEdward Tomasz Napierala if (unlikely(ret))
2614814a0a4SEdward Tomasz Napierala ISER_ERR("Failed to send control pdu %p", iser_pdu);
2624814a0a4SEdward Tomasz Napierala } else {
2634814a0a4SEdward Tomasz Napierala ret = iser_send_command(iser_conn, iser_pdu);
2644814a0a4SEdward Tomasz Napierala if (unlikely(ret))
2654814a0a4SEdward Tomasz Napierala ISER_ERR("Failed to send command pdu %p", iser_pdu);
2664814a0a4SEdward Tomasz Napierala }
2674814a0a4SEdward Tomasz Napierala }
2684814a0a4SEdward Tomasz Napierala
2694814a0a4SEdward Tomasz Napierala static struct icl_conn *
iser_new_conn(const char * name,struct mtx * lock)2704814a0a4SEdward Tomasz Napierala iser_new_conn(const char *name, struct mtx *lock)
2714814a0a4SEdward Tomasz Napierala {
2724814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn;
2734814a0a4SEdward Tomasz Napierala struct icl_conn *ic;
2744814a0a4SEdward Tomasz Napierala
2754814a0a4SEdward Tomasz Napierala refcount_acquire(&icl_iser_ncons);
2764814a0a4SEdward Tomasz Napierala
2774814a0a4SEdward Tomasz Napierala iser_conn = (struct iser_conn *)kobj_create(&icl_iser_class, M_ICL_ISER, M_WAITOK | M_ZERO);
2784814a0a4SEdward Tomasz Napierala if (!iser_conn) {
2794814a0a4SEdward Tomasz Napierala ISER_ERR("failed to allocate iser conn");
2804814a0a4SEdward Tomasz Napierala refcount_release(&icl_iser_ncons);
2814814a0a4SEdward Tomasz Napierala return (NULL);
2824814a0a4SEdward Tomasz Napierala }
2834814a0a4SEdward Tomasz Napierala
2844814a0a4SEdward Tomasz Napierala cv_init(&iser_conn->up_cv, "iser_cv");
2854814a0a4SEdward Tomasz Napierala sx_init(&iser_conn->state_mutex, "iser_conn_state_mutex");
2862b378326SHans Petter Selasky mtx_init(&iser_conn->ib_conn.beacon.flush_lock, "iser_flush_lock", NULL, MTX_DEF);
2874814a0a4SEdward Tomasz Napierala cv_init(&iser_conn->ib_conn.beacon.flush_cv, "flush_cv");
2882b378326SHans Petter Selasky mtx_init(&iser_conn->ib_conn.lock, "iser_lock", NULL, MTX_DEF);
2894814a0a4SEdward Tomasz Napierala
2904814a0a4SEdward Tomasz Napierala ic = &iser_conn->icl_conn;
2914814a0a4SEdward Tomasz Napierala ic->ic_lock = lock;
2924814a0a4SEdward Tomasz Napierala ic->ic_name = name;
29395c4a392SEdward Tomasz Napierala ic->ic_offload = strdup("iser", M_TEMP);
2944814a0a4SEdward Tomasz Napierala ic->ic_iser = true;
29595c4a392SEdward Tomasz Napierala ic->ic_unmapped = true;
2964814a0a4SEdward Tomasz Napierala
2974814a0a4SEdward Tomasz Napierala return (ic);
2984814a0a4SEdward Tomasz Napierala }
2994814a0a4SEdward Tomasz Napierala
3004814a0a4SEdward Tomasz Napierala void
iser_conn_free(struct icl_conn * ic)3014814a0a4SEdward Tomasz Napierala iser_conn_free(struct icl_conn *ic)
3024814a0a4SEdward Tomasz Napierala {
3034814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
3044814a0a4SEdward Tomasz Napierala
30595c4a392SEdward Tomasz Napierala iser_conn_release(ic);
3062b378326SHans Petter Selasky mtx_destroy(&iser_conn->ib_conn.lock);
3074814a0a4SEdward Tomasz Napierala cv_destroy(&iser_conn->ib_conn.beacon.flush_cv);
3084814a0a4SEdward Tomasz Napierala mtx_destroy(&iser_conn->ib_conn.beacon.flush_lock);
3094814a0a4SEdward Tomasz Napierala sx_destroy(&iser_conn->state_mutex);
3104814a0a4SEdward Tomasz Napierala cv_destroy(&iser_conn->up_cv);
3114814a0a4SEdward Tomasz Napierala kobj_delete((struct kobj *)iser_conn, M_ICL_ISER);
3124814a0a4SEdward Tomasz Napierala refcount_release(&icl_iser_ncons);
3134814a0a4SEdward Tomasz Napierala }
3144814a0a4SEdward Tomasz Napierala
3154814a0a4SEdward Tomasz Napierala int
iser_conn_handoff(struct icl_conn * ic,int fd)31695c4a392SEdward Tomasz Napierala iser_conn_handoff(struct icl_conn *ic, int fd)
3174814a0a4SEdward Tomasz Napierala {
3184814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
3194814a0a4SEdward Tomasz Napierala int error = 0;
3204814a0a4SEdward Tomasz Napierala
3214814a0a4SEdward Tomasz Napierala sx_xlock(&iser_conn->state_mutex);
3224814a0a4SEdward Tomasz Napierala if (iser_conn->state != ISER_CONN_UP) {
3234814a0a4SEdward Tomasz Napierala error = EINVAL;
3244814a0a4SEdward Tomasz Napierala ISER_ERR("iser_conn %p state is %d, teardown started\n",
3254814a0a4SEdward Tomasz Napierala iser_conn, iser_conn->state);
3264814a0a4SEdward Tomasz Napierala goto out;
3274814a0a4SEdward Tomasz Napierala }
3284814a0a4SEdward Tomasz Napierala
32995c4a392SEdward Tomasz Napierala error = iser_alloc_rx_descriptors(iser_conn, ic->ic_maxtags);
3304814a0a4SEdward Tomasz Napierala if (error)
3314814a0a4SEdward Tomasz Napierala goto out;
3324814a0a4SEdward Tomasz Napierala
3334814a0a4SEdward Tomasz Napierala error = iser_post_recvm(iser_conn, iser_conn->min_posted_rx);
3344814a0a4SEdward Tomasz Napierala if (error)
3354814a0a4SEdward Tomasz Napierala goto post_error;
3364814a0a4SEdward Tomasz Napierala
33795c4a392SEdward Tomasz Napierala iser_conn->handoff_done = true;
33895c4a392SEdward Tomasz Napierala
3394814a0a4SEdward Tomasz Napierala sx_xunlock(&iser_conn->state_mutex);
3404814a0a4SEdward Tomasz Napierala return (error);
3414814a0a4SEdward Tomasz Napierala
3424814a0a4SEdward Tomasz Napierala post_error:
3434814a0a4SEdward Tomasz Napierala iser_free_rx_descriptors(iser_conn);
3444814a0a4SEdward Tomasz Napierala out:
3454814a0a4SEdward Tomasz Napierala sx_xunlock(&iser_conn->state_mutex);
3464814a0a4SEdward Tomasz Napierala return (error);
3474814a0a4SEdward Tomasz Napierala
3484814a0a4SEdward Tomasz Napierala }
3494814a0a4SEdward Tomasz Napierala
3504814a0a4SEdward Tomasz Napierala /**
3514814a0a4SEdward Tomasz Napierala * Frees all conn objects
3524814a0a4SEdward Tomasz Napierala */
35395c4a392SEdward Tomasz Napierala static void
iser_conn_release(struct icl_conn * ic)3544814a0a4SEdward Tomasz Napierala iser_conn_release(struct icl_conn *ic)
3554814a0a4SEdward Tomasz Napierala {
3564814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
3574814a0a4SEdward Tomasz Napierala struct ib_conn *ib_conn = &iser_conn->ib_conn;
3584814a0a4SEdward Tomasz Napierala struct iser_conn *curr, *tmp;
3594814a0a4SEdward Tomasz Napierala
3604814a0a4SEdward Tomasz Napierala mtx_lock(&ig.connlist_mutex);
3614814a0a4SEdward Tomasz Napierala /*
3624814a0a4SEdward Tomasz Napierala * Search for iser connection in global list.
3634814a0a4SEdward Tomasz Napierala * It may not be there in case of failure in connection establishment
3644814a0a4SEdward Tomasz Napierala * stage.
3654814a0a4SEdward Tomasz Napierala */
3664814a0a4SEdward Tomasz Napierala list_for_each_entry_safe(curr, tmp, &ig.connlist, conn_list) {
3674814a0a4SEdward Tomasz Napierala if (iser_conn == curr) {
3684814a0a4SEdward Tomasz Napierala ISER_WARN("found iser_conn %p", iser_conn);
3694814a0a4SEdward Tomasz Napierala list_del(&iser_conn->conn_list);
3704814a0a4SEdward Tomasz Napierala }
3714814a0a4SEdward Tomasz Napierala }
3724814a0a4SEdward Tomasz Napierala mtx_unlock(&ig.connlist_mutex);
3734814a0a4SEdward Tomasz Napierala
3744814a0a4SEdward Tomasz Napierala /*
3754814a0a4SEdward Tomasz Napierala * In case we reconnecting or removing session, we need to
3764814a0a4SEdward Tomasz Napierala * release IB resources (which is safe to call more than once).
3774814a0a4SEdward Tomasz Napierala */
3784814a0a4SEdward Tomasz Napierala sx_xlock(&iser_conn->state_mutex);
3794814a0a4SEdward Tomasz Napierala iser_free_ib_conn_res(iser_conn, true);
3804814a0a4SEdward Tomasz Napierala sx_xunlock(&iser_conn->state_mutex);
3814814a0a4SEdward Tomasz Napierala
3824814a0a4SEdward Tomasz Napierala if (ib_conn->cma_id != NULL) {
3834814a0a4SEdward Tomasz Napierala rdma_destroy_id(ib_conn->cma_id);
3844814a0a4SEdward Tomasz Napierala ib_conn->cma_id = NULL;
3854814a0a4SEdward Tomasz Napierala }
3864814a0a4SEdward Tomasz Napierala
3874814a0a4SEdward Tomasz Napierala }
3884814a0a4SEdward Tomasz Napierala
3894814a0a4SEdward Tomasz Napierala void
iser_conn_close(struct icl_conn * ic)3904814a0a4SEdward Tomasz Napierala iser_conn_close(struct icl_conn *ic)
3914814a0a4SEdward Tomasz Napierala {
3924814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
3934814a0a4SEdward Tomasz Napierala
3944814a0a4SEdward Tomasz Napierala ISER_INFO("closing conn %p", iser_conn);
3954814a0a4SEdward Tomasz Napierala
3964814a0a4SEdward Tomasz Napierala sx_xlock(&iser_conn->state_mutex);
3974814a0a4SEdward Tomasz Napierala /*
3984814a0a4SEdward Tomasz Napierala * In case iser connection is waiting on conditional variable
3994814a0a4SEdward Tomasz Napierala * (state PENDING) and we try to close it before connection establishment,
4004814a0a4SEdward Tomasz Napierala * we need to signal it to continue releasing connection properly.
4014814a0a4SEdward Tomasz Napierala */
4024814a0a4SEdward Tomasz Napierala if (!iser_conn_terminate(iser_conn) && iser_conn->state == ISER_CONN_PENDING)
4034814a0a4SEdward Tomasz Napierala cv_signal(&iser_conn->up_cv);
4044814a0a4SEdward Tomasz Napierala sx_xunlock(&iser_conn->state_mutex);
4054814a0a4SEdward Tomasz Napierala
4064814a0a4SEdward Tomasz Napierala }
4074814a0a4SEdward Tomasz Napierala
4084814a0a4SEdward Tomasz Napierala int
iser_conn_connect(struct icl_conn * ic,int domain,int socktype,int protocol,struct sockaddr * from_sa,struct sockaddr * to_sa)4094814a0a4SEdward Tomasz Napierala iser_conn_connect(struct icl_conn *ic, int domain, int socktype,
4104814a0a4SEdward Tomasz Napierala int protocol, struct sockaddr *from_sa, struct sockaddr *to_sa)
4114814a0a4SEdward Tomasz Napierala {
4124814a0a4SEdward Tomasz Napierala struct iser_conn *iser_conn = icl_to_iser_conn(ic);
4134814a0a4SEdward Tomasz Napierala struct ib_conn *ib_conn = &iser_conn->ib_conn;
4144814a0a4SEdward Tomasz Napierala int err = 0;
4154814a0a4SEdward Tomasz Napierala
41695c4a392SEdward Tomasz Napierala iser_conn_release(ic);
41795c4a392SEdward Tomasz Napierala
4184814a0a4SEdward Tomasz Napierala sx_xlock(&iser_conn->state_mutex);
4194814a0a4SEdward Tomasz Napierala /* the device is known only --after-- address resolution */
4204814a0a4SEdward Tomasz Napierala ib_conn->device = NULL;
42195c4a392SEdward Tomasz Napierala iser_conn->handoff_done = false;
4224814a0a4SEdward Tomasz Napierala
4234814a0a4SEdward Tomasz Napierala iser_conn->state = ISER_CONN_PENDING;
4244814a0a4SEdward Tomasz Napierala
42541dbd9ddSHans Petter Selasky ib_conn->cma_id = rdma_create_id(&init_net, iser_cma_handler, (void *)iser_conn,
4264814a0a4SEdward Tomasz Napierala RDMA_PS_TCP, IB_QPT_RC);
4274814a0a4SEdward Tomasz Napierala if (IS_ERR(ib_conn->cma_id)) {
4284814a0a4SEdward Tomasz Napierala err = -PTR_ERR(ib_conn->cma_id);
4294814a0a4SEdward Tomasz Napierala ISER_ERR("rdma_create_id failed: %d", err);
4304814a0a4SEdward Tomasz Napierala goto id_failure;
4314814a0a4SEdward Tomasz Napierala }
4324814a0a4SEdward Tomasz Napierala
4334814a0a4SEdward Tomasz Napierala err = rdma_resolve_addr(ib_conn->cma_id, from_sa, to_sa, 1000);
4344814a0a4SEdward Tomasz Napierala if (err) {
4354814a0a4SEdward Tomasz Napierala ISER_ERR("rdma_resolve_addr failed: %d", err);
4364814a0a4SEdward Tomasz Napierala if (err < 0)
4374814a0a4SEdward Tomasz Napierala err = -err;
4384814a0a4SEdward Tomasz Napierala goto addr_failure;
4394814a0a4SEdward Tomasz Napierala }
4404814a0a4SEdward Tomasz Napierala
4414814a0a4SEdward Tomasz Napierala ISER_DBG("before cv_wait: %p", iser_conn);
4424814a0a4SEdward Tomasz Napierala cv_wait(&iser_conn->up_cv, &iser_conn->state_mutex);
4434814a0a4SEdward Tomasz Napierala ISER_DBG("after cv_wait: %p", iser_conn);
4444814a0a4SEdward Tomasz Napierala
4454814a0a4SEdward Tomasz Napierala if (iser_conn->state != ISER_CONN_UP) {
4464814a0a4SEdward Tomasz Napierala err = EIO;
4474814a0a4SEdward Tomasz Napierala goto addr_failure;
4484814a0a4SEdward Tomasz Napierala }
4494814a0a4SEdward Tomasz Napierala
4504814a0a4SEdward Tomasz Napierala err = iser_alloc_login_buf(iser_conn);
4514814a0a4SEdward Tomasz Napierala if (err)
4524814a0a4SEdward Tomasz Napierala goto addr_failure;
4534814a0a4SEdward Tomasz Napierala sx_xunlock(&iser_conn->state_mutex);
4544814a0a4SEdward Tomasz Napierala
4554814a0a4SEdward Tomasz Napierala mtx_lock(&ig.connlist_mutex);
4564814a0a4SEdward Tomasz Napierala list_add(&iser_conn->conn_list, &ig.connlist);
4574814a0a4SEdward Tomasz Napierala mtx_unlock(&ig.connlist_mutex);
4584814a0a4SEdward Tomasz Napierala
4594814a0a4SEdward Tomasz Napierala return (0);
4604814a0a4SEdward Tomasz Napierala
4614814a0a4SEdward Tomasz Napierala id_failure:
4624814a0a4SEdward Tomasz Napierala ib_conn->cma_id = NULL;
4634814a0a4SEdward Tomasz Napierala addr_failure:
4644814a0a4SEdward Tomasz Napierala sx_xunlock(&iser_conn->state_mutex);
4654814a0a4SEdward Tomasz Napierala return (err);
4664814a0a4SEdward Tomasz Napierala }
4674814a0a4SEdward Tomasz Napierala
4684814a0a4SEdward Tomasz Napierala int
iser_conn_task_setup(struct icl_conn * ic,struct icl_pdu * ip,struct ccb_scsiio * csio,uint32_t * task_tagp,void ** prvp)46995c4a392SEdward Tomasz Napierala iser_conn_task_setup(struct icl_conn *ic, struct icl_pdu *ip,
47095c4a392SEdward Tomasz Napierala struct ccb_scsiio *csio,
47195c4a392SEdward Tomasz Napierala uint32_t *task_tagp, void **prvp)
4724814a0a4SEdward Tomasz Napierala {
4734814a0a4SEdward Tomasz Napierala struct icl_iser_pdu *iser_pdu = icl_to_iser_pdu(ip);
4744814a0a4SEdward Tomasz Napierala
4754814a0a4SEdward Tomasz Napierala *prvp = ip;
4764814a0a4SEdward Tomasz Napierala iser_pdu->csio = csio;
4774814a0a4SEdward Tomasz Napierala
4784814a0a4SEdward Tomasz Napierala return (0);
4794814a0a4SEdward Tomasz Napierala }
4804814a0a4SEdward Tomasz Napierala
4814814a0a4SEdward Tomasz Napierala void
iser_conn_task_done(struct icl_conn * ic,void * prv)4824814a0a4SEdward Tomasz Napierala iser_conn_task_done(struct icl_conn *ic, void *prv)
4834814a0a4SEdward Tomasz Napierala {
4844814a0a4SEdward Tomasz Napierala struct icl_pdu *ip = prv;
4854814a0a4SEdward Tomasz Napierala struct icl_iser_pdu *iser_pdu = icl_to_iser_pdu(ip);
4864814a0a4SEdward Tomasz Napierala struct iser_device *device = iser_pdu->iser_conn->ib_conn.device;
4874814a0a4SEdward Tomasz Napierala struct iser_tx_desc *tx_desc = &iser_pdu->desc;
4884814a0a4SEdward Tomasz Napierala
4894814a0a4SEdward Tomasz Napierala if (iser_pdu->dir[ISER_DIR_IN]) {
4904814a0a4SEdward Tomasz Napierala iser_unreg_rdma_mem(iser_pdu, ISER_DIR_IN);
4914814a0a4SEdward Tomasz Napierala iser_dma_unmap_task_data(iser_pdu,
4924814a0a4SEdward Tomasz Napierala &iser_pdu->data[ISER_DIR_IN],
4934814a0a4SEdward Tomasz Napierala DMA_FROM_DEVICE);
4944814a0a4SEdward Tomasz Napierala }
4954814a0a4SEdward Tomasz Napierala
4964814a0a4SEdward Tomasz Napierala if (iser_pdu->dir[ISER_DIR_OUT]) {
4974814a0a4SEdward Tomasz Napierala iser_unreg_rdma_mem(iser_pdu, ISER_DIR_OUT);
4984814a0a4SEdward Tomasz Napierala iser_dma_unmap_task_data(iser_pdu,
4994814a0a4SEdward Tomasz Napierala &iser_pdu->data[ISER_DIR_OUT],
5004814a0a4SEdward Tomasz Napierala DMA_TO_DEVICE);
5014814a0a4SEdward Tomasz Napierala }
5024814a0a4SEdward Tomasz Napierala
5034814a0a4SEdward Tomasz Napierala if (likely(tx_desc->mapped)) {
5044814a0a4SEdward Tomasz Napierala ib_dma_unmap_single(device->ib_device, tx_desc->dma_addr,
5054814a0a4SEdward Tomasz Napierala ISER_HEADERS_LEN, DMA_TO_DEVICE);
5064814a0a4SEdward Tomasz Napierala tx_desc->mapped = false;
5074814a0a4SEdward Tomasz Napierala }
5084814a0a4SEdward Tomasz Napierala
5094814a0a4SEdward Tomasz Napierala iser_pdu_free(ic, ip);
5104814a0a4SEdward Tomasz Napierala }
5114814a0a4SEdward Tomasz Napierala
5124814a0a4SEdward Tomasz Napierala static int
iser_limits(struct icl_drv_limits * idl,int socket)513*7b02c1e8SJohn Baldwin iser_limits(struct icl_drv_limits *idl, int socket)
5144814a0a4SEdward Tomasz Napierala {
5159ac7c5a6SHans Petter Selasky
51697b84d34SNavdeep Parhar idl->idl_max_recv_data_segment_length = 128 * 1024;
5179ac7c5a6SHans Petter Selasky idl->idl_max_send_data_segment_length = 128 * 1024;
5189ac7c5a6SHans Petter Selasky idl->idl_max_burst_length = 262144;
5199ac7c5a6SHans Petter Selasky idl->idl_first_burst_length = 65536;
5204814a0a4SEdward Tomasz Napierala
5214814a0a4SEdward Tomasz Napierala return (0);
5224814a0a4SEdward Tomasz Napierala }
5234814a0a4SEdward Tomasz Napierala
5244814a0a4SEdward Tomasz Napierala static int
icl_iser_load(void)5254814a0a4SEdward Tomasz Napierala icl_iser_load(void)
5264814a0a4SEdward Tomasz Napierala {
5274814a0a4SEdward Tomasz Napierala int error;
5284814a0a4SEdward Tomasz Napierala
5294814a0a4SEdward Tomasz Napierala ISER_DBG("Starting iSER datamover...");
5304814a0a4SEdward Tomasz Napierala
5314814a0a4SEdward Tomasz Napierala icl_pdu_zone = uma_zcreate("icl_iser_pdu", sizeof(struct icl_iser_pdu),
5324814a0a4SEdward Tomasz Napierala NULL, NULL, NULL, NULL,
5334814a0a4SEdward Tomasz Napierala UMA_ALIGN_PTR, 0);
5344814a0a4SEdward Tomasz Napierala /* FIXME: Check rc */
5354814a0a4SEdward Tomasz Napierala
5364814a0a4SEdward Tomasz Napierala refcount_init(&icl_iser_ncons, 0);
5374814a0a4SEdward Tomasz Napierala
53895c4a392SEdward Tomasz Napierala error = icl_register("iser", true, 0, iser_limits, iser_new_conn);
5394814a0a4SEdward Tomasz Napierala KASSERT(error == 0, ("failed to register iser"));
5404814a0a4SEdward Tomasz Napierala
5414814a0a4SEdward Tomasz Napierala memset(&ig, 0, sizeof(struct iser_global));
5424814a0a4SEdward Tomasz Napierala
5434814a0a4SEdward Tomasz Napierala /* device init is called only after the first addr resolution */
5444814a0a4SEdward Tomasz Napierala sx_init(&ig.device_list_mutex, "global_device_lock");
5454814a0a4SEdward Tomasz Napierala INIT_LIST_HEAD(&ig.device_list);
5462b378326SHans Petter Selasky mtx_init(&ig.connlist_mutex, "iser_global_conn_lock", NULL, MTX_DEF);
5474814a0a4SEdward Tomasz Napierala INIT_LIST_HEAD(&ig.connlist);
5484814a0a4SEdward Tomasz Napierala sx_init(&ig.close_conns_mutex, "global_close_conns_lock");
5494814a0a4SEdward Tomasz Napierala
5504814a0a4SEdward Tomasz Napierala return (error);
5514814a0a4SEdward Tomasz Napierala }
5524814a0a4SEdward Tomasz Napierala
5534814a0a4SEdward Tomasz Napierala static int
icl_iser_unload(void)5544814a0a4SEdward Tomasz Napierala icl_iser_unload(void)
5554814a0a4SEdward Tomasz Napierala {
5564814a0a4SEdward Tomasz Napierala ISER_DBG("Removing iSER datamover...");
5574814a0a4SEdward Tomasz Napierala
5584814a0a4SEdward Tomasz Napierala if (icl_iser_ncons != 0)
5594814a0a4SEdward Tomasz Napierala return (EBUSY);
5604814a0a4SEdward Tomasz Napierala
5614814a0a4SEdward Tomasz Napierala sx_destroy(&ig.close_conns_mutex);
5624814a0a4SEdward Tomasz Napierala mtx_destroy(&ig.connlist_mutex);
5634814a0a4SEdward Tomasz Napierala sx_destroy(&ig.device_list_mutex);
5644814a0a4SEdward Tomasz Napierala
56595c4a392SEdward Tomasz Napierala icl_unregister("iser", true);
5664814a0a4SEdward Tomasz Napierala
5674814a0a4SEdward Tomasz Napierala uma_zdestroy(icl_pdu_zone);
5684814a0a4SEdward Tomasz Napierala
5694814a0a4SEdward Tomasz Napierala return (0);
5704814a0a4SEdward Tomasz Napierala }
5714814a0a4SEdward Tomasz Napierala
5724814a0a4SEdward Tomasz Napierala static int
icl_iser_modevent(module_t mod,int what,void * arg)5734814a0a4SEdward Tomasz Napierala icl_iser_modevent(module_t mod, int what, void *arg)
5744814a0a4SEdward Tomasz Napierala {
5754814a0a4SEdward Tomasz Napierala switch (what) {
5764814a0a4SEdward Tomasz Napierala case MOD_LOAD:
5774814a0a4SEdward Tomasz Napierala return (icl_iser_load());
5784814a0a4SEdward Tomasz Napierala case MOD_UNLOAD:
5794814a0a4SEdward Tomasz Napierala return (icl_iser_unload());
5804814a0a4SEdward Tomasz Napierala default:
5814814a0a4SEdward Tomasz Napierala return (EINVAL);
5824814a0a4SEdward Tomasz Napierala }
5834814a0a4SEdward Tomasz Napierala }
5844814a0a4SEdward Tomasz Napierala
5854814a0a4SEdward Tomasz Napierala moduledata_t icl_iser_data = {
5864814a0a4SEdward Tomasz Napierala .name = "icl_iser",
5874814a0a4SEdward Tomasz Napierala .evhand = icl_iser_modevent,
5884814a0a4SEdward Tomasz Napierala .priv = 0
5894814a0a4SEdward Tomasz Napierala };
5904814a0a4SEdward Tomasz Napierala
5914814a0a4SEdward Tomasz Napierala DECLARE_MODULE(icl_iser, icl_iser_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
5924814a0a4SEdward Tomasz Napierala MODULE_DEPEND(icl_iser, icl, 1, 1, 1);
5934814a0a4SEdward Tomasz Napierala MODULE_DEPEND(icl_iser, ibcore, 1, 1, 1);
5944814a0a4SEdward Tomasz Napierala MODULE_VERSION(icl_iser, 1);
595