aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxge
diff options
context:
space:
mode:
authorSreenivasa Honnur <Sreenivasa.Honnur@neterion.com>2010-03-28 18:07:34 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-29 19:57:20 -0400
commit18dec74c16abaa92d663dfef64ee6503e085be89 (patch)
tree88c03fb3ec663cb4b1c2d2ed4ae7d6ac180ae32b /drivers/net/vxge
parent7905e357ebe67a26d9dc8caa1a0b8346431b5f0d (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')
-rw-r--r--drivers/net/vxge/vxge-traffic.c18
-rw-r--r--drivers/net/vxge/vxge-traffic.h45
2 files changed, 56 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 }
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h
index 861c853e3e84..3c35e446e247 100644
--- a/drivers/net/vxge/vxge-traffic.h
+++ b/drivers/net/vxge/vxge-traffic.h
@@ -1866,6 +1866,51 @@ struct vxge_hw_ring_rxd_info {
1866 u32 rth_hash_type; 1866 u32 rth_hash_type;
1867 u32 rth_value; 1867 u32 rth_value;
1868}; 1868};
1869/**
1870 * enum vxge_hw_ring_tcode - Transfer codes returned by adapter
1871 * @VXGE_HW_RING_T_CODE_OK: Transfer ok.
1872 * @VXGE_HW_RING_T_CODE_L3_CKSUM_MISMATCH: Layer 3 checksum presentation
1873 * configuration mismatch.
1874 * @VXGE_HW_RING_T_CODE_L4_CKSUM_MISMATCH: Layer 4 checksum presentation
1875 * configuration mismatch.
1876 * @VXGE_HW_RING_T_CODE_L3_L4_CKSUM_MISMATCH: Layer 3 and Layer 4 checksum
1877 * presentation configuration mismatch.
1878 * @VXGE_HW_RING_T_CODE_L3_PKT_ERR: Layer 3 error unparseable packet,
1879 * such as unknown IPv6 header.
1880 * @VXGE_HW_RING_T_CODE_L2_FRM_ERR: Layer 2 error frame integrity
1881 * error, such as FCS or ECC).
1882 * @VXGE_HW_RING_T_CODE_BUF_SIZE_ERR: Buffer size error the RxD buffer(
1883 * s) were not appropriately sized and data loss occurred.
1884 * @VXGE_HW_RING_T_CODE_INT_ECC_ERR: Internal ECC error RxD corrupted.
1885 * @VXGE_HW_RING_T_CODE_BENIGN_OVFLOW: Benign overflow the contents of
1886 * Segment1 exceeded the capacity of Buffer1 and the remainder
1887 * was placed in Buffer2. Segment2 now starts in Buffer3.
1888 * No data loss or errors occurred.
1889 * @VXGE_HW_RING_T_CODE_ZERO_LEN_BUFF: Buffer size 0 one of the RxDs
1890 * assigned buffers has a size of 0 bytes.
1891 * @VXGE_HW_RING_T_CODE_FRM_DROP: Frame dropped either due to
1892 * VPath Reset or because of a VPIN mismatch.
1893 * @VXGE_HW_RING_T_CODE_UNUSED: Unused
1894 * @VXGE_HW_RING_T_CODE_MULTI_ERR: Multiple errors more than one
1895 * transfer code condition occurred.
1896 *
1897 * Transfer codes returned by adapter.
1898 */
1899enum vxge_hw_ring_tcode {
1900 VXGE_HW_RING_T_CODE_OK = 0x0,
1901 VXGE_HW_RING_T_CODE_L3_CKSUM_MISMATCH = 0x1,
1902 VXGE_HW_RING_T_CODE_L4_CKSUM_MISMATCH = 0x2,
1903 VXGE_HW_RING_T_CODE_L3_L4_CKSUM_MISMATCH = 0x3,
1904 VXGE_HW_RING_T_CODE_L3_PKT_ERR = 0x5,
1905 VXGE_HW_RING_T_CODE_L2_FRM_ERR = 0x6,
1906 VXGE_HW_RING_T_CODE_BUF_SIZE_ERR = 0x7,
1907 VXGE_HW_RING_T_CODE_INT_ECC_ERR = 0x8,
1908 VXGE_HW_RING_T_CODE_BENIGN_OVFLOW = 0x9,
1909 VXGE_HW_RING_T_CODE_ZERO_LEN_BUFF = 0xA,
1910 VXGE_HW_RING_T_CODE_FRM_DROP = 0xC,
1911 VXGE_HW_RING_T_CODE_UNUSED = 0xE,
1912 VXGE_HW_RING_T_CODE_MULTI_ERR = 0xF
1913};
1869 1914
1870/** 1915/**
1871 * enum enum vxge_hw_ring_hash_type - RTH hash types 1916 * enum enum vxge_hw_ring_hash_type - RTH hash types