1 /** 2 * This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux. 3 * 4 * Copyright (C) 2011-2016 Chelsio Communications. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation. 9 * 10 * Written and Maintained by: 11 * Manoj Malviya (manojmalviya@chelsio.com) 12 * Atul Gupta (atul.gupta@chelsio.com) 13 * Jitendra Lulla (jlulla@chelsio.com) 14 * Yeshaswi M R Gowda (yeshaswi@chelsio.com) 15 * Harsh Jain (harsh@chelsio.com) 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/skbuff.h> 21 22 #include <crypto/aes.h> 23 #include <crypto/hash.h> 24 25 #include "t4_msg.h" 26 #include "chcr_core.h" 27 #include "cxgb4_uld.h" 28 29 static LIST_HEAD(uld_ctx_list); 30 static DEFINE_MUTEX(dev_mutex); 31 static atomic_t dev_count; 32 33 typedef int (*chcr_handler_func)(struct chcr_dev *dev, unsigned char *input); 34 static int cpl_fw6_pld_handler(struct chcr_dev *dev, unsigned char *input); 35 static void *chcr_uld_add(const struct cxgb4_lld_info *lld); 36 static int chcr_uld_state_change(void *handle, enum cxgb4_state state); 37 38 static chcr_handler_func work_handlers[NUM_CPL_CMDS] = { 39 [CPL_FW6_PLD] = cpl_fw6_pld_handler, 40 }; 41 42 static struct cxgb4_pci_uld_info chcr_uld_info = { 43 .name = DRV_MODULE_NAME, 44 .nrxq = 4, 45 .rxq_size = 1024, 46 .nciq = 0, 47 .ciq_size = 0, 48 .add = chcr_uld_add, 49 .state_change = chcr_uld_state_change, 50 .rx_handler = chcr_uld_rx_handler, 51 }; 52 53 int assign_chcr_device(struct chcr_dev **dev) 54 { 55 struct uld_ctx *u_ctx; 56 57 /* 58 * Which device to use if multiple devices are available TODO 59 * May be select the device based on round robin. One session 60 * must go to the same device to maintain the ordering. 61 */ 62 mutex_lock(&dev_mutex); /* TODO ? */ 63 u_ctx = list_first_entry(&uld_ctx_list, struct uld_ctx, entry); 64 if (!u_ctx) { 65 mutex_unlock(&dev_mutex); 66 return -ENXIO; 67 } 68 69 *dev = u_ctx->dev; 70 mutex_unlock(&dev_mutex); 71 return 0; 72 } 73 74 static int chcr_dev_add(struct uld_ctx *u_ctx) 75 { 76 struct chcr_dev *dev; 77 78 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 79 if (!dev) 80 return -ENXIO; 81 82 spin_lock_init(&dev->lock_chcr_dev); 83 u_ctx->dev = dev; 84 dev->u_ctx = u_ctx; 85 atomic_inc(&dev_count); 86 return 0; 87 } 88 89 static int chcr_dev_remove(struct uld_ctx *u_ctx) 90 { 91 kfree(u_ctx->dev); 92 u_ctx->dev = NULL; 93 atomic_dec(&dev_count); 94 return 0; 95 } 96 97 static int cpl_fw6_pld_handler(struct chcr_dev *dev, 98 unsigned char *input) 99 { 100 struct crypto_async_request *req; 101 struct cpl_fw6_pld *fw6_pld; 102 u32 ack_err_status = 0; 103 int error_status = 0; 104 105 fw6_pld = (struct cpl_fw6_pld *)input; 106 req = (struct crypto_async_request *)(uintptr_t)be64_to_cpu( 107 fw6_pld->data[1]); 108 109 ack_err_status = 110 ntohl(*(__be32 *)((unsigned char *)&fw6_pld->data[0] + 4)); 111 if (ack_err_status) { 112 if (CHK_MAC_ERR_BIT(ack_err_status) || 113 CHK_PAD_ERR_BIT(ack_err_status)) 114 error_status = -EINVAL; 115 } 116 /* call completion callback with failure status */ 117 if (req) { 118 if (!chcr_handle_resp(req, input, error_status)) 119 req->complete(req, error_status); 120 else 121 return -EINVAL; 122 } else { 123 pr_err("Incorrect request address from the firmware\n"); 124 return -EFAULT; 125 } 126 return 0; 127 } 128 129 int chcr_send_wr(struct sk_buff *skb) 130 { 131 return cxgb4_ofld_send(skb->dev, skb); 132 } 133 134 static void *chcr_uld_add(const struct cxgb4_lld_info *lld) 135 { 136 struct uld_ctx *u_ctx; 137 138 /* Create the device and add it in the device list */ 139 u_ctx = kzalloc(sizeof(*u_ctx), GFP_KERNEL); 140 if (!u_ctx) { 141 u_ctx = ERR_PTR(-ENOMEM); 142 goto out; 143 } 144 u_ctx->lldi = *lld; 145 mutex_lock(&dev_mutex); 146 list_add_tail(&u_ctx->entry, &uld_ctx_list); 147 mutex_unlock(&dev_mutex); 148 out: 149 return u_ctx; 150 } 151 152 int chcr_uld_rx_handler(void *handle, const __be64 *rsp, 153 const struct pkt_gl *pgl) 154 { 155 struct uld_ctx *u_ctx = (struct uld_ctx *)handle; 156 struct chcr_dev *dev = u_ctx->dev; 157 const struct cpl_act_establish *rpl = (struct cpl_act_establish 158 *)rsp; 159 160 if (rpl->ot.opcode != CPL_FW6_PLD) { 161 pr_err("Unsupported opcode\n"); 162 return 0; 163 } 164 165 if (!pgl) 166 work_handlers[rpl->ot.opcode](dev, (unsigned char *)&rsp[1]); 167 else 168 work_handlers[rpl->ot.opcode](dev, pgl->va); 169 return 0; 170 } 171 172 static int chcr_uld_state_change(void *handle, enum cxgb4_state state) 173 { 174 struct uld_ctx *u_ctx = handle; 175 int ret = 0; 176 177 switch (state) { 178 case CXGB4_STATE_UP: 179 if (!u_ctx->dev) { 180 ret = chcr_dev_add(u_ctx); 181 if (ret != 0) 182 return ret; 183 } 184 if (atomic_read(&dev_count) == 1) 185 ret = start_crypto(); 186 break; 187 188 case CXGB4_STATE_DETACH: 189 if (u_ctx->dev) { 190 mutex_lock(&dev_mutex); 191 chcr_dev_remove(u_ctx); 192 mutex_unlock(&dev_mutex); 193 } 194 if (!atomic_read(&dev_count)) 195 stop_crypto(); 196 break; 197 198 case CXGB4_STATE_START_RECOVERY: 199 case CXGB4_STATE_DOWN: 200 default: 201 break; 202 } 203 return ret; 204 } 205 206 static int __init chcr_crypto_init(void) 207 { 208 if (cxgb4_register_pci_uld(CXGB4_PCI_ULD1, &chcr_uld_info)) { 209 pr_err("ULD register fail: No chcr crypto support in cxgb4"); 210 return -1; 211 } 212 213 return 0; 214 } 215 216 static void __exit chcr_crypto_exit(void) 217 { 218 struct uld_ctx *u_ctx, *tmp; 219 220 if (atomic_read(&dev_count)) 221 stop_crypto(); 222 223 /* Remove all devices from list */ 224 mutex_lock(&dev_mutex); 225 list_for_each_entry_safe(u_ctx, tmp, &uld_ctx_list, entry) { 226 if (u_ctx->dev) 227 chcr_dev_remove(u_ctx); 228 kfree(u_ctx); 229 } 230 mutex_unlock(&dev_mutex); 231 cxgb4_unregister_pci_uld(CXGB4_PCI_ULD1); 232 } 233 234 module_init(chcr_crypto_init); 235 module_exit(chcr_crypto_exit); 236 237 MODULE_DESCRIPTION("Crypto Co-processor for Chelsio Terminator cards."); 238 MODULE_LICENSE("GPL"); 239 MODULE_AUTHOR("Chelsio Communications"); 240 MODULE_VERSION(DRV_VERSION); 241