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 |
