diff options
Diffstat (limited to 'drivers/message/i2o/i2o_config.c')
| -rw-r--r-- | drivers/message/i2o/i2o_config.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 8ba275a12773..84e046e94f5f 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
| @@ -554,8 +554,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 554 | return -ENXIO; | 554 | return -ENXIO; |
| 555 | } | 555 | } |
| 556 | 556 | ||
| 557 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | ||
| 558 | |||
| 559 | sb = c->status_block.virt; | 557 | sb = c->status_block.virt; |
| 560 | 558 | ||
| 561 | if (get_user(size, &user_msg[0])) { | 559 | if (get_user(size, &user_msg[0])) { |
| @@ -573,24 +571,30 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 573 | 571 | ||
| 574 | size <<= 2; // Convert to bytes | 572 | size <<= 2; // Convert to bytes |
| 575 | 573 | ||
| 574 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | ||
| 575 | if (IS_ERR(msg)) | ||
| 576 | return PTR_ERR(msg); | ||
| 577 | |||
| 578 | rcode = -EFAULT; | ||
| 576 | /* Copy in the user's I2O command */ | 579 | /* Copy in the user's I2O command */ |
| 577 | if (copy_from_user(msg, user_msg, size)) { | 580 | if (copy_from_user(msg, user_msg, size)) { |
| 578 | osm_warn("unable to copy user message\n"); | 581 | osm_warn("unable to copy user message\n"); |
| 579 | return -EFAULT; | 582 | goto out; |
| 580 | } | 583 | } |
| 581 | i2o_dump_message(msg); | 584 | i2o_dump_message(msg); |
| 582 | 585 | ||
| 583 | if (get_user(reply_size, &user_reply[0]) < 0) | 586 | if (get_user(reply_size, &user_reply[0]) < 0) |
| 584 | return -EFAULT; | 587 | goto out; |
| 585 | 588 | ||
| 586 | reply_size >>= 16; | 589 | reply_size >>= 16; |
| 587 | reply_size <<= 2; | 590 | reply_size <<= 2; |
| 588 | 591 | ||
| 592 | rcode = -ENOMEM; | ||
| 589 | reply = kzalloc(reply_size, GFP_KERNEL); | 593 | reply = kzalloc(reply_size, GFP_KERNEL); |
| 590 | if (!reply) { | 594 | if (!reply) { |
| 591 | printk(KERN_WARNING "%s: Could not allocate reply buffer\n", | 595 | printk(KERN_WARNING "%s: Could not allocate reply buffer\n", |
| 592 | c->name); | 596 | c->name); |
| 593 | return -ENOMEM; | 597 | goto out; |
| 594 | } | 598 | } |
| 595 | 599 | ||
| 596 | sg_offset = (msg->u.head[0] >> 4) & 0x0f; | 600 | sg_offset = (msg->u.head[0] >> 4) & 0x0f; |
| @@ -661,13 +665,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 661 | } | 665 | } |
| 662 | 666 | ||
| 663 | rcode = i2o_msg_post_wait(c, msg, 60); | 667 | rcode = i2o_msg_post_wait(c, msg, 60); |
| 668 | msg = NULL; | ||
| 664 | if (rcode) { | 669 | if (rcode) { |
| 665 | reply[4] = ((u32) rcode) << 24; | 670 | reply[4] = ((u32) rcode) << 24; |
| 666 | goto sg_list_cleanup; | 671 | goto sg_list_cleanup; |
| 667 | } | 672 | } |
| 668 | 673 | ||
| 669 | if (sg_offset) { | 674 | if (sg_offset) { |
| 670 | u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; | 675 | u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; |
| 671 | /* Copy back the Scatter Gather buffers back to user space */ | 676 | /* Copy back the Scatter Gather buffers back to user space */ |
| 672 | u32 j; | 677 | u32 j; |
| 673 | // TODO 64bit fix | 678 | // TODO 64bit fix |
| @@ -675,7 +680,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 675 | int sg_size; | 680 | int sg_size; |
| 676 | 681 | ||
| 677 | // re-acquire the original message to handle correctly the sg copy operation | 682 | // re-acquire the original message to handle correctly the sg copy operation |
| 678 | memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); | 683 | memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); |
| 679 | // get user msg size in u32s | 684 | // get user msg size in u32s |
| 680 | if (get_user(size, &user_msg[0])) { | 685 | if (get_user(size, &user_msg[0])) { |
| 681 | rcode = -EFAULT; | 686 | rcode = -EFAULT; |
| @@ -684,7 +689,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 684 | size = size >> 16; | 689 | size = size >> 16; |
| 685 | size *= 4; | 690 | size *= 4; |
| 686 | /* Copy in the user's I2O command */ | 691 | /* Copy in the user's I2O command */ |
| 687 | if (copy_from_user(msg, user_msg, size)) { | 692 | if (copy_from_user(rmsg, user_msg, size)) { |
| 688 | rcode = -EFAULT; | 693 | rcode = -EFAULT; |
| 689 | goto sg_list_cleanup; | 694 | goto sg_list_cleanup; |
| 690 | } | 695 | } |
| @@ -692,7 +697,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 692 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 697 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
| 693 | 698 | ||
| 694 | // TODO 64bit fix | 699 | // TODO 64bit fix |
| 695 | sg = (struct sg_simple_element *)(msg + sg_offset); | 700 | sg = (struct sg_simple_element *)(rmsg + sg_offset); |
| 696 | for (j = 0; j < sg_count; j++) { | 701 | for (j = 0; j < sg_count; j++) { |
| 697 | /* Copy out the SG list to user's buffer if necessary */ | 702 | /* Copy out the SG list to user's buffer if necessary */ |
| 698 | if (! | 703 | if (! |
| @@ -714,7 +719,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 714 | } | 719 | } |
| 715 | } | 720 | } |
| 716 | 721 | ||
| 717 | sg_list_cleanup: | 722 | sg_list_cleanup: |
| 718 | /* Copy back the reply to user space */ | 723 | /* Copy back the reply to user space */ |
| 719 | if (reply_size) { | 724 | if (reply_size) { |
| 720 | // we wrote our own values for context - now restore the user supplied ones | 725 | // we wrote our own values for context - now restore the user supplied ones |
| @@ -723,7 +728,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 723 | "%s: Could not copy message context FROM user\n", | 728 | "%s: Could not copy message context FROM user\n", |
| 724 | c->name); | 729 | c->name); |
| 725 | rcode = -EFAULT; | 730 | rcode = -EFAULT; |
| 726 | goto sg_list_cleanup; | ||
| 727 | } | 731 | } |
| 728 | if (copy_to_user(user_reply, reply, reply_size)) { | 732 | if (copy_to_user(user_reply, reply, reply_size)) { |
| 729 | printk(KERN_WARNING | 733 | printk(KERN_WARNING |
| @@ -731,12 +735,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, | |||
| 731 | rcode = -EFAULT; | 735 | rcode = -EFAULT; |
| 732 | } | 736 | } |
| 733 | } | 737 | } |
| 734 | |||
| 735 | for (i = 0; i < sg_index; i++) | 738 | for (i = 0; i < sg_index; i++) |
| 736 | i2o_dma_free(&c->pdev->dev, &sg_list[i]); | 739 | i2o_dma_free(&c->pdev->dev, &sg_list[i]); |
| 737 | 740 | ||
| 738 | cleanup: | 741 | cleanup: |
| 739 | kfree(reply); | 742 | kfree(reply); |
| 743 | out: | ||
| 744 | if (msg) | ||
| 745 | i2o_msg_nop(c, msg); | ||
| 740 | return rcode; | 746 | return rcode; |
| 741 | } | 747 | } |
| 742 | 748 | ||
| @@ -793,8 +799,6 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 793 | return -ENXIO; | 799 | return -ENXIO; |
| 794 | } | 800 | } |
| 795 | 801 | ||
| 796 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | ||
| 797 | |||
| 798 | sb = c->status_block.virt; | 802 | sb = c->status_block.virt; |
| 799 | 803 | ||
| 800 | if (get_user(size, &user_msg[0])) | 804 | if (get_user(size, &user_msg[0])) |
| @@ -810,12 +814,17 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 810 | 814 | ||
| 811 | size <<= 2; // Convert to bytes | 815 | size <<= 2; // Convert to bytes |
| 812 | 816 | ||
| 817 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | ||
| 818 | if (IS_ERR(msg)) | ||
| 819 | return PTR_ERR(msg); | ||
| 820 | |||
| 821 | rcode = -EFAULT; | ||
| 813 | /* Copy in the user's I2O command */ | 822 | /* Copy in the user's I2O command */ |
| 814 | if (copy_from_user(msg, user_msg, size)) | 823 | if (copy_from_user(msg, user_msg, size)) |
| 815 | return -EFAULT; | 824 | goto out; |
| 816 | 825 | ||
| 817 | if (get_user(reply_size, &user_reply[0]) < 0) | 826 | if (get_user(reply_size, &user_reply[0]) < 0) |
| 818 | return -EFAULT; | 827 | goto out; |
| 819 | 828 | ||
| 820 | reply_size >>= 16; | 829 | reply_size >>= 16; |
| 821 | reply_size <<= 2; | 830 | reply_size <<= 2; |
| @@ -824,7 +833,8 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 824 | if (!reply) { | 833 | if (!reply) { |
| 825 | printk(KERN_WARNING "%s: Could not allocate reply buffer\n", | 834 | printk(KERN_WARNING "%s: Could not allocate reply buffer\n", |
| 826 | c->name); | 835 | c->name); |
| 827 | return -ENOMEM; | 836 | rcode = -ENOMEM; |
| 837 | goto out; | ||
| 828 | } | 838 | } |
| 829 | 839 | ||
| 830 | sg_offset = (msg->u.head[0] >> 4) & 0x0f; | 840 | sg_offset = (msg->u.head[0] >> 4) & 0x0f; |
| @@ -891,13 +901,14 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 891 | } | 901 | } |
| 892 | 902 | ||
| 893 | rcode = i2o_msg_post_wait(c, msg, 60); | 903 | rcode = i2o_msg_post_wait(c, msg, 60); |
| 904 | msg = NULL; | ||
| 894 | if (rcode) { | 905 | if (rcode) { |
| 895 | reply[4] = ((u32) rcode) << 24; | 906 | reply[4] = ((u32) rcode) << 24; |
| 896 | goto sg_list_cleanup; | 907 | goto sg_list_cleanup; |
| 897 | } | 908 | } |
| 898 | 909 | ||
| 899 | if (sg_offset) { | 910 | if (sg_offset) { |
| 900 | u32 msg[128]; | 911 | u32 rmsg[128]; |
| 901 | /* Copy back the Scatter Gather buffers back to user space */ | 912 | /* Copy back the Scatter Gather buffers back to user space */ |
| 902 | u32 j; | 913 | u32 j; |
| 903 | // TODO 64bit fix | 914 | // TODO 64bit fix |
| @@ -905,7 +916,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 905 | int sg_size; | 916 | int sg_size; |
| 906 | 917 | ||
| 907 | // re-acquire the original message to handle correctly the sg copy operation | 918 | // re-acquire the original message to handle correctly the sg copy operation |
| 908 | memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); | 919 | memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); |
| 909 | // get user msg size in u32s | 920 | // get user msg size in u32s |
| 910 | if (get_user(size, &user_msg[0])) { | 921 | if (get_user(size, &user_msg[0])) { |
| 911 | rcode = -EFAULT; | 922 | rcode = -EFAULT; |
| @@ -914,7 +925,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 914 | size = size >> 16; | 925 | size = size >> 16; |
| 915 | size *= 4; | 926 | size *= 4; |
| 916 | /* Copy in the user's I2O command */ | 927 | /* Copy in the user's I2O command */ |
| 917 | if (copy_from_user(msg, user_msg, size)) { | 928 | if (copy_from_user(rmsg, user_msg, size)) { |
| 918 | rcode = -EFAULT; | 929 | rcode = -EFAULT; |
| 919 | goto sg_list_cleanup; | 930 | goto sg_list_cleanup; |
| 920 | } | 931 | } |
| @@ -922,7 +933,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 922 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 933 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
| 923 | 934 | ||
| 924 | // TODO 64bit fix | 935 | // TODO 64bit fix |
| 925 | sg = (struct sg_simple_element *)(msg + sg_offset); | 936 | sg = (struct sg_simple_element *)(rmsg + sg_offset); |
| 926 | for (j = 0; j < sg_count; j++) { | 937 | for (j = 0; j < sg_count; j++) { |
| 927 | /* Copy out the SG list to user's buffer if necessary */ | 938 | /* Copy out the SG list to user's buffer if necessary */ |
| 928 | if (! | 939 | if (! |
| @@ -944,7 +955,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 944 | } | 955 | } |
| 945 | } | 956 | } |
| 946 | 957 | ||
| 947 | sg_list_cleanup: | 958 | sg_list_cleanup: |
| 948 | /* Copy back the reply to user space */ | 959 | /* Copy back the reply to user space */ |
| 949 | if (reply_size) { | 960 | if (reply_size) { |
| 950 | // we wrote our own values for context - now restore the user supplied ones | 961 | // we wrote our own values for context - now restore the user supplied ones |
| @@ -964,8 +975,11 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 964 | for (i = 0; i < sg_index; i++) | 975 | for (i = 0; i < sg_index; i++) |
| 965 | kfree(sg_list[i]); | 976 | kfree(sg_list[i]); |
| 966 | 977 | ||
| 967 | cleanup: | 978 | cleanup: |
| 968 | kfree(reply); | 979 | kfree(reply); |
| 980 | out: | ||
| 981 | if (msg) | ||
| 982 | i2o_msg_nop(c, msg); | ||
| 969 | return rcode; | 983 | return rcode; |
| 970 | } | 984 | } |
| 971 | #endif | 985 | #endif |
