diff options
-rw-r--r-- | drivers/ieee1394/ieee1394_core.c | 91 |
1 files changed, 41 insertions, 50 deletions
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index d2240a4a1c22..b368958dc06c 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c | |||
@@ -859,12 +859,9 @@ static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extc | |||
859 | packet->data_size = length; | 859 | packet->data_size = length; |
860 | } | 860 | } |
861 | 861 | ||
862 | #define PREP_REPLY_PACKET(length) \ | ||
863 | packet = create_reply_packet(host, data, length); \ | ||
864 | if (packet == NULL) break | ||
865 | |||
866 | static void handle_incoming_packet(struct hpsb_host *host, int tcode, | 862 | static void handle_incoming_packet(struct hpsb_host *host, int tcode, |
867 | quadlet_t *data, size_t size, int write_acked) | 863 | quadlet_t *data, size_t size, |
864 | int write_acked) | ||
868 | { | 865 | { |
869 | struct hpsb_packet *packet; | 866 | struct hpsb_packet *packet; |
870 | int length, rcode, extcode; | 867 | int length, rcode, extcode; |
@@ -874,74 +871,72 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, | |||
874 | u16 flags = (u16) data[0]; | 871 | u16 flags = (u16) data[0]; |
875 | u64 addr; | 872 | u64 addr; |
876 | 873 | ||
877 | /* big FIXME - no error checking is done for an out of bounds length */ | 874 | /* FIXME? |
875 | * Out-of-bounds lengths are left for highlevel_read|write to cap. */ | ||
878 | 876 | ||
879 | switch (tcode) { | 877 | switch (tcode) { |
880 | case TCODE_WRITEQ: | 878 | case TCODE_WRITEQ: |
881 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | 879 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; |
882 | rcode = highlevel_write(host, source, dest, data+3, | 880 | rcode = highlevel_write(host, source, dest, data + 3, |
883 | addr, 4, flags); | 881 | addr, 4, flags); |
884 | 882 | goto handle_write_request; | |
885 | if (!write_acked | ||
886 | && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) | ||
887 | && (rcode >= 0)) { | ||
888 | /* not a broadcast write, reply */ | ||
889 | PREP_REPLY_PACKET(0); | ||
890 | fill_async_write_resp(packet, rcode); | ||
891 | send_packet_nocare(packet); | ||
892 | } | ||
893 | break; | ||
894 | 883 | ||
895 | case TCODE_WRITEB: | 884 | case TCODE_WRITEB: |
896 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | 885 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; |
897 | rcode = highlevel_write(host, source, dest, data+4, | 886 | rcode = highlevel_write(host, source, dest, data + 4, |
898 | addr, data[3]>>16, flags); | 887 | addr, data[3] >> 16, flags); |
899 | 888 | handle_write_request: | |
900 | if (!write_acked | 889 | if (rcode < 0 || write_acked || |
901 | && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) | 890 | NODEID_TO_NODE(data[0] >> 16) == NODE_MASK) |
902 | && (rcode >= 0)) { | 891 | return; |
903 | /* not a broadcast write, reply */ | 892 | /* not a broadcast write, reply */ |
904 | PREP_REPLY_PACKET(0); | 893 | packet = create_reply_packet(host, data, 0); |
894 | if (packet) { | ||
905 | fill_async_write_resp(packet, rcode); | 895 | fill_async_write_resp(packet, rcode); |
906 | send_packet_nocare(packet); | 896 | send_packet_nocare(packet); |
907 | } | 897 | } |
908 | break; | 898 | return; |
909 | 899 | ||
910 | case TCODE_READQ: | 900 | case TCODE_READQ: |
911 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | 901 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; |
912 | rcode = highlevel_read(host, source, &buffer, addr, 4, flags); | 902 | rcode = highlevel_read(host, source, &buffer, addr, 4, flags); |
903 | if (rcode < 0) | ||
904 | return; | ||
913 | 905 | ||
914 | if (rcode >= 0) { | 906 | packet = create_reply_packet(host, data, 0); |
915 | PREP_REPLY_PACKET(0); | 907 | if (packet) { |
916 | fill_async_readquad_resp(packet, rcode, buffer); | 908 | fill_async_readquad_resp(packet, rcode, buffer); |
917 | send_packet_nocare(packet); | 909 | send_packet_nocare(packet); |
918 | } | 910 | } |
919 | break; | 911 | return; |
920 | 912 | ||
921 | case TCODE_READB: | 913 | case TCODE_READB: |
922 | length = data[3] >> 16; | 914 | length = data[3] >> 16; |
923 | PREP_REPLY_PACKET(length); | 915 | packet = create_reply_packet(host, data, length); |
916 | if (!packet) | ||
917 | return; | ||
924 | 918 | ||
925 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | 919 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; |
926 | rcode = highlevel_read(host, source, packet->data, addr, | 920 | rcode = highlevel_read(host, source, packet->data, addr, |
927 | length, flags); | 921 | length, flags); |
928 | 922 | if (rcode < 0) { | |
929 | if (rcode >= 0) { | ||
930 | fill_async_readblock_resp(packet, rcode, length); | ||
931 | send_packet_nocare(packet); | ||
932 | } else { | ||
933 | hpsb_free_packet(packet); | 923 | hpsb_free_packet(packet); |
924 | return; | ||
934 | } | 925 | } |
935 | break; | 926 | fill_async_readblock_resp(packet, rcode, length); |
927 | send_packet_nocare(packet); | ||
928 | return; | ||
936 | 929 | ||
937 | case TCODE_LOCK_REQUEST: | 930 | case TCODE_LOCK_REQUEST: |
938 | length = data[3] >> 16; | 931 | length = data[3] >> 16; |
939 | extcode = data[3] & 0xffff; | 932 | extcode = data[3] & 0xffff; |
940 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; | 933 | addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; |
941 | 934 | ||
942 | PREP_REPLY_PACKET(8); | 935 | packet = create_reply_packet(host, data, 8); |
936 | if (!packet) | ||
937 | return; | ||
943 | 938 | ||
944 | if ((extcode == 0) || (extcode >= 7)) { | 939 | if (extcode == 0 || extcode >= 7) { |
945 | /* let switch default handle error */ | 940 | /* let switch default handle error */ |
946 | length = 0; | 941 | length = 0; |
947 | } | 942 | } |
@@ -949,12 +944,12 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, | |||
949 | switch (length) { | 944 | switch (length) { |
950 | case 4: | 945 | case 4: |
951 | rcode = highlevel_lock(host, source, packet->data, addr, | 946 | rcode = highlevel_lock(host, source, packet->data, addr, |
952 | data[4], 0, extcode,flags); | 947 | data[4], 0, extcode, flags); |
953 | fill_async_lock_resp(packet, rcode, extcode, 4); | 948 | fill_async_lock_resp(packet, rcode, extcode, 4); |
954 | break; | 949 | break; |
955 | case 8: | 950 | case 8: |
956 | if ((extcode != EXTCODE_FETCH_ADD) | 951 | if (extcode != EXTCODE_FETCH_ADD && |
957 | && (extcode != EXTCODE_LITTLE_ADD)) { | 952 | extcode != EXTCODE_LITTLE_ADD) { |
958 | rcode = highlevel_lock(host, source, | 953 | rcode = highlevel_lock(host, source, |
959 | packet->data, addr, | 954 | packet->data, addr, |
960 | data[5], data[4], | 955 | data[5], data[4], |
@@ -978,20 +973,16 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, | |||
978 | break; | 973 | break; |
979 | default: | 974 | default: |
980 | rcode = RCODE_TYPE_ERROR; | 975 | rcode = RCODE_TYPE_ERROR; |
981 | fill_async_lock_resp(packet, rcode, | 976 | fill_async_lock_resp(packet, rcode, extcode, 0); |
982 | extcode, 0); | ||
983 | } | 977 | } |
984 | 978 | ||
985 | if (rcode >= 0) { | 979 | if (rcode < 0) |
986 | send_packet_nocare(packet); | ||
987 | } else { | ||
988 | hpsb_free_packet(packet); | 980 | hpsb_free_packet(packet); |
989 | } | 981 | else |
990 | break; | 982 | send_packet_nocare(packet); |
983 | return; | ||
991 | } | 984 | } |
992 | |||
993 | } | 985 | } |
994 | #undef PREP_REPLY_PACKET | ||
995 | 986 | ||
996 | /** | 987 | /** |
997 | * hpsb_packet_received - hand over received packet to the core | 988 | * hpsb_packet_received - hand over received packet to the core |