diff options
Diffstat (limited to 'drivers/net/enic/enic_main.c')
-rw-r--r-- | drivers/net/enic/enic_main.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index b4a11befb3b..452a6b747e3 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -1091,6 +1091,7 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1091 | unsigned int rq_work_to_do = budget; | 1091 | unsigned int rq_work_to_do = budget; |
1092 | unsigned int wq_work_to_do = -1; /* no limit */ | 1092 | unsigned int wq_work_to_do = -1; /* no limit */ |
1093 | unsigned int work_done, rq_work_done, wq_work_done; | 1093 | unsigned int work_done, rq_work_done, wq_work_done; |
1094 | int err; | ||
1094 | 1095 | ||
1095 | /* Service RQ (first) and WQ | 1096 | /* Service RQ (first) and WQ |
1096 | */ | 1097 | */ |
@@ -1114,16 +1115,19 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1114 | 0 /* don't unmask intr */, | 1115 | 0 /* don't unmask intr */, |
1115 | 0 /* don't reset intr timer */); | 1116 | 0 /* don't reset intr timer */); |
1116 | 1117 | ||
1117 | if (rq_work_done > 0) { | 1118 | err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); |
1118 | 1119 | ||
1119 | /* Replenish RQ | 1120 | /* Buffer allocation failed. Stay in polling |
1120 | */ | 1121 | * mode so we can try to fill the ring again. |
1122 | */ | ||
1121 | 1123 | ||
1122 | vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); | 1124 | if (err) |
1125 | rq_work_done = rq_work_to_do; | ||
1123 | 1126 | ||
1124 | } else { | 1127 | if (rq_work_done < rq_work_to_do) { |
1125 | 1128 | ||
1126 | /* If no work done, flush all LROs and exit polling | 1129 | /* Some work done, but not enough to stay in polling, |
1130 | * flush all LROs and exit polling | ||
1127 | */ | 1131 | */ |
1128 | 1132 | ||
1129 | if (netdev->features & NETIF_F_LRO) | 1133 | if (netdev->features & NETIF_F_LRO) |
@@ -1142,6 +1146,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1142 | struct net_device *netdev = enic->netdev; | 1146 | struct net_device *netdev = enic->netdev; |
1143 | unsigned int work_to_do = budget; | 1147 | unsigned int work_to_do = budget; |
1144 | unsigned int work_done; | 1148 | unsigned int work_done; |
1149 | int err; | ||
1145 | 1150 | ||
1146 | /* Service RQ | 1151 | /* Service RQ |
1147 | */ | 1152 | */ |
@@ -1149,25 +1154,30 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1149 | work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], | 1154 | work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], |
1150 | work_to_do, enic_rq_service, NULL); | 1155 | work_to_do, enic_rq_service, NULL); |
1151 | 1156 | ||
1152 | if (work_done > 0) { | 1157 | /* Return intr event credits for this polling |
1153 | 1158 | * cycle. An intr event is the completion of a | |
1154 | /* Replenish RQ | 1159 | * RQ packet. |
1155 | */ | 1160 | */ |
1156 | |||
1157 | vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); | ||
1158 | |||
1159 | /* Return intr event credits for this polling | ||
1160 | * cycle. An intr event is the completion of a | ||
1161 | * RQ packet. | ||
1162 | */ | ||
1163 | 1161 | ||
1162 | if (work_done > 0) | ||
1164 | vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], | 1163 | vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], |
1165 | work_done, | 1164 | work_done, |
1166 | 0 /* don't unmask intr */, | 1165 | 0 /* don't unmask intr */, |
1167 | 0 /* don't reset intr timer */); | 1166 | 0 /* don't reset intr timer */); |
1168 | } else { | ||
1169 | 1167 | ||
1170 | /* If no work done, flush all LROs and exit polling | 1168 | err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); |
1169 | |||
1170 | /* Buffer allocation failed. Stay in polling mode | ||
1171 | * so we can try to fill the ring again. | ||
1172 | */ | ||
1173 | |||
1174 | if (err) | ||
1175 | work_done = work_to_do; | ||
1176 | |||
1177 | if (work_done < work_to_do) { | ||
1178 | |||
1179 | /* Some work done, but not enough to stay in polling, | ||
1180 | * flush all LROs and exit polling | ||
1171 | */ | 1181 | */ |
1172 | 1182 | ||
1173 | if (netdev->features & NETIF_F_LRO) | 1183 | if (netdev->features & NETIF_F_LRO) |
@@ -1350,11 +1360,13 @@ static int enic_open(struct net_device *netdev) | |||
1350 | } | 1360 | } |
1351 | 1361 | ||
1352 | for (i = 0; i < enic->rq_count; i++) { | 1362 | for (i = 0; i < enic->rq_count; i++) { |
1353 | err = vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); | 1363 | vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); |
1354 | if (err) { | 1364 | /* Need at least one buffer on ring to get going */ |
1365 | if (vnic_rq_desc_used(&enic->rq[i]) == 0) { | ||
1355 | printk(KERN_ERR PFX | 1366 | printk(KERN_ERR PFX |
1356 | "%s: Unable to alloc receive buffers.\n", | 1367 | "%s: Unable to alloc receive buffers.\n", |
1357 | netdev->name); | 1368 | netdev->name); |
1369 | err = -ENOMEM; | ||
1358 | goto err_out_notify_unset; | 1370 | goto err_out_notify_unset; |
1359 | } | 1371 | } |
1360 | } | 1372 | } |