aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Haverkamp <markh@linux-foundation.org>2007-03-15 13:27:32 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-03-20 11:55:40 -0400
commitf2b1a06ad46209c6e631e3099138d1fa3f14d3a8 (patch)
tree37310a406089a30fbe4f587668fdc8ce9738e7a9 /drivers
parent9e7c349c91db3a9f9ac6cd74a693c4093c7d4571 (diff)
[SCSI] aacraid: fix srb ioctl for 64 bits
Received from Mark Salyzyn, The raw srb ioctl is supposed to be able to take packets with 32 and 64 bit virtual address SG elements, it did not handle the frames with 64 bit SG elements well when communicating with 64 bit DMA capable adapters, and it did not handle the 32 bit limited DMA adapters at all. The enclosed patch now handles all four quadrants (32 bit / 64 bit SG elements in SRB requests + 32 bit or 64 bit DMA capable adapters) This fix is required before Java based management applications in a 64 bit user space can submit raw srb requests to the array physical components via the ioctl mechanism, the allocated user memory pool on 64 bit machines under this environment forced the management software's hands to submit 64 bit user space virtual address SG elements in via the ioctl. Signed-off-by: Mark Haverkamp <markh@linux-foundation.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/aacraid/commctrl.c259
1 files changed, 157 insertions, 102 deletions
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 3a8e7cac9ee2..987e35e4078e 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -5,7 +5,7 @@
5 * based on the old aacraid driver that is.. 5 * based on the old aacraid driver that is..
6 * Adaptec aacraid device driver for Linux. 6 * Adaptec aacraid device driver for Linux.
7 * 7 *
8 * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) 8 * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -468,7 +468,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
468 void *sg_list[32]; 468 void *sg_list[32];
469 u32 sg_indx = 0; 469 u32 sg_indx = 0;
470 u32 byte_count = 0; 470 u32 byte_count = 0;
471 u32 actual_fibsize = 0; 471 u32 actual_fibsize64, actual_fibsize = 0;
472 int i; 472 int i;
473 473
474 474
@@ -481,7 +481,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
481 return -EPERM; 481 return -EPERM;
482 } 482 }
483 /* 483 /*
484 * Allocate and initialize a Fib then setup a BlockWrite command 484 * Allocate and initialize a Fib then setup a SRB command
485 */ 485 */
486 if (!(srbfib = aac_fib_alloc(dev))) { 486 if (!(srbfib = aac_fib_alloc(dev))) {
487 return -ENOMEM; 487 return -ENOMEM;
@@ -548,129 +548,183 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
548 rcode = -EINVAL; 548 rcode = -EINVAL;
549 goto cleanup; 549 goto cleanup;
550 } 550 }
551 if (dev->dac_support == 1) { 551 actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) +
552 ((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry));
553 actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) *
554 (sizeof(struct sgentry64) - sizeof(struct sgentry));
555 /* User made a mistake - should not continue */
556 if ((actual_fibsize != fibsize) && (actual_fibsize64 != fibsize)) {
557 dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
558 "Raw SRB command calculated fibsize=%lu;%lu "
559 "user_srbcmd->sg.count=%d aac_srb=%lu sgentry=%lu;%lu "
560 "issued fibsize=%d\n",
561 actual_fibsize, actual_fibsize64, user_srbcmd->sg.count,
562 sizeof(struct aac_srb), sizeof(struct sgentry),
563 sizeof(struct sgentry64), fibsize));
564 rcode = -EINVAL;
565 goto cleanup;
566 }
567 if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
568 dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
569 rcode = -EINVAL;
570 goto cleanup;
571 }
572 byte_count = 0;
573 if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
552 struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg; 574 struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
553 struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; 575 struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
554 struct user_sgmap* usg;
555 byte_count = 0;
556 576
557 /* 577 /*
558 * This should also catch if user used the 32 bit sgmap 578 * This should also catch if user used the 32 bit sgmap
559 */ 579 */
560 actual_fibsize = sizeof(struct aac_srb) - 580 if (actual_fibsize64 == fibsize) {
561 sizeof(struct sgentry) + 581 actual_fibsize = actual_fibsize64;
562 ((upsg->count & 0xff) * 582 for (i = 0; i < upsg->count; i++) {
563 sizeof(struct sgentry)); 583 u64 addr;
564 if(actual_fibsize != fibsize){ // User made a mistake - should not continue 584 void* p;
565 dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n")); 585 /* Does this really need to be GFP_DMA? */
566 rcode = -EINVAL; 586 p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA);
567 goto cleanup; 587 if(p == 0) {
568 } 588 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
569 usg = kmalloc(actual_fibsize - sizeof(struct aac_srb) 589 upsg->sg[i].count,i,upsg->count));
570 + sizeof(struct sgmap), GFP_KERNEL); 590 rcode = -ENOMEM;
571 if (!usg) { 591 goto cleanup;
572 dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n")); 592 }
573 rcode = -ENOMEM; 593 addr = (u64)upsg->sg[i].addr[0];
574 goto cleanup; 594 addr += ((u64)upsg->sg[i].addr[1]) << 32;
575 } 595 sg_user[i] = (void __user *)(ptrdiff_t)addr;
576 memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb) 596 sg_list[i] = p; // save so we can clean up later
577 + sizeof(struct sgmap)); 597 sg_indx = i;
578 actual_fibsize = sizeof(struct aac_srb) - 598
579 sizeof(struct sgentry) + ((usg->count & 0xff) * 599 if( flags & SRB_DataOut ){
580 sizeof(struct sgentry64)); 600 if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
581 if ((data_dir == DMA_NONE) && upsg->count) { 601 dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
582 kfree (usg); 602 rcode = -EFAULT;
583 dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n")); 603 goto cleanup;
584 rcode = -EINVAL; 604 }
585 goto cleanup; 605 }
586 } 606 addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir);
587 607
588 for (i = 0; i < usg->count; i++) { 608 psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
589 u64 addr; 609 psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
590 void* p; 610 byte_count += upsg->sg[i].count;
591 /* Does this really need to be GFP_DMA? */ 611 psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
592 p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); 612 }
593 if(p == 0) { 613 } else {
594 kfree (usg); 614 struct user_sgmap* usg;
595 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 615 usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
596 usg->sg[i].count,i,usg->count)); 616 + sizeof(struct sgmap), GFP_KERNEL);
617 if (!usg) {
618 dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
597 rcode = -ENOMEM; 619 rcode = -ENOMEM;
598 goto cleanup; 620 goto cleanup;
599 } 621 }
600 sg_user[i] = (void __user *)(long)usg->sg[i].addr; 622 memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
601 sg_list[i] = p; // save so we can clean up later 623 + sizeof(struct sgmap));
602 sg_indx = i; 624 actual_fibsize = actual_fibsize64;
603 625
604 if( flags & SRB_DataOut ){ 626 for (i = 0; i < usg->count; i++) {
605 if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ 627 u64 addr;
628 void* p;
629 /* Does this really need to be GFP_DMA? */
630 p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
631 if(p == 0) {
606 kfree (usg); 632 kfree (usg);
607 dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 633 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
608 rcode = -EFAULT; 634 usg->sg[i].count,i,usg->count));
635 rcode = -ENOMEM;
609 goto cleanup; 636 goto cleanup;
610 } 637 }
611 } 638 sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr;
612 addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir); 639 sg_list[i] = p; // save so we can clean up later
640 sg_indx = i;
641
642 if( flags & SRB_DataOut ){
643 if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
644 kfree (usg);
645 dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
646 rcode = -EFAULT;
647 goto cleanup;
648 }
649 }
650 addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
613 651
614 psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); 652 psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
615 psg->sg[i].addr[1] = cpu_to_le32(addr>>32); 653 psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
616 psg->sg[i].count = cpu_to_le32(usg->sg[i].count); 654 byte_count += usg->sg[i].count;
617 byte_count += usg->sg[i].count; 655 psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
656 }
657 kfree (usg);
618 } 658 }
619 kfree (usg);
620
621 srbcmd->count = cpu_to_le32(byte_count); 659 srbcmd->count = cpu_to_le32(byte_count);
622 psg->count = cpu_to_le32(sg_indx+1); 660 psg->count = cpu_to_le32(sg_indx+1);
623 status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); 661 status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
624 } else { 662 } else {
625 struct user_sgmap* upsg = &user_srbcmd->sg; 663 struct user_sgmap* upsg = &user_srbcmd->sg;
626 struct sgmap* psg = &srbcmd->sg; 664 struct sgmap* psg = &srbcmd->sg;
627 byte_count = 0; 665
628 666 if (actual_fibsize64 == fibsize) {
629 actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); 667 struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;
630 if(actual_fibsize != fibsize){ // User made a mistake - should not continue 668 for (i = 0; i < upsg->count; i++) {
631 dprintk((KERN_DEBUG"aacraid: Bad Size specified in " 669 u64 addr;
632 "Raw SRB command calculated fibsize=%d " 670 void* p;
633 "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d " 671 /* Does this really need to be GFP_DMA? */
634 "issued fibsize=%d\n", 672 p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
635 actual_fibsize, user_srbcmd->sg.count, 673 if(p == 0) {
636 sizeof(struct aac_srb), sizeof(struct sgentry), 674 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
637 fibsize)); 675 usg->sg[i].count,i,usg->count));
638 rcode = -EINVAL; 676 rcode = -ENOMEM;
639 goto cleanup;
640 }
641 if ((data_dir == DMA_NONE) && upsg->count) {
642 dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
643 rcode = -EINVAL;
644 goto cleanup;
645 }
646 for (i = 0; i < upsg->count; i++) {
647 dma_addr_t addr;
648 void* p;
649 p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
650 if(p == 0) {
651 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
652 upsg->sg[i].count, i, upsg->count));
653 rcode = -ENOMEM;
654 goto cleanup;
655 }
656 sg_user[i] = (void __user *)(long)upsg->sg[i].addr;
657 sg_list[i] = p; // save so we can clean up later
658 sg_indx = i;
659
660 if( flags & SRB_DataOut ){
661 if(copy_from_user(p, sg_user[i],
662 upsg->sg[i].count)) {
663 dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
664 rcode = -EFAULT;
665 goto cleanup; 677 goto cleanup;
666 } 678 }
679 addr = (u64)usg->sg[i].addr[0];
680 addr += ((u64)usg->sg[i].addr[1]) << 32;
681 sg_user[i] = (void __user *)(ptrdiff_t)addr;
682 sg_list[i] = p; // save so we can clean up later
683 sg_indx = i;
684
685 if( flags & SRB_DataOut ){
686 if(copy_from_user(p,sg_user[i],usg->sg[i].count)){
687 dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
688 rcode = -EFAULT;
689 goto cleanup;
690 }
691 }
692 addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
693
694 psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
695 byte_count += usg->sg[i].count;
696 psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
667 } 697 }
668 addr = pci_map_single(dev->pdev, p, 698 } else {
669 upsg->sg[i].count, data_dir); 699 for (i = 0; i < upsg->count; i++) {
700 dma_addr_t addr;
701 void* p;
702 p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
703 if(p == 0) {
704 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
705 upsg->sg[i].count, i, upsg->count));
706 rcode = -ENOMEM;
707 goto cleanup;
708 }
709 sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr;
710 sg_list[i] = p; // save so we can clean up later
711 sg_indx = i;
712
713 if( flags & SRB_DataOut ){
714 if(copy_from_user(p, sg_user[i],
715 upsg->sg[i].count)) {
716 dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
717 rcode = -EFAULT;
718 goto cleanup;
719 }
720 }
721 addr = pci_map_single(dev->pdev, p,
722 upsg->sg[i].count, data_dir);
670 723
671 psg->sg[i].addr = cpu_to_le32(addr); 724 psg->sg[i].addr = cpu_to_le32(addr);
672 psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); 725 byte_count += upsg->sg[i].count;
673 byte_count += upsg->sg[i].count; 726 psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
727 }
674 } 728 }
675 srbcmd->count = cpu_to_le32(byte_count); 729 srbcmd->count = cpu_to_le32(byte_count);
676 psg->count = cpu_to_le32(sg_indx+1); 730 psg->count = cpu_to_le32(sg_indx+1);
@@ -689,7 +743,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
689 743
690 if( flags & SRB_DataIn ) { 744 if( flags & SRB_DataIn ) {
691 for(i = 0 ; i <= sg_indx; i++){ 745 for(i = 0 ; i <= sg_indx; i++){
692 byte_count = le32_to_cpu((dev->dac_support == 1) 746 byte_count = le32_to_cpu(
747 (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)
693 ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count 748 ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
694 : srbcmd->sg.sg[i].count); 749 : srbcmd->sg.sg[i].count);
695 if(copy_to_user(sg_user[i], sg_list[i], byte_count)){ 750 if(copy_to_user(sg_user[i], sg_list[i], byte_count)){