]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/pms/freebsd/driver/common/lxencrypt.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / pms / freebsd / driver / common / lxencrypt.c
1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved. 
3 *
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided 
5 *that the following conditions are met: 
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7 *following disclaimer. 
8 *2. Redistributions in binary form must reproduce the above copyright notice, 
9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10 *with the distribution. 
11 *
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20 *
21 * $FreeBSD$
22 *
23 *******************************************************************************/
24 /*******************************************************************************
25 **
26 ** Version Control Information:
27 **
28 **  $Revision: 113920 $
29 **  $Author: mcleanda $
30 **  $Date: 2012-05-08 11:30:44 -0700 (Tue, 08 May 2012) $
31 **  $Id: lxencrypt.c 113920 2012-05-08 18:30:44Z mcleanda $
32 **
33 *******************************************************************************/
34
35 #include <dev/pms/RefTisa/tisa/sassata/common/tdioctl.h>
36 #include <dev/pms/RefTisa/tisa/api/titypes.h>
37
38 #include <dev/pms/freebsd/driver/common/lxencrypt.h>
39 #include <sys/param.h>
40 #include <sys/queue.h>
41 #include <vm/uma.h>
42
43
44 static atomic_t ioerr_queue_count;
45 #ifdef ENCRYPT_ENHANCE
46 /******************************************************************************
47 careful_write():
48
49 Purpose:
50 Parameters:
51 Return:
52 Note:
53 ******************************************************************************/
54 static int
55 careful_write(char *buf, int offset, int max, const char *fmt, ...)
56 {
57     static char s[PAGE_SIZE]; /* Assumes serialization */
58     va_list args;
59     int i;
60
61     if(offset > max)
62         return 0;
63     s[PAGE_SIZE - 1] = '\0';
64
65     va_start(args, fmt);    
66     i = vsnprintf(s, PAGE_SIZE - 1, fmt, args);
67     if((offset + i) > max) 
68         return 0;
69     memcpy(buf + offset, s, i); 
70     va_end(args);
71
72     return i;
73 }
74
75 /******************************************************************************
76 set_dek_table_entry():
77
78 Purpose:
79 Parameters:
80 Return:
81 Note:
82 ******************************************************************************/
83 static inline int
84 set_dek_table_entry(struct device *dev, const char *buf, size_t len, dek_table_e table)
85 {
86     int index;
87     struct Scsi_Host *shost = class_to_shost(dev);
88     struct agtiapi_softc *pCard = (struct agtiapi_softc *) shost->hostdata;
89
90     /* Check permissions */
91     if(!capable(CAP_SYS_ADMIN))
92         return -EACCES;
93
94     if(!pCard->encrypt)
95         return -EINVAL;
96
97     if(table != DEK_TABLE_0 && table != DEK_TABLE_1)
98         return -EINVAL;
99
100     sscanf(buf, "%d", &index);
101     if(index >= 0 && index < DEK_MAX_TABLE_ITEMS) { 
102         pCard->dek_index[table] = index;
103         return strlen(buf);
104     }
105     return -EINVAL;
106 }
107
108 /******************************************************************************
109 set_dek_table_entry0():
110
111 Purpose:
112 Parameters:
113 Return:
114 Note:
115 ******************************************************************************/
116 ssize_t
117 set_dek_table_entry0(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
118 {
119     return set_dek_table_entry(dev, buf, len, DEK_TABLE_0);
120 }
121
122 /******************************************************************************
123 set_dek_table_entry1():
124
125 Purpose:
126 Parameters:
127 Return:
128 Note:
129 ******************************************************************************/
130 ssize_t
131 set_dek_table_entry1(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
132 {
133     return set_dek_table_entry(dev, buf, len, DEK_TABLE_1);
134 }
135
136
137 /******************************************************************************
138 show_dek_table_entry():
139
140 Purpose:
141 Parameters:
142 Return:
143 Note:
144 ******************************************************************************/
145 static inline int
146 show_dek_table_entry(struct device *dev, char *buf, unsigned int table)
147 {
148     int i = 0, j;
149     unsigned char *p;
150     struct Scsi_Host *sh = class_to_shost(dev);
151     ag_card_t *pCard = (ag_card_t *) sh->hostdata;
152     ag_card_info_t *pCardInfo = pCard->pCardInfo;
153     ag_resource_info_t *pRscInfo = &pCardInfo->tiRscInfo;
154     tiEncryptDekBlob_t *pDekTable = NULL;
155
156     if(!pCard->encrypt)
157         return -EINVAL;
158
159     if(table == DEK_TABLE_0)
160         pDekTable = pRscInfo->tiLoLevelResource.loLevelMem.mem[DEK_MEM_INDEX_1].virtPtr;
161     else if(table == DEK_TABLE_1)
162         pDekTable = pRscInfo->tiLoLevelResource.loLevelMem.mem[DEK_MEM_INDEX_2].virtPtr;
163     if(pDekTable == NULL)
164         return -EINVAL;
165
166     if(pCard->dek_index[table] >= 0 || pCard->dek_index[table] < DEK_MAX_TABLE_ITEMS) {
167         i += careful_write(buf, i, PAGE_SIZE, "%4d: ", pCard->dek_index[table]);
168         p = (unsigned char *) &pDekTable[pCard->dek_index[table]];
169         for(j = 0; j < sizeof(tiEncryptDekBlob_t); j++) {
170             i += careful_write(buf, i, PAGE_SIZE, "%02x", p[j]);
171         }
172         i += careful_write(buf, i, PAGE_SIZE, "\n");
173     } else {
174         i += careful_write(buf, i, PAGE_SIZE, "Bad DEK index %d; range: 0 - %d\n", pCard->dek_index[table], DEK_MAX_TABLE_ITEMS);
175     }
176
177     /* BUG if we return more than a single page of data */
178     //BUG_ON(i > PAGE_SIZE);
179     if (i > PAGE_SIZE)
180         i = PAGE_SIZE;
181
182     return i;
183 }
184
185 /******************************************************************************
186 show_dek_table_entry0():
187
188 Purpose:
189 Parameters:
190 Return:
191 Note:
192 ******************************************************************************/
193 ssize_t
194 show_dek_table_entry0(struct device *dev, struct device_attribute *attr, char *buf)
195 {
196     return show_dek_table_entry(dev, buf, DEK_TABLE_0);
197 }
198
199 /******************************************************************************
200 show_dek_table_entry1():
201
202 Purpose:
203 Parameters:
204 Return:
205 Note:
206 ******************************************************************************/
207 ssize_t
208 show_dek_table_entry1(struct device *dev, struct device_attribute *attr, char *buf)
209 {
210     return show_dek_table_entry(dev, buf, DEK_TABLE_1);
211 }
212
213 /******************************************************************************
214 show_kek_table():
215
216 Purpose:
217 Parameters:
218 Return:
219 Note:
220 ******************************************************************************/
221 ssize_t
222 show_kek_table(struct device *dev, struct device_attribute *attr, char *buf)
223 {
224     int i = 0, j, kek_index;
225     unsigned char *p;
226     struct Scsi_Host *sh = class_to_shost(dev);
227     ag_card_t *pCard = (ag_card_t *) sh->hostdata;
228
229     if(!pCard->encrypt)
230         return -EINVAL;
231
232     for(kek_index = 0; kek_index < KEK_TABLE_MAX_ENTRY; kek_index++) {
233         i += careful_write(buf, i, PAGE_SIZE, " %4d: %08x ", kek_index, pCard->kek_table[kek_index].wrapperIndex); 
234         p = (unsigned char *) &pCard->kek_table[kek_index].kekBlob;
235         for(j = 0; j < sizeof(tiEncryptKekBlob_t); j++) {
236             i += careful_write(buf, i, PAGE_SIZE, "%02x", p[j]);
237         }
238         i += careful_write(buf, i, PAGE_SIZE, "\n");
239     }
240     i += careful_write(buf, i, PAGE_SIZE, "\n");
241
242     /* BUG if we return more than a single page of data */
243     //BUG_ON(i > PAGE_SIZE);
244     if (i > PAGE_SIZE)
245         i = PAGE_SIZE;
246
247     return i;
248 }
249
250 /******************************************************************************
251 show_dek_kek_map():
252
253 Purpose:
254 Parameters:
255 Return:
256 Note:
257 ******************************************************************************/
258 static inline int
259 show_dek_kek_map(struct device *dev, char *buf, unsigned int table)
260 {
261     int i = 0, dek_index;
262     struct Scsi_Host *sh = class_to_shost(dev);
263     ag_card_t *pCard = (ag_card_t *) sh->hostdata;
264
265     if(!pCard->encrypt)
266         return -EINVAL;
267
268     if(table != DEK_TABLE_0 && table != DEK_TABLE_1)
269         return -EINVAL;
270
271     i += careful_write(buf, i, PAGE_SIZE, "Table %d\n", table);
272     i += careful_write(buf, i, PAGE_SIZE, "=======\n");
273     for(dek_index = 0; dek_index < DEK_MAX_TABLE_ITEMS; dek_index++) { 
274         i += careful_write(buf, i, PAGE_SIZE, " %4d: %08x\n", dek_index, pCard->dek_kek_map[table][dek_index].kekIndex);
275     }
276     i += sprintf(buf + i, "\n");
277
278     /* BUG if we return more than a single page of data */
279     //BUG_ON(i > PAGE_SIZE);
280     if (i > PAGE_SIZE)
281         i = PAGE_SIZE;
282     
283     return i;
284 }
285
286 /******************************************************************************
287 show_dek_kek_map0():
288
289 Purpose:
290 Parameters:
291 Return:
292 Note:
293 ******************************************************************************/
294 ssize_t
295
296 show_dek_kek_map0(struct device *dev, struct device_attribute *attr, char *buf)
297 {
298     return show_dek_kek_map(dev, buf, 0);
299 }
300
301 /******************************************************************************
302 show_dek_kek_map1():
303
304 Purpose:
305 Parameters:
306 Return:
307 Note:
308 ******************************************************************************/
309 ssize_t
310 show_dek_kek_map1(struct device *dev, struct device_attribute *attr, char *buf)
311 {
312     return show_dek_kek_map(dev, buf, 1);
313 }
314
315 /******************************************************************************
316 show_target_dek_map():
317
318 Purpose:
319 Parameters:
320 Return:
321 Note:
322 ******************************************************************************/
323 ssize_t
324 show_target_dek_map(struct device *dev, struct device_attribute *attr, char *buf)
325 {
326     int i = 0;
327     unsigned int chan, device, lun = 0;
328     ag_encrypt_map_t *p;
329     struct list_head *lh;
330     struct Scsi_Host *sh = class_to_shost(dev);
331     ag_card_t *pCard = (ag_card_t *) sh->hostdata;
332
333     if(!pCard->encrypt)
334         return -EINVAL;
335
336     for(chan = 0; chan <= AGTIAPI_MAX_CHANNEL_NUM; chan++) {
337         for(device = 0; device < pCard->devDiscover; device++) {
338 #ifdef REPORT_ALL_LUNS
339             for(lun = 0; lun < AGTIAPI_MAX_LUN; lun++) {
340 #endif
341                 lh = MAP_TABLE_ENTRY(pCard, chan, device, lun);
342                 if(lh) {
343                     list_for_each_entry(p, lh, list) {
344                         if(p->dekIndex != DEK_INDEX_INVALID)
345                             i += careful_write(buf, i, PAGE_SIZE, " %u:%u:%u: %x %8x %8x %16lx %16lx %08x:%08x %1x\n", chan, device, lun, p->dekTable, p->dekIndex, p->kekIndex, p->lbaMin, p->lbaMax, p->keyTag[1], p->keyTag[0], p->keyTagCheck);
346                     }
347                 }
348 #ifdef REPORT_ALL_LUNS
349             }
350 #endif
351         }
352     }
353
354     if (i > PAGE_SIZE)
355         i = PAGE_SIZE;
356
357     return i;
358 }
359
360
361 /******************************************************************************
362 agtiapi_AddDek():
363
364 Purpose:
365 Parameters:
366 Return:
367 Note:
368 ******************************************************************************/
369 static int
370 agtiapi_AddDek(ag_card_t *pCard, bit32 dek_table, bit32 dek_index, bit32 blob_format, bit32 entry_sz, tiEncryptDekBlob_t *dek_blob, U32_64 *addr) 
371 {
372     ag_resource_info_t *pRscInfo = &pCard->pCardInfo->tiRscInfo;
373     tiEncryptDekBlob_t *pDekTable;
374     char *p;
375
376     if (dek_index >= DEK_MAX_TABLE_ITEMS) {
377         printf("%s: Bad dek index 0x%x (MAX: 0x%x).\n", __FUNCTION__, dek_index, DEK_MAX_TABLE_ITEMS);
378         return -E_DEK_INDEX;
379     }
380
381     switch(dek_table) {
382         case DEK_TABLE_0:
383             pDekTable = pRscInfo->tiLoLevelResource.loLevelMem.mem[DEK_MEM_INDEX_1].virtPtr;
384             break;
385         case DEK_TABLE_1:
386             pDekTable = pRscInfo->tiLoLevelResource.loLevelMem.mem[DEK_MEM_INDEX_2].virtPtr;
387             break;
388         default:
389             printf("%s: Unknown dek table %d\n", __FUNCTION__, dek_table);
390             return -E_DEK_TABLE;
391     }
392
393     #ifdef __VMKLNX__
394         *addr = (U32_64) __pa(&pDekTable[0]);
395     #else
396         *addr = (U32_64) virt_to_phys(&pDekTable[0]);
397     #endif
398
399     p = (char *) &pDekTable[0] + (dek_index * pCard->dek_size);
400
401     printf("%s: Base: %p, Index: %08x, Virt: %p Size: %d\n", __FUNCTION__, pDekTable, dek_index, &pDekTable[dek_index], pCard->dek_size);
402     memcpy(p, dek_blob, pCard->dek_size);
403     wmb();
404
405     /* Flush entry */
406     ostiCacheFlush(&pCard->tiRoot, NULL, p, pCard->dek_size);
407
408     return 0;
409 }
410
411 /******************************************************************************
412 agtiapi_MapDekKek():
413
414 Purpose:
415 Parameters:
416 Return:
417 Note:
418 ******************************************************************************/
419 static int
420 agtiapi_MapDekKek(ag_card_t *pCard, bit32 dek_table, bit32 dek_index, bit32 kek_index)
421 {
422     if (dek_index >= DEK_MAX_TABLE_ITEMS) {
423         printf("%s: Bad dek index 0x%x (MAX: 0x%x).\n", __FUNCTION__, dek_index, DEK_MAX_TABLE_ITEMS);
424         return -E_DEK_INDEX;
425     }
426
427     if (dek_table >= DEK_MAX_TABLES) {
428         printf("%s: Bad dek table.\n", __FUNCTION__);
429         return -E_DEK_TABLE;
430     }
431
432     if (kek_index >= KEK_TABLE_MAX_ENTRY) {
433         printf("%s: Bad kek index.\n", __FUNCTION__);
434         return -E_KEK_INDEX;
435     }
436    
437     pCard->dek_kek_map[dek_table][dek_index].kekIndex = kek_index; 
438     return 0;
439 }
440
441 /******************************************************************************
442 agtiapi_AddKek():
443
444 Purpose:
445 Parameters:
446 Return:
447 Note:
448 ******************************************************************************/
449 static int
450 agtiapi_AddKek(ag_card_t *pCard, bit32 kek_index, bit32 wrapper_kek_index, tiEncryptKekBlob_t *kek_blob)
451 {
452     if (kek_index >= KEK_TABLE_MAX_ENTRY) {
453         printf("%s: Bad kek index.\n", __FUNCTION__);
454         return -E_KEK_INDEX;
455     }
456     if (wrapper_kek_index >= KEK_TABLE_MAX_ENTRY) {
457         printf("%s: Bad kek wrapper index.\n", __FUNCTION__);
458         return -E_KEK_INDEX;
459     }
460     pCard->kek_table[kek_index].wrapperIndex = wrapper_kek_index;
461     memcpy(&pCard->kek_table[kek_index].kekBlob, kek_blob, sizeof(tiEncryptKekBlob_t));
462     return 0;
463 }
464
465 /******************************************************************************
466 agtiapi_MapDek():
467
468 Purpose:
469 Parameters:
470 Return:
471 Note:
472 ******************************************************************************/
473 static int
474 agtiapi_MapDek(ag_card_t *pCard, EncryptDeviceDekMap_t *dek_map)
475 {
476     int found = 0;
477     bit32 chan, device, lun;
478     bit32 dek_table, dek_index, kek_index;
479     unsigned long long lba_min, lba_max;
480     ag_encrypt_map_t *p, *n;
481     struct list_head *lh;
482
483     chan = dek_map->channel;
484     device = dek_map->device;
485     lun = dek_map->lun;
486
487     lba_min = dek_map->dekMapEntry[0].startLBA;
488     lba_max = dek_map->dekMapEntry[0].endLBA;
489
490     dek_table = dek_map->dekMapEntry[0].dek.dekTable;
491     dek_index = dek_map->dekMapEntry[0].dek.dekIndex;
492
493     /* Sanity check channel, device, lun */
494     if (chan > AGTIAPI_MAX_CHANNEL_NUM) {
495         printf("%s: Bad channel %d.\n", __FUNCTION__, chan);
496         return -E_CHANNEL_INDEX;
497     }
498     if (device >= pCard->devDiscover) {
499         printf("%s: Bad device %d.\n", __FUNCTION__, device);
500         return -E_DEVICE_INDEX;
501     }
502     if (lun >= AGTIAPI_MAX_LUN) {
503         printf("%s: Bad lun %d.\n", __FUNCTION__, lun);
504         return -E_LUN_INDEX;
505     }
506
507     /* Sanity check dek index */
508     if (dek_index >= DEK_MAX_TABLE_ITEMS) {
509         printf("%s: Bad dek index 0x%x (MAX: 0x%x).\n", __FUNCTION__, dek_index, DEK_MAX_TABLE_ITEMS);
510         return -E_DEK_INDEX;
511     }
512
513     /* Sanity check dek table */
514     if (dek_table >= DEK_MAX_TABLES) {
515         printf("%s: Bad dek table %d.\n", __FUNCTION__, dek_table);
516         return -E_DEK_TABLE;
517     }
518
519     /* Check that lba min and lba max are sane */
520     if (lba_min >= lba_max) {
521         printf("%s: Bad lba min and lba max: %llx %llx.\n", __FUNCTION__, lba_min, lba_max);
522         return -E_LBA_RANGE;
523     } 
524
525     /* dek_table and dek_index are valid, look up kek */
526     kek_index = pCard->dek_kek_map[dek_table][dek_index].kekIndex;
527
528     lh = MAP_TABLE_ENTRY(pCard, chan, device, lun);
529
530     if (dek_map->dekMapEntry[0].flags & ENCRYPT_DEK_MAP_ENTRY_CLEAR) { 
531         /* Delete the entry */
532         found = 0;
533         list_for_each_entry_safe(p, n, lh, list) {
534             if (p->lbaMin   == lba_min   &&
535                 p->lbaMax   == lba_max   &&
536                 p->dekTable == dek_table &&
537                 p->dekIndex == dek_index &&
538                 p->kekIndex == kek_index) {
539                 /* Entry found, unlink and reclaim it */
540                 found = 1;
541                 list_del(&p->list);
542                 mempool_free(p, pCard->map_mempool);
543             }
544         }
545         if (!found) {
546             printf("%s: Entry %x %x %x %llx %llx not found.\n", __FUNCTION__, dek_table, dek_index, kek_index, lba_min, lba_max);
547             return -E_NOT_FOUND;
548         }
549     } else if (dek_map->dekMapEntry[0].flags & ENCRYPT_DEK_MAP_ENTRY_VALID) {
550         /* Add the entry */
551
552           p = (ag_encrypt_map_t *)uma_zalloc(pCard->map_cache, M_WAITOK); //Encryption
553         if (!p) {
554             printf("%s: Unable to allocate from memory pool.\n", __FUNCTION__);
555             return -E_MEMPOOL_ALLOC;
556         }
557
558         /* Populate it */
559         p->lbaMin = lba_min;
560         p->lbaMax = lba_max;
561         p->dekTable = dek_table;
562         p->dekIndex = dek_index;
563         p->kekIndex = kek_index;
564         p->keyTagCheck = dek_map->keytag_check;
565         memcpy(&p->keyTag, &dek_map->keytag, sizeof(p->keyTag));
566
567         /* Test to see if this new mapping overlaps an existing mapping */
568         list_for_each_entry(n, lh, list) {
569             /* 
570              * Check if the start lba falls in existing range ||
571              * Check if the end lba falls in existing range   ||
572              * Check if the start lba of the existing range falls in the new range
573              */
574             if (((p->lbaMin >= n->lbaMin) && (p->lbaMin <= n->lbaMax)) ||
575                 ((p->lbaMax >= n->lbaMin) && (p->lbaMax <= n->lbaMax)) ||
576                 ((n->lbaMin >= p->lbaMin) && (n->lbaMin <= p->lbaMax))) {
577                 printf("%s: WARNING: New entry lba range overlap: %llx - %llx vs %llx - %llx.\n", __FUNCTION__, p->lbaMin, p->lbaMax, n->lbaMin, n->lbaMax);
578             }
579         }
580
581         /* Link it in to list at the head so it takes precedence */
582         list_add(&p->list, lh);
583
584         /* TODO: Decide if/how to refcount each dek/kek index used by the mapping */
585
586     } else {
587         printf("%s: Bad flags %08x\n", __FUNCTION__, dek_map->dekMapEntry[0].flags);
588         return -E_FLAGS;
589     } 
590
591     return 0;
592 }
593 #endif
594 #ifdef HIALEAH_ENCRYPTION
595 /******************************************************************************
596 agtiapi_SetupEncryption():
597
598 Purpose:
599 Parameters:
600 Return:
601 Note:
602 ******************************************************************************/
603 int
604 agtiapi_SetupEncryption(struct agtiapi_softc *pCard)
605 {
606   tiRoot_t *tiRoot = (tiRoot_t *) &pCard->tiRoot;
607   bit32 status = tiSuccess;
608   printf("agtiapi_SetupEncryption: HIALEAH_ENCRYPTION\n");
609   if (pCard->encrypt == agTRUE)
610   {
611     status = tiCOMEncryptGetInfo(tiRoot);
612     printf("agtiapi_SetupEncryption: HIALEAH_ENCRYPTION tiCOMEncryptGetInfo Status 0x%x\n",status);
613
614     if(status == 1 )
615     {
616         status = tiCOMEncryptHilSet(tiRoot );
617         if (status) {
618             pCard->encrypt = agFALSE;
619             printf("agtiapi_SetupEncryption: HIALEAH_ENCRYPTION not set\n");
620         }
621     }
622   }
623     return 0;
624 }
625 #ifdef ENCRYPT_ENHANCE
626 /******************************************************************************
627 agtiapi_SetupEncryptionPools():
628
629 Purpose:
630 Parameters:
631 Return:
632 Note:
633 ******************************************************************************/
634 int
635 agtiapi_SetupEncryptionPools(struct agtiapi_softc *pCard)
636 {
637     /* Configure encryption memory pool */
638     memset(pCard->map_cache_name, 0, sizeof(pCard->map_cache_name));
639     snprintf(pCard->map_cache_name, sizeof(pCard->map_cache_name) - 1, "map_cache_%d", pCard->cardNo);
640
641 //zone allocation
642      pCard->map_cache = uma_zcreate(pCard->map_cache_name, sizeof(ag_encrypt_map_t),NULL, NULL, NULL, NULL, 0, 0);
643     if(!pCard->map_cache) {
644         /*
645          * This error may be due to an existing cache in the kernel
646          * from an earlier kmem_cache that wasn't properly freed
647          */
648         printf("Unable to create uma_zcreate cache for encryption map mempool.\n");
649         return -EFAULT;
650     }
651     uma_zone_set_max(pCard->map_cache, ENCRYPTION_MAP_MEMPOOL_SIZE); 
652    
653
654     /* Configure encryption IO error pool */
655     INIT_LIST_HEAD(&pCard->ioerr_queue);
656 /*#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)) // ####
657     pCard->ioerr_queue_lock = SPIN_LOCK_UNLOCKED;
658 #else */
659     pCard->ioerr_queue_lock = AG_SPIN_UNLOCK(pCard->ioerr_queue_lock); 
660 //#endif
661
662
663     memset(pCard->ioerr_cache_name, 0, sizeof(pCard->ioerr_cache_name));
664     snprintf(pCard->ioerr_cache_name, sizeof(pCard->ioerr_cache_name) - 1, "ioerr_cache_%d", pCard->cardNo);
665
666     pCard->ioerr_cache = uma_zcreate(pCard->ioerr_cache_name, sizeof(ag_encrypt_ioerr_t), NULL, NULL, NULL, NULL, 0, 0);
667     if(!pCard->ioerr_cache) {
668         /*
669          * This error may be due to an existing cache in the kernel
670          * from an earlier kmem_cache that wasn't properly freed
671          */
672         printf("Unable to create kmem cache for encryption IO error mempool.\n");
673         return -EFAULT;
674     } 
675     uma_zone_set_max(pCard->ioerr_cache,  ENCRYPTION_IO_ERR_MEMPOOL_SIZE);
676
677     /* Set cipher mode to something invalid */
678     pCard->cipher_mode = CIPHER_MODE_INVALID;
679
680     return 0;
681 }
682 #endif
683 /******************************************************************************
684 agtiapi_CleanupEncryption():
685
686 Purpose:
687 Parameters:
688 Return:
689 Note:
690 ******************************************************************************/
691 void
692 agtiapi_CleanupEncryption(struct agtiapi_softc *pCard)
693 {
694 #ifdef ENCRYPT_ENHANCE
695    if(pCard->encrypt_map) {
696         int chan, device, lun;
697         struct list_head *lh;
698         ag_encrypt_map_t *p, *n;
699
700         for (chan = 0; chan < (AGTIAPI_MAX_CHANNEL_NUM + 1); chan++) {
701             for (device = 0; device < pCard->devDiscover; device++) {
702                 for (lun = 0; lun < AGTIAPI_MAX_LUN; lun++) {
703                     lh = MAP_TABLE_ENTRY(pCard, chan, device, lun);
704                     list_for_each_entry_safe(p, n, lh, list) {
705         //                mempool_free(p, pCard->map_mempool);
706                     }
707                 }
708             }
709         }
710         vfree(pCard->encrypt_map);
711         pCard->encrypt_map = NULL;
712     }
713 #endif
714 }
715
716 #ifdef ENCRYPT_ENHANCE
717 /******************************************************************************
718 agtiapi_CleanupEncryptionPools():
719
720 Purpose:
721 Parameters:
722 Return:
723 Note:
724 ******************************************************************************/
725 void
726 agtiapi_CleanupEncryptionPools(struct agtiapi_softc *pCard)
727 {
728     ag_encrypt_ioerr_t *ioerr, *tmp;
729     atomic_set(&ioerr_queue_count);
730
731     /* 
732      * TODO: check "outstanding_encrypted_io_count" for non-zero 
733      *       and free all mempool items prior to destroying pool
734      */
735
736     /* Clean up memory pools */
737     if (pCard->map_mempool) {
738         mempool_destroy(pCard->map_mempool);
739         printf("Encryption Map mempool released.\n");
740         pCard->map_mempool = NULL;
741     }
742
743     /* Clean up kmem cache */
744     if (pCard->map_cache) {
745         kmem_cache_destroy(pCard->map_cache);
746         printf("Kernel memory cache %s released.\n", pCard->map_cache_name);
747         pCard->map_cache = NULL;
748     }
749
750     /* Clean up memory pools */
751     list_for_each_entry_safe(ioerr, tmp, &pCard->ioerr_queue, list) {
752         list_del_init(&ioerr->list);
753         mempool_free(ioerr, pCard->ioerr_mempool);
754         atomic_dec(&ioerr_queue_count);
755     }
756
757     if (pCard->ioerr_mempool) {
758         mempool_destroy(pCard->ioerr_mempool);
759         printf("Encryption IO Error mempool released.\n");
760         pCard->ioerr_mempool = NULL;
761     }
762
763     /* Clean up kmem cache */
764     if (pCard->ioerr_cache) {
765         kmem_cache_destroy(pCard->ioerr_cache);
766         printf("Kernel memory cache %s released.\n", pCard->ioerr_cache_name);
767         pCard->ioerr_cache = NULL;
768     }
769 }
770
771 /******************************************************************************
772 agtiapi_EncryptionIoctl():
773
774 Purpose:
775 Parameters:
776 Return:
777 Note:
778 ******************************************************************************/
779 int
780 agtiapi_EncryptionIoctl(struct agtiapi_softc *pCard, IoctlEncrypt_t *pIoctlPayload) 
781 {
782     int rv, rc = 0, skip_wait = 0;
783     tiRoot_t *tiRoot = (tiRoot_t *) &pCard->tiRoot;
784     IoctlTISAEncrypt_t *ioctl_data = &pIoctlPayload->body;
785     pIoctlPayload->hdr.Status = IOCTL_ERR_STATUS_INVALID_CODE;
786     pCard->ioctl_data = (void *) ioctl_data;
787     init_completion(&pCard->ioctl_completion);
788
789     /* Check that the system is quiesced */
790     if (atomic_read(&outstanding_encrypted_io_count) != 0) 
791         printf("%s: WARNING: Attempting encryption management update with outstanding encrypted IOs!\n", __FUNCTION__);
792
793 printf("%s: Minor %d\n", __FUNCTION__, pIoctlPayload->hdr.MinorFunction);
794     switch(pIoctlPayload->hdr.MinorFunction) {
795         case IOCTL_MN_ENCRYPTION_GET_INFO:
796             {
797                 //IoctlEncryptGetInfo_t *get_info = (IoctlEncryptGetInfo_t *) &ioctl_data->request;
798                 rc = tiCOMEncryptGetInfo(tiRoot);
799             }
800             break;
801         case IOCTL_MN_ENCRYPTION_SET_MODE:
802             {
803                 u32 reg_val = 0, new_cipher_mode = 0;
804                 IoctlEncryptSetMode_t *set_mode = (IoctlEncryptSetMode_t *) &ioctl_data->request;
805
806                 printf("%s: input %08x\n", __FUNCTION__, set_mode->securityCipherMode);
807
808                 /* Set security mode */
809                 if(TI_ENCRYPT_SEC_MODE_FACT_INIT)
810                     if(set_mode->securityCipherMode & TI_ENCRYPT_SEC_MODE_FACT_INIT) {
811                         reg_val |= TI_ENCRYPT_SEC_MODE_FACT_INIT;
812                         pCard->dek_size = DEK_SIZE_PLAIN;
813                     }
814                 if(set_mode->securityCipherMode & TI_ENCRYPT_SEC_MODE_A) {
815                     reg_val |= TI_ENCRYPT_SEC_MODE_A;
816                     pCard->dek_size = DEK_SIZE_ENCRYPT;
817                 } else if(set_mode->securityCipherMode & TI_ENCRYPT_SEC_MODE_B) {
818                     reg_val |= TI_ENCRYPT_SEC_MODE_B;
819                     pCard->dek_size = DEK_SIZE_ENCRYPT;
820                 }
821
822                 /* Set cipher mode */
823                 if(set_mode->securityCipherMode & TI_ENCRYPT_ATTRIB_CIPHER_XTS) {
824                     reg_val |= TI_ENCRYPT_ATTRIB_CIPHER_XTS;
825                     new_cipher_mode = TI_ENCRYPT_MODE_XTS_AES;
826                 }
827
828                 printf("%s: Setting security cipher mode to: 0x%08x\n", __FUNCTION__, reg_val);
829                 pCard->cipher_mode = new_cipher_mode;
830
831                 rc = tiCOMEncryptSetMode(tiRoot, reg_val);
832             } 
833             break;
834         case IOCTL_MN_ENCRYPTION_KEK_ADD:
835             {
836                 tiEncryptKekBlob_t kek_blob;
837                 IoctlEncryptKekAdd_t *kek_add = (IoctlEncryptKekAdd_t *) &ioctl_data->request;
838                 printf("%s: Add kek at index 0x%x wrapper 0x%x format 0x%x\n", __FUNCTION__, kek_add->kekIndex, kek_add->wrapperKekIndex, kek_add->blobFormat);
839                 
840                 /* Copy kek_blob from user pointer to local buffer */
841                 if(access_ok(VERIFY_READ, kek_add->EncryptKekBlob, sizeof(kek_blob))) {
842                     printf("%s: Starting copy from user %p to kernel %p\n", __FUNCTION__, kek_add->EncryptKekBlob, &kek_blob);
843                     if((rv = copy_from_user(&kek_blob, kek_add->EncryptKekBlob, sizeof(kek_blob))) != 0) {
844                         printf("%s: Copy error, %d left\n", __FUNCTION__, rv);
845                         return IOCTL_CALL_FAIL;
846                     }
847                     rc = tiCOMEncryptKekAdd(tiRoot, kek_add->kekIndex, kek_add->wrapperKekIndex, kek_add->blobFormat, &kek_blob);
848                     
849                     /* Add kek to local kek table (in case of chip reset) */
850                     if(rc == tiSuccess) {
851                         if(agtiapi_AddKek(pCard, kek_add->kekIndex, kek_add->wrapperKekIndex, &kek_blob) < 0) {
852                             return IOCTL_CALL_FAIL;
853                         }
854                     }
855                 } else { 
856                     return IOCTL_CALL_FAIL;
857                 }
858             }
859             break;
860         case IOCTL_MN_ENCRYPTION_DEK_ADD:
861             {
862                 tiEncryptDekBlob_t dek_blob; /* Copied in */
863                 IoctlEncryptDekAdd_t *dek_add = (IoctlEncryptDekAdd_t *) &ioctl_data->request;
864                 bit32 kek_index = dek_add->kekIndex;
865                 bit32 dek_index = dek_add->dekIndex;
866                 bit32 dek_table = dek_add->dekTable;
867                 bit32 blob_format = dek_add->dekBlobFormat;
868                 bit32 entry_sz = dek_add->dekTableKeyEntrySize;
869                 U32_64 addr = 0;
870                 bit32 addr_table[2];
871                 memset(addr_table, 0, sizeof(addr_table));
872
873                 printf("%s: Add dek at index 0x%x, table %x, kek index %x, blob format %x, entry size %x\n", __FUNCTION__, dek_index, dek_table, kek_index, blob_format, entry_sz);
874                 
875                 /* Copy dek_blob from user pointer to local buffer */
876                 if(access_ok(VERIFY_READ, dek_add->dekBlob, sizeof(dek_blob))) {
877                     printf("%s: Starting copy from user %p to kernel %p\n", __FUNCTION__, dek_add->dekBlob, &dek_blob);
878                     if((rv = copy_from_user(&dek_blob, dek_add->dekBlob, sizeof(dek_blob))) != 0) {
879                         printf("%s: Copy error, %d left\n", __FUNCTION__, rv);
880                         return IOCTL_CALL_FAIL;
881                     }
882                     
883                     /* Add DEK to local table */
884                     if (agtiapi_AddDek(pCard, dek_table, dek_index, blob_format, entry_sz, &dek_blob, &addr) < 0) {
885                         return IOCTL_CALL_FAIL;
886                     }
887                     memcpy(addr_table, &addr, sizeof(addr));
888
889                     /* Add DEK-KEK association in local table */
890                     if (agtiapi_MapDekKek(pCard, dek_table, dek_index, kek_index) < 0) {
891                         return IOCTL_CALL_FAIL;
892                     }
893                 
894                     /* Push DEK to chip */    
895                     rc = tiCOMEncryptDekAdd(tiRoot, kek_index, dek_table, addr_table[1], addr_table[0], dek_index, 1, blob_format, entry_sz);
896                 } else {
897                     return IOCTL_CALL_FAIL;
898                 }
899             }
900             break;
901         case IOCTL_MN_ENCRYPTION_DEK_INVALID:
902             {
903                 IoctlEncryptDekInvalidate_t *dek_to_invalidate = (IoctlEncryptDekInvalidate_t *) &ioctl_data->request;
904                 printf("%s: Invalidating dek at index 0x%x, table %x\n", __FUNCTION__, dek_to_invalidate->dek.dekIndex, dek_to_invalidate->dek.dekTable);
905
906                 rc = tiCOMEncryptDekInvalidate(tiRoot, dek_to_invalidate->dek.dekTable, dek_to_invalidate->dek.dekIndex);
907                 /* TODO: What to do in local tables? Mark it? */
908             }
909             break;
910         case IOCTL_MN_ENCRYPTION_KEK_NVRAM:
911             {
912                 rc = tiError;
913             }
914             break;
915         case IOCTL_MN_ENCRYPTION_DEK_ASSIGN:
916             {
917                 IoctlEncryptDekMapTable_t *p_dek_map = (IoctlEncryptDekMapTable_t *) &ioctl_data->request;
918                 
919                 /* Fill in host */
920                 p_dek_map->dekMap[0].host = (bit32) pCard->pHost->host_no;
921
922                 printf("%s: Host %u: Mapping %u:%u:%u (%llx to %llx) to dek at index 0x%x, table %x, keytag %08x:%08x\n", __FUNCTION__, p_dek_map->dekMap[0].host, p_dek_map->dekMap[0].channel, p_dek_map->dekMap[0].device, p_dek_map->dekMap[0].lun, p_dek_map->dekMap[0].dekMapEntry[0].startLBA, p_dek_map->dekMap[0].dekMapEntry[0].endLBA, p_dek_map->dekMap[0].dekMapEntry[0].dek.dekIndex, p_dek_map->dekMap[0].dekMapEntry[0].dek.dekTable, p_dek_map->dekMap[0].keytag[1], p_dek_map->dekMap[0].keytag[0]);
923
924                 /* Create a mapping in local tables */
925                 if (agtiapi_MapDek(pCard, &p_dek_map->dekMap[0]) < 0) {
926                     pIoctlPayload->hdr.Status = IOCTL_ERR_STATUS_INVALID_CODE;
927                     return IOCTL_CALL_FAIL;
928                 }
929
930                 rc = tiSuccess;
931                 skip_wait = 1;
932                 ioctl_data->encryptFunction = encryptSetDekMap;
933                 ioctl_data->status = tiSuccess;
934                 ioctl_data->subEvent = 0;
935             } 
936             break;
937         case IOCTL_MN_ENCRYPTION_ERROR_QUERY:
938             {
939                 unsigned long flags, i, query_flag;
940                 ag_encrypt_ioerr_t *ioerr, *tmp; 
941                 IoctlEncryptErrorQuery_t *perr = (IoctlEncryptErrorQuery_t *) &ioctl_data->request;
942
943                 printf("%s: query flag %x\n", __FUNCTION__, perr->query_flag);
944                 query_flag = perr->query_flag;
945
946                 /* initialize */
947                 memset(perr, 0, sizeof(IoctlEncryptErrorQuery_t));
948
949 error_query_restart:
950                 /* Take spinlock */
951               //  spin_lock_irqsave(&pCard->ioerr_queue_lock, flags);
952                 AG_SPIN_LOCK_IRQ(&pCard->ioerr_queue_lock, flags);  
953                 
954                 /* Walk list */
955                 i = 0;
956                 list_for_each_entry_safe(ioerr, tmp, &pCard->ioerr_queue, list) {
957                     if (i >= 32) 
958                         break;
959                     
960                     perr->valid_mask |= (1 << i);
961                     memcpy(&perr->error[i], &ioerr->ioerr, sizeof(IoctlEncryptIOError_t));
962                     list_del_init(&ioerr->list);
963                     mempool_free(ioerr, pCard->ioerr_mempool);
964                     i++;
965                     atomic_dec(&ioerr_queue_count);
966                 }
967
968                 /* Release spinlock */
969              //   spin_unlock_irqrestore(&pCard->ioerr_queue_lock, flags);
970                 AG_SPIN_UNLOCK_IRQ(&pCard->ioerr_queue_lock, flags); //for test
971
972                 if (!perr->valid_mask) {
973                     /* No encryption IO error events, check flags to see if blocking wait OK */
974                     if (query_flag == ERROR_QUERY_FLAG_BLOCK) {
975                         if (wait_event_interruptible(ioerr_waitq, (atomic_read(&ioerr_queue_count)))) {
976                             /* Awoken by signal */
977                             return IOCTL_CALL_FAIL;
978                         } else {
979                             /* Awoken by IO error */
980                             goto error_query_restart;
981                         }
982                     }
983                 }
984                 rc = tiSuccess;
985                 skip_wait = 1;
986                 ioctl_data->encryptFunction = encryptErrorQuery;
987                 ioctl_data->status = tiSuccess;
988                 ioctl_data->subEvent = 0;
989             }
990             break;
991         default:
992             printf("%s: Unrecognized Minor Function %d\n", __FUNCTION__, pIoctlPayload->hdr.MinorFunction);
993             pIoctlPayload->hdr.Status = IOCTL_ERR_STATUS_INVALID_CODE;
994             return IOCTL_CALL_FAIL;
995             break;
996     }
997
998     /* Demux rc */
999     switch(rc) {
1000         case tiSuccess:
1001             if(!skip_wait)
1002                 wait_for_completion(&pCard->ioctl_completion);
1003                 /* Maybe: wait_for_completion_timeout() */
1004             pIoctlPayload->hdr.Status = ioctl_data->status;
1005             break;
1006         case tiNotSupported:
1007             pIoctlPayload->hdr.Status = IOCTL_ERR_STATUS_NOT_SUPPORTED;
1008             break;
1009         default:
1010             printf("%s: Status: %d\n", __FUNCTION__, rc);
1011             pIoctlPayload->hdr.Status = IOCTL_ERR_STATUS_INVALID_CODE;
1012             break;
1013     }
1014
1015     printf("%s: Encryption ioctl %d successful.\n", __FUNCTION__, pIoctlPayload->hdr.MinorFunction);
1016     return IOCTL_CALL_SUCCESS;
1017 }
1018 #endif
1019 /******************************************************************************
1020 agtiapi_SetupEncryptedIO():
1021
1022 Purpose:
1023 Parameters:
1024 Return:
1025 Note:
1026 ******************************************************************************/
1027 int
1028 agtiapi_SetupEncryptedIO(struct agtiapi_softc *pCard, ccb_t *pccb, unsigned long long block)
1029 {
1030
1031     pCard->cipher_mode = TI_ENCRYPT_ATTRIB_CIPHER_XTS;
1032     /* Check that cipher mode is set properly */
1033     if (pCard->cipher_mode == CIPHER_MODE_INVALID) {
1034         printf("%s: Cipher mode not yet set.\n", __FUNCTION__);
1035         return -E_BAD_CIPHER_MODE;
1036     }
1037
1038     memset(&(pccb->tiSuperScsiRequest.Encrypt), 0, sizeof(pccb->tiSuperScsiRequest.Encrypt));
1039     pccb->tiSuperScsiRequest.Encrypt.keyTagCheck = FALSE;
1040     pccb->tiSuperScsiRequest.Encrypt.encryptMode = pCard->cipher_mode;
1041     pccb->tiSuperScsiRequest.Encrypt.tweakVal_W0 = block; 
1042     if(pccb->tiSuperScsiRequest.scsiCmnd.cdb[0] == READ_16 ||
1043         pccb->tiSuperScsiRequest.scsiCmnd.cdb[0] == WRITE_16)
1044     {
1045         pccb->tiSuperScsiRequest.Encrypt.tweakVal_W0 = ((pccb->tiSuperScsiRequest.scsiCmnd.cdb[6] << 24 ) |
1046                                                            (pccb->tiSuperScsiRequest.scsiCmnd.cdb[7] << 16 ) |
1047                                                            (pccb->tiSuperScsiRequest.scsiCmnd.cdb[8] << 8 ) |
1048                                                            (pccb->tiSuperScsiRequest.scsiCmnd.cdb[9]));
1049     pccb->tiSuperScsiRequest.Encrypt.tweakVal_W1 = ((pccb->tiSuperScsiRequest.scsiCmnd.cdb[2] << 24 ) |
1050                                                            (pccb->tiSuperScsiRequest.scsiCmnd.cdb[3] << 16 ) |
1051                                                            (pccb->tiSuperScsiRequest.scsiCmnd.cdb[4] << 8 ) |
1052                                                            (pccb->tiSuperScsiRequest.scsiCmnd.cdb[5]));
1053     }
1054     /* Mark IO as valid encrypted IO */
1055     pccb->flags |= ENCRYPTED_IO;
1056     pccb->tiSuperScsiRequest.flags = TI_SCSI_INITIATOR_ENCRYPT;
1057
1058     /* Bump refcount (atomic) */
1059     atomic_inc(&outstanding_encrypted_io_count);
1060     return 0;
1061 }
1062
1063 /******************************************************************************
1064 agtiapi_CleanupEncryptedIO():
1065
1066 Purpose:
1067 Parameters:
1068 Return:
1069 Note:
1070 ******************************************************************************/
1071 void
1072 agtiapi_CleanupEncryptedIO(struct agtiapi_softc *pCard, ccb_t *pccb)
1073 {
1074     if ((pccb->flags & ENCRYPTED_IO)) {
1075         /* Decrement refcount */
1076         atomic_dec(&outstanding_encrypted_io_count);
1077     }
1078     pccb->tiSuperScsiRequest.flags &= ~TI_SCSI_INITIATOR_ENCRYPT;
1079     pccb->flags &= ~ENCRYPTED_IO;
1080 }
1081 #ifdef ENCRYPT_ENHANCE
1082 /******************************************************************************
1083 agtiapi_HandleEncryptedIOFailure():
1084
1085 Purpose:
1086 Parameters:
1087 Return:
1088 Note:
1089 ******************************************************************************/
1090 void
1091 agtiapi_HandleEncryptedIOFailure(ag_device_t *pDev, ccb_t *pccb) 
1092 {
1093     unsigned long flags, qdepth;
1094     struct scsi_cmnd *cmd;
1095     ag_encrypt_ioerr_t *perr;
1096     ag_card_t *pCard;
1097
1098     cmd = pccb->cmd;
1099     if (!cmd) {
1100         printf("%s: Malformed pccb %p.\n", __FUNCTION__, pccb);
1101         return;
1102     }
1103
1104     pCard = pDev->pCard;
1105
1106     /* Sanity check */
1107     if (!(pccb->flags & ENCRYPTED_IO)) {
1108         printf("%s: Skipping IO %lx: Not Encrypted.\n", __FUNCTION__, cmd->serial_number);
1109         return;
1110     }
1111
1112     /* Check queue depth against max */
1113     qdepth = atomic_read(&ioerr_queue_count);
1114     if (qdepth >= IOERR_QUEUE_DEPTH_MAX) {
1115         printf("%s: Not queueing IO error due to queue full: %lu entries.\n", __FUNCTION__, qdepth);
1116         return;
1117     }
1118
1119     /* Get a container for the ag_encrypt_ioerr_t item from the mempool */
1120 //    perr = mempool_alloc(pCard->ioerr_mempool, GFP_ATOMIC);     
1121           p = (ag_encrypt_map_t *)uma_zalloc(pCard->map_cache, M_WAITOK); //Encryption
1122     if (!perr) {
1123         printf("%s: Mempool allocation failure.\n", __FUNCTION__);
1124         return;
1125     }
1126
1127     /* Populate ag_encrypt_ioerr_t container */
1128     perr->ioerr.error_id = cmd->serial_number;
1129     perr->ioerr.timestamp = cmd->jiffies_at_alloc;
1130     perr->ioerr.host = (unsigned int) cmd->device->host->host_no;
1131     perr->ioerr.channel = cmd->device->channel;
1132     perr->ioerr.device = cmd->device->id;
1133     perr->ioerr.lun = cmd->device->lun;
1134     perr->ioerr.scsi_cmd = (unsigned int) cmd->cmnd[0];
1135     perr->ioerr.dek_index = pccb->tiSuperScsiRequest.Encrypt.dekInfo.dekIndex;
1136     perr->ioerr.dek_table = pccb->tiSuperScsiRequest.Encrypt.dekInfo.dekTable;
1137     perr->ioerr.kek_index = pccb->tiSuperScsiRequest.Encrypt.kekIndex;
1138     perr->ioerr.keytag_check = pccb->tiSuperScsiRequest.Encrypt.keyTagCheck;
1139     perr->ioerr.encrypt_mode = pccb->tiSuperScsiRequest.Encrypt.encryptMode;
1140     perr->ioerr.keytag[0] = pccb->tiSuperScsiRequest.Encrypt.keyTag_W0;
1141     perr->ioerr.keytag[1] = pccb->tiSuperScsiRequest.Encrypt.keyTag_W1;
1142  
1143     switch(pccb->scsiStatus) {
1144         case tiDetailDekKeyCacheMiss:
1145         case tiDetailDekIVMismatch:
1146             perr->ioerr.error_type = pccb->scsiStatus;
1147             break;
1148         default:
1149             printf("%s: Unrecognized encrypted IO completion error status: %d\n", __FUNCTION__, pccb->scsiStatus);
1150             perr->ioerr.error_type = 0xffffffff;
1151             break;
1152     }
1153
1154     /* Link IO err into queue */
1155     AG_SPIN_LOCK_IRQ(&pCard->ioerr_queue_lock, flags);
1156     list_add_tail(&perr->list, &pCard->ioerr_queue);
1157     AG_SPIN_UNLOCK_IRQ(&pCard->ioerr_queue_lock, flags);   
1158  
1159     /* Notify any wait queue waiters that an IO error has occurred */
1160     atomic_inc(&ioerr_queue_count);
1161     wake_up_interruptible(&ioerr_waitq);    
1162
1163 }
1164 #endif
1165 #endif