Merge branch 'svn-trunk'

This commit is contained in:
Bart Van Assche
2015-07-10 20:47:04 -07:00
15 changed files with 230 additions and 111 deletions

View File

@@ -24,7 +24,6 @@ NUMA node, you want the HCA to be close to the same node.
Limitations:
-------------
* Bidirectional commands are not supported
* Block size over 512KB is not supported
* Maximum number of concurent login requests that can be handled is 127 by default.
Note that there may be more connections, but only up to 127 login requests
can be handled at the same time. If you wish to increase this, load isert_scst with

View File

@@ -1,6 +1,5 @@
* Add suppport for immediate data in iSER
* Add suppport for data-out in iSER
* Look into allocating wr and sg entries dynamically from kmem_cache instead of embedding them into iser_cmnd
* Look into seperating between RX pdu and TX pdu
* Do not signal every "response sent" notification
* Make the code NUMA aware

View File

@@ -40,6 +40,13 @@
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <rdma/ib_verbs.h>
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 == 5
static inline u16 vlan_dev_vlan_id(const void *dev)
{
BUG();
return 0;
}
#endif
#include <rdma/rdma_cm.h>
#include "iser_hdr.h"
@@ -95,9 +102,6 @@ struct isert_wr {
};
} ____cacheline_aligned;
#define ISER_MAX_SGE 128
#define ISER_MAX_RDMAS 5
#define ISER_SQ_SIZE 128
#define ISER_MAX_WCE 2048
@@ -108,8 +112,10 @@ struct isert_cmnd {
struct isert_buf buf;
struct isert_buf rdma_buf;
struct isert_wr wr[ISER_MAX_RDMAS];
struct ib_sge sg_pool[ISER_MAX_SGE];
struct isert_wr *wr;
struct ib_sge *sg_pool;
int n_wr;
int n_sge;
struct isert_hdr *isert_hdr ____cacheline_aligned;
struct iscsi_hdr *bhs;

View File

@@ -166,6 +166,50 @@ static inline int isert_pdu_prepare_send(struct isert_connection *isert_conn,
return sg_cnt;
}
static int isert_alloc_for_rdma(struct isert_cmnd *pdu, int sge_cnt,
struct isert_connection *isert_conn)
{
struct isert_wr *wr;
struct ib_sge *sg_pool;
int i, ret = 0;
int wr_cnt;
sg_pool = kmalloc(sizeof(*sg_pool) * sge_cnt, GFP_KERNEL);
if (unlikely(sg_pool == NULL)) {
ret = -ENOMEM;
goto out;
}
wr_cnt = DIV_ROUND_UP(sge_cnt, isert_conn->max_sge);
wr = kmalloc(sizeof(*wr) * wr_cnt, GFP_KERNEL);
if (unlikely(wr == NULL)) {
ret = -ENOMEM;
goto out_free_sg_pool;
}
kfree(pdu->wr);
pdu->wr = wr;
kfree(pdu->sg_pool);
pdu->sg_pool = sg_pool;
pdu->n_wr = wr_cnt;
pdu->n_sge = sge_cnt;
for (i = 0; i < wr_cnt; ++i)
isert_wr_set_fields(&pdu->wr[i], isert_conn, pdu);
for (i = 0; i < sge_cnt; ++i)
pdu->sg_pool[i].lkey = isert_conn->isert_dev->mr->lkey;
goto out;
out_free_sg_pool:
kfree(sg_pool);
out:
return ret;
}
static inline void isert_link_send_wrs(struct isert_wr *from_wr,
struct isert_wr *to_wr)
{
@@ -204,10 +248,10 @@ int isert_prepare_rdma(struct isert_cmnd *isert_pdu,
else
isert_buf->dma_dir = DMA_FROM_DEVICE;
if (unlikely(isert_buf->sg_cnt > ISER_MAX_SGE)) {
pr_err("Scatterlist too large: %d\n", isert_buf->sg_cnt);
wr_cnt = -EOPNOTSUPP;
goto out;
if (unlikely(isert_buf->sg_cnt > isert_pdu->n_sge)) {
wr_cnt = isert_alloc_for_rdma(isert_pdu, isert_buf->sg_cnt, isert_conn);
if (unlikely(wr_cnt))
goto out;
}
err = ib_dma_map_sg(ib_dev, isert_buf->sg, isert_buf->sg_cnt,
@@ -245,12 +289,18 @@ out:
void isert_pdu_free(struct isert_cmnd *pdu)
{
unsigned int i;
int i;
list_del(&pdu->pool_node);
for (i = 0; i < ARRAY_SIZE(pdu->wr); ++i)
for (i = 0; i < pdu->n_wr; ++i)
isert_wr_release(&pdu->wr[i]);
kfree(pdu->wr);
pdu->wr = NULL;
kfree(pdu->sg_pool);
pdu->sg_pool = NULL;
isert_pdu_kfree(pdu);
}
@@ -259,7 +309,6 @@ struct isert_cmnd *isert_rx_pdu_alloc(struct isert_connection *isert_conn,
{
struct isert_cmnd *pdu = NULL;
int err;
unsigned int i;
TRACE_ENTRY();
@@ -269,6 +318,12 @@ struct isert_cmnd *isert_rx_pdu_alloc(struct isert_connection *isert_conn,
goto out;
}
err = isert_alloc_for_rdma(pdu, 4, isert_conn);
if (unlikely(err)) {
pr_err("Failed to alloc sge and wr for rx pdu\n");
goto out;
}
err = isert_buf_alloc_data_buf(isert_conn->isert_dev->ib_dev,
&pdu->buf, size, DMA_FROM_DEVICE);
if (unlikely(err)) {
@@ -283,12 +338,6 @@ struct isert_cmnd *isert_rx_pdu_alloc(struct isert_connection *isert_conn,
goto pdu_init_failed;
}
for (i = 0; i < ARRAY_SIZE(pdu->wr); ++i)
isert_wr_set_fields(&pdu->wr[i], isert_conn, pdu);
for (i = 0; i < ARRAY_SIZE(pdu->sg_pool); ++i)
pdu->sg_pool[i].lkey = isert_conn->isert_dev->mr->lkey;
list_add_tail(&pdu->pool_node, &isert_conn->rx_buf_list);
goto out;
@@ -308,7 +357,6 @@ struct isert_cmnd *isert_tx_pdu_alloc(struct isert_connection *isert_conn,
{
struct isert_cmnd *pdu = NULL;
int err;
unsigned int i;
TRACE_ENTRY();
@@ -318,6 +366,12 @@ struct isert_cmnd *isert_tx_pdu_alloc(struct isert_connection *isert_conn,
goto out;
}
err = isert_alloc_for_rdma(pdu, 4, isert_conn);
if (unlikely(err)) {
pr_err("Failed to alloc sge and wr for tx pdu\n");
goto out;
}
err = isert_buf_alloc_data_buf(isert_conn->isert_dev->ib_dev,
&pdu->buf, size, DMA_TO_DEVICE);
if (unlikely(err)) {
@@ -331,14 +385,9 @@ struct isert_cmnd *isert_tx_pdu_alloc(struct isert_connection *isert_conn,
&pdu->wr, size, err);
goto buf_init_failed;
}
isert_tx_pdu_init(pdu, isert_conn);
for (i = 0; i < ARRAY_SIZE(pdu->wr); ++i)
isert_wr_set_fields(&pdu->wr[i], isert_conn, pdu);
for (i = 0; i < ARRAY_SIZE(pdu->sg_pool); ++i)
pdu->sg_pool[i].lkey = isert_conn->isert_dev->mr->lkey;
isert_pdu_set_hdr_plain(pdu);
list_add_tail(&pdu->pool_node, &isert_conn->tx_free_list);

View File

@@ -604,14 +604,21 @@ static int isert_poll_cq(struct isert_cq *cq)
}
/* callback function for isert_dev->[cq]->cq_comp_work */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) && !defined(BACKPORT_LINUX_WORKQUEUE_TO_2_6_19)
/* A vanilla 2.6.19 or older kernel without backported OFED kernel headers. */
static void isert_cq_comp_work_cb(void *ctx)
{
struct isert_cq *cq_desc = ctx;
#else
static void isert_cq_comp_work_cb(struct work_struct *work)
{
struct isert_cq *cq_desc;
struct isert_cq *cq_desc =
container_of(work, struct isert_cq, cq_comp_work);
#endif
int ret;
TRACE_ENTRY();
cq_desc = container_of(work, struct isert_cq, cq_comp_work);
ret = isert_poll_cq(cq_desc);
if (unlikely(ret < 0)) { /* poll error */
pr_err("ib_poll_cq failed\n");
@@ -636,8 +643,12 @@ static void isert_cq_comp_handler(struct ib_cq *cq, void *context)
{
struct isert_cq *cq_desc = context;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
queue_work(cq_desc->cq_workqueue, &cq_desc->cq_comp_work);
#else
queue_work_on(smp_processor_id(), cq_desc->cq_workqueue,
&cq_desc->cq_comp_work);
#endif
}
static const char *ib_event_type_str(enum ib_event_type ev_type)
@@ -1000,21 +1011,6 @@ static int isert_conn_qp_create(struct isert_connection *isert_conn)
isert_conn->cq_desc = &isert_dev->cq_desc[cq_idx];
/*
* A quote from the OFED 1.5.3.1 release notes
* (docs/release_notes/mthca_release_notes.txt), section "Known Issues":
* In mem-free devices, RC QPs can be created with a maximum of
* (max_sge - 1) entries only; UD QPs can be created with a maximum of
* (max_sge - 3) entries.
* A quote from the OFED 1.2.5 release notes
* (docs/mthca_release_notes.txt), section "Known Issues":
* In mem-free devices, RC QPs can be created with a maximum of
* (max_sge - 3) entries only.
*/
isert_conn->max_sge = isert_dev->device_attr.max_sge - 3;
WARN_ON(isert_conn->max_sge < 1);
qp_attr.cap.max_send_sge = isert_conn->max_sge;
qp_attr.cap.max_recv_sge = 3;
qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
@@ -1078,6 +1074,21 @@ static struct isert_connection *isert_conn_create(struct rdma_cm_id *cm_id,
isert_conn->cm_id = cm_id;
isert_conn->isert_dev = isert_dev;
/*
* A quote from the OFED 1.5.3.1 release notes
* (docs/release_notes/mthca_release_notes.txt), section "Known Issues":
* In mem-free devices, RC QPs can be created with a maximum of
* (max_sge - 1) entries only; UD QPs can be created with a maximum of
* (max_sge - 3) entries.
* A quote from the OFED 1.2.5 release notes
* (docs/mthca_release_notes.txt), section "Known Issues":
* In mem-free devices, RC QPs can be created with a maximum of
* (max_sge - 3) entries only.
*/
isert_conn->max_sge = isert_dev->device_attr.max_sge - 3;
WARN_ON(isert_conn->max_sge < 1);
INIT_LIST_HEAD(&isert_conn->rx_buf_list);
INIT_LIST_HEAD(&isert_conn->tx_free_list);
INIT_LIST_HEAD(&isert_conn->tx_busy_list);
@@ -1571,7 +1582,8 @@ struct isert_portal *isert_portal_create(void)
goto err_alloc;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) && !defined(RHEL_MAJOR)
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) && \
(!defined(RHEL_MAJOR) || RHEL_MAJOR -0 <= 5)
cm_id = rdma_create_id(isert_cm_evt_handler, portal, RDMA_PS_TCP);
#else
cm_id = rdma_create_id(isert_cm_evt_handler, portal, RDMA_PS_TCP,

View File

@@ -38,7 +38,12 @@
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/poll.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
#include <linux/freezer.h>
#else
#define wait_event_freezable(wq, cond) ({ wait_event(wq, cond); 0; })
#endif
#include <linux/file.h>
#include "isert_dbg.h"
#include "../iscsi.h"
@@ -887,7 +892,10 @@ static void __init isert_setup_cdev(struct isert_conn_dev *dev,
PRINT_ERROR("Error %d adding "ISER_CONN_DEV_PREFIX"%d", err,
index);
dev->dev = device_create(isert_class, NULL, dev->devno, NULL,
dev->dev = device_create(isert_class, NULL, dev->devno,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
NULL,
#endif
ISER_CONN_DEV_PREFIX"%d", index);
TRACE_EXIT();
@@ -914,7 +922,10 @@ static void __init isert_setup_listener_cdev(struct isert_listener_dev *dev)
if (unlikely(err))
PRINT_ERROR("Error %d adding isert_scst", err);
dev->dev = device_create(isert_class, NULL, dev->devno, NULL,
dev->dev = device_create(isert_class, NULL, dev->devno,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
NULL,
#endif
"isert_scst");
TRACE_EXIT();

View File

@@ -575,14 +575,21 @@ out:
* Access control code
*/
static int netmask_match_v6(struct sockaddr *sa1, struct sockaddr *sa2, uint32_t mbit)
typedef union {
struct sockaddr sa;
struct sockaddr_in sa_in;
struct sockaddr_in6 sa_in6;
} sockaddress;
static int netmask_match_v6(const struct sockaddr_in6 *sa1,
const struct sockaddr_in6 *sa2, uint32_t mbit)
{
uint16_t mask, a1[8], a2[8];
int i;
for (i = 0; i < 8; i++) {
a1[i] = ntohs(((struct sockaddr_in6 *) sa1)->sin6_addr.s6_addr16[i]);
a2[i] = ntohs(((struct sockaddr_in6 *) sa2)->sin6_addr.s6_addr16[i]);
a1[i] = ntohs(sa1->sin6_addr.s6_addr16[i]);
a2[i] = ntohs(sa2->sin6_addr.s6_addr16[i]);
}
for (i = 0; i < mbit / 16; i++)
@@ -598,12 +605,14 @@ static int netmask_match_v6(struct sockaddr *sa1, struct sockaddr *sa2, uint32_t
return 1;
}
static int netmask_match_v4(struct sockaddr *sa1, struct sockaddr *sa2, uint32_t mbit)
static int netmask_match_v4(const struct sockaddr_in *sa1,
const struct sockaddr_in *sa2,
uint32_t mbit)
{
uint32_t s1, s2, mask = ~((1 << (32 - mbit)) - 1);
s1 = htonl(((struct sockaddr_in *) sa1)->sin_addr.s_addr);
s2 = htonl(((struct sockaddr_in *) sa2)->sin_addr.s_addr);
s1 = htonl(sa1->sin_addr.s_addr);
s2 = htonl(sa2->sin_addr.s_addr);
if (~mask & s1)
return 0;
@@ -614,10 +623,11 @@ static int netmask_match_v4(struct sockaddr *sa1, struct sockaddr *sa2, uint32_t
return 0;
}
static int netmask_match(struct sockaddr *sa1, struct sockaddr *sa2, char *buf)
static int netmask_match(const sockaddress *sa1, const sockaddress *sa2,
char *buf)
{
unsigned long mbit;
uint8_t family = sa1->sa_family;
uint8_t family = sa1->sa.sa_family;
mbit = strtoul(buf, NULL, 0);
if (mbit == ULONG_MAX ||
@@ -626,21 +636,21 @@ static int netmask_match(struct sockaddr *sa1, struct sockaddr *sa2, char *buf)
return 0;
if (family == AF_INET)
return netmask_match_v4(sa1, sa2, mbit);
return netmask_match_v4(&sa1->sa_in, &sa2->sa_in, mbit);
return netmask_match_v6(sa1, sa2, mbit);
return netmask_match_v6(&sa1->sa_in6, &sa2->sa_in6, mbit);
}
static int address_match(struct sockaddr *sa1, struct sockaddr *sa2)
static int address_match(const sockaddress *sa1, const sockaddress *sa2)
{
if (sa1->sa_family == AF_INET)
return ((struct sockaddr_in *) sa1)->sin_addr.s_addr ==
((struct sockaddr_in *) sa2)->sin_addr.s_addr;
if (sa1->sa.sa_family == AF_INET)
return sa1->sa_in.sin_addr.s_addr ==
sa2->sa_in.sin_addr.s_addr;
else {
struct in6_addr *a1, *a2;
const struct in6_addr *a1, *a2;
a1 = &((struct sockaddr_in6 *) sa1)->sin6_addr;
a2 = &((struct sockaddr_in6 *) sa2)->sin6_addr;
a1 = &sa1->sa_in6.sin6_addr;
a2 = &sa2->sa_in6.sin6_addr;
return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
a1->s6_addr32[1] == a2->s6_addr32[1] &&
@@ -653,7 +663,7 @@ static int address_match(struct sockaddr *sa1, struct sockaddr *sa2)
static int __initiator_match(int fd, char *str)
{
struct sockaddr_storage from;
sockaddress from;
socklen_t len;
char *p, *q;
int err = 0;
@@ -690,11 +700,9 @@ static int __initiator_match(int fd, char *str)
return 0;
if (q)
err = netmask_match(res->ai_addr,
(struct sockaddr *) &from, q);
err = netmask_match((sockaddress *)res->ai_addr, &from, q);
else
err = address_match(res->ai_addr,
(struct sockaddr *) &from);
err = address_match((sockaddress *)res->ai_addr, &from);
freeaddrinfo(res);

View File

@@ -3,18 +3,18 @@
ABT_DETAILS="x86_64"
ABT_JOBS=5
ABT_KERNELS=" \
4.1 \
4.0.7-nc \
4.1.2 \
4.0.8-nc \
3.19.7-nc \
3.18.8-nc \
3.17.8-nc \
3.16.7-nc \
3.15.10-nc \
3.14.46-nc \
3.14.48-nc \
3.13.11-nc \
3.12.44-nc \
3.11.10-nc \
3.10.82-nc \
3.10.84-nc \
3.9.11-nc \
3.8.13-nc \
3.7.10-nc \

View File

@@ -1717,7 +1717,7 @@ int
qla2x00_fdmi_register(scsi_qla_host_t *vha)
{
int rval;
struct qla_hw_data *ha = vha->hw;
struct qla_hw_data *ha = vha->hw;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return QLA_FUNCTION_FAILED;

View File

@@ -530,7 +530,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x00d4,
"Unable to initialize ISP84XX.\n");
qla84xx_put_chip(vha);
qla84xx_put_chip(vha);
}
}

View File

@@ -388,9 +388,9 @@ qla2x00_start_scsi(srb_t *sp)
req->cnt = req->length -
(req->ring_index - cnt);
}
/* If still no head room then bail out */
if (req->cnt < (req_cnt + 2))
goto queuing_error;
/* If still no head room then bail out */
if (req->cnt < (req_cnt + 2))
goto queuing_error;
/* Build command packet */
req->current_outstanding_cmd = handle;

View File

@@ -1842,7 +1842,7 @@ qla82xx_set_product_offset(struct qla_hw_data *ha)
ptab_desc = qla82xx_get_table_desc(unirom,
QLA82XX_URI_DIR_SECT_PRODUCT_TBL);
if (!ptab_desc)
if (!ptab_desc)
return -1;
entries = cpu_to_le32(ptab_desc->num_entries);

View File

@@ -165,6 +165,20 @@ typedef cpumask_t cpumask_var_t[1];
#define nr_cpumask_bits NR_CPUS
#endif
#ifdef CONFIG_CPUMASK_OFFSTACK
bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags);
void free_cpumask_var(cpumask_var_t mask);
#else
static inline void free_cpumask_var(cpumask_var_t mask)
{
}
static inline bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
{
return true;
}
#endif
/* verify cpu argument to cpumask_* operators */
static inline unsigned int cpumask_check(unsigned int cpu)
{
@@ -201,6 +215,16 @@ static inline unsigned int cpumask_next(int n, const cpumask_t *srcp)
(cpu) = cpumask_next((cpu), (mask)), \
(cpu) < nr_cpu_ids;)
/**
* cpumask_set_cpu - set a cpu in a cpumask
* @cpu: cpu number (< nr_cpu_ids)
* @dstp: the cpumask pointer
*/
static inline void cpumask_set_cpu(unsigned int cpu, cpumask_t *dstp)
{
set_bit(cpu, cpumask_bits(dstp));
}
/**
* cpumask_copy - *dstp = *srcp
* @dstp: the result
@@ -4677,6 +4701,38 @@ static inline __be16 scst_cmd_get_dif_app_tag(struct scst_cmd *cmd,
return cmd->dev->dev_dif_static_app_tag;
}
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5
static inline uint16_t get_unaligned_be16(const void *p)
{
return be16_to_cpu(get_unaligned((__be16 *)p));
}
static inline void put_unaligned_be16(uint16_t i, void *p)
{
put_unaligned(cpu_to_be16(i), (__be16 *)p);
}
static inline uint32_t get_unaligned_be32(const void *p)
{
return be32_to_cpu(get_unaligned((__be32 *)p));
}
static inline void put_unaligned_be32(uint32_t i, void *p)
{
put_unaligned(cpu_to_be32(i), (__be32 *)p);
}
static inline uint64_t get_unaligned_be64(const void *p)
{
return be64_to_cpu(get_unaligned((__be64 *)p));
}
static inline void put_unaligned_be64(uint64_t i, void *p)
{
put_unaligned(cpu_to_be64(i), (__be64 *)p);
}
#endif
/*
* Returns T10-PI type 2 expected initial reference tag as LBA, i.e. converted
* into CPU endianness. Valid only with protection type 2.
@@ -5568,38 +5624,6 @@ if (!(condition)) { \
finish_wait(&(wq), &__wait); \
}
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5
static inline uint16_t get_unaligned_be16(const void *p)
{
return be16_to_cpu(get_unaligned((__be16 *)p));
}
static inline void put_unaligned_be16(uint16_t i, void *p)
{
put_unaligned(cpu_to_be16(i), (__be16 *)p);
}
static inline uint32_t get_unaligned_be32(const void *p)
{
return be32_to_cpu(get_unaligned((__be32 *)p));
}
static inline void put_unaligned_be32(uint32_t i, void *p)
{
put_unaligned(cpu_to_be32(i), (__be32 *)p);
}
static inline uint64_t get_unaligned_be64(const void *p)
{
return be64_to_cpu(get_unaligned((__be64 *)p));
}
static inline void put_unaligned_be64(uint64_t i, void *p)
{
put_unaligned(cpu_to_be64(i), (__be64 *)p);
}
#endif
/* Only use get_unaligned_be24() if reading p - 1 is allowed. */
static inline uint32_t get_unaligned_be24(const uint8_t *const p)
{

View File

@@ -375,6 +375,9 @@ static inline int scst_sense_response_code(const uint8_t *sense)
/* Upstream commit 93aae17a (v2.6.38) */
#define GET_EVENT_STATUS_NOTIFICATION 0x4a
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
#define VARIABLE_LENGTH_CMD 0x7f
#endif
#ifndef READ_16
#define READ_16 0x88
#endif

View File

@@ -35,7 +35,10 @@
#include <asm/kmap_types.h>
#include <asm/unaligned.h>
#include <asm/checksum.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#include <linux/crc-t10dif.h>
#endif
#include <linux/namei.h>
#include <linux/mount.h>
@@ -7867,7 +7870,12 @@ EXPORT_SYMBOL(scst_put_buf_full);
static __be16 scst_dif_crc_fn(const void *data, unsigned int len)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
return cpu_to_be16(crc_t10dif(data, len));
#else
WARN_ON_ONCE(true);
return 0;
#endif
}
static __be16 scst_dif_ip_fn(const void *data, unsigned int len)