/** * Check for link state changes * * @v netdev Network device * @v stat Status flags */ static void nii_poll_link ( struct net_device *netdev, unsigned int stat ) { int no_media = ( stat & PXE_STATFLAGS_GET_STATUS_NO_MEDIA ); if ( no_media && netdev_link_ok ( netdev ) ) { netdev_link_down ( netdev ); } else if ( ( ! no_media ) && ( ! netdev_link_ok ( netdev ) ) ) { netdev_link_up ( netdev ); } }
/** * Update link status based on network status register * * @v dm96xx DM96xx device * @v nsr Network status register */ static void dm96xx_link_nsr ( struct dm96xx_device *dm96xx, unsigned int nsr ) { struct net_device *netdev = dm96xx->netdev; if ( nsr & DM96XX_NSR_LINKST ) { if ( ! netdev_link_ok ( netdev ) ) netdev_link_up ( netdev ); } else { if ( netdev_link_ok ( netdev ) ) netdev_link_down ( netdev ); } }
/** * Check link state * * @v netdev Network device */ static void snpnet_check_link ( struct net_device *netdev ) { struct snp_nic *snp = netdev_priv ( netdev ); EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode; /* Do nothing unless media presence detection is supported */ if ( ! mode->MediaPresentSupported ) return; /* Report any link status change */ if ( mode->MediaPresent && ( ! netdev_link_ok ( netdev ) ) ) { netdev_link_up ( netdev ); } else if ( ( ! mode->MediaPresent ) && netdev_link_ok ( netdev ) ) { netdev_link_down ( netdev ); } }
/** * Print status of network device * * @v netdev Network device */ void ifstat ( struct net_device *netdev ) { printf ( "%s: %s on %s (%s)\n" " [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n", netdev->name, netdev_addr ( netdev ), netdev->dev->name, ( netdev_is_open ( netdev ) ? "open" : "closed" ), ( netdev_link_ok ( netdev ) ? "up" : "down" ), netdev->tx_stats.good, netdev->tx_stats.bad, netdev->rx_stats.good, netdev->rx_stats.bad ); if ( ! netdev_link_ok ( netdev ) ) { printf ( " [Link status: %s]\n", strerror ( netdev->link_rc ) ); } ifstat_errors ( &netdev->tx_stats, "TXE" ); ifstat_errors ( &netdev->rx_stats, "RXE" ); }
/** * Check link status * * @v smsc95xx SMSC95xx device * @ret rc Return status code */ static int smsc95xx_check_link ( struct smsc95xx_device *smsc95xx ) { struct net_device *netdev = smsc95xx->netdev; int intr; int rc; /* Read PHY interrupt source */ intr = mii_read ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_SOURCE ); if ( intr < 0 ) { rc = intr; DBGC ( smsc95xx, "SMSC95XX %p could not get PHY interrupt " "source: %s\n", smsc95xx, strerror ( rc ) ); return rc; } /* Acknowledge PHY interrupt */ if ( ( rc = mii_write ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_SOURCE, intr ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not acknowledge PHY " "interrupt: %s\n", smsc95xx, strerror ( rc ) ); return rc; } /* Check link status */ if ( ( rc = mii_check_link ( &smsc95xx->mii, netdev ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not check link: %s\n", smsc95xx, strerror ( rc ) ); return rc; } DBGC ( smsc95xx, "SMSC95XX %p link %s (intr %#04x)\n", smsc95xx, ( netdev_link_ok ( netdev ) ? "up" : "down" ), intr ); return 0; }
/** * mii_check_link - check MII link status * @mii: MII interface * * If the link status changed (previous != current), call * netif_carrier_on() if current link status is Up or call * netif_carrier_off() if current link status is Down. */ void mii_check_link(struct mii_if_info *mii) { #warning "figure out what to do about etherboot netdev; does ours work?" #if 0 int cur_link = mii_link_ok(mii); int prev_link = netdev_link_ok(mii->dev); if (cur_link && !prev_link) netdev_link_up(mii->dev); else if (prev_link && !cur_link) netdev_link_down(mii->dev); #endif }
/** * Wait for link-up, with status indication * * @v netdev Network device * @v max_wait_ms Maximum time to wait, in ms */ int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) { int key; int rc; if ( netdev_link_ok ( netdev ) ) return 0; printf ( "Waiting for link-up on %s...", netdev->name ); while ( 1 ) { if ( netdev_link_ok ( netdev ) ) { rc = 0; break; } if ( max_wait_ms-- == 0 ) { rc = netdev->link_rc; break; } step(); if ( iskey() ) { key = getchar(); if ( key == CTRL_C ) { rc = -ECANCELED; break; } } mdelay ( 1 ); } if ( rc == 0 ) { printf ( " ok\n" ); } else { printf ( " failed: %s\n", strerror ( rc ) ); } return rc; }
/** * vxge_xmit * @skb : the socket buffer containing the Tx data. * @dev : device pointer. * * This function is the Tx entry point of the driver. Neterion NIC supports * certain protocol assist features on Tx side, namely CSO, S/G, LSO. */ static int vxge_xmit(struct net_device *dev, struct io_buffer *iobuf) { struct vxge_fifo *fifo = NULL; struct vxgedev *vdev = NULL; struct __vxge_hw_fifo *fifoh; struct vxge_hw_fifo_txd *txdp; vxge_trace(); vdev = (struct vxgedev *)netdev_priv(dev); if (!is_vxge_card_up(vdev)) { vxge_debug(VXGE_ERR, "%s: vdev not initialized\n", dev->name); return -EIO; } if (!netdev_link_ok(dev)) { vxge_debug(VXGE_ERR, "%s: Link down, transmit failed\n", dev->name); return -ENETDOWN; } fifo = &vdev->vpath.fifo; fifoh = fifo->fifoh; txdp = vxge_hw_fifo_free_txdl_get(fifoh); if (!txdp) { vxge_debug(VXGE_ERR, "%s: Out of tx descriptors\n", dev->name); return -ENOBUFS; } vxge_debug(VXGE_XMIT, "%s: %s:%d fifoh offset= %d\n", dev->name, __func__, __LINE__, fifoh->sw_offset); vxge_hw_fifo_txdl_buffer_set(fifoh, txdp, iobuf); vxge_hw_fifo_txdl_post(fifoh, txdp); return 0; }
/** * Set EFI SNP mode based on iPXE net device parameters * * @v snp SNP interface */ static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) { struct net_device *netdev = snpdev->netdev; EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode; struct ll_protocol *ll_protocol = netdev->ll_protocol; unsigned int ll_addr_len = ll_protocol->ll_addr_len; mode->HwAddressSize = ll_addr_len; mode->MediaHeaderSize = ll_protocol->ll_header_len; mode->MaxPacketSize = netdev->max_pkt_len; mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ); assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) ); memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len ); memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len ); ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress ); mode->IfType = ntohs ( ll_protocol->ll_proto ); mode->MacAddressChangeable = TRUE; mode->MediaPresentSupported = TRUE; mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE ); }