* [RFC TLS Offload Support 03/15] tcp: export tcp_rate_check_app_limited function
From: Aviad Yehezkel @ 2017-03-28 13:26 UTC (permalink / raw)
To: davem, aviadye, ilyal, borisp, davejwatson, netdev
Cc: matanb, liranl, haggaie, tom, herbert, nmav, fridolin.pokorny,
ilant, kliteyn, linux-crypto, saeedm, aviadye
In-Reply-To: <1490707592-1430-1-git-send-email-aviadye@mellanox.com>
We will use it via tls new code.
Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
net/ipv4/tcp_rate.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv4/tcp_rate.c b/net/ipv4/tcp_rate.c
index 9be1581..a226f76 100644
--- a/net/ipv4/tcp_rate.c
+++ b/net/ipv4/tcp_rate.c
@@ -184,3 +184,4 @@ void tcp_rate_check_app_limited(struct sock *sk)
tp->app_limited =
(tp->delivered + tcp_packets_in_flight(tp)) ? : 1;
}
+EXPORT_SYMBOL(tcp_rate_check_app_limited);
--
2.7.4
^ permalink raw reply related
* [RFC TLS Offload Support 15/15] net/tls: Add software offload
From: Aviad Yehezkel @ 2017-03-28 13:26 UTC (permalink / raw)
To: davem, aviadye, ilyal, borisp, davejwatson, netdev
Cc: matanb, liranl, haggaie, tom, herbert, nmav, fridolin.pokorny,
ilant, kliteyn, linux-crypto, saeedm, aviadye
In-Reply-To: <1490707592-1430-1-git-send-email-aviadye@mellanox.com>
From: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Dave Watson <davejwatson@fb.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
---
MAINTAINERS | 1 +
include/net/tls.h | 44 ++++
net/tls/Makefile | 2 +-
net/tls/tls_main.c | 34 +--
net/tls/tls_sw.c | 729 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 794 insertions(+), 16 deletions(-)
create mode 100644 net/tls/tls_sw.c
diff --git a/MAINTAINERS b/MAINTAINERS
index e3b70c3..413c1d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8491,6 +8491,7 @@ M: Ilya Lesokhin <ilyal@mellanox.com>
M: Aviad Yehezkel <aviadye@mellanox.com>
M: Boris Pismenny <borisp@mellanox.com>
M: Haggai Eran <haggaie@mellanox.com>
+M: Dave Watson <davejwatson@fb.com>
L: netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
diff --git a/include/net/tls.h b/include/net/tls.h
index f7f0cde..bb1f41e 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -48,6 +48,7 @@
#define TLS_CRYPTO_INFO_READY(info) ((info)->cipher_type)
#define TLS_IS_STATE_HW(info) ((info)->state == TLS_STATE_HW)
+#define TLS_IS_STATE_SW(info) ((info)->state == TLS_STATE_SW)
#define TLS_RECORD_TYPE_DATA 0x17
@@ -68,6 +69,37 @@ struct tls_offload_context {
spinlock_t lock; /* protects records list */
};
+#define TLS_DATA_PAGES (TLS_MAX_PAYLOAD_SIZE / PAGE_SIZE)
+/* +1 for aad, +1 for tag, +1 for chaining */
+#define TLS_SG_DATA_SIZE (TLS_DATA_PAGES + 3)
+#define ALG_MAX_PAGES 16 /* for skb_to_sgvec */
+#define TLS_AAD_SPACE_SIZE 21
+#define TLS_AAD_SIZE 13
+#define TLS_TAG_SIZE 16
+
+#define TLS_NONCE_SIZE 8
+#define TLS_PREPEND_SIZE (TLS_HEADER_SIZE + TLS_NONCE_SIZE)
+#define TLS_OVERHEAD (TLS_PREPEND_SIZE + TLS_TAG_SIZE)
+
+struct tls_sw_context {
+ struct sock *sk;
+ void (*sk_write_space)(struct sock *sk);
+ struct crypto_aead *aead_send;
+
+ /* Sending context */
+ struct scatterlist sg_tx_data[TLS_SG_DATA_SIZE];
+ struct scatterlist sg_tx_data2[ALG_MAX_PAGES + 1];
+ char aad_send[TLS_AAD_SPACE_SIZE];
+ char tag_send[TLS_TAG_SIZE];
+ skb_frag_t tx_frag;
+ int wmem_len;
+ int order_npages;
+ struct scatterlist sgaad_send[2];
+ struct scatterlist sgtag_send[2];
+ struct sk_buff_head tx_queue;
+ int unsent;
+};
+
struct tls_context {
union {
struct tls_crypto_info crypto_send;
@@ -102,6 +134,12 @@ int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
int tls_device_sendpage(struct sock *sk, struct page *page,
int offset, size_t size, int flags);
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx);
+void tls_clear_sw_offload(struct sock *sk);
+int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
+int tls_sw_sendpage(struct sock *sk, struct page *page,
+ int offset, size_t size, int flags);
+
struct tls_record_info *tls_get_record(struct tls_offload_context *context,
u32 seq);
@@ -174,6 +212,12 @@ static inline struct tls_context *tls_get_ctx(const struct sock *sk)
return sk->sk_user_data;
}
+static inline struct tls_sw_context *tls_sw_ctx(
+ const struct tls_context *tls_ctx)
+{
+ return (struct tls_sw_context *)tls_ctx->priv_ctx;
+}
+
static inline struct tls_offload_context *tls_offload_ctx(
const struct tls_context *tls_ctx)
{
diff --git a/net/tls/Makefile b/net/tls/Makefile
index 65e5677..61457e0 100644
--- a/net/tls/Makefile
+++ b/net/tls/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_TLS) += tls.o
-tls-y := tls_main.o tls_device.o
+tls-y := tls_main.o tls_device.o tls_sw.o
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 6a3df25..a4efd02 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -46,6 +46,7 @@ MODULE_DESCRIPTION("Transport Layer Security Support");
MODULE_LICENSE("Dual BSD/GPL");
static struct proto tls_device_prot;
+static struct proto tls_sw_prot;
int tls_push_frags(struct sock *sk,
struct tls_context *ctx,
@@ -188,13 +189,10 @@ int tls_sk_query(struct sock *sk, int optname, char __user *optval,
rc = -EINVAL;
goto out;
}
- if (TLS_IS_STATE_HW(crypto_info)) {
- lock_sock(sk);
- memcpy(crypto_info_aes_gcm_128->iv,
- ctx->iv,
- TLS_CIPHER_AES_GCM_128_IV_SIZE);
- release_sock(sk);
- }
+ lock_sock(sk);
+ memcpy(crypto_info_aes_gcm_128->iv, ctx->iv,
+ TLS_CIPHER_AES_GCM_128_IV_SIZE);
+ release_sock(sk);
rc = copy_to_user(optval,
crypto_info_aes_gcm_128,
sizeof(*crypto_info_aes_gcm_128));
@@ -224,6 +222,7 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
struct tls_context *ctx = tls_get_ctx(sk);
struct tls_crypto_info *crypto_info;
bool allocated_tls_ctx = false;
+ struct proto *prot = NULL;
if (!optval || (optlen < sizeof(*crypto_info))) {
rc = -EINVAL;
@@ -267,12 +266,6 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
goto err_sk_user_data;
}
- /* currently we support only HW offload */
- if (!TLS_IS_STATE_HW(crypto_info)) {
- rc = -ENOPROTOOPT;
- goto err_crypto_info;
- }
-
/* check version */
if (crypto_info->version != TLS_1_2_VERSION) {
rc = -ENOTSUPP;
@@ -306,6 +299,12 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
if (TLS_IS_STATE_HW(crypto_info)) {
rc = tls_set_device_offload(sk, ctx);
+ prot = &tls_device_prot;
+ if (rc)
+ goto err_crypto_info;
+ } else if (TLS_IS_STATE_SW(crypto_info)) {
+ rc = tls_set_sw_offload(sk, ctx);
+ prot = &tls_sw_prot;
if (rc)
goto err_crypto_info;
}
@@ -315,8 +314,9 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
goto err_set_device_offload;
}
- /* TODO: add protection */
- sk->sk_prot = &tls_device_prot;
+ rc = 0;
+
+ sk->sk_prot = prot;
goto out;
err_set_device_offload:
@@ -337,6 +337,10 @@ static int __init tls_init(void)
tls_device_prot.sendmsg = tls_device_sendmsg;
tls_device_prot.sendpage = tls_device_sendpage;
+ tls_sw_prot = tcp_prot;
+ tls_sw_prot.sendmsg = tls_sw_sendmsg;
+ tls_sw_prot.sendpage = tls_sw_sendpage;
+
return 0;
}
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
new file mode 100644
index 0000000..4698dc7
--- /dev/null
+++ b/net/tls/tls_sw.c
@@ -0,0 +1,729 @@
+/*
+ * af_tls: TLS socket
+ *
+ * Copyright (C) 2016
+ *
+ * Original authors:
+ * Fridolin Pokorny <fridolin.pokorny@gmail.com>
+ * Nikos Mavrogiannopoulos <nmav@gnults.org>
+ * Dave Watson <davejwatson@fb.com>
+ * Lance Chao <lancerchao@fb.com>
+ *
+ * Based on RFC 5288, RFC 6347, RFC 5246, RFC 6655
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <net/tcp.h>
+#include <net/inet_common.h>
+#include <linux/highmem.h>
+#include <linux/netdevice.h>
+#include <crypto/aead.h>
+
+#include <net/tls.h>
+
+static int tls_kernel_sendpage(struct sock *sk, int flags);
+
+static inline void tls_make_aad(struct sock *sk,
+ int recv,
+ char *buf,
+ size_t size,
+ char *nonce_explicit,
+ unsigned char record_type)
+{
+ memcpy(buf, nonce_explicit, TLS_NONCE_SIZE);
+
+ buf[8] = record_type;
+ buf[9] = TLS_1_2_VERSION_MAJOR;
+ buf[10] = TLS_1_2_VERSION_MINOR;
+ buf[11] = size >> 8;
+ buf[12] = size & 0xFF;
+}
+
+static int tls_do_encryption(struct sock *sk, struct scatterlist *sgin,
+ struct scatterlist *sgout, size_t data_len,
+ struct sk_buff *skb)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ int ret;
+ unsigned int req_size = sizeof(struct aead_request) +
+ crypto_aead_reqsize(ctx->aead_send);
+ struct aead_request *aead_req;
+
+ pr_debug("tls_do_encryption %p\n", sk);
+
+ aead_req = kmalloc(req_size, GFP_ATOMIC);
+
+ if (!aead_req)
+ return -ENOMEM;
+
+ aead_request_set_tfm(aead_req, ctx->aead_send);
+ aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
+ aead_request_set_crypt(aead_req, sgin, sgout, data_len, tls_ctx->iv);
+
+ ret = crypto_aead_encrypt(aead_req);
+
+ kfree(aead_req);
+ if (ret < 0)
+ return ret;
+ tls_kernel_sendpage(sk, MSG_DONTWAIT);
+
+ return ret;
+}
+
+/* Allocates enough pages to hold the decrypted data, as well as
+ * setting ctx->sg_tx_data to the pages
+ */
+static int tls_pre_encrypt(struct sock *sk, size_t data_len)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ int i;
+ unsigned int npages;
+ size_t aligned_size;
+ size_t encrypt_len;
+ struct scatterlist *sg;
+ int ret = 0;
+ struct page *tx_pages;
+
+ encrypt_len = data_len + TLS_OVERHEAD;
+ npages = encrypt_len / PAGE_SIZE;
+ aligned_size = npages * PAGE_SIZE;
+ if (aligned_size < encrypt_len)
+ npages++;
+
+ ctx->order_npages = order_base_2(npages);
+ WARN_ON(ctx->order_npages < 0 || ctx->order_npages > 3);
+ /* The first entry in sg_tx_data is AAD so skip it */
+ sg_init_table(ctx->sg_tx_data, TLS_SG_DATA_SIZE);
+ sg_set_buf(&ctx->sg_tx_data[0], ctx->aad_send, sizeof(ctx->aad_send));
+ tx_pages = alloc_pages(GFP_KERNEL | __GFP_COMP,
+ ctx->order_npages);
+ if (!tx_pages) {
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ sg = ctx->sg_tx_data + 1;
+ /* For the first page, leave room for prepend. It will be
+ * copied into the page later
+ */
+ sg_set_page(sg, tx_pages, PAGE_SIZE - TLS_PREPEND_SIZE,
+ TLS_PREPEND_SIZE);
+ for (i = 1; i < npages; i++)
+ sg_set_page(sg + i, tx_pages + i, PAGE_SIZE, 0);
+
+ __skb_frag_set_page(&ctx->tx_frag, tx_pages);
+
+ return ret;
+}
+
+static void tls_release_tx_frag(struct sock *sk)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ struct page *tx_page = skb_frag_page(&ctx->tx_frag);
+
+ if (!tls_is_pending_open_record(tls_ctx) && tx_page) {
+ struct sk_buff *head;
+ /* Successfully sent the whole packet, account for it*/
+
+ head = skb_peek(&ctx->tx_queue);
+ skb_dequeue(&ctx->tx_queue);
+ sk->sk_wmem_queued -= ctx->wmem_len;
+ sk_mem_uncharge(sk, ctx->wmem_len);
+ ctx->wmem_len = 0;
+ kfree_skb(head);
+ ctx->unsent -= skb_frag_size(&ctx->tx_frag) - TLS_OVERHEAD;
+ tls_increment_seqno(tls_ctx->iv, sk);
+ __free_pages(tx_page,
+ ctx->order_npages);
+ __skb_frag_set_page(&ctx->tx_frag, NULL);
+ }
+ ctx->sk_write_space(sk);
+}
+
+static int tls_kernel_sendpage(struct sock *sk, int flags)
+{
+ int ret;
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+
+ skb_frag_size_add(&ctx->tx_frag, TLS_OVERHEAD);
+ ret = tls_push_frags(sk, tls_ctx, &ctx->tx_frag, 1, 0, flags);
+ if (ret >= 0)
+ tls_release_tx_frag(sk);
+ else if (ret != -EAGAIN)
+ tls_err_abort(sk);
+
+ return ret;
+}
+
+static int tls_push_zerocopy(struct sock *sk, struct scatterlist *sgin,
+ int pages, int bytes, unsigned char record_type)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ int ret;
+
+ tls_make_aad(sk, 0, ctx->aad_send, bytes, tls_ctx->iv, record_type);
+
+ sg_chain(ctx->sgaad_send, 2, sgin);
+ //sg_unmark_end(&sgin[pages - 1]);
+ sg_chain(sgin, pages + 1, ctx->sgtag_send);
+ ret = sg_nents_for_len(ctx->sgaad_send, bytes + 13 + 16);
+
+ ret = tls_pre_encrypt(sk, bytes);
+ if (ret < 0)
+ goto out;
+
+ tls_fill_prepend(tls_ctx,
+ page_address(skb_frag_page(&ctx->tx_frag)),
+ bytes, record_type);
+
+ skb_frag_size_set(&ctx->tx_frag, bytes);
+
+ ret = tls_do_encryption(sk,
+ ctx->sgaad_send,
+ ctx->sg_tx_data,
+ bytes, NULL);
+
+ if (ret < 0)
+ goto out;
+
+out:
+ if (ret < 0) {
+ sk->sk_err = EPIPE;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tls_push(struct sock *sk, unsigned char record_type)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ int bytes = min_t(int, ctx->unsent, (int)TLS_MAX_PAYLOAD_SIZE);
+ int nsg, ret = 0;
+ struct sk_buff *head = skb_peek(&ctx->tx_queue);
+
+ if (!head)
+ return 0;
+
+ bytes = min_t(int, bytes, head->len);
+
+ sg_init_table(ctx->sg_tx_data2, ARRAY_SIZE(ctx->sg_tx_data2));
+ nsg = skb_to_sgvec(head, &ctx->sg_tx_data2[0], 0, bytes);
+
+ /* The length of sg into decryption must not be over
+ * ALG_MAX_PAGES. The aad takes the first sg, so the payload
+ * must be less than ALG_MAX_PAGES - 1
+ */
+ if (nsg > ALG_MAX_PAGES - 1) {
+ ret = -EBADMSG;
+ goto out;
+ }
+
+ tls_make_aad(sk, 0, ctx->aad_send, bytes, tls_ctx->iv, record_type);
+
+ sg_chain(ctx->sgaad_send, 2, ctx->sg_tx_data2);
+ sg_chain(ctx->sg_tx_data2,
+ nsg + 1,
+ ctx->sgtag_send);
+
+ ret = tls_pre_encrypt(sk, bytes);
+ if (ret < 0)
+ goto out;
+
+ tls_fill_prepend(tls_ctx,
+ page_address(skb_frag_page(&ctx->tx_frag)),
+ bytes, record_type);
+
+ skb_frag_size_set(&ctx->tx_frag, bytes);
+ tls_ctx->pending_offset = 0;
+ head->sk = sk;
+
+ ret = tls_do_encryption(sk,
+ ctx->sgaad_send,
+ ctx->sg_tx_data,
+ bytes, head);
+
+ if (ret < 0)
+ goto out;
+
+out:
+ if (ret < 0) {
+ sk->sk_err = EPIPE;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int zerocopy_from_iter(struct iov_iter *from,
+ struct scatterlist *sg, int *bytes)
+{
+ //int len = iov_iter_count(from);
+ int n = 0;
+
+ if (bytes)
+ *bytes = 0;
+
+ //TODO pass in number of pages
+ while (iov_iter_count(from) && n < MAX_SKB_FRAGS - 1) {
+ struct page *pages[MAX_SKB_FRAGS];
+ size_t start;
+ ssize_t copied;
+ int j = 0;
+
+ if (bytes && *bytes >= TLS_MAX_PAYLOAD_SIZE)
+ break;
+
+ copied = iov_iter_get_pages(from, pages, TLS_MAX_PAYLOAD_SIZE,
+ MAX_SKB_FRAGS - n, &start);
+ if (bytes)
+ *bytes += copied;
+ if (copied < 0)
+ return -EFAULT;
+
+ iov_iter_advance(from, copied);
+
+ while (copied) {
+ int size = min_t(int, copied, PAGE_SIZE - start);
+
+ sg_set_page(&sg[n], pages[j], size, start);
+ start = 0;
+ copied -= size;
+ j++;
+ n++;
+ }
+ }
+ return n;
+}
+
+int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ int ret = 0;
+ long timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
+ bool eor = !(msg->msg_flags & MSG_MORE);
+ struct sk_buff *skb = NULL;
+ size_t copy, copied = 0;
+ unsigned char record_type = TLS_RECORD_TYPE_DATA;
+
+ lock_sock(sk);
+
+ if (msg->msg_flags & MSG_OOB) {
+ if (!eor || ctx->unsent) {
+ ret = -EINVAL;
+ goto send_end;
+ }
+
+ ret = copy_from_iter(&record_type, 1, &msg->msg_iter);
+ if (ret != 1) {
+ return -EFAULT;
+ goto send_end;
+ }
+ }
+
+ while (msg_data_left(msg)) {
+ bool merge = true;
+ int i;
+ struct page_frag *pfrag;
+
+ if (sk->sk_err)
+ goto send_end;
+ if (!sk_stream_memory_free(sk))
+ goto wait_for_memory;
+
+ skb = skb_peek_tail(&ctx->tx_queue);
+ // Try for zerocopy
+ if (!skb && !skb_frag_page(&ctx->tx_frag) && eor) {
+ int pages;
+ int err;
+ // TODO can send partial pages?
+ int page_count = iov_iter_npages(&msg->msg_iter,
+ ALG_MAX_PAGES);
+ struct scatterlist sgin[ALG_MAX_PAGES + 1];
+ int bytes;
+
+ sg_init_table(sgin, ALG_MAX_PAGES + 1);
+
+ if (page_count >= ALG_MAX_PAGES)
+ goto reg_send;
+
+ // TODO check pages?
+ err = zerocopy_from_iter(&msg->msg_iter, &sgin[0],
+ &bytes);
+ pages = err;
+ ctx->unsent += bytes;
+ if (err < 0)
+ goto send_end;
+
+ // Try to send msg
+ tls_push_zerocopy(sk, sgin, pages, bytes, record_type);
+ for (; pages > 0; pages--)
+ put_page(sg_page(&sgin[pages - 1]));
+ if (err < 0) {
+ tls_err_abort(sk);
+ goto send_end;
+ }
+ continue;
+ }
+
+reg_send:
+ while (!skb) {
+ skb = alloc_skb(0, sk->sk_allocation);
+ if (skb)
+ __skb_queue_tail(&ctx->tx_queue, skb);
+ }
+
+ i = skb_shinfo(skb)->nr_frags;
+ pfrag = sk_page_frag(sk);
+
+ if (!sk_page_frag_refill(sk, pfrag))
+ goto wait_for_memory;
+
+ if (!skb_can_coalesce(skb, i, pfrag->page,
+ pfrag->offset)) {
+ if (i == ALG_MAX_PAGES) {
+ struct sk_buff *tskb;
+
+ tskb = alloc_skb(0, sk->sk_allocation);
+ if (!tskb)
+ goto wait_for_memory;
+
+ if (skb)
+ skb->next = tskb;
+ else
+ __skb_queue_tail(&ctx->tx_queue,
+ tskb);
+
+ skb = tskb;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ continue;
+ }
+ merge = false;
+ }
+
+ copy = min_t(int, msg_data_left(msg),
+ pfrag->size - pfrag->offset);
+ copy = min_t(int, copy, TLS_MAX_PAYLOAD_SIZE - ctx->unsent);
+
+ if (!sk_wmem_schedule(sk, copy))
+ goto wait_for_memory;
+
+ ret = skb_copy_to_page_nocache(sk, &msg->msg_iter, skb,
+ pfrag->page,
+ pfrag->offset,
+ copy);
+ ctx->wmem_len += copy;
+ if (ret)
+ goto send_end;
+
+ /* Update the skb. */
+ if (merge) {
+ skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
+ } else {
+ skb_fill_page_desc(skb, i, pfrag->page,
+ pfrag->offset, copy);
+ get_page(pfrag->page);
+ }
+
+ pfrag->offset += copy;
+ copied += copy;
+ ctx->unsent += copy;
+
+ if (ctx->unsent >= TLS_MAX_PAYLOAD_SIZE) {
+ ret = tls_push(sk, record_type);
+ if (ret)
+ goto send_end;
+ }
+
+ continue;
+
+wait_for_memory:
+ ret = tls_push(sk, record_type);
+ if (ret)
+ goto send_end;
+//push_wait:
+ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ ret = sk_stream_wait_memory(sk, &timeo);
+ if (ret)
+ goto send_end;
+ }
+
+ if (eor)
+ ret = tls_push(sk, record_type);
+
+send_end:
+ ret = sk_stream_error(sk, msg->msg_flags, ret);
+
+ /* make sure we wake any epoll edge trigger waiter */
+ if (unlikely(skb_queue_len(&ctx->tx_queue) == 0 && ret == -EAGAIN))
+ sk->sk_write_space(sk);
+
+ release_sock(sk);
+ return ret < 0 ? ret : size;
+}
+
+void tls_sw_sk_destruct(struct sock *sk)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ struct page *tx_page = skb_frag_page(&ctx->tx_frag);
+
+ crypto_free_aead(ctx->aead_send);
+
+ if (tx_page)
+ __free_pages(tx_page, ctx->order_npages);
+
+ skb_queue_purge(&ctx->tx_queue);
+ tls_sk_destruct(sk, tls_ctx);
+}
+
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
+{
+ char keyval[TLS_CIPHER_AES_GCM_128_KEY_SIZE +
+ TLS_CIPHER_AES_GCM_128_SALT_SIZE];
+ struct tls_crypto_info *crypto_info;
+ struct tls_crypto_info_aes_gcm_128 *gcm_128_info;
+ struct tls_sw_context *sw_ctx;
+ u16 nonece_size, tag_size, iv_size;
+ char *iv;
+ int rc = 0;
+
+ if (!ctx) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (ctx->priv_ctx) {
+ rc = -EEXIST;
+ goto out;
+ }
+
+ sw_ctx = kzalloc(sizeof(*sw_ctx), GFP_KERNEL);
+ if (!sw_ctx) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ ctx->priv_ctx = (struct tls_offload_context *)sw_ctx;
+
+ crypto_info = &ctx->crypto_send;
+ switch (crypto_info->cipher_type) {
+ case TLS_CIPHER_AES_GCM_128: {
+ nonece_size = TLS_CIPHER_AES_GCM_128_IV_SIZE;
+ tag_size = TLS_CIPHER_AES_GCM_128_TAG_SIZE;
+ iv_size = TLS_CIPHER_AES_GCM_128_IV_SIZE;
+ iv = ((struct tls_crypto_info_aes_gcm_128 *)crypto_info)->iv;
+ gcm_128_info =
+ (struct tls_crypto_info_aes_gcm_128 *)crypto_info;
+ break;
+ }
+ default:
+ rc = -EINVAL;
+ goto out;
+ }
+
+ ctx->prepand_size = TLS_HEADER_SIZE + nonece_size;
+ ctx->tag_size = tag_size;
+ ctx->iv_size = iv_size;
+ ctx->iv = kmalloc(iv_size, GFP_KERNEL);
+ if (!ctx->iv) {
+ rc = ENOMEM;
+ goto out;
+ }
+ memcpy(ctx->iv, iv, iv_size);
+
+ /* Preallocation for sending
+ * scatterlist: AAD | data | TAG (for crypto API)
+ * vec: HEADER | data | TAG
+ */
+ sg_init_table(sw_ctx->sg_tx_data, TLS_SG_DATA_SIZE);
+ sg_set_buf(&sw_ctx->sg_tx_data[0], sw_ctx->aad_send,
+ sizeof(sw_ctx->aad_send));
+
+ sg_set_buf(sw_ctx->sg_tx_data + TLS_SG_DATA_SIZE - 2,
+ sw_ctx->tag_send, sizeof(sw_ctx->tag_send));
+ sg_mark_end(sw_ctx->sg_tx_data + TLS_SG_DATA_SIZE - 1);
+
+ sg_init_table(sw_ctx->sgaad_send, 2);
+ sg_init_table(sw_ctx->sgtag_send, 2);
+
+ sg_set_buf(&sw_ctx->sgaad_send[0], sw_ctx->aad_send,
+ sizeof(sw_ctx->aad_send));
+ /* chaining to tag is performed on actual data size when sending */
+ sg_set_buf(&sw_ctx->sgtag_send[0], sw_ctx->tag_send,
+ sizeof(sw_ctx->tag_send));
+
+ sg_unmark_end(&sw_ctx->sgaad_send[1]);
+
+ if (!sw_ctx->aead_send) {
+ sw_ctx->aead_send =
+ crypto_alloc_aead("rfc5288(gcm(aes))",
+ CRYPTO_ALG_INTERNAL, 0);
+ if (IS_ERR(sw_ctx->aead_send)) {
+ rc = PTR_ERR(sw_ctx->aead_send);
+ sw_ctx->aead_send = NULL;
+ pr_err("bind fail\n"); // TODO
+ goto out;
+ }
+ }
+
+ sk->sk_destruct = tls_sw_sk_destruct;
+ sw_ctx->sk_write_space = ctx->sk_write_space;
+ ctx->sk_write_space = tls_release_tx_frag;
+
+ skb_queue_head_init(&sw_ctx->tx_queue);
+ sw_ctx->sk = sk;
+
+ memcpy(keyval, gcm_128_info->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
+ memcpy(keyval + TLS_CIPHER_AES_GCM_128_KEY_SIZE, gcm_128_info->salt,
+ TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+
+ rc = crypto_aead_setkey(sw_ctx->aead_send, keyval,
+ TLS_CIPHER_AES_GCM_128_KEY_SIZE +
+ TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+ if (rc)
+ goto out;
+
+ rc = crypto_aead_setauthsize(sw_ctx->aead_send, TLS_TAG_SIZE);
+ if (rc)
+ goto out;
+
+out:
+ return rc;
+}
+
+int tls_sw_sendpage(struct sock *sk, struct page *page,
+ int offset, size_t size, int flags)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
+ int ret = 0, i;
+ long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+ bool eor;
+ struct sk_buff *skb = NULL;
+ size_t queued = 0;
+ unsigned char record_type = TLS_RECORD_TYPE_DATA;
+
+ if (flags & MSG_SENDPAGE_NOTLAST)
+ flags |= MSG_MORE;
+
+ /* No MSG_EOR from splice, only look at MSG_MORE */
+ eor = !(flags & MSG_MORE);
+
+ lock_sock(sk);
+
+ if (flags & MSG_OOB) {
+ ret = -ENOTSUPP;
+ goto sendpage_end;
+ }
+ sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
+
+ /* Call the sk_stream functions to manage the sndbuf mem. */
+ while (size > 0) {
+ size_t send_size = min(size, TLS_MAX_PAYLOAD_SIZE);
+
+ if (!sk_stream_memory_free(sk) ||
+ (ctx->unsent + send_size > TLS_MAX_PAYLOAD_SIZE)) {
+ ret = tls_push(sk, record_type);
+ if (ret)
+ goto sendpage_end;
+ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ ret = sk_stream_wait_memory(sk, &timeo);
+ if (ret)
+ goto sendpage_end;
+ }
+
+ if (sk->sk_err)
+ goto sendpage_end;
+
+ skb = skb_peek_tail(&ctx->tx_queue);
+ if (skb) {
+ i = skb_shinfo(skb)->nr_frags;
+
+ if (skb_can_coalesce(skb, i, page, offset)) {
+ skb_frag_size_add(
+ &skb_shinfo(skb)->frags[i - 1],
+ send_size);
+ skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
+ goto coalesced;
+ }
+
+ if (i >= ALG_MAX_PAGES) {
+ struct sk_buff *tskb;
+
+ tskb = alloc_skb(0, sk->sk_allocation);
+ while (!tskb) {
+ ret = tls_push(sk, record_type);
+ if (ret)
+ goto sendpage_end;
+ set_bit(SOCK_NOSPACE,
+ &sk->sk_socket->flags);
+ ret = sk_stream_wait_memory(sk, &timeo);
+ if (ret)
+ goto sendpage_end;
+
+ tskb = alloc_skb(0, sk->sk_allocation);
+ }
+
+ if (skb)
+ skb->next = tskb;
+ else
+ __skb_queue_tail(&ctx->tx_queue,
+ tskb);
+ skb = tskb;
+ i = 0;
+ }
+ } else {
+ skb = alloc_skb(0, sk->sk_allocation);
+ __skb_queue_tail(&ctx->tx_queue, skb);
+ i = 0;
+ }
+
+ get_page(page);
+ skb_fill_page_desc(skb, i, page, offset, send_size);
+ skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
+
+coalesced:
+ skb->len += send_size;
+ skb->data_len += send_size;
+ skb->truesize += send_size;
+ sk->sk_wmem_queued += send_size;
+ ctx->wmem_len += send_size;
+ sk_mem_charge(sk, send_size);
+ ctx->unsent += send_size;
+ queued += send_size;
+ offset += queued;
+ size -= send_size;
+
+ if (eor || ctx->unsent >= TLS_MAX_PAYLOAD_SIZE) {
+ ret = tls_push(sk, record_type);
+ if (ret)
+ goto sendpage_end;
+ }
+ }
+
+ if (eor || ctx->unsent >= TLS_MAX_PAYLOAD_SIZE)
+ ret = tls_push(sk, record_type);
+
+sendpage_end:
+ ret = sk_stream_error(sk, flags, ret);
+
+ if (ret < 0)
+ ret = sk_stream_error(sk, flags, ret);
+
+ release_sock(sk);
+
+ return ret < 0 ? ret : queued;
+}
--
2.7.4
^ permalink raw reply related
* [RFC TLS Offload Support 08/15] mlx/tls: Hardware interface
From: Aviad Yehezkel @ 2017-03-28 13:26 UTC (permalink / raw)
To: davem, aviadye, ilyal, borisp, davejwatson, netdev
Cc: matanb, liranl, haggaie, tom, herbert, nmav, fridolin.pokorny,
ilant, kliteyn, linux-crypto, saeedm, aviadye
In-Reply-To: <1490707592-1430-1-git-send-email-aviadye@mellanox.com>
From: Ilya Lesokhin <ilyal@mellanox.com>
Implement the hardware interface to set up TLS offload.
Signed-off-by: Guy Shapiro <guysh@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
---
.../ethernet/mellanox/accelerator/tls/tls_cmds.h | 112 ++++++
.../net/ethernet/mellanox/accelerator/tls/tls_hw.c | 429 +++++++++++++++++++++
.../net/ethernet/mellanox/accelerator/tls/tls_hw.h | 49 +++
3 files changed, 590 insertions(+)
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/tls_cmds.h
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.c
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.h
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/tls_cmds.h b/drivers/net/ethernet/mellanox/accelerator/tls/tls_cmds.h
new file mode 100644
index 0000000..8916f00
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/tls_cmds.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef MLX_TLS_CMDS_H
+#define MLX_TLS_CMDS_H
+
+#define MLX_TLS_SADB_RDMA
+
+enum fpga_cmds {
+ CMD_SETUP_STREAM = 1,
+ CMD_TEARDOWN_STREAM = 2,
+};
+
+enum fpga_response {
+ EVENT_SETUP_STREAM_RESPONSE = 0x81,
+};
+
+#define TLS_TCP_IP_PROTO BIT(3) /* 0 - UDP; 1 - TCP */
+#define TLS_TCP_INIT BIT(2) /* 1 - Initialized */
+#define TLS_TCP_VALID BIT(1) /* 1 - Valid */
+#define TLS_TCP_IPV6 BIT(0) /* 0 - IPv4;1 - IPv6 */
+
+struct tls_cntx_tcp {
+ __be32 ip_da[4];
+ __be32 flags;
+ __be16 src_port;
+ __be16 dst_port;
+ u32 pad;
+ __be32 tcp_sn;
+ __be32 ip_sa[4];
+} __packed;
+
+struct tls_cntx_crypto {
+ u8 enc_state[16];
+ u8 enc_key[32];
+} __packed;
+
+struct tls_cntx_record {
+ u8 rcd_sn[8];
+ u16 pad;
+ u8 flags;
+ u8 rcd_type_ver;
+ __be32 rcd_tcp_sn_nxt;
+ __be32 rcd_implicit_iv;
+ u8 rcd_residue[32];
+} __packed;
+
+#define TLS_RCD_ENC_AES_GCM128 (0)
+#define TLS_RCD_ENC_AES_GCM256 (BIT(4))
+#define TLS_RCD_AUTH_AES_GCM128 (0)
+#define TLS_RCD_AUTH_AES_GCM256 (1)
+
+#define TLS_RCD_VER_1_2 (3)
+
+struct tls_cntx {
+ struct tls_cntx_tcp tcp;
+ struct tls_cntx_record rcd;
+ struct tls_cntx_crypto crypto;
+} __packed;
+
+struct setup_stream_cmd {
+ u8 cmd;
+ __be32 stream_id;
+ struct tls_cntx tls;
+} __packed;
+
+struct teardown_stream_cmd {
+ u8 cmd;
+ __be32 stream_id;
+} __packed;
+
+struct generic_event {
+ __be32 opcode;
+ __be32 stream_id;
+};
+
+struct setup_stream_response {
+ __be32 opcode;
+ __be32 stream_id;
+};
+
+#endif /* MLX_TLS_CMDS_H */
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.c b/drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.c
new file mode 100644
index 0000000..3a02f1e
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include "tls_hw.h"
+#include "tls_cmds.h"
+#include <linux/inetdevice.h>
+#include <linux/socket.h>
+
+static void mlx_tls_del_work(struct work_struct *w);
+
+static DEFINE_SPINLOCK(tls_del_lock);
+static DECLARE_WORK(tls_del_work, mlx_tls_del_work);
+static LIST_HEAD(tls_del_list);
+
+static int build_ctx(struct tls_crypto_info_aes_gcm_128 *crypto_info,
+ u32 expectedSN,
+ unsigned short skc_family,
+ struct inet_sock *inet,
+ struct tls_cntx *tls)
+{
+ if (skc_family != PF_INET6) {
+ tls->tcp.ip_sa[3] = inet->inet_rcv_saddr;
+ tls->tcp.ip_da[3] = inet->inet_daddr;
+ } else {
+#if IS_ENABLED(CONFIG_IPV6)
+ memcpy((void *)tls->tcp.ip_sa,
+ inet->pinet6->saddr.in6_u.u6_addr8, 16);
+ memcpy((void *)tls->tcp.ip_da,
+ inet->pinet6->daddr_cache->in6_u.u6_addr8, 16);
+#endif
+ pr_err("IPv6 isn't supported yet\n");
+ return -EINVAL;
+ }
+ tls->tcp.flags |= htonl(TLS_TCP_IP_PROTO);
+ tls->tcp.flags |= htonl(TLS_TCP_VALID);
+ tls->tcp.flags |= htonl(TLS_TCP_INIT);
+ tls->tcp.src_port = inet->inet_sport;
+ tls->tcp.dst_port = inet->inet_dport;
+ tls->tcp.tcp_sn = htonl(expectedSN);
+
+ tls->rcd.rcd_tcp_sn_nxt = htonl(expectedSN);
+// tls->rcd.enc_auth_mode |= TLS_RCD_AUTH_AES_GCM128;
+// tls->rcd.enc_auth_mode |= TLS_RCD_ENC_AES_GCM128;
+ tls->rcd.rcd_type_ver |= TLS_RCD_VER_1_2 << 4;
+
+ memcpy(&tls->rcd.rcd_implicit_iv, crypto_info->salt,
+ TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+ memcpy(tls->rcd.rcd_sn, crypto_info->iv,
+ TLS_CIPHER_AES_GCM_128_IV_SIZE);
+ memcpy(tls->crypto.enc_key, crypto_info->key,
+ TLS_CIPHER_AES_GCM_128_KEY_SIZE);
+ memcpy(tls->crypto.enc_key + TLS_CIPHER_AES_GCM_128_KEY_SIZE,
+ crypto_info->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
+
+ return 0;
+}
+
+#ifdef MLX_TLS_SADB_RDMA
+static int send_teardown_cmd(struct mlx_tls_dev *dev, __be32 swid)
+{
+ struct mlx_accel_core_dma_buf *buf;
+ struct teardown_stream_cmd *cmd;
+ int size = sizeof(*buf) + sizeof(*cmd);
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf->data = buf + 1;
+ buf->data_size = sizeof(*cmd);
+
+ cmd = (struct teardown_stream_cmd *)buf->data;
+ cmd->cmd = CMD_TEARDOWN_STREAM;
+ cmd->stream_id = swid;
+
+ return mlx_accel_core_sendmsg(dev->conn, buf);
+}
+#endif
+
+static void mlx_tls_del_work(struct work_struct *w)
+{
+ struct mlx_tls_offload_context *context;
+ struct mlx_tls_dev *dev;
+
+ spin_lock_irq(&tls_del_lock);
+ while (true) {
+ context =
+ list_first_entry_or_null(&tls_del_list,
+ struct mlx_tls_offload_context,
+ tls_del_list);
+ spin_unlock_irq(&tls_del_lock);
+ if (!context)
+ break;
+
+ dev = mlx_tls_find_dev_by_netdev(context->netdev);
+
+#ifdef MLX_TLS_SADB_RDMA
+ if (send_teardown_cmd(dev, context->swid)) {
+ /* try again later */
+ schedule_work(w);
+ break;
+ }
+#endif
+
+ ida_simple_remove(&dev->swid_ida, ntohl(context->swid));
+
+ module_put(THIS_MODULE);
+
+ spin_lock_irq(&tls_del_lock);
+ list_del(&context->tls_del_list);
+ kfree(context);
+ }
+}
+
+void mlx_tls_hw_stop_cmd(struct net_device *netdev,
+ struct mlx_tls_offload_context *context)
+{
+ unsigned long flags;
+
+ pr_info("mlx_tls_hw_stop_cmd\n");
+ spin_lock_irqsave(&tls_del_lock, flags);
+ list_add_tail(&context->tls_del_list, &tls_del_list);
+ context->netdev = netdev;
+ schedule_work(&tls_del_work);
+ spin_unlock_irqrestore(&tls_del_lock, flags);
+}
+
+#ifndef MLX_TLS_SADB_RDMA
+#include "../core/accel_core.h"
+
+#define GW_CTRL_RW htonl(BIT(29))
+#define GW_CTRL_BUSY htonl(BIT(30))
+#define GW_CTRL_LOCK htonl(BIT(31))
+
+#define GW_CTRL_ADDR_SHIFT 26
+
+static int mlx_accel_gw_waitfor(struct mlx5_core_dev *dev, u64 addr, u32 mask,
+ u32 value)
+{
+ int ret = 0;
+ u32 gw_value;
+ int try = 0;
+ static const int max_tries = 100;
+
+ while (true) {
+ pr_debug("Waiting for %x/%x. Try %d\n", value, mask, try);
+ ret = mlx5_fpga_access_reg(dev, sizeof(u32), addr,
+ (u8 *)&gw_value, false);
+ if (ret)
+ return ret;
+
+ pr_debug("Value is %x\n", gw_value);
+ if ((gw_value & mask) == value)
+ break; //lock is taken automatically if it was 0.
+ try++;
+ if (try >= max_tries) {
+ pr_debug("Timeout waiting for %x/%x at %llx. Value is %x after %d tries\n",
+ value, mask, addr, gw_value, try);
+ return -EBUSY;
+ }
+ usleep_range(10, 100);
+ };
+ return 0;
+}
+
+static int mlx_accel_gw_lock(struct mlx5_core_dev *dev, u64 addr)
+{
+ return mlx_accel_gw_waitfor(dev, addr, GW_CTRL_LOCK, 0);
+}
+
+static int mlx_accel_gw_unlock(struct mlx5_core_dev *dev, u64 addr)
+{
+ u32 gw_value;
+ int ret;
+
+ pr_debug("Unlocking %llx\n", addr);
+ ret = mlx5_fpga_access_reg(dev, sizeof(u32), addr,
+ (u8 *)&gw_value, false);
+ if (ret)
+ return ret;
+
+ if ((gw_value & GW_CTRL_LOCK) != GW_CTRL_LOCK)
+ pr_warn("Lock expected when unlocking, but not held for device %s addr %llx\n",
+ dev->priv.name, addr);
+
+ pr_debug("Old value %x\n", gw_value);
+ gw_value &= ~GW_CTRL_LOCK;
+ pr_debug("New value %x\n", gw_value);
+ ret = mlx5_fpga_access_reg(dev, sizeof(u32), addr,
+ (u8 *)&gw_value, true);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static int mlx_accel_gw_op(struct mlx5_core_dev *dev, u64 addr,
+ unsigned int index, bool write)
+{
+ u32 gw_value;
+ int ret;
+
+ if (index >= 8)
+ pr_warn("Trying to access index %u out of range for GW at %llx\n",
+ index, addr);
+
+ pr_debug("Performing op %u at %llx\n", write, addr);
+ ret = mlx5_fpga_access_reg(dev, sizeof(u32), addr,
+ (u8 *)&gw_value, false);
+ if (ret)
+ return ret;
+
+ pr_debug("Old op value is %x\n", gw_value);
+ if ((gw_value & GW_CTRL_LOCK) != GW_CTRL_LOCK)
+ pr_warn("Lock expected for %s, but not held for device %s addr %llx\n",
+ write ? "write" : "read", dev->priv.name, addr);
+
+ gw_value &= htonl(~(7 << GW_CTRL_ADDR_SHIFT));
+ gw_value |= htonl(index << GW_CTRL_ADDR_SHIFT);
+ if (write)
+ gw_value &= ~GW_CTRL_RW;
+ else
+ gw_value |= GW_CTRL_RW;
+
+ gw_value |= GW_CTRL_BUSY;
+
+ pr_debug("New op value is %x\n", gw_value);
+ ret = mlx5_fpga_access_reg(dev, sizeof(u32), addr,
+ (u8 *)&gw_value, true);
+ if (ret)
+ return ret;
+
+ return mlx_accel_gw_waitfor(dev, addr, GW_CTRL_BUSY, 0);
+}
+
+static int mlx_accel_gw_write(struct mlx5_core_dev *dev, u64 addr,
+ unsigned int index)
+{
+ return mlx_accel_gw_op(dev, addr, index, true);
+}
+
+#define CRSPACE_TCP_BASE 0x0
+#define CRSPACE_TCP_OFFSET 0x10
+#define CRSPACE_RECORD_BASE 0x100
+#define CRSPACE_RECORD_OFFSET 0xc
+#define CRSPACE_CRYPTO_BASE 0x180
+#define CRSPACE_CRYPTO_OFFSET 0x10
+
+static void write_context(struct mlx5_core_dev *dev, void *ctx,
+ size_t size, u64 base, u32 offset) {
+ mlx_accel_gw_lock(dev, base);
+ mlx5_fpga_access_reg(dev, size, base + offset, ctx, true);
+ mlx_accel_gw_write(dev, base, 0);
+ mlx_accel_gw_unlock(dev, base);
+}
+
+int mlx_tls_hw_start_cmd(struct mlx_tls_dev *dev, struct sock *sk,
+ struct tls_crypto_info_aes_gcm_128 *crypto_info,
+ struct mlx_tls_offload_context *context)
+{
+ struct tls_cntx tls;
+ int ret;
+ struct inet_sock *inet = inet_sk(sk);
+ u32 expectedSN = context->context.expectedSN;
+
+ memset(&tls, 0, sizeof(tls));
+
+ ret = build_ctx(crypto_info,
+ expectedSN,
+ sk->sk_family,
+ inet,
+ &tls);
+ if (ret)
+ return ret;
+
+ write_context(dev->accel_device->hw_dev,
+ &tls.rcd,
+ sizeof(tls.rcd),
+ CRSPACE_RECORD_BASE,
+ CRSPACE_RECORD_OFFSET);
+
+ write_context(dev->accel_device->hw_dev,
+ &tls.crypto,
+ sizeof(tls.crypto),
+ CRSPACE_CRYPTO_BASE,
+ CRSPACE_CRYPTO_OFFSET);
+
+ write_context(dev->accel_device->hw_dev,
+ &tls.tcp,
+ sizeof(tls.tcp),
+ CRSPACE_TCP_BASE,
+ CRSPACE_TCP_OFFSET);
+ return 0;
+}
+
+#else /* MLX_TLS_SADB_RDMA */
+static DEFINE_SPINLOCK(setup_stream_lock);
+static LIST_HEAD(setup_stream_list);
+struct setup_stream_t {
+ struct list_head list;
+ __be32 swid;
+ struct completion x;
+};
+
+static void mlx_accel_core_kfree_complete(struct mlx_accel_core_conn *conn,
+ struct mlx_accel_core_dma_buf *buf,
+ struct ib_wc *wc)
+{
+ kfree(buf);
+}
+
+int mlx_tls_hw_start_cmd(struct mlx_tls_dev *dev,
+ struct sock *sk,
+ struct tls_crypto_info_aes_gcm_128 *crypto_info,
+ struct mlx_tls_offload_context *context)
+{
+ struct mlx_accel_core_dma_buf *buf;
+ struct setup_stream_cmd *cmd;
+ struct inet_sock *inet = inet_sk(sk);
+ u32 expectedSN = context->context.expectedSN;
+ int ret;
+ int size = sizeof(*buf) + sizeof(*cmd);
+ struct setup_stream_t ss;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf->data = buf + 1;
+ buf->data_size = sizeof(*cmd);
+ buf->complete = mlx_accel_core_kfree_complete;
+
+ cmd = (struct setup_stream_cmd *)buf->data;
+ cmd->cmd = CMD_SETUP_STREAM;
+ cmd->stream_id = context->swid;
+
+ ret = build_ctx(crypto_info,
+ expectedSN,
+ sk->sk_family,
+ inet,
+ &cmd->tls);
+ if (ret) {
+ kfree(buf);
+ return ret;
+ }
+
+ ss.swid = context->swid;
+ init_completion(&ss.x);
+ spin_lock_irq(&setup_stream_lock);
+ list_add_tail(&ss.list, &setup_stream_list);
+ spin_unlock_irq(&setup_stream_lock);
+
+ mlx_accel_core_sendmsg(dev->conn, buf);
+ ret = wait_for_completion_killable(&ss.x);
+ if (ret) {
+ spin_lock_irq(&setup_stream_lock);
+ list_del(&ss.list);
+ spin_unlock_irq(&setup_stream_lock);
+ }
+
+ return ret;
+}
+
+static void handle_setup_stream_response(__be32 swid)
+{
+ struct setup_stream_t *ss;
+ unsigned long flags;
+ int found = 0;
+
+ spin_lock_irqsave(&setup_stream_lock, flags);
+ list_for_each_entry(ss, &setup_stream_list, list) {
+ if (ss->swid == swid) {
+ list_del(&ss->list);
+ complete(&ss->x);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&setup_stream_lock, flags);
+
+ if (!found)
+ pr_err("Got unexpected setup stream response swid = %u\n",
+ ntohl(swid));
+}
+
+void mlx_tls_hw_qp_recv_cb(void *cb_arg,
+ struct mlx_accel_core_dma_buf *buf)
+{
+ struct generic_event *ev = (struct generic_event *)buf->data;
+
+ switch (ev->opcode) {
+ case htonl(EVENT_SETUP_STREAM_RESPONSE):
+ handle_setup_stream_response(ev->stream_id);
+ break;
+ default:
+ pr_warn("mlx_tls_hw_qp_recv_cb: unexpected event opcode %u\n",
+ ntohl(ev->opcode));
+ }
+}
+
+#endif /* MLX_TLS_SADB_RDMA */
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.h b/drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.h
new file mode 100644
index 0000000..5a11d30
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/tls_hw.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#ifndef __TLS_HW_H__
+#define __TLS_HW_H__
+
+#include "tls.h"
+
+int mlx_tls_hw_init(void);
+void mlx_tls_hw_deinit(void);
+
+int mlx_tls_hw_start_cmd(struct mlx_tls_dev *dev, struct sock *sk,
+ struct tls_crypto_info_aes_gcm_128 *crypto_info,
+ struct mlx_tls_offload_context *context);
+void mlx_tls_hw_stop_cmd(struct net_device *netdev,
+ struct mlx_tls_offload_context *context);
+void mlx_tls_hw_qp_recv_cb(void *cb_arg,
+ struct mlx_accel_core_dma_buf *buf);
+
+#endif /* __TLS_HW_H__ */
--
2.7.4
^ permalink raw reply related
* [RFC TLS Offload Support 11/15] mlx/tls: TLS offload driver Add the main module entrypoints and tie the module into the build system
From: Aviad Yehezkel @ 2017-03-28 13:26 UTC (permalink / raw)
To: davem, aviadye, ilyal, borisp, davejwatson, netdev
Cc: matanb, liranl, haggaie, tom, herbert, nmav, fridolin.pokorny,
ilant, kliteyn, linux-crypto, saeedm, aviadye
In-Reply-To: <1490707592-1430-1-git-send-email-aviadye@mellanox.com>
From: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Guy Shapiro <guysh@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
---
drivers/net/ethernet/mellanox/Kconfig | 1 +
drivers/net/ethernet/mellanox/Makefile | 1 +
.../net/ethernet/mellanox/accelerator/tls/Kconfig | 11 ++++
.../net/ethernet/mellanox/accelerator/tls/Makefile | 4 ++
.../ethernet/mellanox/accelerator/tls/tls_main.c | 77 ++++++++++++++++++++++
5 files changed, 94 insertions(+)
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/Kconfig
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/Makefile
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/tls_main.c
diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig
index 1b3ca6a..f270b76 100644
--- a/drivers/net/ethernet/mellanox/Kconfig
+++ b/drivers/net/ethernet/mellanox/Kconfig
@@ -21,6 +21,7 @@ source "drivers/net/ethernet/mellanox/mlx5/core/Kconfig"
source "drivers/net/ethernet/mellanox/mlxsw/Kconfig"
source "drivers/net/ethernet/mellanox/accelerator/core/Kconfig"
source "drivers/net/ethernet/mellanox/accelerator/ipsec/Kconfig"
+source "drivers/net/ethernet/mellanox/accelerator/tls/Kconfig"
source "drivers/net/ethernet/mellanox/accelerator/tools/Kconfig"
endif # NET_VENDOR_MELLANOX
diff --git a/drivers/net/ethernet/mellanox/Makefile b/drivers/net/ethernet/mellanox/Makefile
index 96a5856..fd8afc0 100644
--- a/drivers/net/ethernet/mellanox/Makefile
+++ b/drivers/net/ethernet/mellanox/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_MLX5_CORE) += mlx5/core/
obj-$(CONFIG_MLXSW_CORE) += mlxsw/
obj-$(CONFIG_MLX_ACCEL_CORE) += accelerator/core/
obj-$(CONFIG_MLX_ACCEL_IPSEC) += accelerator/ipsec/
+obj-$(CONFIG_MLX_ACCEL_TLS) += accelerator/tls/
obj-$(CONFIG_MLX_ACCEL_TOOLS) += accelerator/tools/
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/Kconfig b/drivers/net/ethernet/mellanox/accelerator/tls/Kconfig
new file mode 100644
index 0000000..d9c0733
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/Kconfig
@@ -0,0 +1,11 @@
+#
+# Mellanox tls accelerator driver configuration
+#
+
+config MLX_ACCEL_TLS
+ tristate "Mellanox Technologies TLS accelarator driver"
+ depends on MLX_ACCEL_CORE
+ default n
+ ---help---
+ TLS accelarator driver by Mellanox Technologies.
+
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/Makefile b/drivers/net/ethernet/mellanox/accelerator/tls/Makefile
new file mode 100644
index 0000000..93a7733
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MLX_ACCEL_TLS) += mlx_tls.o
+
+ccflags-y := -I$(srctree)/
+mlx_tls-y := tls_main.o tls_sysfs.o tls_hw.o tls.o
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/tls_main.c b/drivers/net/ethernet/mellanox/accelerator/tls/tls_main.c
new file mode 100644
index 0000000..85078f5
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/tls_main.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include <linux/module.h>
+
+#include "tls.h"
+
+MODULE_AUTHOR("Mellanox Technologies Advance Develop Team <adv-dev@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox Innova TLS Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+static struct mlx_accel_core_client mlx_tls_client = {
+ .name = "mlx_tls",
+ .add = mlx_tls_add_one,
+ .remove = mlx_tls_remove_one,
+};
+
+static struct notifier_block mlx_tls_netdev_notifier = {
+ .notifier_call = mlx_tls_netdev_event,
+};
+
+static int __init mlx_tls_init(void)
+{
+ int err = 0;
+
+ err = register_netdevice_notifier(&mlx_tls_netdev_notifier);
+ if (err) {
+ pr_warn("mlx_tls_init error in register_netdevice_notifier %d\n",
+ err);
+ goto out_wq;
+ }
+
+ mlx_accel_core_client_register(&mlx_tls_client);
+
+out_wq:
+ return err;
+}
+
+static void __exit mlx_tls_exit(void)
+{
+ mlx_accel_core_client_unregister(&mlx_tls_client);
+ unregister_netdevice_notifier(&mlx_tls_netdev_notifier);
+}
+
+module_init(mlx_tls_init);
+module_exit(mlx_tls_exit);
+
--
2.7.4
^ permalink raw reply related
* [RFC TLS Offload Support 02/15] tcp: export do_tcp_sendpages function
From: Aviad Yehezkel @ 2017-03-28 13:26 UTC (permalink / raw)
To: davem, aviadye, ilyal, borisp, davejwatson, netdev
Cc: matanb, liranl, haggaie, tom, herbert, nmav, fridolin.pokorny,
ilant, kliteyn, linux-crypto, saeedm, aviadye
In-Reply-To: <1490707592-1430-1-git-send-email-aviadye@mellanox.com>
We will use it via tls new code.
Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
---
include/net/tcp.h | 2 ++
net/ipv4/tcp.c | 5 +++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 207147b..3a72d4c 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -348,6 +348,8 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
int flags);
+ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
+ size_t size, int flags);
void tcp_release_cb(struct sock *sk);
void tcp_wfree(struct sk_buff *skb);
void tcp_write_timer_handler(struct sock *sk);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1149b48..302fee9 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -873,8 +873,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
return mss_now;
}
-static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
- size_t size, int flags)
+ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
+ size_t size, int flags)
{
struct tcp_sock *tp = tcp_sk(sk);
int mss_now, size_goal;
@@ -1003,6 +1003,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
}
return sk_stream_error(sk, flags, err);
}
+EXPORT_SYMBOL(do_tcp_sendpages);
int tcp_sendpage(struct sock *sk, struct page *page, int offset,
size_t size, int flags)
--
2.7.4
^ permalink raw reply related
* [PATCH] crypto: ccp - Remove redundant cpu-to-le32 macros
From: Gary R Hook @ 2017-03-28 13:58 UTC (permalink / raw)
To: linux-crypto; +Cc: thomas.lendacky, gary.hook, herbert, davem
Endianness is dealt with when the command descriptor is
copied into the command queue. Remove any occurrences of
cpu_to_le32() found elsewhere.
Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
drivers/crypto/ccp/ccp-dev-v5.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
index 5e08654..e03d06a 100644
--- a/drivers/crypto/ccp/ccp-dev-v5.c
+++ b/drivers/crypto/ccp/ccp-dev-v5.c
@@ -419,22 +419,22 @@ static int ccp5_perform_des3(struct ccp_op *op)
CCP_DES3_ENCRYPT(&function) = op->u.des3.action;
CCP_DES3_MODE(&function) = op->u.des3.mode;
CCP_DES3_TYPE(&function) = op->u.des3.type;
- CCP5_CMD_FUNCTION(&desc) = cpu_to_le32(function.raw);
+ CCP5_CMD_FUNCTION(&desc) = function.raw;
- CCP5_CMD_LEN(&desc) = cpu_to_le32(op->src.u.dma.length);
+ CCP5_CMD_LEN(&desc) = op->src.u.dma.length;
- CCP5_CMD_SRC_LO(&desc) = cpu_to_le32(ccp_addr_lo(&op->src.u.dma));
- CCP5_CMD_SRC_HI(&desc) = cpu_to_le32(ccp_addr_hi(&op->src.u.dma));
- CCP5_CMD_SRC_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SYSTEM);
+ CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(&op->src.u.dma);
+ CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(&op->src.u.dma);
+ CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM;
- CCP5_CMD_DST_LO(&desc) = cpu_to_le32(ccp_addr_lo(&op->dst.u.dma));
- CCP5_CMD_DST_HI(&desc) = cpu_to_le32(ccp_addr_hi(&op->dst.u.dma));
- CCP5_CMD_DST_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SYSTEM);
+ CCP5_CMD_DST_LO(&desc) = ccp_addr_lo(&op->dst.u.dma);
+ CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(&op->dst.u.dma);
+ CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM;
- CCP5_CMD_KEY_LO(&desc) = cpu_to_le32(lower_32_bits(key_addr));
+ CCP5_CMD_KEY_LO(&desc) = lower_32_bits(key_addr);
CCP5_CMD_KEY_HI(&desc) = 0;
- CCP5_CMD_KEY_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SB);
- CCP5_CMD_LSB_ID(&desc) = cpu_to_le32(op->sb_ctx);
+ CCP5_CMD_KEY_MEM(&desc) = CCP_MEMTYPE_SB;
+ CCP5_CMD_LSB_ID(&desc) = op->sb_ctx;
return ccp5_do_cmd(&desc, op->cmd_q);
}
^ permalink raw reply related
* Re: [PATCH 2/2] crypto: ccp - Mark driver as little-endian only
From: Gary R Hook @ 2017-03-28 14:08 UTC (permalink / raw)
To: Arnd Bergmann, Lendacky, Thomas, Hook, Gary, Herbert Xu,
David S. Miller
Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20170328095814.3734615-2-arnd@arndb.de>
Ack. Didn't reply all.... Sorry, Arnd.
There was a krobot warning about this and I submitted a patch just now.
(I thought) my mistake was (in this function) not handling the structure
elements in the same manner as other functions. My patch rectifies that.
On 03/28/2017 04:58 AM, Arnd Bergmann wrote:
> The driver causes a warning when built as big-endian:
>
> drivers/crypto/ccp/ccp-dev-v5.c: In function 'ccp5_perform_des3':
> include/uapi/linux/byteorder/big_endian.h:32:26: error: large integer
> implicitly truncated to unsigned type [-Werror=overflow]
> #define __cpu_to_le32(x) ((__force __le32)__swab32((x)))
> ^
> include/linux/byteorder/generic.h:87:21: note: in expansion of macro
> '__cpu_to_le32'
> #define cpu_to_le32 __cpu_to_le32
> ^~~~~~~~~~~~~
> drivers/crypto/ccp/ccp-dev-v5.c:436:28: note: in expansion of macro
> 'cpu_to_le32'
> CCP5_CMD_KEY_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SB);
>
> The warning is correct, doing a 32-bit byte swap on a value that gets
> assigned into a bit field cannot work, since we would only write zeroes
> in this case, regardless of the input.
Yes, this was all wrong.
> In fact, the use of bit fields in hardware defined data structures is
> not portable to start with, so until all these bit fields get replaced
> by something else, the driver cannot work on big-endian machines, and
> I'm adding an annotation here to prevent it from being selected.
This is a driver that talks to hardware, a device which, AFAIK, has no
plan to be implemented in a big endian flavor. I clearly need to be more
diligent in building with various checkers enabled. I'd prefer my fix
over your suggested refusal to compile, if that's okay.
> The CCPv3 code seems to not suffer from this problem, only v5 uses
> bitfields.
Yes, I took a different approach when I wrote the code. IMO (arguably)
more readable. Same result: words full of hardware-dependent bit patterns.
Please help me understand what I could do better.
--
This is my day job. Follow me at:
IG/Twitter/Facebook: @grhookphoto
IG/Twitter/Facebook: @grhphotographer
^ permalink raw reply
* Re: [PATCH 1/2] crypto: ccp - Reduce stack frame size with KASAN
From: Gary R Hook @ 2017-03-28 14:15 UTC (permalink / raw)
To: Arnd Bergmann, Lendacky, Thomas, Hook, Gary, Herbert Xu,
David S. Miller
Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20170328095814.3734615-1-arnd@arndb.de>
On 03/28/2017 04:58 AM, Arnd Bergmann wrote:> The newly added AES GCM
implementation uses one of the largest stack frames
> in the kernel, around 1KB on normal 64-bit kernels, and 1.6KB when
> CONFIG_KASAN
> is enabled:
>
> drivers/crypto/ccp/ccp-ops.c: In function 'ccp_run_aes_gcm_cmd':
> drivers/crypto/ccp/ccp-ops.c:851:1: error: the frame size of 1632 bytes
> is larger than 1536 bytes [-Werror=frame-larger-than=]
>
> This is problematic for multiple reasons:
>
> - The crypto functions are often used in deep call chains, e.g. behind
> mm, fs and dm layers, making it more likely to run into an actual stack
> overflow
>
> - Using this much stack space is an indicator that the code is not
> written to be as efficient as it could be.
I'm not sure I agree that A -> B, but I will certainly look into this.
> - While this goes unnoticed at the moment in mainline with the frame size
> warning being disabled when KASAN is in use, I would like to enable
> the warning again, and the current code is slightly above my arbitrary
> pick for a limit of 1536 bytes (I already did patches for every other
> driver exceeding this).
I've got my stack frame size (also) set to 1536, and would have paid
more attention
had a warning occurred due to my code.
> A more drastic refactoring of the driver might be needed to reduce the
> stack usage more substantially, but this patch is fairly simple and
> at least addresses the third one of the problems I mentioned, reducing the
> stack size by about 150 bytes and bringing it below the warning limit
> I picked.
Again, I'll devote some time to this.
> diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
> index 3a45c2af2fbd..c5ea0796a891 100644
> --- a/drivers/crypto/ccp/ccp-dev.h
> +++ b/drivers/crypto/ccp/ccp-dev.h
> @@ -432,24 +432,24 @@ struct ccp_dma_info {
> unsigned int offset;
> unsigned int length;
> enum dma_data_direction dir;
> -};
> +} __packed __aligned(4);
My gcc 4.8 doesn't understand __aligned(). Shouldn't we use
#pragma(4) here?
> struct ccp_dm_workarea {
> struct device *dev;
> struct dma_pool *dma_pool;
> - unsigned int length;
>
> u8 *address;
> struct ccp_dma_info dma;
> + unsigned int length;
> };
>
> struct ccp_sg_workarea {
> struct scatterlist *sg;
> int nents;
> + unsigned int dma_count;
>
> struct scatterlist *dma_sg;
> struct device *dma_dev;
> - unsigned int dma_count;
> enum dma_data_direction dma_dir;
>
> unsigned int sg_used;
I'm okay with rearranging, but I'm going to submit an alternative patch.
^ permalink raw reply
* Re: [RFC TLS Offload Support 05/15] tcp: Add TLS socket options for TCP sockets
From: Tom Herbert @ 2017-03-28 14:56 UTC (permalink / raw)
To: Aviad Yehezkel
Cc: David S. Miller, ilyal, borisp, Dave Watson,
Linux Kernel Network Developers, matanb, liranl, haggaie,
Herbert Xu, nmav, fridolin.pokorny, ilant, kliteyn,
Linux Crypto Mailing List, Saeed Mahameed, aviadye
In-Reply-To: <1490707592-1430-6-git-send-email-aviadye@mellanox.com>
On Tue, Mar 28, 2017 at 6:26 AM, Aviad Yehezkel <aviadye@mellanox.com> wrote:
> This patch adds TLS_TX and TLS_RX TCP socket options.
>
> Setting these socket options will change the sk->sk_prot
> operations of the TCP socket. The user is responsible to
> prevent races between calls to the previous operations
> and the new operations. After successful return, data
> sent on this socket will be encapsulated in TLS.
>
> Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
> Signed-off-by: Boris Pismenny <borisp@mellanox.com>
> Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
> ---
> include/uapi/linux/tcp.h | 2 ++
> net/ipv4/tcp.c | 32 ++++++++++++++++++++++++++++++++
> 2 files changed, 34 insertions(+)
>
> diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
> index c53de26..f9f0e29 100644
> --- a/include/uapi/linux/tcp.h
> +++ b/include/uapi/linux/tcp.h
> @@ -116,6 +116,8 @@ enum {
> #define TCP_SAVE_SYN 27 /* Record SYN headers for new connections */
> #define TCP_SAVED_SYN 28 /* Get SYN headers recorded for connection */
> #define TCP_REPAIR_WINDOW 29 /* Get/set window parameters */
> +#define TCP_TLS_TX 30
> +#define TCP_TLS_RX 31
>
> struct tcp_repair_opt {
> __u32 opt_code;
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index 302fee9..2d190e3 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -273,6 +273,7 @@
> #include <net/icmp.h>
> #include <net/inet_common.h>
> #include <net/tcp.h>
> +#include <net/tls.h>
> #include <net/xfrm.h>
> #include <net/ip.h>
> #include <net/sock.h>
> @@ -2676,6 +2677,21 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
> tp->notsent_lowat = val;
> sk->sk_write_space(sk);
> break;
> + case TCP_TLS_TX:
> + case TCP_TLS_RX: {
> + int (*fn)(struct sock *sk, int optname,
> + char __user *optval, unsigned int optlen);
> +
> + fn = symbol_get(tls_sk_attach);
> + if (!fn) {
> + err = -EINVAL;
> + break;
> + }
> +
> + err = fn(sk, optname, optval, optlen);
> + symbol_put(tls_sk_attach);
> + break;
> + }
> default:
> err = -ENOPROTOOPT;
> break;
> @@ -3064,6 +3080,22 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
> }
> return 0;
> }
> + case TCP_TLS_TX:
> + case TCP_TLS_RX: {
> + int err;
> + int (*fn)(struct sock *sk, int optname,
> + char __user *optval, int __user *optlen);
> +
> + fn = symbol_get(tls_sk_query);
> + if (!fn) {
> + err = -EINVAL;
> + break;
> + }
> +
> + err = fn(sk, optname, optval, optlen);
> + symbol_put(tls_sk_query);
> + return err;
> + }
This mechanism should be generalized. If we can do this with TLS then
there will likely be other ULPs that we might want to set on a TCP
socket. Maybe something like TCP_ULP_PUSH, TCP_ULP_POP (borrowing from
STREAMS ever so slightly :-) ). I'd also suggest that the ULPs are
indicated by a text string in the socket option argument, then have
each ULP perform a registration for their service.
> default:
> return -ENOPROTOOPT;
> }
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH 2/2] crypto: ccp - Mark driver as little-endian only
From: Arnd Bergmann @ 2017-03-28 14:59 UTC (permalink / raw)
To: Gary R Hook
Cc: Lendacky, Thomas, Hook, Gary, Herbert Xu, David S. Miller,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <f5780ea9-3479-22df-30a6-c03f40803c0d@amd.com>
On Tue, Mar 28, 2017 at 4:08 PM, Gary R Hook <ghook@amd.com> wrote:
>> In fact, the use of bit fields in hardware defined data structures is
>> not portable to start with, so until all these bit fields get replaced
>> by something else, the driver cannot work on big-endian machines, and
>> I'm adding an annotation here to prevent it from being selected.
>
>
> This is a driver that talks to hardware, a device which, AFAIK, has no
> plan to be implemented in a big endian flavor. I clearly need to be more
> diligent in building with various checkers enabled. I'd prefer my fix
> over your suggested refusal to compile, if that's okay.
It's hard to predict the future. If this device ever makes it into an
ARM based chip, the chances are relatively high that someone
will eventually run a big-endian kernel on it. As long as it's guaranteed
to be x86-only, the risk of anyone running into the bug is close to
zero, but we normally still try to write device drivers in portable C
code to prevent it from getting copied incorrectly into another driver.
>> The CCPv3 code seems to not suffer from this problem, only v5 uses
>> bitfields.
>
>
> Yes, I took a different approach when I wrote the code. IMO (arguably)
> more readable. Same result: words full of hardware-dependent bit patterns.
>
> Please help me understand what I could do better.
The rule for portable drivers is that you must not use bitfields in structures
that can be accessed by the hardware. I think you can do this in a more
readable way by removing the CCP5_CMD_* macros etc completely
and just accessing the members of the structure as __le32 words.
The main advantage for readability here is that you can grep for the
struct members and see where they are used without following the
macros. If it helps, you can also encapsulate the generation of the
word inside of an inline function, like:
static inline __le32 ccp5_cmd_dw0(bool soc, bool ioc, bool init, bool
eom, u32 engine)
{
u32 dw0 = (soc ? CCP5_WORD0_SOC : 0) |
(ioc ? CCP5_WORD0_IOC : 0) |
(init ? CCP5_WORD0_INIT : 0) |
(eom ? CCP5_WORD0_EOM : 0) |
CCP5_WORD0_ENGINE(engine);
return __cpu_to_le32(dw0);
}
...
desc->dw0 = ccp5_cmd_dw0(op->soc, 0, op->init, op->oem, op->engine);
Arnd
^ permalink raw reply
* Re: [PATCH 1/2] crypto: ccp - Reduce stack frame size with KASAN
From: Arnd Bergmann @ 2017-03-28 15:03 UTC (permalink / raw)
To: Gary R Hook
Cc: Lendacky, Thomas, Hook, Gary, Herbert Xu, David S. Miller,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <f04b2ede-f291-2ffa-d4a8-124d4af06199@amd.com>
On Tue, Mar 28, 2017 at 4:15 PM, Gary R Hook <ghook@amd.com> wrote:
>> A more drastic refactoring of the driver might be needed to reduce the
>> stack usage more substantially, but this patch is fairly simple and
>> at least addresses the third one of the problems I mentioned, reducing the
>> stack size by about 150 bytes and bringing it below the warning limit
>> I picked.
>
>
> Again, I'll devote some time to this.
>
>> diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
>> index 3a45c2af2fbd..c5ea0796a891 100644
>> --- a/drivers/crypto/ccp/ccp-dev.h
>> +++ b/drivers/crypto/ccp/ccp-dev.h
>> @@ -432,24 +432,24 @@ struct ccp_dma_info {
>> unsigned int offset;
>> unsigned int length;
>> enum dma_data_direction dir;
>> -};
>> +} __packed __aligned(4);
>
>
> My gcc 4.8 doesn't understand __aligned(). Shouldn't we use
> #pragma(4) here?
>> struct ccp_dm_workarea {
>> struct device *dev;
>> struct dma_pool *dma_pool;
>> - unsigned int length;
>>
>> u8 *address;
>> struct ccp_dma_info dma;
>> + unsigned int length;
>> };
>>
>> struct ccp_sg_workarea {
>> struct scatterlist *sg;
>> int nents;
>> + unsigned int dma_count;
>>
>> struct scatterlist *dma_sg;
>> struct device *dma_dev;
>> - unsigned int dma_count;
>> enum dma_data_direction dma_dir;
>>
>> unsigned int sg_used;
>
>
> I'm okay with rearranging, but I'm going to submit an alternative patch.
Ok, thanks a lot!
^ permalink raw reply
* Re: [PATCH 1/2] crypto: ccp - Reduce stack frame size with KASAN
From: Arnd Bergmann @ 2017-03-28 15:10 UTC (permalink / raw)
To: Gary R Hook
Cc: Lendacky, Thomas, Hook, Gary, Herbert Xu, David S. Miller,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <f04b2ede-f291-2ffa-d4a8-124d4af06199@amd.com>
On Tue, Mar 28, 2017 at 4:15 PM, Gary R Hook <ghook@amd.com> wrote:
> On 03/28/2017 04:58 AM, Arnd Bergmann wrote:> The newly added AES GCM
> implementation uses one of the largest stack frames
>> diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
>> index 3a45c2af2fbd..c5ea0796a891 100644
>> --- a/drivers/crypto/ccp/ccp-dev.h
>> +++ b/drivers/crypto/ccp/ccp-dev.h
>> @@ -432,24 +432,24 @@ struct ccp_dma_info {
>> unsigned int offset;
>> unsigned int length;
>> enum dma_data_direction dir;
>> -};
>> +} __packed __aligned(4);
>
>
> My gcc 4.8 doesn't understand __aligned(). Shouldn't we use
> #pragma(4) here?
That is odd, the __aligned() macro gets defined for all compiler versions
in linux/compiler.h, and the aligned attribute should work for all supported
compilers (3.2 and higher), while #pragma pack() requires gcc-4.0 or
higher.
We generally prefer attribute syntax in the kernel over pragmas, even
when they are functionally the same.
Arnd
^ permalink raw reply
* Re: [PATCH 2/2] crypto: ccp - Mark driver as little-endian only
From: Gary R Hook @ 2017-03-28 15:26 UTC (permalink / raw)
To: Arnd Bergmann, Hook, Gary
Cc: Lendacky, Thomas, Herbert Xu, David S. Miller,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CAK8P3a1TH9Lb5_HjTappqXr1X3S03b4M9TLPERa3BZqFeRKnTg@mail.gmail.com>
On 03/28/2017 09:59 AM, Arnd Bergmann wrote:
> On Tue, Mar 28, 2017 at 4:08 PM, Gary R Hook <ghook@amd.com> wrote:
>
>>> In fact, the use of bit fields in hardware defined data structures is
>>> not portable to start with, so until all these bit fields get replaced
>>> by something else, the driver cannot work on big-endian machines, and
>>> I'm adding an annotation here to prevent it from being selected.
>>
>>
>> This is a driver that talks to hardware, a device which, AFAIK, has no
>> plan to be implemented in a big endian flavor. I clearly need to be more
>> diligent in building with various checkers enabled. I'd prefer my fix
>> over your suggested refusal to compile, if that's okay.
>
> It's hard to predict the future. If this device ever makes it into an
> ARM based chip, the chances are relatively high that someone
> will eventually run a big-endian kernel on it. As long as it's guaranteed
> to be x86-only, the risk of anyone running into the bug is close to
> zero, but we normally still try to write device drivers in portable C
> code to prevent it from getting copied incorrectly into another driver.
Understood, and I had surmised as such. Totally agree.
>>> The CCPv3 code seems to not suffer from this problem, only v5 uses
>>> bitfields.
>>
>>
>> Yes, I took a different approach when I wrote the code. IMO (arguably)
>> more readable. Same result: words full of hardware-dependent bit patterns.
>>
>> Please help me understand what I could do better.
>
> The rule for portable drivers is that you must not use bitfields in
> structures
> that can be accessed by the hardware. I think you can do this in a more
> readable way by removing the CCP5_CMD_* macros etc completely
> and just accessing the members of the structure as __le32 words.
> The main advantage for readability here is that you can grep for the
> struct members and see where they are used without following the
> macros. If it helps, you can also encapsulate the generation of the
> word inside of an inline function, like:
>
Please see my follow-on patch.
--
This is my day job. Follow me at:
IG/Twitter/Facebook: @grhookphoto
IG/Twitter/Facebook: @grhphotographer
^ permalink raw reply
* Re: [PATCH 1/2] crypto: ccp - Reduce stack frame size with KASAN
From: Gary R Hook @ 2017-03-28 15:28 UTC (permalink / raw)
To: Arnd Bergmann, Hook, Gary
Cc: Lendacky, Thomas, Herbert Xu, David S. Miller,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CAK8P3a2T4ZmT+EWqARw0L7X+E-B36_RwmBRD7PM-8YBnSMR0Pw@mail.gmail.com>
On 03/28/2017 10:10 AM, Arnd Bergmann wrote:
> On Tue, Mar 28, 2017 at 4:15 PM, Gary R Hook <ghook@amd.com> wrote:
>> On 03/28/2017 04:58 AM, Arnd Bergmann wrote:> The newly added AES GCM
>> implementation uses one of the largest stack frames
>
>>> diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
>>> index 3a45c2af2fbd..c5ea0796a891 100644
>>> --- a/drivers/crypto/ccp/ccp-dev.h
>>> +++ b/drivers/crypto/ccp/ccp-dev.h
>>> @@ -432,24 +432,24 @@ struct ccp_dma_info {
>>> unsigned int offset;
>>> unsigned int length;
>>> enum dma_data_direction dir;
>>> -};
>>> +} __packed __aligned(4);
>>
>>
>> My gcc 4.8 doesn't understand __aligned(). Shouldn't we use
>> #pragma(4) here?
>
> That is odd, the __aligned() macro gets defined for all compiler versions
> in linux/compiler.h, and the aligned attribute should work for all supported
> compilers (3.2 and higher), while #pragma pack() requires gcc-4.0 or
> higher.
>
> We generally prefer attribute syntax in the kernel over pragmas, even
> when they are functionally the same.
Yes, it's extremely odd, and I understand this preference. Please ignore my
submitted alternate and let me track this down....
--
This is my day job. Follow me at:
IG/Twitter/Facebook: @grhookphoto
IG/Twitter/Facebook: @grhphotographer
^ permalink raw reply
* Re: [PATCH 1/2] crypto: ccp - Reduce stack frame size with KASAN
From: Gary R Hook @ 2017-03-28 15:56 UTC (permalink / raw)
To: Arnd Bergmann, Hook, Gary
Cc: Lendacky, Thomas, Herbert Xu, David S. Miller,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CAK8P3a2T4ZmT+EWqARw0L7X+E-B36_RwmBRD7PM-8YBnSMR0Pw@mail.gmail.com>
On 03/28/2017 10:10 AM, Arnd Bergmann wrote:
>>> -};
>>> +} __packed __aligned(4);
>>
>> My gcc 4.8 doesn't understand __aligned(). Shouldn't we use
>> #pragma(4) here?
>
> That is odd, the __aligned() macro gets defined for all compiler versions
> in linux/compiler.h, and the aligned attribute should work for all supported
> compilers (3.2 and higher), while #pragma pack() requires gcc-4.0 or
> higher.
>
Tried again in a couple of trees. Not sure what I did wrong, but the
compiler
seems to be happy now. Huh.
Will submit a V2.
--
This is my day job. Follow me at:
IG/Twitter/Facebook: @grhookphoto
IG/Twitter/Facebook: @grhphotographer
^ permalink raw reply
* [PATCH V2] crypto: ccp - Rearrange structure members to minimize size
From: Gary R Hook @ 2017-03-28 15:57 UTC (permalink / raw)
To: linux-crypto; +Cc: thomas.lendacky, gary.hook, herbert, arnd, davem
The AES GCM function (in ccp-ops) requires a fair amount of
stack space, which elicits a complaint when KASAN is enabled.
Rearranging and packing a few structures eliminates the
warning.
Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
drivers/crypto/ccp/ccp-dev.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index 3a45c2a..191274d 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -427,33 +427,33 @@ enum ccp_memtype {
};
#define CCP_MEMTYPE_LSB CCP_MEMTYPE_KSB
+
struct ccp_dma_info {
dma_addr_t address;
unsigned int offset;
unsigned int length;
enum dma_data_direction dir;
-};
+} __packed __aligned(4);
struct ccp_dm_workarea {
struct device *dev;
struct dma_pool *dma_pool;
- unsigned int length;
u8 *address;
struct ccp_dma_info dma;
+ unsigned int length;
};
struct ccp_sg_workarea {
struct scatterlist *sg;
int nents;
+ unsigned int sg_used;
struct scatterlist *dma_sg;
struct device *dma_dev;
unsigned int dma_count;
enum dma_data_direction dma_dir;
- unsigned int sg_used;
-
u64 bytes_left;
};
^ permalink raw reply related
* Re: [PATCH v3 1/3] crypto: hw_random - Add new Exynos RNG driver
From: Krzysztof Kozlowski @ 2017-03-28 16:48 UTC (permalink / raw)
To: Stephan Müller
Cc: PrasannaKumar Muralidharan, Kukjin Kim, Javier Martinez Canillas,
Matt Mackall, Herbert Xu, David S. Miller, linux-kernel,
linux-arm-kernel, linux-samsung-soc, linux-crypto,
Bartlomiej Zolnierkiewicz, Arnd Bergmann, Olof Johansson
In-Reply-To: <1564458.pWTRdRYEuG@positron.chronox.de>
On Mon, Mar 27, 2017 at 03:53:03PM +0200, Stephan Müller wrote:
> Am Montag, 27. März 2017, 06:23:11 CEST schrieb PrasannaKumar Muralidharan:
>
> Hi PrasannaKumar,
>
> > > Oh my, if you are right with your first guess, this is a bad DRNG design.
> > >
> > > Just out of curiousity: what happens if a caller invokes the seed function
> > > twice or more times (each time with the sufficient amount of bits)? What
> > > is
> > > your guess here?
> >
> > Should the second seed use the random data generated by the device?
>
> A DRNG should be capable of processing an arbitrary amount of seed data. It
> may be the case that the seed data must be processed in chunks though.
>
As I said, I do not know the implementation details about hardware. They
are just not disclossed.
> That said, it may be the case that after injecting one chunk of seed the
> currently discussed RNG simply needs to generate a random number to process
> the input data before another seed can be added. But that is pure speculation.
>
> But I guess that can be easily tested: inject a known seed into the DRNG,
> generate a random number, inject the same seed again and again generate a
> random number. If both are identical (which I do not hope), then the internal
> state is simply overwritten (strange DRNG design).
>
> A similar test can be made to see whether a larger set of seed simply
> overwrites the state or is really processed.
>
> 1. seed
> 2. generate random data
> 3. reset
> 4. seed with anther seed
> 5. generate random data
> 6. reset
> 7. seed with same data from 1
> 8. seed with same data from 2
> 9. generate random data
>
> If data from 9 is identical to 2, then additional seed data is discarded ->
> bad design. If data from 9 is identical to 5, then the additional data
> overwrites the initial data -> bad DRNG design. If data from 9 neither matches
> 2 or 5, then all seed is taken -> good design.
I tested a little bit and:
1. Seeding with some value
2. generating random,
3. kcapi_rng_destroy+kcrng_init, (I cannot do a hardware reset except
reboot of entire system)
4. seeding with the same value as in (1) - different random numbers.
Doing a system reboot and repeating above - different random numbers
(all are different: step (2) and in (4)).
Your test case also produces different random values every time.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 1/3] crypto: hw_random - Add new Exynos RNG driver
From: Stephan Müller @ 2017-03-28 17:41 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: PrasannaKumar Muralidharan, Kukjin Kim, Javier Martinez Canillas,
Matt Mackall, Herbert Xu, David S. Miller, linux-kernel,
linux-arm-kernel, linux-samsung-soc, linux-crypto,
Bartlomiej Zolnierkiewicz, Arnd Bergmann, Olof Johansson
In-Reply-To: <20170328164824.3qjaojqzf2riwpqj@kozik-lap>
Am Dienstag, 28. März 2017, 18:48:24 CEST schrieb Krzysztof Kozlowski:
Hi Krzysztof,
> I tested a little bit and:
> 1. Seeding with some value
> 2. generating random,
> 3. kcapi_rng_destroy+kcrng_init, (I cannot do a hardware reset except
> reboot of entire system)
> 4. seeding with the same value as in (1) - different random numbers.
>
> Doing a system reboot and repeating above - different random numbers
> (all are different: step (2) and in (4)).
>
> Your test case also produces different random values every time.
Then I would assume that simply adding an outer loop to your for() loop to
inject seed larger than the minimum required seed size should be fine.
>
> Best regards,
> Krzysztof
Ciao
Stephan
^ permalink raw reply
* Re: [PATCH v3 1/3] crypto: hw_random - Add new Exynos RNG driver
From: Krzysztof Kozlowski @ 2017-03-28 17:43 UTC (permalink / raw)
To: Stephan Müller
Cc: PrasannaKumar Muralidharan, Kukjin Kim, Javier Martinez Canillas,
Matt Mackall, Herbert Xu, David S. Miller, linux-kernel,
linux-arm-kernel, linux-samsung-soc, linux-crypto,
Bartlomiej Zolnierkiewicz, Arnd Bergmann, Olof Johansson
In-Reply-To: <93183073.lKE0KLq0vu@tauon.atsec.com>
On Tue, Mar 28, 2017 at 07:41:47PM +0200, Stephan Müller wrote:
> Am Dienstag, 28. März 2017, 18:48:24 CEST schrieb Krzysztof Kozlowski:
>
> Hi Krzysztof,
>
> > I tested a little bit and:
> > 1. Seeding with some value
> > 2. generating random,
> > 3. kcapi_rng_destroy+kcrng_init, (I cannot do a hardware reset except
> > reboot of entire system)
> > 4. seeding with the same value as in (1) - different random numbers.
> >
> > Doing a system reboot and repeating above - different random numbers
> > (all are different: step (2) and in (4)).
> >
> > Your test case also produces different random values every time.
>
> Then I would assume that simply adding an outer loop to your for() loop to
> inject seed larger than the minimum required seed size should be fine.
Yes, makes sense. I'll send an updated version of patch.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 0/7] crypto: aes - allow generic AES to be omitted
From: Eric Biggers @ 2017-03-28 17:55 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: linux-crypto@vger.kernel.org, Herbert Xu, nico@linaro.org
In-Reply-To: <CAKv+Gu8P8ET541OPGa=cqPt4qLd4dkiNAztoOZ2mSR47KDYE7g@mail.gmail.com>
On Tue, Mar 28, 2017 at 09:51:54AM +0100, Ard Biesheuvel wrote:
> On 28 March 2017 at 06:43, Eric Biggers <ebiggers3@gmail.com> wrote:
> >
> > Just a thought: how about renaming CRYPTO_AES to CRYPTO_AES_GENERIC, then
> > renaming what you called CRYPTO_NEED_AES to CRYPTO_AES? Then all the 'select
> > CRYPTO_AES' can remain as-is, instead of replacing them with the (in my opinion
> > uglier) 'select CRYPTO_NEED_AES'. And it should still work for people who have
> > CRYPTO_AES=y or CRYPTO_AES=m in their kernel config, since they'll still get at
> > least one AES implementation (though they may stop getting the generic one).
> >
> > Also, in general I think we need better Kconfig help text. As proposed you can
> > now toggle simply "AES cipher algorithms", and nowhere in the help text is it
> > mentioned that that is only the generic implementation, which you don't need if
> > you have enabled some other implementation. Similarly for "Fixed time AES
> > cipher"; it perhaps should be mentioned that it's only useful if a fixed-time
> > implementation using special CPU instructions like AES-NI or ARMv8-CE isn't
> > usable.
> >
>
> Thanks for the feedback. I take it you are on board with the general idea then?
>
> Re name change, those are good points. I will experiment with that.
>
> I was a bit on the fence about modifying the x86 code more than
> required, but actually, I think it makes sense for the AES-NI code to
> use fixed-time AES as a fallback rather than the table-based x86 code,
> given that the fallback is rarely used (only when executed in the
> context of an interrupt taken from kernel code that is already using
> the FPU) and falling back to a non-fixed time implementation loses
> some guarantees that the AES-NI code gives.
Definitely, I just feel it needs to be cleaned up a little so that the different
AES config options and modules aren't quite as confusing to those not as
familiar with them.
Did you also consider having
crypto_aes_set_key_generic()
and
crypto_aes_expand_key_ti()
crypto_aes_set_key_ti()
instead of crypto_aes_set_key() and crypto_aes_expand_key()? As-is, it isn't
immediately clear which function is part of which module.
- Eric
^ permalink raw reply
* Re: [RFC PATCH v2 16/32] x86: kvm: Provide support to create Guest and HV shared per-CPU variables
From: Borislav Petkov @ 2017-03-28 18:39 UTC (permalink / raw)
To: Brijesh Singh
Cc: simon.guinot, linux-efi, kvm, rkrcmar, matt, linux-pci,
linus.walleij, gary.hook, linux-mm, paul.gortmaker, hpa, cl,
dan.j.williams, aarcange, sfr, andriy.shevchenko, herbert, bhe,
xemul, joro, x86, peterz, piotr.luc, mingo, msalter, ross.zwisler,
dyoung, thomas.lendacky, jroedel, keescook, arnd, toshi.kani,
mathieu.desnoyers, luto, devel, bhelgaas
In-Reply-To: <148846773666.2349.9492983018843773590.stgit@brijesh-build-machine>
On Thu, Mar 02, 2017 at 10:15:36AM -0500, Brijesh Singh wrote:
> Some KVM specific MSR's (steal-time, asyncpf, avic_eio) allocates per-CPU
> variable at compile time and share its physical address with hypervisor.
> It presents a challege when SEV is active in guest OS. When SEV is active,
> guest memory is encrypted with guest key and hypervisor will no longer able
> to modify the guest memory. When SEV is active, we need to clear the
> encryption attribute of shared physical addresses so that both guest and
> hypervisor can access the data.
>
> To solve this problem, I have tried these three options:
>
> 1) Convert the static per-CPU to dynamic per-CPU allocation. When SEV is
> detected then clear the encryption attribute. But while doing so I found
> that per-CPU dynamic allocator was not ready when kvm_guest_cpu_init was
> called.
>
> 2) Since the encryption attributes works on PAGE_SIZE hence add some extra
> padding to 'struct kvm-steal-time' to make it PAGE_SIZE and then at runtime
> clear the encryption attribute of the full PAGE. The downside of this was
> now we need to modify structure which may break the compatibility.
>From SEV-ES whitepaper:
"To facilitate this communication, the SEV-ES architecture defines
a Guest Hypervisor Communication Block (GHCB). The GHCB resides in
page of shared memory so it is accessible to both the guest VM and the
hypervisor."
So this is kinda begging to be implemented with a shared page between
guest and host. And then put steal-time, ... etc in there too. Provided
there's enough room in the single page for the GHCB *and* our stuff.
>
> 3) Define a new per-CPU section (.data..percpu.hv_shared) which will be
> used to hold the compile time shared per-CPU variables. When SEV is
> detected we map this section with encryption attribute cleared.
>
> This patch implements #3. It introduces a new DEFINE_PER_CPU_HV_SHAHRED
> macro to create a compile time per-CPU variable. When SEV is detected we
> map the per-CPU variable as decrypted (i.e with encryption attribute cleared).
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/kernel/kvm.c | 43 +++++++++++++++++++++++++++++++------
> include/asm-generic/vmlinux.lds.h | 3 +++
> include/linux/percpu-defs.h | 9 ++++++++
> 3 files changed, 48 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index 099fcba..706a08e 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -75,8 +75,8 @@ static int parse_no_kvmclock_vsyscall(char *arg)
>
> early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
>
> -static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
> -static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
> +static DEFINE_PER_CPU_HV_SHARED(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
> +static DEFINE_PER_CPU_HV_SHARED(struct kvm_steal_time, steal_time) __aligned(64);
> static int has_steal_clock = 0;
>
> /*
> @@ -290,6 +290,22 @@ static void __init paravirt_ops_setup(void)
> #endif
> }
>
> +static int kvm_map_percpu_hv_shared(void *addr, unsigned long size)
> +{
> + /* When SEV is active, the percpu static variables initialized
> + * in data section will contain the encrypted data so we first
> + * need to decrypt it and then map it as decrypted.
> + */
Kernel comments style is:
/*
* A sentence ending with a full-stop.
* Another sentence. ...
* More sentences. ...
*/
But you get the idea. Please check your whole patchset for this.
> + if (sev_active()) {
> + unsigned long pa = slow_virt_to_phys(addr);
> +
> + sme_early_decrypt(pa, size);
> + return early_set_memory_decrypted(addr, size);
> + }
> +
> + return 0;
> +}
> +
> static void kvm_register_steal_time(void)
> {
> int cpu = smp_processor_id();
> @@ -298,12 +314,17 @@ static void kvm_register_steal_time(void)
> if (!has_steal_clock)
> return;
>
> + if (kvm_map_percpu_hv_shared(st, sizeof(*st))) {
> + pr_err("kvm-stealtime: failed to map hv_shared percpu\n");
> + return;
> + }
> +
> wrmsrl(MSR_KVM_STEAL_TIME, (slow_virt_to_phys(st) | KVM_MSR_ENABLED));
> pr_info("kvm-stealtime: cpu %d, msr %llx\n",
> cpu, (unsigned long long) slow_virt_to_phys(st));
> }
>
> -static DEFINE_PER_CPU(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED;
> +static DEFINE_PER_CPU_HV_SHARED(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED;
>
> static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
> {
> @@ -327,25 +348,33 @@ static void kvm_guest_cpu_init(void)
> if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) {
> u64 pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason));
>
> + if (kvm_map_percpu_hv_shared(this_cpu_ptr(&apf_reason),
> + sizeof(struct kvm_vcpu_pv_apf_data)))
> + goto skip_asyncpf;
> #ifdef CONFIG_PREEMPT
> pa |= KVM_ASYNC_PF_SEND_ALWAYS;
> #endif
> wrmsrl(MSR_KVM_ASYNC_PF_EN, pa | KVM_ASYNC_PF_ENABLED);
> __this_cpu_write(apf_reason.enabled, 1);
> - printk(KERN_INFO"KVM setup async PF for cpu %d\n",
> - smp_processor_id());
> + printk(KERN_INFO"KVM setup async PF for cpu %d msr %llx\n",
> + smp_processor_id(), pa);
> }
> -
> +skip_asyncpf:
> if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) {
> unsigned long pa;
> /* Size alignment is implied but just to make it explicit. */
> BUILD_BUG_ON(__alignof__(kvm_apic_eoi) < 4);
> + if (kvm_map_percpu_hv_shared(this_cpu_ptr(&kvm_apic_eoi),
> + sizeof(unsigned long)))
> + goto skip_pv_eoi;
> __this_cpu_write(kvm_apic_eoi, 0);
> pa = slow_virt_to_phys(this_cpu_ptr(&kvm_apic_eoi))
> | KVM_MSR_ENABLED;
> wrmsrl(MSR_KVM_PV_EOI_EN, pa);
> + printk(KERN_INFO"KVM setup PV EOI for cpu %d msr %lx\n",
> + smp_processor_id(), pa);
> }
> -
> +skip_pv_eoi:
> if (has_steal_clock)
> kvm_register_steal_time();
> }
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 0968d13..8d29910 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -773,6 +773,9 @@
> . = ALIGN(cacheline); \
> *(.data..percpu) \
> *(.data..percpu..shared_aligned) \
> + . = ALIGN(PAGE_SIZE); \
> + *(.data..percpu..hv_shared) \
> + . = ALIGN(PAGE_SIZE); \
> VMLINUX_SYMBOL(__per_cpu_end) = .;
>
> /**
> diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
> index 8f16299..5af366e 100644
> --- a/include/linux/percpu-defs.h
> +++ b/include/linux/percpu-defs.h
> @@ -172,6 +172,15 @@
> #define DEFINE_PER_CPU_READ_MOSTLY(type, name) \
> DEFINE_PER_CPU_SECTION(type, name, "..read_mostly")
>
> +/* Declaration/definition used for per-CPU variables that must be shared
> + * between hypervisor and guest OS.
> + */
> +#define DECLARE_PER_CPU_HV_SHARED(type, name) \
> + DECLARE_PER_CPU_SECTION(type, name, "..hv_shared")
> +
> +#define DEFINE_PER_CPU_HV_SHARED(type, name) \
> + DEFINE_PER_CPU_SECTION(type, name, "..hv_shared")
> +
If we end up doing something like that, this needs to be in
#ifdef CONFIG_VIRTUALIZATION
...
#endif
Above too.
--
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--
^ permalink raw reply
* Re: [PATCH v3 1/3] clk: meson-gxbb: expose clock CLKID_RNG0
From: Michael Turquette @ 2017-03-28 22:07 UTC (permalink / raw)
To: Herbert Xu
Cc: Kevin Hilman, Heiner Kallweit, Jerome Brunet, Neil Armstrong,
linux-amlogic, linux-crypto, Stephen Boyd, linux-clk, Linux-DT
In-Reply-To: <20170323075602.GA6054@gondor.apana.org.au>
Herbert,
On Thu, Mar 23, 2017 at 12:56 AM, Herbert Xu
<herbert@gondor.apana.org.au> wrote:
> On Wed, Mar 22, 2017 at 08:24:08AM -0700, Kevin Hilman wrote:
>>
>> Because this will be causing conflicts with both the platform (amlogic)
>> tree and the clk tree, could provide an immutable branch where these are
>> applied to help us handle these conflicts?
>
> If you apply the same patches to your tree there should be no
> conflicts at all. git is able to resolve this automatically.
The commits will have different SHA1 hashes (commit id's). Having
multiple "copies" of the same patch with separate id's is undesirable
and completely avoidable. Immutable, shared branches resolve this
issue.
Best regards,
Mike
>
> Cheers,
> --
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v2 1/5] dt-bindings: Document STM32 CRC bindings
From: Rob Herring @ 2017-03-29 0:28 UTC (permalink / raw)
To: Fabien Dessenne
Cc: Herbert Xu, David S . Miller, Mark Rutland, Maxime Coquelin,
Alexandre Torgue, Russell King, linux-crypto, devicetree,
linux-arm-kernel, Benjamin Gaignard
In-Reply-To: <1490109211-4869-2-git-send-email-fabien.dessenne@st.com>
On Tue, Mar 21, 2017 at 04:13:27PM +0100, Fabien Dessenne wrote:
> Document device tree bindings for the STM32 CRC (crypto CRC32)
>
> Signed-off-by: Fabien Dessenne <fabien.dessenne@st.com>
> ---
> .../devicetree/bindings/crypto/st,stm32-crc.txt | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/crypto/st,stm32-crc.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v2] arm64: dts: ls1012a: add crypto node
From: Shawn Guo @ 2017-03-29 3:04 UTC (permalink / raw)
To: Horia Geantă
Cc: Rob Herring, Mark Rutland, devicetree, Herbert Xu, Harninder Rai,
Catalin Marinas, Bhaskar Upadhaya, Will Deacon, Dan Douglass,
linux-crypto, David S. Miller, linux-arm-kernel
In-Reply-To: <20170328114619.16568-1-horia.geanta@nxp.com>
On Tue, Mar 28, 2017 at 02:46:19PM +0300, Horia Geantă wrote:
> LS1012A has a SEC v5.4 security engine.
>
> Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH v6 0/4] Broadcom SBA RAID support
From: Anup Patel @ 2017-03-29 6:05 UTC (permalink / raw)
To: Vinod Koul
Cc: Jassi Brar, Rob Herring, Mark Rutland, Herbert Xu,
David S . Miller, Dan Williams, Ray Jui, Scott Branden, Jon Mason,
Rob Rice, BCM Kernel Feedback, dmaengine, Device Tree,
Linux ARM Kernel, Linux Kernel, linux-crypto, linux-raid
In-Reply-To: <20170321091829.GZ2843@localhost>
On Tue, Mar 21, 2017 at 2:48 PM, Vinod Koul <vinod.koul@intel.com> wrote:
> On Tue, Mar 21, 2017 at 02:17:21PM +0530, Anup Patel wrote:
>> On Tue, Mar 21, 2017 at 2:00 PM, Vinod Koul <vinod.koul@intel.com> wrote:
>> > On Mon, Mar 06, 2017 at 03:13:24PM +0530, Anup Patel wrote:
>> >> The Broadcom SBA RAID is a stream-based device which provides
>> >> RAID5/6 offload.
>> >>
>> >> It requires a SoC specific ring manager (such as Broadcom FlexRM
>> >> ring manager) to provide ring-based programming interface. Due to
>> >> this, the Broadcom SBA RAID driver (mailbox client) implements
>> >> DMA device having one DMA channel using a set of mailbox channels
>> >> provided by Broadcom SoC specific ring manager driver (mailbox
>> >> controller).
>> >>
>> >> The Broadcom SBA RAID hardware requires PQ disk position instead
>> >> of PQ disk coefficient. To address this, we have added raid_gflog
>> >> table which will help driver to convert PQ disk coefficient to PQ
>> >> disk position.
>> >>
>> >> This patchset is based on Linux-4.11-rc1 and depends on patchset
>> >> "[PATCH v5 0/2] Broadcom FlexRM ring manager support"
>> >
>> > Okay I applied and was about to push when I noticed this :(
>> >
>> > So what is the status of this..?
>>
>> PATCH2 is Acked but PATCH1 is under-review. Currently, its
>> v6 of that patchset.
>>
>> The only dependency on that patchset is the changes in
>> brcm-message.h which are required by this BCM-SBA-RAID
>> driver.
>>
>> @Jassi,
>> Can you please have a look at PATCH v6?
>
> And I would need an immutable branch/tag once merged. I am going to keep
> this series pending till then.
The Broadcom FlexRM patchset is pickedup by Jassi and
can be found in mailbox-for-next branch of
git://git.linaro.org/landing-teams/working/fujitsu/integration
Both patchset (Broadcom FlexRM patchset and this one) are
also available in sba-raid-v7 branch of
https://github.com/Broadcom/arm64-linux.git
Regards,
Anup
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox