diff options
author | Jon Mason <jon.mason@exar.com> | 2010-11-10 23:25:54 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-11-11 12:30:19 -0500 |
commit | 4d2a5b406c02b224bd3f50992c8b02450c65a730 (patch) | |
tree | 624d968e9ae73e1ff14dcfbc4a26e0fbbe069124 /drivers/net/vxge/vxge-config.c | |
parent | 47f01db44b2470d9517848f6b73c75883ef5fda0 (diff) |
vxge: Wait for Rx to become idle before reseting or closing
Wait for the receive traffic to become idle before attempting to close
or reset the adapter. To enable the processing of packets while Receive
Idle, move the clearing of __VXGE_STATE_CARD_UP bit in vxge_close to
after it. Also, modify the return value of the ISR when the adapter is
down to IRQ_HANDLED. Otherwise there are unhandled interrupts for the
device.
Signed-off-by: Jon Mason <jon.mason@exar.com>
Signed-off-by: Ram Vepa <ram.vepa@exar.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxge/vxge-config.c')
-rw-r--r-- | drivers/net/vxge/vxge-config.c | 86 |
1 files changed, 83 insertions, 3 deletions
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index 0a35ab1ee2e1..212e301bdd68 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c | |||
@@ -193,6 +193,88 @@ static enum vxge_hw_status | |||
193 | __vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath, | 193 | __vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath, |
194 | struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats); | 194 | struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats); |
195 | 195 | ||
196 | static void | ||
197 | vxge_hw_vpath_set_zero_rx_frm_len(struct vxge_hw_vpath_reg __iomem *vp_reg) | ||
198 | { | ||
199 | u64 val64; | ||
200 | |||
201 | val64 = readq(&vp_reg->rxmac_vcfg0); | ||
202 | val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff); | ||
203 | writeq(val64, &vp_reg->rxmac_vcfg0); | ||
204 | val64 = readq(&vp_reg->rxmac_vcfg0); | ||
205 | |||
206 | return; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * vxge_hw_vpath_wait_receive_idle - Wait for Rx to become idle | ||
211 | */ | ||
212 | int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id) | ||
213 | { | ||
214 | struct vxge_hw_vpath_reg __iomem *vp_reg; | ||
215 | struct __vxge_hw_virtualpath *vpath; | ||
216 | u64 val64, rxd_count, rxd_spat; | ||
217 | int count = 0, total_count = 0; | ||
218 | |||
219 | vpath = &hldev->virtual_paths[vp_id]; | ||
220 | vp_reg = vpath->vp_reg; | ||
221 | |||
222 | vxge_hw_vpath_set_zero_rx_frm_len(vp_reg); | ||
223 | |||
224 | /* Check that the ring controller for this vpath has enough free RxDs | ||
225 | * to send frames to the host. This is done by reading the | ||
226 | * PRC_RXD_DOORBELL_VPn register and comparing the read value to the | ||
227 | * RXD_SPAT value for the vpath. | ||
228 | */ | ||
229 | val64 = readq(&vp_reg->prc_cfg6); | ||
230 | rxd_spat = VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val64) + 1; | ||
231 | /* Use a factor of 2 when comparing rxd_count against rxd_spat for some | ||
232 | * leg room. | ||
233 | */ | ||
234 | rxd_spat *= 2; | ||
235 | |||
236 | do { | ||
237 | mdelay(1); | ||
238 | |||
239 | rxd_count = readq(&vp_reg->prc_rxd_doorbell); | ||
240 | |||
241 | /* Check that the ring controller for this vpath does | ||
242 | * not have any frame in its pipeline. | ||
243 | */ | ||
244 | val64 = readq(&vp_reg->frm_in_progress_cnt); | ||
245 | if ((rxd_count <= rxd_spat) || (val64 > 0)) | ||
246 | count = 0; | ||
247 | else | ||
248 | count++; | ||
249 | total_count++; | ||
250 | } while ((count < VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT) && | ||
251 | (total_count < VXGE_HW_MAX_POLLING_COUNT)); | ||
252 | |||
253 | if (total_count >= VXGE_HW_MAX_POLLING_COUNT) | ||
254 | printk(KERN_ALERT "%s: Still Receiving traffic. Abort wait\n", | ||
255 | __func__); | ||
256 | |||
257 | return total_count; | ||
258 | } | ||
259 | |||
260 | /* vxge_hw_device_wait_receive_idle - This function waits until all frames | ||
261 | * stored in the frame buffer for each vpath assigned to the given | ||
262 | * function (hldev) have been sent to the host. | ||
263 | */ | ||
264 | void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev) | ||
265 | { | ||
266 | int i, total_count = 0; | ||
267 | |||
268 | for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) { | ||
269 | if (!(hldev->vpaths_deployed & vxge_mBIT(i))) | ||
270 | continue; | ||
271 | |||
272 | total_count += vxge_hw_vpath_wait_receive_idle(hldev, i); | ||
273 | if (total_count >= VXGE_HW_MAX_POLLING_COUNT) | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | |||
196 | /* | 278 | /* |
197 | * __vxge_hw_channel_allocate - Allocate memory for channel | 279 | * __vxge_hw_channel_allocate - Allocate memory for channel |
198 | * This function allocates required memory for the channel and various arrays | 280 | * This function allocates required memory for the channel and various arrays |
@@ -390,7 +472,7 @@ __vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis) | |||
390 | return ret; | 472 | return ret; |
391 | } | 473 | } |
392 | 474 | ||
393 | /* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset | 475 | /* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset |
394 | * in progress | 476 | * in progress |
395 | * This routine checks the vpath reset in progress register is turned zero | 477 | * This routine checks the vpath reset in progress register is turned zero |
396 | */ | 478 | */ |
@@ -1165,7 +1247,6 @@ exit: | |||
1165 | * It can be used to set or reset Pause frame generation or reception | 1247 | * It can be used to set or reset Pause frame generation or reception |
1166 | * support of the NIC. | 1248 | * support of the NIC. |
1167 | */ | 1249 | */ |
1168 | |||
1169 | enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev, | 1250 | enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev, |
1170 | u32 port, u32 tx, u32 rx) | 1251 | u32 port, u32 tx, u32 rx) |
1171 | { | 1252 | { |
@@ -1409,7 +1490,6 @@ exit: | |||
1409 | /* | 1490 | /* |
1410 | * __vxge_hw_ring_create - Create a Ring | 1491 | * __vxge_hw_ring_create - Create a Ring |
1411 | * This function creates Ring and initializes it. | 1492 | * This function creates Ring and initializes it. |
1412 | * | ||
1413 | */ | 1493 | */ |
1414 | static enum vxge_hw_status | 1494 | static enum vxge_hw_status |
1415 | __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp, | 1495 | __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp, |