aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxge/vxge-config.c
diff options
context:
space:
mode:
authorJon Mason <jon.mason@exar.com>2010-11-10 23:25:54 -0500
committerDavid S. Miller <davem@davemloft.net>2010-11-11 12:30:19 -0500
commit4d2a5b406c02b224bd3f50992c8b02450c65a730 (patch)
tree624d968e9ae73e1ff14dcfbc4a26e0fbbe069124 /drivers/net/vxge/vxge-config.c
parent47f01db44b2470d9517848f6b73c75883ef5fda0 (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.c86
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
196static void
197vxge_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 */
212int 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 */
264void 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
1169enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev, 1250enum 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 */
1414static enum vxge_hw_status 1494static 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,