diff options
author | Markus Lidel <Markus.Lidel@shadowconnect.com> | 2005-06-24 01:02:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:28 -0400 |
commit | 61fbfa8129c1771061a0e9f47747854293081c5b (patch) | |
tree | 03fe14c41e2a49d3841ae6820a2dd43a91fddee9 /drivers/message/i2o/i2o_config.c | |
parent | 34d6e07570ef74b965131452a862b13dfa779188 (diff) |
[PATCH] I2O: bugfixes and compability enhancements
Changes:
- Fixed sysfs bug where user and parent links where added to the I2O
device itself
- Fixed bug when calculating TID for the event handler and cleaned up the
workflow of i2o_driver_dispatch()
- Fixed oops when no I2O device could be found for an event delivered to
Exec-OSM
- Fixed initialization of spinlock in Exec-OSM
- Fixed memory leak in i2o_cfg_passthru() and i2o_cfg_passthru()
- Removed MTRR support
- Added PCI ID of Promise SX6000 with firmware >= 1.20.x.x
- Turn of caching for ioremapped memory of in_queue
- Added initialization sequence for Promise controllers
- Moved definition of u8 / u16 / u32 for raidutils before first use
Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/message/i2o/i2o_config.c')
-rw-r--r-- | drivers/message/i2o/i2o_config.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 1fb5cdf67f8f..46d373287a30 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -555,6 +555,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
555 | u32 sg_offset = 0; | 555 | u32 sg_offset = 0; |
556 | u32 sg_count = 0; | 556 | u32 sg_count = 0; |
557 | u32 i = 0; | 557 | u32 i = 0; |
558 | u32 sg_index = 0; | ||
558 | i2o_status_block *sb; | 559 | i2o_status_block *sb; |
559 | struct i2o_message *msg; | 560 | struct i2o_message *msg; |
560 | u32 m; | 561 | u32 m; |
@@ -634,8 +635,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
634 | if (sg_count > SG_TABLESIZE) { | 635 | if (sg_count > SG_TABLESIZE) { |
635 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", | 636 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", |
636 | c->name, sg_count); | 637 | c->name, sg_count); |
637 | kfree(reply); | 638 | rcode = -EINVAL; |
638 | return -EINVAL; | 639 | goto cleanup; |
639 | } | 640 | } |
640 | 641 | ||
641 | for (i = 0; i < sg_count; i++) { | 642 | for (i = 0; i < sg_count; i++) { |
@@ -651,7 +652,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
651 | goto cleanup; | 652 | goto cleanup; |
652 | } | 653 | } |
653 | sg_size = sg[i].flag_count & 0xffffff; | 654 | sg_size = sg[i].flag_count & 0xffffff; |
654 | p = &(sg_list[i]); | 655 | p = &(sg_list[sg_index++]); |
655 | /* Allocate memory for the transfer */ | 656 | /* Allocate memory for the transfer */ |
656 | if (i2o_dma_alloc | 657 | if (i2o_dma_alloc |
657 | (&c->pdev->dev, p, sg_size, | 658 | (&c->pdev->dev, p, sg_size, |
@@ -660,7 +661,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
660 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 661 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
661 | c->name, sg_size, i, sg_count); | 662 | c->name, sg_size, i, sg_count); |
662 | rcode = -ENOMEM; | 663 | rcode = -ENOMEM; |
663 | goto cleanup; | 664 | goto sg_list_cleanup; |
664 | } | 665 | } |
665 | /* Copy in the user's SG buffer if necessary */ | 666 | /* Copy in the user's SG buffer if necessary */ |
666 | if (sg[i]. | 667 | if (sg[i]. |
@@ -673,7 +674,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
673 | "%s: Could not copy SG buf %d FROM user\n", | 674 | "%s: Could not copy SG buf %d FROM user\n", |
674 | c->name, i); | 675 | c->name, i); |
675 | rcode = -EFAULT; | 676 | rcode = -EFAULT; |
676 | goto cleanup; | 677 | goto sg_list_cleanup; |
677 | } | 678 | } |
678 | } | 679 | } |
679 | //TODO 64bit fix | 680 | //TODO 64bit fix |
@@ -683,10 +684,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
683 | 684 | ||
684 | rcode = i2o_msg_post_wait(c, m, 60); | 685 | rcode = i2o_msg_post_wait(c, m, 60); |
685 | if (rcode) | 686 | if (rcode) |
686 | goto cleanup; | 687 | goto sg_list_cleanup; |
687 | 688 | ||
688 | if (sg_offset) { | 689 | if (sg_offset) { |
689 | u32 msg[128]; | 690 | u32 msg[MSG_FRAME_SIZE]; |
690 | /* Copy back the Scatter Gather buffers back to user space */ | 691 | /* Copy back the Scatter Gather buffers back to user space */ |
691 | u32 j; | 692 | u32 j; |
692 | // TODO 64bit fix | 693 | // TODO 64bit fix |
@@ -698,14 +699,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
698 | // get user msg size in u32s | 699 | // get user msg size in u32s |
699 | if (get_user(size, &user_msg[0])) { | 700 | if (get_user(size, &user_msg[0])) { |
700 | rcode = -EFAULT; | 701 | rcode = -EFAULT; |
701 | goto cleanup; | 702 | goto sg_list_cleanup; |
702 | } | 703 | } |
703 | size = size >> 16; | 704 | size = size >> 16; |
704 | size *= 4; | 705 | size *= 4; |
705 | /* Copy in the user's I2O command */ | 706 | /* Copy in the user's I2O command */ |
706 | if (copy_from_user(msg, user_msg, size)) { | 707 | if (copy_from_user(msg, user_msg, size)) { |
707 | rcode = -EFAULT; | 708 | rcode = -EFAULT; |
708 | goto cleanup; | 709 | goto sg_list_cleanup; |
709 | } | 710 | } |
710 | sg_count = | 711 | sg_count = |
711 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 712 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
@@ -727,7 +728,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
727 | c->name, sg_list[j].virt, | 728 | c->name, sg_list[j].virt, |
728 | sg[j].addr_bus); | 729 | sg[j].addr_bus); |
729 | rcode = -EFAULT; | 730 | rcode = -EFAULT; |
730 | goto cleanup; | 731 | goto sg_list_cleanup; |
731 | } | 732 | } |
732 | } | 733 | } |
733 | } | 734 | } |
@@ -741,6 +742,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
741 | "%s: Could not copy message context FROM user\n", | 742 | "%s: Could not copy message context FROM user\n", |
742 | c->name); | 743 | c->name); |
743 | rcode = -EFAULT; | 744 | rcode = -EFAULT; |
745 | goto sg_list_cleanup; | ||
744 | } | 746 | } |
745 | if (copy_to_user(user_reply, reply, reply_size)) { | 747 | if (copy_to_user(user_reply, reply, reply_size)) { |
746 | printk(KERN_WARNING | 748 | printk(KERN_WARNING |
@@ -749,6 +751,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
749 | } | 751 | } |
750 | } | 752 | } |
751 | 753 | ||
754 | sg_list_cleanup: | ||
755 | for (i = 0; i < sg_index; i++) | ||
756 | i2o_dma_free(&c->pdev->dev, &sg_list[i]); | ||
757 | |||
752 | cleanup: | 758 | cleanup: |
753 | kfree(reply); | 759 | kfree(reply); |
754 | return rcode; | 760 | return rcode; |
@@ -862,8 +868,8 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
862 | if (sg_count > SG_TABLESIZE) { | 868 | if (sg_count > SG_TABLESIZE) { |
863 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", | 869 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", |
864 | c->name, sg_count); | 870 | c->name, sg_count); |
865 | kfree(reply); | 871 | rcode = -EINVAL; |
866 | return -EINVAL; | 872 | goto cleanup; |
867 | } | 873 | } |
868 | 874 | ||
869 | for (i = 0; i < sg_count; i++) { | 875 | for (i = 0; i < sg_count; i++) { |
@@ -875,7 +881,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
875 | "%s:Bad SG element %d - not simple (%x)\n", | 881 | "%s:Bad SG element %d - not simple (%x)\n", |
876 | c->name, i, sg[i].flag_count); | 882 | c->name, i, sg[i].flag_count); |
877 | rcode = -EINVAL; | 883 | rcode = -EINVAL; |
878 | goto cleanup; | 884 | goto sg_list_cleanup; |
879 | } | 885 | } |
880 | sg_size = sg[i].flag_count & 0xffffff; | 886 | sg_size = sg[i].flag_count & 0xffffff; |
881 | /* Allocate memory for the transfer */ | 887 | /* Allocate memory for the transfer */ |
@@ -885,7 +891,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
885 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 891 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
886 | c->name, sg_size, i, sg_count); | 892 | c->name, sg_size, i, sg_count); |
887 | rcode = -ENOMEM; | 893 | rcode = -ENOMEM; |
888 | goto cleanup; | 894 | goto sg_list_cleanup; |
889 | } | 895 | } |
890 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. | 896 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. |
891 | /* Copy in the user's SG buffer if necessary */ | 897 | /* Copy in the user's SG buffer if necessary */ |
@@ -899,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
899 | "%s: Could not copy SG buf %d FROM user\n", | 905 | "%s: Could not copy SG buf %d FROM user\n", |
900 | c->name, i); | 906 | c->name, i); |
901 | rcode = -EFAULT; | 907 | rcode = -EFAULT; |
902 | goto cleanup; | 908 | goto sg_list_cleanup; |
903 | } | 909 | } |
904 | } | 910 | } |
905 | //TODO 64bit fix | 911 | //TODO 64bit fix |
@@ -909,7 +915,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
909 | 915 | ||
910 | rcode = i2o_msg_post_wait(c, m, 60); | 916 | rcode = i2o_msg_post_wait(c, m, 60); |
911 | if (rcode) | 917 | if (rcode) |
912 | goto cleanup; | 918 | goto sg_list_cleanup; |
913 | 919 | ||
914 | if (sg_offset) { | 920 | if (sg_offset) { |
915 | u32 msg[128]; | 921 | u32 msg[128]; |
@@ -924,14 +930,14 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
924 | // get user msg size in u32s | 930 | // get user msg size in u32s |
925 | if (get_user(size, &user_msg[0])) { | 931 | if (get_user(size, &user_msg[0])) { |
926 | rcode = -EFAULT; | 932 | rcode = -EFAULT; |
927 | goto cleanup; | 933 | goto sg_list_cleanup; |
928 | } | 934 | } |
929 | size = size >> 16; | 935 | size = size >> 16; |
930 | size *= 4; | 936 | size *= 4; |
931 | /* Copy in the user's I2O command */ | 937 | /* Copy in the user's I2O command */ |
932 | if (copy_from_user(msg, user_msg, size)) { | 938 | if (copy_from_user(msg, user_msg, size)) { |
933 | rcode = -EFAULT; | 939 | rcode = -EFAULT; |
934 | goto cleanup; | 940 | goto sg_list_cleanup; |
935 | } | 941 | } |
936 | sg_count = | 942 | sg_count = |
937 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 943 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
@@ -953,7 +959,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
953 | c->name, sg_list[j], | 959 | c->name, sg_list[j], |
954 | sg[j].addr_bus); | 960 | sg[j].addr_bus); |
955 | rcode = -EFAULT; | 961 | rcode = -EFAULT; |
956 | goto cleanup; | 962 | goto sg_list_cleanup; |
957 | } | 963 | } |
958 | } | 964 | } |
959 | } | 965 | } |
@@ -975,6 +981,10 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
975 | } | 981 | } |
976 | } | 982 | } |
977 | 983 | ||
984 | sg_list_cleanup: | ||
985 | for (i = 0; i < sg_index; i++) | ||
986 | kfree(sg_list[i]); | ||
987 | |||
978 | cleanup: | 988 | cleanup: |
979 | kfree(reply); | 989 | kfree(reply); |
980 | return rcode; | 990 | return rcode; |