diff options
author | Sreenivasa Honnur <Sreenivasa.Honnur@neterion.com> | 2010-03-28 18:07:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-29 19:57:20 -0400 |
commit | 18dec74c16abaa92d663dfef64ee6503e085be89 (patch) | |
tree | 88c03fb3ec663cb4b1c2d2ed4ae7d6ac180ae32b /drivers/net/vxge/vxge-traffic.c | |
parent | 7905e357ebe67a26d9dc8caa1a0b8346431b5f0d (diff) |
vxge: Fix a receive stall due to driver being out of synch with chip.
- Fix a receive stall due to driver being out of synch with chip. In a corner
case scenario the adapter's ring controller may return a RxD with transfer code
of 0xC, while the host ownership bit is still set to the adapter. The driver
needs to assume that this case where (host_ownership == 1 or adapter) and
(transfer_code == 0xC) is valid, that is, this RxD has been returned by the
receive ring controller but no frame data is associated with the rxd.
- Restore the transfer code field of each newly replenished RxD to 0x0.
- Code cleanup. Removed usage of magic numbers.
Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxge/vxge-traffic.c')
-rw-r--r-- | drivers/net/vxge/vxge-traffic.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index 2c012f4ce465..c8b3997e9eeb 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c | |||
@@ -878,7 +878,7 @@ void vxge_hw_ring_rxd_post_post(struct __vxge_hw_ring *ring, void *rxdh) | |||
878 | 878 | ||
879 | channel = &ring->channel; | 879 | channel = &ring->channel; |
880 | 880 | ||
881 | rxdp->control_0 |= VXGE_HW_RING_RXD_LIST_OWN_ADAPTER; | 881 | rxdp->control_0 = VXGE_HW_RING_RXD_LIST_OWN_ADAPTER; |
882 | 882 | ||
883 | if (ring->stats->common_stats.usage_cnt > 0) | 883 | if (ring->stats->common_stats.usage_cnt > 0) |
884 | ring->stats->common_stats.usage_cnt--; | 884 | ring->stats->common_stats.usage_cnt--; |
@@ -902,7 +902,7 @@ void vxge_hw_ring_rxd_post(struct __vxge_hw_ring *ring, void *rxdh) | |||
902 | channel = &ring->channel; | 902 | channel = &ring->channel; |
903 | 903 | ||
904 | wmb(); | 904 | wmb(); |
905 | rxdp->control_0 |= VXGE_HW_RING_RXD_LIST_OWN_ADAPTER; | 905 | rxdp->control_0 = VXGE_HW_RING_RXD_LIST_OWN_ADAPTER; |
906 | 906 | ||
907 | vxge_hw_channel_dtr_post(channel, rxdh); | 907 | vxge_hw_channel_dtr_post(channel, rxdh); |
908 | 908 | ||
@@ -966,6 +966,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed( | |||
966 | struct __vxge_hw_channel *channel; | 966 | struct __vxge_hw_channel *channel; |
967 | struct vxge_hw_ring_rxd_1 *rxdp; | 967 | struct vxge_hw_ring_rxd_1 *rxdp; |
968 | enum vxge_hw_status status = VXGE_HW_OK; | 968 | enum vxge_hw_status status = VXGE_HW_OK; |
969 | u64 control_0, own; | ||
969 | 970 | ||
970 | channel = &ring->channel; | 971 | channel = &ring->channel; |
971 | 972 | ||
@@ -977,8 +978,12 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed( | |||
977 | goto exit; | 978 | goto exit; |
978 | } | 979 | } |
979 | 980 | ||
981 | control_0 = rxdp->control_0; | ||
982 | own = control_0 & VXGE_HW_RING_RXD_LIST_OWN_ADAPTER; | ||
983 | *t_code = (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0); | ||
984 | |||
980 | /* check whether it is not the end */ | 985 | /* check whether it is not the end */ |
981 | if (!(rxdp->control_0 & VXGE_HW_RING_RXD_LIST_OWN_ADAPTER)) { | 986 | if (!own || ((*t_code == VXGE_HW_RING_T_CODE_FRM_DROP) && own)) { |
982 | 987 | ||
983 | vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control != | 988 | vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control != |
984 | 0); | 989 | 0); |
@@ -986,8 +991,6 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed( | |||
986 | ++ring->cmpl_cnt; | 991 | ++ring->cmpl_cnt; |
987 | vxge_hw_channel_dtr_complete(channel); | 992 | vxge_hw_channel_dtr_complete(channel); |
988 | 993 | ||
989 | *t_code = (u8)VXGE_HW_RING_RXD_T_CODE_GET(rxdp->control_0); | ||
990 | |||
991 | vxge_assert(*t_code != VXGE_HW_RING_RXD_T_CODE_UNUSED); | 994 | vxge_assert(*t_code != VXGE_HW_RING_RXD_T_CODE_UNUSED); |
992 | 995 | ||
993 | ring->stats->common_stats.usage_cnt++; | 996 | ring->stats->common_stats.usage_cnt++; |
@@ -1035,12 +1038,13 @@ enum vxge_hw_status vxge_hw_ring_handle_tcode( | |||
1035 | * such as unknown UPV6 header), Drop it !!! | 1038 | * such as unknown UPV6 header), Drop it !!! |
1036 | */ | 1039 | */ |
1037 | 1040 | ||
1038 | if (t_code == 0 || t_code == 5) { | 1041 | if (t_code == VXGE_HW_RING_T_CODE_OK || |
1042 | t_code == VXGE_HW_RING_T_CODE_L3_PKT_ERR) { | ||
1039 | status = VXGE_HW_OK; | 1043 | status = VXGE_HW_OK; |
1040 | goto exit; | 1044 | goto exit; |
1041 | } | 1045 | } |
1042 | 1046 | ||
1043 | if (t_code > 0xF) { | 1047 | if (t_code > VXGE_HW_RING_T_CODE_MULTI_ERR) { |
1044 | status = VXGE_HW_ERR_INVALID_TCODE; | 1048 | status = VXGE_HW_ERR_INVALID_TCODE; |
1045 | goto exit; | 1049 | goto exit; |
1046 | } | 1050 | } |