diff options
Diffstat (limited to 'drivers/net/enic/enic_main.c')
-rw-r--r-- | drivers/net/enic/enic_main.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 2821a1db547..58cae6e6a59 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -851,6 +851,50 @@ static int enic_rq_alloc_buf(struct vnic_rq *rq) | |||
851 | return 0; | 851 | return 0; |
852 | } | 852 | } |
853 | 853 | ||
854 | static int enic_rq_alloc_buf_a1(struct vnic_rq *rq) | ||
855 | { | ||
856 | struct rq_enet_desc *desc = vnic_rq_next_desc(rq); | ||
857 | |||
858 | if (vnic_rq_posting_soon(rq)) { | ||
859 | |||
860 | /* SW workaround for A0 HW erratum: if we're just about | ||
861 | * to write posted_index, insert a dummy desc | ||
862 | * of type resvd | ||
863 | */ | ||
864 | |||
865 | rq_enet_desc_enc(desc, 0, RQ_ENET_TYPE_RESV2, 0); | ||
866 | vnic_rq_post(rq, 0, 0, 0, 0); | ||
867 | } else { | ||
868 | return enic_rq_alloc_buf(rq); | ||
869 | } | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | static int enic_set_rq_alloc_buf(struct enic *enic) | ||
875 | { | ||
876 | enum vnic_dev_hw_version hw_ver; | ||
877 | int err; | ||
878 | |||
879 | err = vnic_dev_hw_version(enic->vdev, &hw_ver); | ||
880 | if (err) | ||
881 | return err; | ||
882 | |||
883 | switch (hw_ver) { | ||
884 | case VNIC_DEV_HW_VER_A1: | ||
885 | enic->rq_alloc_buf = enic_rq_alloc_buf_a1; | ||
886 | break; | ||
887 | case VNIC_DEV_HW_VER_A2: | ||
888 | case VNIC_DEV_HW_VER_UNKNOWN: | ||
889 | enic->rq_alloc_buf = enic_rq_alloc_buf; | ||
890 | break; | ||
891 | default: | ||
892 | return -ENODEV; | ||
893 | } | ||
894 | |||
895 | return 0; | ||
896 | } | ||
897 | |||
854 | static int enic_get_skb_header(struct sk_buff *skb, void **iphdr, | 898 | static int enic_get_skb_header(struct sk_buff *skb, void **iphdr, |
855 | void **tcph, u64 *hdr_flags, void *priv) | 899 | void **tcph, u64 *hdr_flags, void *priv) |
856 | { | 900 | { |
@@ -1058,7 +1102,7 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1058 | /* Replenish RQ | 1102 | /* Replenish RQ |
1059 | */ | 1103 | */ |
1060 | 1104 | ||
1061 | vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); | 1105 | vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); |
1062 | 1106 | ||
1063 | } else { | 1107 | } else { |
1064 | 1108 | ||
@@ -1093,7 +1137,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1093 | /* Replenish RQ | 1137 | /* Replenish RQ |
1094 | */ | 1138 | */ |
1095 | 1139 | ||
1096 | vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); | 1140 | vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); |
1097 | 1141 | ||
1098 | /* Return intr event credits for this polling | 1142 | /* Return intr event credits for this polling |
1099 | * cycle. An intr event is the completion of a | 1143 | * cycle. An intr event is the completion of a |
@@ -1269,7 +1313,7 @@ static int enic_open(struct net_device *netdev) | |||
1269 | } | 1313 | } |
1270 | 1314 | ||
1271 | for (i = 0; i < enic->rq_count; i++) { | 1315 | for (i = 0; i < enic->rq_count; i++) { |
1272 | err = vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf); | 1316 | err = vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); |
1273 | if (err) { | 1317 | if (err) { |
1274 | printk(KERN_ERR PFX | 1318 | printk(KERN_ERR PFX |
1275 | "%s: Unable to alloc receive buffers.\n", | 1319 | "%s: Unable to alloc receive buffers.\n", |