00001
00045 #include <buffer.h>
00046 #include <debug.h>
00047 #include <dmapool.h>
00048 #include <interrupt.h>
00049 #include <workqueue.h>
00050 #include <timer_tc.h>
00051 #include <board/init.h>
00052 #include <chip/memory-map.h>
00053 #include <chip/clk.h>
00054 #include <block/device.h>
00055 #include <status-codes.h>
00056 #include <malloc.h>
00057 #include <string.h>
00058 #include <aes.h>
00059 #include <atomic.h>
00060 #include <block/aesblk.h>
00061
00062 static void aesblk_worker(void *data);
00063
00073 void aesblk_init(struct aes_block_device *abdev,
00074 struct block_device *card_bdev)
00075 {
00076 struct block_device *bdev;
00077
00078 bdev = &abdev->bdev;
00079 abdev->card_bdev = card_bdev;
00080
00081 bdev->prepare_req = aesblk_prepare_req;
00082 bdev->alloc_req = aesblk_alloc_req;
00083 bdev->free_req = aesblk_free_req;
00084 }
00085
00091 void aesblk_update(struct aes_block_device *abdev)
00092 {
00093 struct block_device *bdev = &abdev->bdev;
00094 struct block_device *card_bdev = abdev->card_bdev;
00095
00096 bdev->block_size = card_bdev->block_size;
00097 bdev->nr_blocks = card_bdev->nr_blocks;
00098 bdev->flags = card_bdev->flags;
00099 bdev->get_dev_id = card_bdev->get_dev_id;
00100 }
00101
00102 static inline struct aes_block_device *bdev_to_abdev(
00103 struct block_device *bdev)
00104 {
00105 return container_of(bdev, struct aes_block_device, bdev);
00106 }
00107
00108 static inline struct aes_block_request *abreq_of(
00109 struct block_request *req)
00110 {
00111 return container_of(req, struct aes_block_request, breq);
00112 }
00113
00114
00115 static void aesblk_buf_list_decrypt_done(struct aes_request *areq,
00116 struct slist *buf_list, void *context)
00117 {
00118 struct aes_block_request *abreq = context;
00119 struct block_request *breq = &abreq->breq;
00120 unsigned int iflags;
00121
00122 assert(abreq);
00123
00124 iflags = cpu_irq_save();
00125
00126 slist_move_to_tail(&breq->buf_list, buf_list);
00127 aes_free_request(areq);
00128
00129
00130 workqueue_add_item_safe(&main_workqueue, &abreq->worker_item);
00131 abreq->state |= AES_BLK_STATE_LIST_DECRYPTION_DONE;
00132
00133
00134
00135 if (--abreq->buf_counter == 0 && (abreq->state
00136 & AES_BLK_STATE_DECRYPTION_DONE_PENDING)) {
00137 abreq->state &= ~AES_BLK_STATE_DECRYPTION_DONE_PENDING;
00138 abreq->state |= AES_BLK_STATE_REQ_DECRYPTION_DONE;
00139 }
00140 cpu_irq_restore(iflags);
00141 }
00142
00143
00144
00145 static void aesblk_read_buf_list_done(struct block_device *bdev,
00146 struct block_request *breq, struct slist *buf_list)
00147 {
00148 struct aes_block_request *abreq = breq->context;
00149 struct aes_block_device *abdev = abreq->abdev;
00150 struct aes_module *module = &abdev->module;
00151 struct aes_request *areq;
00152
00153
00154
00155 assert(aes_get_cipher(module) == AES_DECRYPT);
00156
00157
00158
00159
00160 abreq->buf_counter++;
00161
00162
00163 areq = aes_alloc_request(module);
00164 aes_prepare_request(areq, buf_list);
00165 areq->req_done = aesblk_buf_list_decrypt_done;
00166 areq->context = abreq;
00167 aes_submit_request(areq);
00168 }
00169
00170
00171
00172 static int aesblk_submit_read_buf_list(struct block_device *bdev,
00173 struct block_request *breq, struct slist *buf_list)
00174 {
00175 struct aes_block_request *abreq = abreq_of(breq);
00176 struct aes_block_device *abdev = bdev_to_abdev(bdev);
00177 struct block_request *card_breq = abreq->card_breq;
00178 unsigned int iflags;
00179
00180 assert(bdev);
00181 assert(bdev == breq->bdev);
00182 assert(breq);
00183 assert(buf_list);
00184 assert(!slist_is_empty(buf_list));
00185
00186 iflags = cpu_irq_save();
00187
00188 slist_move_to_tail(&card_breq->buf_list, buf_list);
00189 cpu_irq_restore(iflags);
00190
00191 return block_submit_buf_list(abdev->card_bdev, card_breq,
00192 &card_breq->buf_list);
00193 }
00194
00195
00196
00197 static void aesblk_req_decrypt_done(struct aes_request *areq,
00198 struct slist *buf_list, void *context)
00199 {
00200 struct aes_block_request *abreq = context;
00201 struct block_request *breq = &abreq->breq;
00202 unsigned int iflags;
00203
00204 assert(areq);
00205
00206 iflags = cpu_irq_save();
00207
00208 if (!slist_is_empty(buf_list))
00209 slist_move_to_tail(&breq->buf_list, buf_list);
00210 aes_free_request(areq);
00211
00212 if (abreq->buf_counter > 0) {
00213
00214
00215 abreq->state |= AES_BLK_STATE_DECRYPTION_DONE_PENDING;
00216 } else {
00217
00218
00219 workqueue_add_item_safe(&main_workqueue, &abreq->worker_item);
00220 abreq->state |= AES_BLK_STATE_REQ_DECRYPTION_DONE;
00221 }
00222 cpu_irq_restore(iflags);
00223 }
00224
00225
00226
00227 static void aesblk_req_data_read(struct block_device *bdev,
00228 struct block_request *card_breq)
00229 {
00230 struct aes_block_request *abreq = card_breq->context;
00231 struct aes_module *module = &abreq->abdev->module;
00232 struct aes_request *areq;
00233
00234 assert(abreq);
00235
00236
00237 areq = aes_alloc_request(module);
00238 aes_prepare_request(areq, &card_breq->buf_list);
00239 areq->req_done = aesblk_req_decrypt_done;
00240 areq->context = abreq;
00241 aes_submit_request(areq);
00242 }
00243
00244
00245 static void aesblk_submit_read_req(struct block_device *bdev,
00246 struct block_request *breq)
00247 {
00248 struct aes_block_request *abreq = abreq_of(breq);
00249 struct aes_block_device *abdev = bdev_to_abdev(bdev);
00250 struct aes_module *module = &abreq->abdev->module;
00251 struct block_request *card_breq = abreq->card_breq;
00252 unsigned int iflags;
00253
00254 iflags = cpu_irq_save();
00255
00256
00257 if (!slist_is_empty(&breq->buf_list))
00258 slist_move_to_tail(&card_breq->buf_list, &breq->buf_list);
00259 cpu_irq_restore(iflags);
00260
00261
00262 aes_set_cipher(module, AES_DECRYPT);
00263
00264 block_submit_req(abdev->card_bdev, card_breq);
00265 }
00266
00267
00268
00269 static void aesblk_write_buf_list_done(struct block_device *bdev,
00270 struct block_request *card_breq, struct slist *buf_list)
00271 {
00272 struct aes_block_request *abreq = card_breq->context;
00273 struct block_request *breq = &abreq->breq;
00274 unsigned int iflags;
00275
00276 assert(!slist_is_empty(buf_list));
00277
00278
00279 assert(card_breq->status == -STATUS_IN_PROGRESS);
00280
00281 iflags = cpu_irq_save();
00282 slist_move_to_tail(&breq->buf_list, buf_list);
00283 workqueue_add_item_safe(&main_workqueue, &abreq->worker_item);
00284 abreq->state |= AES_BLK_STATE_WRITE_LIST_DONE;
00285 cpu_irq_restore(iflags);
00286 }
00287
00288
00289
00290 static void aesblk_buf_list_encrypt_done(struct aes_request *areq,
00291 struct slist *buf_list, void *context)
00292 {
00293 struct aes_block_request *abreq = context;
00294 unsigned int iflags;
00295
00296 assert(abreq);
00297 assert(buf_list);
00298 assert(!slist_is_empty(buf_list));
00299 assert(abreq->card_breq->status == -STATUS_IN_PROGRESS);
00300
00301 iflags = cpu_irq_save();
00302
00303
00304 slist_move_to_tail(&abreq->buf_list, buf_list);
00305 aes_free_request(areq);
00306
00307
00308
00309 workqueue_add_item_safe(&main_workqueue, &abreq->worker_item);
00310 abreq->state |= AES_BLK_STATE_LIST_ENCRYPTION_DONE;
00311 assert(abreq->buf_counter);
00312 cpu_irq_restore(iflags);
00313 }
00314
00315
00316
00317 static int aesblk_submit_write_buf_list(struct block_device *bdev,
00318 struct block_request *breq, struct slist *buf_list)
00319 {
00320 struct aes_block_request *abreq = abreq_of(breq);
00321 struct aes_block_device *abdev = abreq->abdev;
00322 struct aes_module *module = &abdev->module;
00323 struct aes_request *areq;
00324
00325 assert(bdev);
00326 assert(bdev == breq->bdev);
00327 assert(abreq);
00328 assert(buf_list);
00329 assert(!slist_is_empty(buf_list));
00330
00331
00332 assert(aes_get_cipher(module) == AES_ENCRYPT);
00333
00334
00335 areq = aes_alloc_request(&abdev->module);
00336 aes_prepare_request(areq, buf_list);
00337 areq->req_done = aesblk_buf_list_encrypt_done;
00338 areq->context = abreq;
00339 aes_submit_request(areq);
00340
00341 return 0;
00342 }
00343
00344
00345
00346 static void aesblk_req_data_written(struct block_device *bdev,
00347 struct block_request *card_breq)
00348 {
00349 struct aes_block_request *abreq = card_breq->context;
00350 struct block_request *breq = &abreq->breq;
00351 unsigned int iflags;
00352
00353 assert(abreq);
00354
00355
00356 assert(!card_breq->status);
00357
00358 iflags = cpu_irq_save();
00359
00360
00361 if (!slist_is_empty(&card_breq->buf_list))
00362 slist_move_to_tail(&breq->buf_list, &card_breq->buf_list);
00363 workqueue_add_item_safe(&main_workqueue, &abreq->worker_item);
00364 abreq->state |= AES_BLK_STATE_WRITE_REQ_DONE;
00365 cpu_irq_restore(iflags);
00366 }
00367
00368
00369
00370 static void aesblk_req_encrypt_done(struct aes_request *areq,
00371 struct slist *buf_list, void *context)
00372 {
00373 struct aes_block_request *abreq = context;
00374 unsigned int iflags;
00375
00376 assert(abreq);
00377
00378 iflags = cpu_irq_save();
00379
00380
00381 if (!slist_is_empty(buf_list))
00382 slist_move_to_tail(&abreq->buf_list, buf_list);
00383 aes_free_request(areq);
00384
00385
00386 workqueue_add_item_safe(&main_workqueue, &abreq->worker_item);
00387 abreq->state |= AES_BLK_STATE_REQ_ENCRYPTION_DONE;
00388 abreq->buf_counter++;
00389 cpu_irq_restore(iflags);
00390 }
00391
00392
00393 static void aesblk_submit_write_req(struct block_device *bdev,
00394 struct block_request *breq)
00395 {
00396 struct aes_block_request *abreq = abreq_of(breq);
00397 struct aes_block_device *abdev = bdev_to_abdev(bdev);
00398 struct aes_module *module = &abdev->module;
00399 struct aes_request *aes_req;
00400
00401
00402
00403 aes_set_cipher(module, AES_ENCRYPT);
00404
00405 aes_req = aes_alloc_request(module);
00406 aes_prepare_request(aes_req, &abreq->breq.buf_list);
00407 aes_req->req_done = aesblk_req_encrypt_done;
00408 aes_req->context = abreq;
00409 aes_submit_request(aes_req);
00410 }
00411
00412
00413
00414 static void aesblk_worker(void *data)
00415 {
00416 struct aes_block_request *abreq = data;
00417 struct aes_block_device *abdev = abreq->abdev;
00418 struct block_request *breq = &abreq->breq;
00419 struct block_request *card_breq = abreq->card_breq;
00420 struct block_device *card_bdev = abdev->card_bdev;
00421
00422 cpu_irq_disable();
00423 if (abreq->state & AES_BLK_STATE_REQ_ENCRYPTION_DONE) {
00424 abreq->state &= ~AES_BLK_STATE_REQ_ENCRYPTION_DONE;
00425 cpu_irq_enable();
00426 block_submit_req(card_bdev, card_breq);
00427 cpu_irq_disable();
00428 }
00429 if (abreq->state & AES_BLK_STATE_LIST_ENCRYPTION_DONE) {
00430 abreq->state &= ~AES_BLK_STATE_LIST_ENCRYPTION_DONE;
00431 cpu_irq_enable();
00432 assert(abreq->card_breq->status == -STATUS_IN_PROGRESS);
00433 block_submit_buf_list(card_bdev, card_breq, &abreq->buf_list);
00434 cpu_irq_disable();
00435 }
00436 if (abreq->state & AES_BLK_STATE_WRITE_LIST_DONE) {
00437 abreq->state &= ~AES_BLK_STATE_WRITE_LIST_DONE;
00438 if (breq->buf_list_done) {
00439 cpu_irq_enable();
00440 breq->buf_list_done(breq->bdev, breq,
00441 &breq->buf_list);
00442 cpu_irq_disable();
00443 }
00444 }
00445 if (abreq->state & AES_BLK_STATE_WRITE_REQ_DONE) {
00446 breq->status = card_breq->status;
00447 breq->bytes_xfered = card_breq->bytes_xfered;
00448 cpu_irq_enable();
00449 if (breq->req_done)
00450 breq->req_done(&abdev->bdev, &abreq->breq);
00451 cpu_irq_disable();
00452 }
00453
00454 if (abreq->state & AES_BLK_STATE_LIST_DECRYPTION_DONE) {
00455 abreq->state &= ~AES_BLK_STATE_LIST_DECRYPTION_DONE;
00456 cpu_irq_enable();
00457 if (breq->buf_list_done)
00458 breq->buf_list_done(breq->bdev, breq,
00459 &breq->buf_list);
00460 cpu_irq_disable();
00461 }
00462 if (abreq->state & AES_BLK_STATE_REQ_DECRYPTION_DONE) {
00463 abreq->state &= ~AES_BLK_STATE_REQ_DECRYPTION_DONE;
00464 cpu_irq_enable();
00465 breq->status = card_breq->status;
00466 breq->bytes_xfered = card_breq->bytes_xfered;
00467 if (breq->req_done)
00468 breq->req_done(&abdev->bdev, breq);
00469 cpu_irq_disable();
00470 }
00471 cpu_irq_enable();
00472 }
00473
00486 void aesblk_prepare_req(struct block_device *bdev,
00487 struct block_request *breq,
00488 uint32_t lba, uint32_t nr_blocks,
00489 enum block_operation operation)
00490 {
00491 struct aes_block_device *abdev = bdev_to_abdev(bdev);
00492 struct aes_block_request *abreq = abreq_of(breq);
00493 struct block_device *card_bdev = abdev->card_bdev;
00494 struct block_request *card_breq = abreq->card_breq;
00495
00496 dbg_verbose("aes prep req %p: LBA %08x blocks %u op %d\n",
00497 abreq, lba, nr_blocks, operation);
00498
00499 slist_init(&abreq->breq.buf_list);
00500 breq->status = -STATUS_IN_PROGRESS;
00501 breq->bytes_xfered = 0;
00502
00503 breq->bdev = bdev;
00504 abreq->abdev = abdev;
00505 abreq->state = 0;
00506 abreq->buf_counter = 0;
00507 slist_init(&abreq->buf_list);
00508
00509 workqueue_init_item(&abreq->worker_item, aesblk_worker, abreq);
00510
00511 switch (operation) {
00512 case BLK_OP_READ:
00513 block_prepare_req(card_bdev, card_breq,
00514 lba, nr_blocks, operation);
00515 breq->req_submit = aesblk_submit_read_req;
00516 breq->req_submit_buf_list = aesblk_submit_read_buf_list;
00517 card_breq->req_done = aesblk_req_data_read;
00518 card_breq->buf_list_done = aesblk_read_buf_list_done;
00519 break;
00520
00521 case BLK_OP_WRITE:
00522 block_prepare_req(card_bdev, card_breq,
00523 lba, nr_blocks, operation);
00524 breq->req_submit = aesblk_submit_write_req;
00525 breq->req_submit_buf_list = aesblk_submit_write_buf_list;
00526 card_breq->req_done = aesblk_req_data_written;
00527 card_breq->buf_list_done = aesblk_write_buf_list_done;
00528 break;
00529
00530 default:
00531 unhandled_case(operation);
00532 }
00533
00534 card_breq->context = abreq;
00535 }
00536
00547 struct block_request *aesblk_alloc_req(struct block_device *bdev)
00548 {
00549 struct aes_block_request *abreq;
00550 struct aes_block_device *abdev = bdev_to_abdev(bdev);
00551
00552 abreq = malloc(sizeof(struct aes_block_request));
00553 if (unlikely(!abreq))
00554 goto err_aes;
00555
00556 memset(abreq, 0, sizeof(struct aes_block_request));
00557 abreq->card_breq = block_alloc_request(abdev->card_bdev);
00558 if (unlikely(!abreq->card_breq))
00559 goto err_card;
00560
00561 return &abreq->breq;
00562
00563 err_card:
00564 free(abreq);
00565 err_aes:
00566 return NULL;
00567 }
00568
00576 void aesblk_free_req(struct block_device *bdev,
00577 struct block_request *breq)
00578 {
00579 struct aes_block_request *abreq = abreq_of(breq);
00580
00581 block_free_request(abreq->abdev->card_bdev, abreq->card_breq);
00582 free(abreq);
00583 }