diff options
-rw-r--r-- | drivers/staging/wlags49_h2/wl_netdev.c | 1949 |
1 files changed, 999 insertions, 950 deletions
diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c index 85fdeda..ae42c8e 100644 --- a/drivers/staging/wlags49_h2/wl_netdev.c +++ b/drivers/staging/wlags49_h2/wl_netdev.c @@ -104,16 +104,15 @@ #ifdef USE_PROFILE #include <wl_profile.h> -#endif /* USE_PROFILE */ +#endif /* USE_PROFILE */ #ifdef BUS_PCMCIA #include <wl_cs.h> -#endif /* BUS_PCMCIA */ +#endif /* BUS_PCMCIA */ #ifdef BUS_PCI #include <wl_pci.h> -#endif /* BUS_PCI */ - +#endif /* BUS_PCI */ #if HCF_ENCAP #define MTU_MAX (HCF_MAX_MSG - ETH_HLEN - 8) @@ -158,20 +157,21 @@ * errno value otherwise * ******************************************************************************/ -int wl_init( struct net_device *dev ) +int wl_init(struct net_device *dev) { // unsigned long flags; // struct wl_private *lp = wl_priv(dev); - DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - /* Nothing to do, but grab the spinlock anyway just in case we ever need - this routine */ + /* Nothing to do, but grab the spinlock anyway just in case we ever need + this routine */ // wl_lock( lp, &flags ); // wl_unlock( lp, &flags ); - return 0; -} // wl_init + return 0; +} // wl_init + /*============================================================================*/ /******************************************************************************* @@ -193,17 +193,18 @@ int wl_init( struct net_device *dev ) * errno otherwise * ******************************************************************************/ -int wl_config( struct net_device *dev, struct ifmap *map ) +int wl_config(struct net_device *dev, struct ifmap *map) { - DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); - DBG_PARAM( DbgInfo, "map", "0x%p", map ); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "map", "0x%p", map); + + /* The only thing we care about here is a port change. Since this not needed, + ignore the request. */ + DBG_TRACE(DbgInfo, "%s: %s called.\n", dev->name, __func__); - /* The only thing we care about here is a port change. Since this not needed, - ignore the request. */ - DBG_TRACE(DbgInfo, "%s: %s called.\n", dev->name, __func__); + return 0; +} // wl_config - return 0; -} // wl_config /*============================================================================*/ /******************************************************************************* @@ -224,48 +225,49 @@ int wl_config( struct net_device *dev, struct ifmap *map ) * statistics. * ******************************************************************************/ -struct net_device_stats *wl_stats( struct net_device *dev ) +struct net_device_stats *wl_stats(struct net_device *dev) { #ifdef USE_WDS - int count; -#endif /* USE_WDS */ - unsigned long flags; - struct net_device_stats *pStats; - struct wl_private *lp = wl_priv(dev); + int count; +#endif /* USE_WDS */ + unsigned long flags; + struct net_device_stats *pStats; + struct wl_private *lp = wl_priv(dev); - //DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + //DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); - pStats = NULL; + pStats = NULL; - wl_lock( lp, &flags ); + wl_lock(lp, &flags); #ifdef USE_RTS - if( lp->useRTS == 1 ) { - wl_unlock( lp, &flags ); - return NULL; - } -#endif /* USE_RTS */ + if (lp->useRTS == 1) { + wl_unlock(lp, &flags); + return NULL; + } +#endif /* USE_RTS */ - /* Return the statistics for the appropriate device */ + /* Return the statistics for the appropriate device */ #ifdef USE_WDS - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - if( dev == lp->wds_port[count].dev ) { - pStats = &( lp->wds_port[count].stats ); + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (dev == lp->wds_port[count].dev) { + pStats = &(lp->wds_port[count].stats); + } } - } -#endif /* USE_WDS */ +#endif /* USE_WDS */ + + /* If pStats is still NULL, then the device is not a WDS port */ + if (pStats == NULL) { + pStats = &(lp->stats); + } - /* If pStats is still NULL, then the device is not a WDS port */ - if( pStats == NULL ) { - pStats = &( lp->stats ); - } + wl_unlock(lp, &flags); - wl_unlock( lp, &flags ); + return pStats; +} // wl_stats - return pStats; -} // wl_stats /*============================================================================*/ /******************************************************************************* @@ -288,75 +290,75 @@ struct net_device_stats *wl_stats( struct net_device *dev ) ******************************************************************************/ int wl_open(struct net_device *dev) { - int status = HCF_SUCCESS; - struct wl_private *lp = wl_priv(dev); - unsigned long flags; + int status = HCF_SUCCESS; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; - wl_lock( lp, &flags ); + wl_lock(lp, &flags); #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_TRACE( DbgInfo, "Skipping device open, in RTS mode\n" ); - wl_unlock( lp, &flags ); - return -EIO; - } -#endif /* USE_RTS */ + if (lp->useRTS == 1) { + DBG_TRACE(DbgInfo, "Skipping device open, in RTS mode\n"); + wl_unlock(lp, &flags); + return -EIO; + } +#endif /* USE_RTS */ #ifdef USE_PROFILE - parse_config( dev ); + parse_config(dev); #endif - if( lp->portState == WVLAN_PORT_STATE_DISABLED ) { - DBG_TRACE( DbgInfo, "Enabling Port 0\n" ); - status = wl_enable( lp ); - - if( status != HCF_SUCCESS ) { - DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", status ); - } - } - - // Holding the lock too long, make a gap to allow other processes - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - if ( strlen( lp->fw_image_filename ) ) { - DBG_TRACE( DbgInfo, ";???? Kludgy way to force a download\n" ); - status = wl_go( lp ); - } else { - status = wl_apply( lp ); - } - - // Holding the lock too long, make a gap to allow other processes - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - if( status != HCF_SUCCESS ) { - // Unsuccessful, try reset of the card to recover - status = wl_reset( dev ); - } - - // Holding the lock too long, make a gap to allow other processes - wl_unlock(lp, &flags); - wl_lock( lp, &flags ); - - if( status == HCF_SUCCESS ) { - netif_carrier_on( dev ); - WL_WDS_NETIF_CARRIER_ON( lp ); - - lp->is_handling_int = WL_HANDLING_INT; // Start handling interrupts - wl_act_int_on( lp ); - - netif_start_queue( dev ); - WL_WDS_NETIF_START_QUEUE( lp ); - } else { - wl_hcf_error( dev, status ); /* Report the error */ - netif_device_detach( dev ); /* Stop the device and queue */ - } - - wl_unlock( lp, &flags ); - - return status; -} // wl_open + if (lp->portState == WVLAN_PORT_STATE_DISABLED) { + DBG_TRACE(DbgInfo, "Enabling Port 0\n"); + status = wl_enable(lp); + + if (status != HCF_SUCCESS) { + DBG_TRACE(DbgInfo, "Enable port 0 failed: 0x%x\n", + status); + } + } + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock(lp, &flags); + + if (strlen(lp->fw_image_filename)) { + DBG_TRACE(DbgInfo, ";???? Kludgy way to force a download\n"); + status = wl_go(lp); + } else { + status = wl_apply(lp); + } + + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock(lp, &flags); + + if (status != HCF_SUCCESS) { + // Unsuccessful, try reset of the card to recover + status = wl_reset(dev); + } + // Holding the lock too long, make a gap to allow other processes + wl_unlock(lp, &flags); + wl_lock(lp, &flags); + + if (status == HCF_SUCCESS) { + netif_carrier_on(dev); + WL_WDS_NETIF_CARRIER_ON(lp); + + lp->is_handling_int = WL_HANDLING_INT; // Start handling interrupts + wl_act_int_on(lp); + + netif_start_queue(dev); + WL_WDS_NETIF_START_QUEUE(lp); + } else { + wl_hcf_error(dev, status); /* Report the error */ + netif_device_detach(dev); /* Stop the device and queue */ + } + + wl_unlock(lp, &flags); + + return status; +} // wl_open + /*============================================================================*/ /******************************************************************************* @@ -377,73 +379,73 @@ int wl_open(struct net_device *dev) * errno otherwise * ******************************************************************************/ -int wl_close( struct net_device *dev ) +int wl_close(struct net_device *dev) { - struct wl_private *lp = wl_priv(dev); - unsigned long flags; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; - DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - /* Mark the adapter as busy */ - netif_stop_queue( dev ); - WL_WDS_NETIF_STOP_QUEUE( lp ); + /* Mark the adapter as busy */ + netif_stop_queue(dev); + WL_WDS_NETIF_STOP_QUEUE(lp); - netif_carrier_off( dev ); - WL_WDS_NETIF_CARRIER_OFF( lp ); + netif_carrier_off(dev); + WL_WDS_NETIF_CARRIER_OFF(lp); - /* Shutdown the adapter: - Disable adapter interrupts - Stop Tx/Rx - Update statistics - Set low power mode - */ + /* Shutdown the adapter: + Disable adapter interrupts + Stop Tx/Rx + Update statistics + Set low power mode + */ - wl_lock( lp, &flags ); + wl_lock(lp, &flags); - wl_act_int_off( lp ); - lp->is_handling_int = WL_NOT_HANDLING_INT; // Stop handling interrupts + wl_act_int_off(lp); + lp->is_handling_int = WL_NOT_HANDLING_INT; // Stop handling interrupts #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_TRACE( DbgInfo, "Skipping device close, in RTS mode\n" ); - wl_unlock( lp, &flags ); - return -EIO; - } -#endif /* USE_RTS */ + if (lp->useRTS == 1) { + DBG_TRACE(DbgInfo, "Skipping device close, in RTS mode\n"); + wl_unlock(lp, &flags); + return -EIO; + } +#endif /* USE_RTS */ + + /* Disable the ports */ + wl_disable(lp); - /* Disable the ports */ - wl_disable( lp ); + wl_unlock(lp, &flags); - wl_unlock( lp, &flags ); + return 0; +} // wl_close - return 0; -} // wl_close /*============================================================================*/ static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION_STR, sizeof(info->version)); -// strlcpy(info.fw_version, priv->fw_name, -// sizeof(info.fw_version)); - - if (dev->dev.parent) { - dev_set_name(dev->dev.parent, "%s", info->bus_info); - //strlcpy(info->bus_info, dev->dev.parent->bus_id, - // sizeof(info->bus_info)); - } else { - snprintf(info->bus_info, sizeof(info->bus_info), - "PCMCIA FIXME"); -// "PCMCIA 0x%lx", priv->hw.iobase); - } -} // wl_get_drvinfo + strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION_STR, sizeof(info->version)); +// strlcpy(info.fw_version, priv->fw_name, +// sizeof(info.fw_version)); + + if (dev->dev.parent) { + dev_set_name(dev->dev.parent, "%s", info->bus_info); + //strlcpy(info->bus_info, dev->dev.parent->bus_id, + // sizeof(info->bus_info)); + } else { + snprintf(info->bus_info, sizeof(info->bus_info), + "PCMCIA FIXME"); +// "PCMCIA 0x%lx", priv->hw.iobase); + } +} // wl_get_drvinfo static struct ethtool_ops wl_ethtool_ops = { - .get_drvinfo = wl_get_drvinfo, - .get_link = ethtool_op_get_link, + .get_drvinfo = wl_get_drvinfo, + .get_link = ethtool_op_get_link, }; - /******************************************************************************* * wl_ioctl() ******************************************************************************* @@ -464,81 +466,86 @@ static struct ethtool_ops wl_ethtool_ops = { * errno value otherwise * ******************************************************************************/ -int wl_ioctl( struct net_device *dev, struct ifreq *rq, int cmd ) +int wl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret = 0; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret = 0; - DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - DBG_PARAM(DbgInfo, "rq", "0x%p", rq); - DBG_PARAM(DbgInfo, "cmd", "0x%04x", cmd); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "rq", "0x%p", rq); + DBG_PARAM(DbgInfo, "cmd", "0x%04x", cmd); - wl_lock( lp, &flags ); + wl_lock(lp, &flags); - wl_act_int_off( lp ); + wl_act_int_off(lp); #ifdef USE_RTS - if( lp->useRTS == 1 ) { - /* Handle any RTS IOCTL here */ - if( cmd == WL_IOCTL_RTS ) { - DBG_TRACE( DbgInfo, "IOCTL: WL_IOCTL_RTS\n" ); - ret = wvlan_rts( (struct rtsreq *)rq, dev->base_addr ); - } else { - DBG_TRACE( DbgInfo, "IOCTL not supported in RTS mode: 0x%X\n", cmd ); - ret = -EOPNOTSUPP; - } + if (lp->useRTS == 1) { + /* Handle any RTS IOCTL here */ + if (cmd == WL_IOCTL_RTS) { + DBG_TRACE(DbgInfo, "IOCTL: WL_IOCTL_RTS\n"); + ret = wvlan_rts((struct rtsreq *)rq, dev->base_addr); + } else { + DBG_TRACE(DbgInfo, + "IOCTL not supported in RTS mode: 0x%X\n", + cmd); + ret = -EOPNOTSUPP; + } - goto out_act_int_on_unlock; - } -#endif /* USE_RTS */ + goto out_act_int_on_unlock; + } +#endif /* USE_RTS */ - /* Only handle UIL IOCTL requests when the UIL has the system blocked. */ - if( !(( lp->flags & WVLAN2_UIL_BUSY ) && ( cmd != WVLAN2_IOCTL_UIL ))) { + /* Only handle UIL IOCTL requests when the UIL has the system blocked. */ + if (!((lp->flags & WVLAN2_UIL_BUSY) && (cmd != WVLAN2_IOCTL_UIL))) { #ifdef USE_UIL - struct uilreq *urq = (struct uilreq *)rq; + struct uilreq *urq = (struct uilreq *)rq; #endif /* USE_UIL */ - switch( cmd ) { - // ================== Private IOCTLs (up to 16) ================== + switch (cmd) { + // ================== Private IOCTLs (up to 16) ================== #ifdef USE_UIL - case WVLAN2_IOCTL_UIL: - DBG_TRACE( DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL\n" ); - ret = wvlan_uil( urq, lp ); - break; -#endif /* USE_UIL */ - - default: - DBG_TRACE(DbgInfo, "IOCTL CODE NOT SUPPORTED: 0x%X\n", cmd ); - ret = -EOPNOTSUPP; - break; + case WVLAN2_IOCTL_UIL: + DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL\n"); + ret = wvlan_uil(urq, lp); + break; +#endif /* USE_UIL */ + + default: + DBG_TRACE(DbgInfo, "IOCTL CODE NOT SUPPORTED: 0x%X\n", + cmd); + ret = -EOPNOTSUPP; + break; + } + } else { + DBG_WARNING(DbgInfo, + "DEVICE IS BUSY, CANNOT PROCESS REQUEST\n"); + ret = -EBUSY; } - } else { - DBG_WARNING( DbgInfo, "DEVICE IS BUSY, CANNOT PROCESS REQUEST\n" ); - ret = -EBUSY; - } #ifdef USE_RTS out_act_int_on_unlock: -#endif /* USE_RTS */ - wl_act_int_on( lp ); +#endif /* USE_RTS */ + wl_act_int_on(lp); + + wl_unlock(lp, &flags); - wl_unlock( lp, &flags ); + return ret; +} // wl_ioctl - return ret; -} // wl_ioctl /*============================================================================*/ #ifdef CONFIG_NET_POLL_CONTROLLER static void wl_poll(struct net_device *dev) { - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - struct pt_regs regs; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + struct pt_regs regs; - wl_lock( lp, &flags ); - wl_isr(dev->irq, dev, ®s); - wl_unlock( lp, &flags ); + wl_lock(lp, &flags); + wl_isr(dev->irq, dev, ®s); + wl_unlock(lp, &flags); } #endif @@ -559,53 +566,55 @@ static void wl_poll(struct net_device *dev) * N/A * ******************************************************************************/ -void wl_tx_timeout( struct net_device *dev ) +void wl_tx_timeout(struct net_device *dev) { #ifdef USE_WDS - int count; -#endif /* USE_WDS */ - unsigned long flags; - struct wl_private *lp = wl_priv(dev); - struct net_device_stats *pStats = NULL; + int count; +#endif /* USE_WDS */ + unsigned long flags; + struct wl_private *lp = wl_priv(dev); + struct net_device_stats *pStats = NULL; - DBG_WARNING( DbgInfo, "%s: Transmit timeout.\n", dev->name ); + DBG_WARNING(DbgInfo, "%s: Transmit timeout.\n", dev->name); - wl_lock( lp, &flags ); + wl_lock(lp, &flags); #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_TRACE( DbgInfo, "Skipping tx_timeout handler, in RTS mode\n" ); - wl_unlock( lp, &flags ); - return; - } -#endif /* USE_RTS */ - - /* Figure out which device (the "root" device or WDS port) this timeout - is for */ + if (lp->useRTS == 1) { + DBG_TRACE(DbgInfo, + "Skipping tx_timeout handler, in RTS mode\n"); + wl_unlock(lp, &flags); + return; + } +#endif /* USE_RTS */ + + /* Figure out which device (the "root" device or WDS port) this timeout + is for */ #ifdef USE_WDS - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - if( dev == lp->wds_port[count].dev ) { - pStats = &( lp->wds_port[count].stats ); + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (dev == lp->wds_port[count].dev) { + pStats = &(lp->wds_port[count].stats); - /* Break the loop so that we can use the counter to access WDS - information in the private structure */ - break; + /* Break the loop so that we can use the counter to access WDS + information in the private structure */ + break; + } } - } -#endif /* USE_WDS */ +#endif /* USE_WDS */ + + /* If pStats is still NULL, then the device is not a WDS port */ + if (pStats == NULL) { + pStats = &(lp->stats); + } - /* If pStats is still NULL, then the device is not a WDS port */ - if( pStats == NULL ) { - pStats = &( lp->stats ); - } + /* Accumulate the timeout error */ + pStats->tx_errors++; - /* Accumulate the timeout error */ - pStats->tx_errors++; + wl_unlock(lp, &flags); +} // wl_tx_timeout - wl_unlock( lp, &flags ); -} // wl_tx_timeout /*============================================================================*/ /******************************************************************************* @@ -626,103 +635,105 @@ void wl_tx_timeout( struct net_device *dev ) * 1 on error * ******************************************************************************/ -int wl_send( struct wl_private *lp ) +int wl_send(struct wl_private *lp) { - int status; - DESC_STRCT *desc; - WVLAN_LFRAME *txF = NULL; - struct list_head *element; - int len; + int status; + DESC_STRCT *desc; + WVLAN_LFRAME *txF = NULL; + struct list_head *element; + int len; /*------------------------------------------------------------------------*/ - if( lp == NULL ) { - DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" ); - return FALSE; - } - if( lp->dev == NULL ) { - DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" ); - return FALSE; - } - - /* Check for the availability of FIDs; if none are available, don't take any - frames off the txQ */ - if( lp->hcfCtx.IFB_RscInd == 0 ) { - return FALSE; - } - - /* Reclaim the TxQ Elements and place them back on the free queue */ - if( !list_empty( &( lp->txQ[0] ))) { - element = lp->txQ[0].next; - - txF = (WVLAN_LFRAME * )list_entry( element, WVLAN_LFRAME, node ); - if( txF != NULL ) { - lp->txF.skb = txF->frame.skb; - lp->txF.port = txF->frame.port; - - txF->frame.skb = NULL; - txF->frame.port = 0; - - list_del( &( txF->node )); - list_add( element, &( lp->txFree )); - - lp->txQ_count--; - - if( lp->txQ_count < TX_Q_LOW_WATER_MARK ) { - if( lp->netif_queue_on == FALSE ) { - DBG_TX( DbgInfo, "Kickstarting Q: %d\n", lp->txQ_count ); - netif_wake_queue( lp->dev ); - WL_WDS_NETIF_WAKE_QUEUE( lp ); - lp->netif_queue_on = TRUE; - } - } - } - } - - if( lp->txF.skb == NULL ) { - return FALSE; - } - - /* If the device has resources (FIDs) available, then Tx the packet */ - /* Format the TxRequest and send it to the adapter */ - len = lp->txF.skb->len < ETH_ZLEN ? ETH_ZLEN : lp->txF.skb->len; - - desc = &( lp->desc_tx ); - desc->buf_addr = lp->txF.skb->data; - desc->BUF_CNT = len; - desc->next_desc_addr = NULL; - - status = hcf_send_msg( &( lp->hcfCtx ), desc, lp->txF.port ); - - if( status == HCF_SUCCESS ) { - lp->dev->trans_start = jiffies; - - DBG_TX( DbgInfo, "Transmit...\n" ); - - if( lp->txF.port == HCF_PORT_0 ) { - lp->stats.tx_packets++; - lp->stats.tx_bytes += lp->txF.skb->len; - } + if (lp == NULL) { + DBG_ERROR(DbgInfo, "Private adapter struct is NULL\n"); + return FALSE; + } + if (lp->dev == NULL) { + DBG_ERROR(DbgInfo, "net_device struct in wl_private is NULL\n"); + return FALSE; + } + + /* Check for the availability of FIDs; if none are available, don't take any + frames off the txQ */ + if (lp->hcfCtx.IFB_RscInd == 0) { + return FALSE; + } + + /* Reclaim the TxQ Elements and place them back on the free queue */ + if (!list_empty(&(lp->txQ[0]))) { + element = lp->txQ[0].next; + + txF = (WVLAN_LFRAME *) list_entry(element, WVLAN_LFRAME, node); + if (txF != NULL) { + lp->txF.skb = txF->frame.skb; + lp->txF.port = txF->frame.port; + + txF->frame.skb = NULL; + txF->frame.port = 0; + + list_del(&(txF->node)); + list_add(element, &(lp->txFree)); + + lp->txQ_count--; + if (lp->txQ_count < TX_Q_LOW_WATER_MARK) { + if (lp->netif_queue_on == FALSE) { + DBG_TX(DbgInfo, "Kickstarting Q: %d\n", + lp->txQ_count); + netif_wake_queue(lp->dev); + WL_WDS_NETIF_WAKE_QUEUE(lp); + lp->netif_queue_on = TRUE; + } + } + } + } + + if (lp->txF.skb == NULL) { + return FALSE; + } + + /* If the device has resources (FIDs) available, then Tx the packet */ + /* Format the TxRequest and send it to the adapter */ + len = lp->txF.skb->len < ETH_ZLEN ? ETH_ZLEN : lp->txF.skb->len; + + desc = &(lp->desc_tx); + desc->buf_addr = lp->txF.skb->data; + desc->BUF_CNT = len; + desc->next_desc_addr = NULL; + + status = hcf_send_msg(&(lp->hcfCtx), desc, lp->txF.port); + + if (status == HCF_SUCCESS) { + lp->dev->trans_start = jiffies; + + DBG_TX(DbgInfo, "Transmit...\n"); + + if (lp->txF.port == HCF_PORT_0) { + lp->stats.tx_packets++; + lp->stats.tx_bytes += lp->txF.skb->len; + } #ifdef USE_WDS - else - { - lp->wds_port[(( lp->txF.port >> 8 ) - 1)].stats.tx_packets++; - lp->wds_port[(( lp->txF.port >> 8 ) - 1)].stats.tx_bytes += lp->txF.skb->len; - } + else { + lp->wds_port[((lp->txF.port >> 8) - + 1)].stats.tx_packets++; + lp->wds_port[((lp->txF.port >> 8) - + 1)].stats.tx_bytes += lp->txF.skb->len; + } -#endif /* USE_WDS */ +#endif /* USE_WDS */ - /* Free the skb and perform queue cleanup, as the buffer was - transmitted successfully */ - dev_kfree_skb( lp->txF.skb ); + /* Free the skb and perform queue cleanup, as the buffer was + transmitted successfully */ + dev_kfree_skb(lp->txF.skb); + + lp->txF.skb = NULL; + lp->txF.port = 0; + } - lp->txF.skb = NULL; - lp->txF.port = 0; - } + return TRUE; +} // wl_send - return TRUE; -} // wl_send /*============================================================================*/ /******************************************************************************* @@ -744,75 +755,74 @@ int wl_send( struct wl_private *lp ) * 1 on error * ******************************************************************************/ -int wl_tx( struct sk_buff *skb, struct net_device *dev, int port ) +int wl_tx(struct sk_buff *skb, struct net_device *dev, int port) { - unsigned long flags; - struct wl_private *lp = wl_priv(dev); - WVLAN_LFRAME *txF = NULL; - struct list_head *element; + unsigned long flags; + struct wl_private *lp = wl_priv(dev); + WVLAN_LFRAME *txF = NULL; + struct list_head *element; /*------------------------------------------------------------------------*/ - /* Grab the spinlock */ - wl_lock( lp, &flags ); - - if( lp->flags & WVLAN2_UIL_BUSY ) { - DBG_WARNING( DbgInfo, "UIL has device blocked\n" ); - /* Start dropping packets here??? */ - wl_unlock( lp, &flags ); - return 1; - } + /* Grab the spinlock */ + wl_lock(lp, &flags); + if (lp->flags & WVLAN2_UIL_BUSY) { + DBG_WARNING(DbgInfo, "UIL has device blocked\n"); + /* Start dropping packets here??? */ + wl_unlock(lp, &flags); + return 1; + } #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_PRINT( "RTS: we're getting a Tx...\n" ); - wl_unlock( lp, &flags ); - return 1; - } -#endif /* USE_RTS */ - - if( !lp->use_dma ) { - /* Get an element from the queue */ - element = lp->txFree.next; - txF = (WVLAN_LFRAME *)list_entry( element, WVLAN_LFRAME, node ); - if( txF == NULL ) { - DBG_ERROR( DbgInfo, "Problem with list_entry\n" ); - wl_unlock( lp, &flags ); - return 1; - } - /* Fill out the frame */ - txF->frame.skb = skb; - txF->frame.port = port; - /* Move the frame to the txQ */ - /* NOTE: Here's where we would do priority queueing */ - list_move(&(txF->node), &(lp->txQ[0])); - - lp->txQ_count++; - if( lp->txQ_count >= DEFAULT_NUM_TX_FRAMES ) { - DBG_TX( DbgInfo, "Q Full: %d\n", lp->txQ_count ); - if( lp->netif_queue_on == TRUE ) { - netif_stop_queue( lp->dev ); - WL_WDS_NETIF_STOP_QUEUE( lp ); - lp->netif_queue_on = FALSE; - } - } - } - wl_act_int_off( lp ); /* Disable Interrupts */ - - /* Send the data to the hardware using the appropriate method */ + if (lp->useRTS == 1) { + DBG_PRINT("RTS: we're getting a Tx...\n"); + wl_unlock(lp, &flags); + return 1; + } +#endif /* USE_RTS */ + + if (!lp->use_dma) { + /* Get an element from the queue */ + element = lp->txFree.next; + txF = (WVLAN_LFRAME *) list_entry(element, WVLAN_LFRAME, node); + if (txF == NULL) { + DBG_ERROR(DbgInfo, "Problem with list_entry\n"); + wl_unlock(lp, &flags); + return 1; + } + /* Fill out the frame */ + txF->frame.skb = skb; + txF->frame.port = port; + /* Move the frame to the txQ */ + /* NOTE: Here's where we would do priority queueing */ + list_move(&(txF->node), &(lp->txQ[0])); + + lp->txQ_count++; + if (lp->txQ_count >= DEFAULT_NUM_TX_FRAMES) { + DBG_TX(DbgInfo, "Q Full: %d\n", lp->txQ_count); + if (lp->netif_queue_on == TRUE) { + netif_stop_queue(lp->dev); + WL_WDS_NETIF_STOP_QUEUE(lp); + lp->netif_queue_on = FALSE; + } + } + } + wl_act_int_off(lp); /* Disable Interrupts */ + + /* Send the data to the hardware using the appropriate method */ #ifdef ENABLE_DMA - if( lp->use_dma ) { - wl_send_dma( lp, skb, port ); - } - else + if (lp->use_dma) { + wl_send_dma(lp, skb, port); + } else #endif - { - wl_send( lp ); - } - /* Re-enable Interrupts, release the spinlock and return */ - wl_act_int_on( lp ); - wl_unlock( lp, &flags ); - return 0; -} // wl_tx + { + wl_send(lp); + } + /* Re-enable Interrupts, release the spinlock and return */ + wl_act_int_on(lp); + wl_unlock(lp, &flags); + return 0; +} // wl_tx + /*============================================================================*/ /******************************************************************************* @@ -835,67 +845,68 @@ int wl_tx( struct sk_buff *skb, struct net_device *dev, int port ) ******************************************************************************/ int wl_rx(struct net_device *dev) { - int port; - struct sk_buff *skb; - struct wl_private *lp = wl_priv(dev); - int status; - hcf_16 pktlen; - hcf_16 hfs_stat; - DESC_STRCT *desc; + int port; + struct sk_buff *skb; + struct wl_private *lp = wl_priv(dev); + int status; + hcf_16 pktlen; + hcf_16 hfs_stat; + DESC_STRCT *desc; /*------------------------------------------------------------------------*/ - DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - if(!( lp->flags & WVLAN2_UIL_BUSY )) { + if (!(lp->flags & WVLAN2_UIL_BUSY)) { #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_PRINT( "RTS: We're getting an Rx...\n" ); - return -EIO; - } -#endif /* USE_RTS */ - - /* Read the HFS_STAT register from the lookahead buffer */ - hfs_stat = (hcf_16)(( lp->lookAheadBuf[HFS_STAT] ) | - ( lp->lookAheadBuf[HFS_STAT + 1] << 8 )); - - /* Make sure the frame isn't bad */ - if(( hfs_stat & HFS_STAT_ERR ) != HCF_SUCCESS ) { - DBG_WARNING( DbgInfo, "HFS_STAT_ERROR (0x%x) in Rx Packet\n", - lp->lookAheadBuf[HFS_STAT] ); - return -EIO; - } - - /* Determine what port this packet is for */ - port = ( hfs_stat >> 8 ) & 0x0007; - DBG_RX( DbgInfo, "Rx frame for port %d\n", port ); - - pktlen = lp->hcfCtx.IFB_RxLen; - if (pktlen != 0) { - skb = ALLOC_SKB(pktlen); - if (skb != NULL) { - /* Set the netdev based on the port */ - switch( port ) { + if (lp->useRTS == 1) { + DBG_PRINT("RTS: We're getting an Rx...\n"); + return -EIO; + } +#endif /* USE_RTS */ + + /* Read the HFS_STAT register from the lookahead buffer */ + hfs_stat = (hcf_16) ((lp->lookAheadBuf[HFS_STAT]) | + (lp->lookAheadBuf[HFS_STAT + 1] << 8)); + + /* Make sure the frame isn't bad */ + if ((hfs_stat & HFS_STAT_ERR) != HCF_SUCCESS) { + DBG_WARNING(DbgInfo, + "HFS_STAT_ERROR (0x%x) in Rx Packet\n", + lp->lookAheadBuf[HFS_STAT]); + return -EIO; + } + + /* Determine what port this packet is for */ + port = (hfs_stat >> 8) & 0x0007; + DBG_RX(DbgInfo, "Rx frame for port %d\n", port); + + pktlen = lp->hcfCtx.IFB_RxLen; + if (pktlen != 0) { + skb = ALLOC_SKB(pktlen); + if (skb != NULL) { + /* Set the netdev based on the port */ + switch (port) { #ifdef USE_WDS - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - skb->dev = lp->wds_port[port-1].dev; - break; -#endif /* USE_WDS */ - - case 0: - default: - skb->dev = dev; - break; - } - - desc = &( lp->desc_rx ); - - desc->next_desc_addr = NULL; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + skb->dev = lp->wds_port[port - 1].dev; + break; +#endif /* USE_WDS */ + + case 0: + default: + skb->dev = dev; + break; + } + + desc = &(lp->desc_rx); + + desc->next_desc_addr = NULL; /* #define BLOCK_INPUT(buf, len) \ @@ -904,67 +915,75 @@ int wl_rx(struct net_device *dev) status = hcf_rcv_msg(&(lp->hcfCtx), desc, 0) */ - GET_PACKET( skb->dev, skb, pktlen ); + GET_PACKET(skb->dev, skb, pktlen); - if( status == HCF_SUCCESS ) { - netif_rx( skb ); + if (status == HCF_SUCCESS) { + netif_rx(skb); - if( port == 0 ) { - lp->stats.rx_packets++; - lp->stats.rx_bytes += pktlen; - } + if (port == 0) { + lp->stats.rx_packets++; + lp->stats.rx_bytes += pktlen; + } #ifdef USE_WDS - else - { - lp->wds_port[port-1].stats.rx_packets++; - lp->wds_port[port-1].stats.rx_bytes += pktlen; - } -#endif /* USE_WDS */ - - dev->last_rx = jiffies; + else { + lp->wds_port[port - + 1].stats. + rx_packets++; + lp->wds_port[port - + 1].stats. + rx_bytes += pktlen; + } +#endif /* USE_WDS */ + + dev->last_rx = jiffies; #ifdef WIRELESS_EXT #ifdef WIRELESS_SPY - if( lp->spydata.spy_number > 0 ) { - char *srcaddr = skb->mac.raw + MAC_ADDR_SIZE; + if (lp->spydata.spy_number > 0) { + char *srcaddr = + skb->mac.raw + + MAC_ADDR_SIZE; - wl_spy_gather( dev, srcaddr ); - } + wl_spy_gather(dev, srcaddr); + } #endif /* WIRELESS_SPY */ #endif /* WIRELESS_EXT */ - } else { - DBG_ERROR( DbgInfo, "Rx request to card FAILED\n" ); + } else { + DBG_ERROR(DbgInfo, + "Rx request to card FAILED\n"); - if( port == 0 ) { - lp->stats.rx_dropped++; - } + if (port == 0) { + lp->stats.rx_dropped++; + } #ifdef USE_WDS - else - { - lp->wds_port[port-1].stats.rx_dropped++; - } -#endif /* USE_WDS */ - - dev_kfree_skb( skb ); - } - } else { - DBG_ERROR( DbgInfo, "Could not alloc skb\n" ); - - if( port == 0 ) { - lp->stats.rx_dropped++; - } + else { + lp->wds_port[port - + 1].stats. + rx_dropped++; + } +#endif /* USE_WDS */ + + dev_kfree_skb(skb); + } + } else { + DBG_ERROR(DbgInfo, "Could not alloc skb\n"); + + if (port == 0) { + lp->stats.rx_dropped++; + } #ifdef USE_WDS - else - { - lp->wds_port[port-1].stats.rx_dropped++; - } -#endif /* USE_WDS */ - } - } - } - - return 0; -} // wl_rx + else { + lp->wds_port[port - + 1].stats.rx_dropped++; + } +#endif /* USE_WDS */ + } + } + } + + return 0; +} // wl_rx + /*============================================================================*/ /******************************************************************************* @@ -986,142 +1005,153 @@ int wl_rx(struct net_device *dev) ******************************************************************************/ #ifdef NEW_MULTICAST -void wl_multicast( struct net_device *dev ) +void wl_multicast(struct net_device *dev) { -#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA //;?should we return an error status in AP mode +#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA //;?should we return an error status in AP mode //;?seems reasonable that even an AP-only driver could afford this small additional footprint - int x; - struct netdev_hw_addr *ha; - struct wl_private *lp = wl_priv(dev); - unsigned long flags; + int x; + struct netdev_hw_addr *ha; + struct wl_private *lp = wl_priv(dev); + unsigned long flags; - DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - if( !wl_adapter_is_open( dev )) - return; + if (!wl_adapter_is_open(dev)) + return; #if DBG - if( DBG_FLAGS( DbgInfo ) & DBG_PARAM_ON ) { - DBG_PRINT(" flags: %s%s%s\n", - ( dev->flags & IFF_PROMISC ) ? "Promiscuous " : "", - ( dev->flags & IFF_MULTICAST ) ? "Multicast " : "", - ( dev->flags & IFF_ALLMULTI ) ? "All-Multicast" : "" ); + if (DBG_FLAGS(DbgInfo) & DBG_PARAM_ON) { + DBG_PRINT(" flags: %s%s%s\n", + (dev->flags & IFF_PROMISC) ? "Promiscuous " : "", + (dev->flags & IFF_MULTICAST) ? "Multicast " : "", + (dev->flags & IFF_ALLMULTI) ? "All-Multicast" : ""); - DBG_PRINT( " mc_count: %d\n", netdev_mc_count(dev)); + DBG_PRINT(" mc_count: %d\n", netdev_mc_count(dev)); - netdev_for_each_mc_addr(ha, dev) - DBG_PRINT(" %pM (%d)\n", ha->addr, dev->addr_len); - } + netdev_for_each_mc_addr(ha, dev) + DBG_PRINT(" %pM (%d)\n", ha->addr, dev->addr_len); + } #endif /* DBG */ - if(!( lp->flags & WVLAN2_UIL_BUSY )) { + if (!(lp->flags & WVLAN2_UIL_BUSY)) { #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_TRACE( DbgInfo, "Skipping multicast, in RTS mode\n" ); - return; - } -#endif /* USE_RTS */ - - wl_lock( lp, &flags ); - wl_act_int_off( lp ); - - if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { - if( dev->flags & IFF_PROMISC ) { - /* Enable promiscuous mode */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 1 ); - DBG_PRINT( "Enabling Promiscuous mode (IFF_PROMISC)\n" ); - hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - } - else if ((netdev_mc_count(dev) > HCF_MAX_MULTICAST) || - ( dev->flags & IFF_ALLMULTI )) { - /* Shutting off this filter will enable all multicast frames to - be sent up from the device; however, this is a static RID, so - a call to wl_apply() is needed */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_CNF_RX_ALL_GROUP_ADDR; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); - DBG_PRINT( "Enabling all multicast mode (IFF_ALLMULTI)\n" ); - hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - wl_apply( lp ); - } - else if (!netdev_mc_empty(dev)) { - /* Set the multicast addresses */ - lp->ltvRecord.len = ( netdev_mc_count(dev) * 3 ) + 1; - lp->ltvRecord.typ = CFG_GROUP_ADDR; - - x = 0; - netdev_for_each_mc_addr(ha, dev) - memcpy(&(lp->ltvRecord.u.u8[x++ * ETH_ALEN]), - ha->addr, ETH_ALEN); - DBG_PRINT( "Setting multicast list\n" ); - hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - } else { - /* Disable promiscuous mode */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); - DBG_PRINT( "Disabling Promiscuous mode\n" ); - hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - /* Disable multicast mode */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_GROUP_ADDR; - DBG_PRINT( "Disabling Multicast mode\n" ); - hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - - /* Turning on this filter will prevent all multicast frames from - being sent up from the device; however, this is a static RID, - so a call to wl_apply() is needed */ - lp->ltvRecord.len = 2; - lp->ltvRecord.typ = CFG_CNF_RX_ALL_GROUP_ADDR; - lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 1 ); - DBG_PRINT( "Disabling all multicast mode (IFF_ALLMULTI)\n" ); - hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); - wl_apply( lp ); - } - } - wl_act_int_on( lp ); - wl_unlock( lp, &flags ); - } + if (lp->useRTS == 1) { + DBG_TRACE(DbgInfo, "Skipping multicast, in RTS mode\n"); + return; + } +#endif /* USE_RTS */ + + wl_lock(lp, &flags); + wl_act_int_off(lp); + + if (CNV_INT_TO_LITTLE(lp->hcfCtx.IFB_FWIdentity.comp_id) == + COMP_ID_FW_STA) { + if (dev->flags & IFF_PROMISC) { + /* Enable promiscuous mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(1); + DBG_PRINT + ("Enabling Promiscuous mode (IFF_PROMISC)\n"); + hcf_put_info(&(lp->hcfCtx), + (LTVP) & (lp->ltvRecord)); + } else if ((netdev_mc_count(dev) > HCF_MAX_MULTICAST) + || (dev->flags & IFF_ALLMULTI)) { + /* Shutting off this filter will enable all multicast frames to + be sent up from the device; however, this is a static RID, so + a call to wl_apply() is needed */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_RX_ALL_GROUP_ADDR; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(0); + DBG_PRINT + ("Enabling all multicast mode (IFF_ALLMULTI)\n"); + hcf_put_info(&(lp->hcfCtx), + (LTVP) & (lp->ltvRecord)); + wl_apply(lp); + } else if (!netdev_mc_empty(dev)) { + /* Set the multicast addresses */ + lp->ltvRecord.len = + (netdev_mc_count(dev) * 3) + 1; + lp->ltvRecord.typ = CFG_GROUP_ADDR; + + x = 0; + netdev_for_each_mc_addr(ha, dev) + memcpy(& + (lp->ltvRecord.u.u8[x++ * ETH_ALEN]), + ha->addr, ETH_ALEN); + DBG_PRINT("Setting multicast list\n"); + hcf_put_info(&(lp->hcfCtx), + (LTVP) & (lp->ltvRecord)); + } else { + /* Disable promiscuous mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(0); + DBG_PRINT("Disabling Promiscuous mode\n"); + hcf_put_info(&(lp->hcfCtx), + (LTVP) & (lp->ltvRecord)); + + /* Disable multicast mode */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_GROUP_ADDR; + DBG_PRINT("Disabling Multicast mode\n"); + hcf_put_info(&(lp->hcfCtx), + (LTVP) & (lp->ltvRecord)); + + /* Turning on this filter will prevent all multicast frames from + being sent up from the device; however, this is a static RID, + so a call to wl_apply() is needed */ + lp->ltvRecord.len = 2; + lp->ltvRecord.typ = CFG_CNF_RX_ALL_GROUP_ADDR; + lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(1); + DBG_PRINT + ("Disabling all multicast mode (IFF_ALLMULTI)\n"); + hcf_put_info(&(lp->hcfCtx), + (LTVP) & (lp->ltvRecord)); + wl_apply(lp); + } + } + wl_act_int_on(lp); + wl_unlock(lp, &flags); + } #endif /* HCF_STA */ -} // wl_multicast +} // wl_multicast + /*============================================================================*/ #else /* NEW_MULTICAST */ -void wl_multicast( struct net_device *dev, int num_addrs, void *addrs ) +void wl_multicast(struct net_device *dev, int num_addrs, void *addrs) { - DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); - DBG_PARAM( DbgInfo, "num_addrs", "%d", num_addrs ); - DBG_PARAM( DbgInfo, "addrs", "0x%p", addrs ); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "num_addrs", "%d", num_addrs); + DBG_PARAM(DbgInfo, "addrs", "0x%p", addrs); #error Obsolete set multicast interface! -} // wl_multicast +} // wl_multicast + /*============================================================================*/ #endif /* NEW_MULTICAST */ -static const struct net_device_ops wl_netdev_ops = -{ - .ndo_start_xmit = &wl_tx_port0, +static const struct net_device_ops wl_netdev_ops = { + .ndo_start_xmit = &wl_tx_port0, - .ndo_set_config = &wl_config, - .ndo_get_stats = &wl_stats, - .ndo_set_rx_mode = &wl_multicast, + .ndo_set_config = &wl_config, + .ndo_get_stats = &wl_stats, + .ndo_set_rx_mode = &wl_multicast, - .ndo_init = &wl_insert, - .ndo_open = &wl_adapter_open, - .ndo_stop = &wl_adapter_close, - .ndo_do_ioctl = &wl_ioctl, + .ndo_init = &wl_insert, + .ndo_open = &wl_adapter_open, + .ndo_stop = &wl_adapter_close, + .ndo_do_ioctl = &wl_ioctl, - .ndo_tx_timeout = &wl_tx_timeout, + .ndo_tx_timeout = &wl_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = wl_poll, + .ndo_poll_controller = wl_poll, #endif }; @@ -1144,48 +1174,47 @@ static const struct net_device_ops wl_netdev_ops = * device. * ******************************************************************************/ -struct net_device * wl_device_alloc( void ) +struct net_device *wl_device_alloc(void) { - struct net_device *dev = NULL; - struct wl_private *lp = NULL; - - /* Alloc a net_device struct */ - dev = alloc_etherdev(sizeof(struct wl_private)); - if (!dev) - return NULL; - - /* Initialize the 'next' pointer in the struct. Currently only used for PCI, - but do it here just in case it's used for other buses in the future */ - lp = wl_priv(dev); - + struct net_device *dev = NULL; + struct wl_private *lp = NULL; + + /* Alloc a net_device struct */ + dev = alloc_etherdev(sizeof(struct wl_private)); + if (!dev) + return NULL; + + /* Initialize the 'next' pointer in the struct. Currently only used for PCI, + but do it here just in case it's used for other buses in the future */ + lp = wl_priv(dev); + + /* Check MTU */ + if (dev->mtu > MTU_MAX) { + DBG_WARNING(DbgInfo, "%s: MTU set too high, limiting to %d.\n", + dev->name, MTU_MAX); + dev->mtu = MTU_MAX; + } - /* Check MTU */ - if( dev->mtu > MTU_MAX ) - { - DBG_WARNING( DbgInfo, "%s: MTU set too high, limiting to %d.\n", - dev->name, MTU_MAX ); - dev->mtu = MTU_MAX; - } + /* Setup the function table in the device structure. */ - /* Setup the function table in the device structure. */ + dev->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; + lp->wireless_data.spy_data = &lp->spy_data; + dev->wireless_data = &lp->wireless_data; - dev->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; - lp->wireless_data.spy_data = &lp->spy_data; - dev->wireless_data = &lp->wireless_data; + dev->netdev_ops = &wl_netdev_ops; - dev->netdev_ops = &wl_netdev_ops; + dev->watchdog_timeo = TX_TIMEOUT; - dev->watchdog_timeo = TX_TIMEOUT; + dev->ethtool_ops = &wl_ethtool_ops; - dev->ethtool_ops = &wl_ethtool_ops; + netif_stop_queue(dev); - netif_stop_queue( dev ); + /* Allocate virtual devices for WDS support if needed */ + WL_WDS_DEVICE_ALLOC(lp); - /* Allocate virtual devices for WDS support if needed */ - WL_WDS_DEVICE_ALLOC( lp ); + return dev; +} // wl_device_alloc - return dev; -} // wl_device_alloc /*============================================================================*/ /******************************************************************************* @@ -1206,15 +1235,16 @@ struct net_device * wl_device_alloc( void ) * N/A * ******************************************************************************/ -void wl_device_dealloc( struct net_device *dev ) +void wl_device_dealloc(struct net_device *dev) { // struct wl_private *lp = wl_priv(dev); - /* Dealloc the WDS ports */ - WL_WDS_DEVICE_DEALLOC( lp ); + /* Dealloc the WDS ports */ + WL_WDS_DEVICE_DEALLOC(lp); + + free_netdev(dev); +} // wl_device_dealloc - free_netdev( dev ); -} // wl_device_dealloc /*============================================================================*/ /******************************************************************************* @@ -1235,15 +1265,16 @@ void wl_device_dealloc( struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port0( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port0(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 0\n" ); + DBG_TX(DbgInfo, "Tx on Port 0\n"); - return wl_tx( skb, dev, HCF_PORT_0 ); + return wl_tx(skb, dev, HCF_PORT_0); #ifdef ENABLE_DMA - return wl_tx_dma( skb, dev, HCF_PORT_0 ); + return wl_tx_dma(skb, dev, HCF_PORT_0); #endif -} // wl_tx_port0 +} // wl_tx_port0 + /*============================================================================*/ #ifdef USE_WDS @@ -1266,11 +1297,12 @@ int wl_tx_port0( struct sk_buff *skb, struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port1( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port1(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 1\n" ); - return wl_tx( skb, dev, HCF_PORT_1 ); -} // wl_tx_port1 + DBG_TX(DbgInfo, "Tx on Port 1\n"); + return wl_tx(skb, dev, HCF_PORT_1); +} // wl_tx_port1 + /*============================================================================*/ /******************************************************************************* @@ -1291,11 +1323,12 @@ int wl_tx_port1( struct sk_buff *skb, struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port2( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port2(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 2\n" ); - return wl_tx( skb, dev, HCF_PORT_2 ); -} // wl_tx_port2 + DBG_TX(DbgInfo, "Tx on Port 2\n"); + return wl_tx(skb, dev, HCF_PORT_2); +} // wl_tx_port2 + /*============================================================================*/ /******************************************************************************* @@ -1316,11 +1349,12 @@ int wl_tx_port2( struct sk_buff *skb, struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port3( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port3(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 3\n" ); - return wl_tx( skb, dev, HCF_PORT_3 ); -} // wl_tx_port3 + DBG_TX(DbgInfo, "Tx on Port 3\n"); + return wl_tx(skb, dev, HCF_PORT_3); +} // wl_tx_port3 + /*============================================================================*/ /******************************************************************************* @@ -1341,11 +1375,12 @@ int wl_tx_port3( struct sk_buff *skb, struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port4( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port4(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 4\n" ); - return wl_tx( skb, dev, HCF_PORT_4 ); -} // wl_tx_port4 + DBG_TX(DbgInfo, "Tx on Port 4\n"); + return wl_tx(skb, dev, HCF_PORT_4); +} // wl_tx_port4 + /*============================================================================*/ /******************************************************************************* @@ -1366,11 +1401,12 @@ int wl_tx_port4( struct sk_buff *skb, struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port5( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port5(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 5\n" ); - return wl_tx( skb, dev, HCF_PORT_5 ); -} // wl_tx_port5 + DBG_TX(DbgInfo, "Tx on Port 5\n"); + return wl_tx(skb, dev, HCF_PORT_5); +} // wl_tx_port5 + /*============================================================================*/ /******************************************************************************* @@ -1391,11 +1427,12 @@ int wl_tx_port5( struct sk_buff *skb, struct net_device *dev ) * N/A * ******************************************************************************/ -int wl_tx_port6( struct sk_buff *skb, struct net_device *dev ) +int wl_tx_port6(struct sk_buff *skb, struct net_device *dev) { - DBG_TX( DbgInfo, "Tx on Port 6\n" ); - return wl_tx( skb, dev, HCF_PORT_6 ); -} // wl_tx_port6 + DBG_TX(DbgInfo, "Tx on Port 6\n"); + return wl_tx(skb, dev, HCF_PORT_6); +} // wl_tx_port6 + /*============================================================================*/ /******************************************************************************* @@ -1417,50 +1454,51 @@ int wl_tx_port6( struct sk_buff *skb, struct net_device *dev ) * structs in the private adapter structure. * ******************************************************************************/ -void wl_wds_device_alloc( struct wl_private *lp ) +void wl_wds_device_alloc(struct wl_private *lp) { - int count; + int count; - /* WDS support requires additional net_device structs to be allocated, - so that user space apps can use these virtual devices to specify the - port on which to Tx/Rx */ - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - struct net_device *dev_wds = NULL; + /* WDS support requires additional net_device structs to be allocated, + so that user space apps can use these virtual devices to specify the + port on which to Tx/Rx */ + for (count = 0; count < NUM_WDS_PORTS; count++) { + struct net_device *dev_wds = NULL; + + dev_wds = kzalloc(sizeof(struct net_device), GFP_KERNEL); + if (!dev_wds) + return; + + ether_setup(dev_wds); + + lp->wds_port[count].dev = dev_wds; + + /* Re-use wl_init for all the devices, as it currently does nothing, but + is required. Re-use the stats/tx_timeout handler for all as well; the + WDS port which is requesting these operations can be determined by + the net_device pointer. Set the private member of all devices to point + to the same net_device struct; that way, all information gets + funnelled through the one "real" net_device. Name the WDS ports + "wds<n>" */ + lp->wds_port[count].dev->init = &wl_init; + lp->wds_port[count].dev->get_stats = &wl_stats; + lp->wds_port[count].dev->tx_timeout = &wl_tx_timeout; + lp->wds_port[count].dev->watchdog_timeo = TX_TIMEOUT; + lp->wds_port[count].dev->priv = lp; + + sprintf(lp->wds_port[count].dev->name, "wds%d", count); + } - dev_wds = kzalloc(sizeof(struct net_device), GFP_KERNEL); - if (!dev_wds) - return; + /* Register the Tx handlers */ + lp->wds_port[0].dev->hard_start_xmit = &wl_tx_port1; + lp->wds_port[1].dev->hard_start_xmit = &wl_tx_port2; + lp->wds_port[2].dev->hard_start_xmit = &wl_tx_port3; + lp->wds_port[3].dev->hard_start_xmit = &wl_tx_port4; + lp->wds_port[4].dev->hard_start_xmit = &wl_tx_port5; + lp->wds_port[5].dev->hard_start_xmit = &wl_tx_port6; + + WL_WDS_NETIF_STOP_QUEUE(lp); +} // wl_wds_device_alloc - ether_setup( dev_wds ); - - lp->wds_port[count].dev = dev_wds; - - /* Re-use wl_init for all the devices, as it currently does nothing, but - is required. Re-use the stats/tx_timeout handler for all as well; the - WDS port which is requesting these operations can be determined by - the net_device pointer. Set the private member of all devices to point - to the same net_device struct; that way, all information gets - funnelled through the one "real" net_device. Name the WDS ports - "wds<n>" */ - lp->wds_port[count].dev->init = &wl_init; - lp->wds_port[count].dev->get_stats = &wl_stats; - lp->wds_port[count].dev->tx_timeout = &wl_tx_timeout; - lp->wds_port[count].dev->watchdog_timeo = TX_TIMEOUT; - lp->wds_port[count].dev->priv = lp; - - sprintf( lp->wds_port[count].dev->name, "wds%d", count ); - } - - /* Register the Tx handlers */ - lp->wds_port[0].dev->hard_start_xmit = &wl_tx_port1; - lp->wds_port[1].dev->hard_start_xmit = &wl_tx_port2; - lp->wds_port[2].dev->hard_start_xmit = &wl_tx_port3; - lp->wds_port[3].dev->hard_start_xmit = &wl_tx_port4; - lp->wds_port[4].dev->hard_start_xmit = &wl_tx_port5; - lp->wds_port[5].dev->hard_start_xmit = &wl_tx_port6; - - WL_WDS_NETIF_STOP_QUEUE( lp ); -} // wl_wds_device_alloc /*============================================================================*/ /******************************************************************************* @@ -1480,26 +1518,27 @@ void wl_wds_device_alloc( struct wl_private *lp ) * N/A * ******************************************************************************/ -void wl_wds_device_dealloc( struct wl_private *lp ) +void wl_wds_device_dealloc(struct wl_private *lp) { - int count; + int count; - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - struct net_device *dev_wds = NULL; + for (count = 0; count < NUM_WDS_PORTS; count++) { + struct net_device *dev_wds = NULL; - dev_wds = lp->wds_port[count].dev; + dev_wds = lp->wds_port[count].dev; - if( dev_wds != NULL ) { - if( dev_wds->flags & IFF_UP ) { - dev_close( dev_wds ); - dev_wds->flags &= ~( IFF_UP | IFF_RUNNING ); - } + if (dev_wds != NULL) { + if (dev_wds->flags & IFF_UP) { + dev_close(dev_wds); + dev_wds->flags &= ~(IFF_UP | IFF_RUNNING); + } + + free_netdev(dev_wds); + lp->wds_port[count].dev = NULL; + } + } +} // wl_wds_device_dealloc - free_netdev(dev_wds); - lp->wds_port[count].dev = NULL; - } - } -} // wl_wds_device_dealloc /*============================================================================*/ /******************************************************************************* @@ -1520,21 +1559,22 @@ void wl_wds_device_dealloc( struct wl_private *lp ) * N/A * ******************************************************************************/ -void wl_wds_netif_start_queue( struct wl_private *lp ) +void wl_wds_netif_start_queue(struct wl_private *lp) { - int count; + int count; /*------------------------------------------------------------------------*/ - if( lp != NULL ) { - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - if( lp->wds_port[count].is_registered && - lp->wds_port[count].netif_queue_on == FALSE ) { - netif_start_queue( lp->wds_port[count].dev ); - lp->wds_port[count].netif_queue_on = TRUE; - } - } - } -} // wl_wds_netif_start_queue + if (lp != NULL) { + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (lp->wds_port[count].is_registered && + lp->wds_port[count].netif_queue_on == FALSE) { + netif_start_queue(lp->wds_port[count].dev); + lp->wds_port[count].netif_queue_on = TRUE; + } + } + } +} // wl_wds_netif_start_queue + /*============================================================================*/ /******************************************************************************* @@ -1555,21 +1595,22 @@ void wl_wds_netif_start_queue( struct wl_private *lp ) * N/A * ******************************************************************************/ -void wl_wds_netif_stop_queue( struct wl_private *lp ) +void wl_wds_netif_stop_queue(struct wl_private *lp) { - int count; + int count; /*------------------------------------------------------------------------*/ - if( lp != NULL ) { - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - if( lp->wds_port[count].is_registered && - lp->wds_port[count].netif_queue_on == TRUE ) { - netif_stop_queue( lp->wds_port[count].dev ); - lp->wds_port[count].netif_queue_on = FALSE; - } - } - } -} // wl_wds_netif_stop_queue + if (lp != NULL) { + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (lp->wds_port[count].is_registered && + lp->wds_port[count].netif_queue_on == TRUE) { + netif_stop_queue(lp->wds_port[count].dev); + lp->wds_port[count].netif_queue_on = FALSE; + } + } + } +} // wl_wds_netif_stop_queue + /*============================================================================*/ /******************************************************************************* @@ -1590,21 +1631,22 @@ void wl_wds_netif_stop_queue( struct wl_private *lp ) * N/A * ******************************************************************************/ -void wl_wds_netif_wake_queue( struct wl_private *lp ) +void wl_wds_netif_wake_queue(struct wl_private *lp) { - int count; + int count; /*------------------------------------------------------------------------*/ - if( lp != NULL ) { - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - if( lp->wds_port[count].is_registered && - lp->wds_port[count].netif_queue_on == FALSE ) { - netif_wake_queue( lp->wds_port[count].dev ); - lp->wds_port[count].netif_queue_on = TRUE; - } - } - } -} // wl_wds_netif_wake_queue + if (lp != NULL) { + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (lp->wds_port[count].is_registered && + lp->wds_port[count].netif_queue_on == FALSE) { + netif_wake_queue(lp->wds_port[count].dev); + lp->wds_port[count].netif_queue_on = TRUE; + } + } + } +} // wl_wds_netif_wake_queue + /*============================================================================*/ /******************************************************************************* @@ -1625,19 +1667,20 @@ void wl_wds_netif_wake_queue( struct wl_private *lp ) * N/A * ******************************************************************************/ -void wl_wds_netif_carrier_on( struct wl_private *lp ) +void wl_wds_netif_carrier_on(struct wl_private *lp) { - int count; + int count; /*------------------------------------------------------------------------*/ - if( lp != NULL ) { - for( count = 0; count < NUM_WDS_PORTS; count++ ) { - if( lp->wds_port[count].is_registered ) { - netif_carrier_on( lp->wds_port[count].dev ); - } - } - } -} // wl_wds_netif_carrier_on + if (lp != NULL) { + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (lp->wds_port[count].is_registered) { + netif_carrier_on(lp->wds_port[count].dev); + } + } + } +} // wl_wds_netif_carrier_on + /*============================================================================*/ /******************************************************************************* @@ -1658,21 +1701,22 @@ void wl_wds_netif_carrier_on( struct wl_private *lp ) * N/A * ******************************************************************************/ -void wl_wds_netif_carrier_off( struct wl_private *lp ) +void wl_wds_netif_carrier_off(struct wl_private *lp) { int count; - if(lp != NULL) { - for(count = 0; count < NUM_WDS_PORTS; count++) { - if(lp->wds_port[count].is_registered) + if (lp != NULL) { + for (count = 0; count < NUM_WDS_PORTS; count++) { + if (lp->wds_port[count].is_registered) netif_carrier_off(lp->wds_port[count].dev); } } -} // wl_wds_netif_carrier_off +} // wl_wds_netif_carrier_off + /*============================================================================*/ -#endif /* USE_WDS */ +#endif /* USE_WDS */ #ifdef ENABLE_DMA /******************************************************************************* @@ -1695,70 +1739,71 @@ void wl_wds_netif_carrier_off( struct wl_private *lp ) * 1 on error * ******************************************************************************/ -int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ) +int wl_send_dma(struct wl_private *lp, struct sk_buff *skb, int port) { - int len; - DESC_STRCT *desc = NULL; - DESC_STRCT *desc_next = NULL; + int len; + DESC_STRCT *desc = NULL; + DESC_STRCT *desc_next = NULL; /*------------------------------------------------------------------------*/ - if( lp == NULL ) { - DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" ); - return FALSE; - } + if (lp == NULL) { + DBG_ERROR(DbgInfo, "Private adapter struct is NULL\n"); + return FALSE; + } + + if (lp->dev == NULL) { + DBG_ERROR(DbgInfo, "net_device struct in wl_private is NULL\n"); + return FALSE; + } - if( lp->dev == NULL ) { - DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" ); - return FALSE; - } + /* AGAIN, ALL THE QUEUEING DONE HERE IN I/O MODE IS NOT PERFORMED */ - /* AGAIN, ALL THE QUEUEING DONE HERE IN I/O MODE IS NOT PERFORMED */ + if (skb == NULL) { + DBG_WARNING(DbgInfo, "Nothing to send.\n"); + return FALSE; + } - if( skb == NULL ) { - DBG_WARNING (DbgInfo, "Nothing to send.\n"); - return FALSE; - } + len = skb->len; - len = skb->len; + /* Get a free descriptor */ + desc = wl_pci_dma_get_tx_packet(lp); - /* Get a free descriptor */ - desc = wl_pci_dma_get_tx_packet( lp ); + if (desc == NULL) { + if (lp->netif_queue_on == TRUE) { + netif_stop_queue(lp->dev); + WL_WDS_NETIF_STOP_QUEUE(lp); + lp->netif_queue_on = FALSE; - if( desc == NULL ) { - if( lp->netif_queue_on == TRUE ) { - netif_stop_queue( lp->dev ); - WL_WDS_NETIF_STOP_QUEUE( lp ); - lp->netif_queue_on = FALSE; + dev_kfree_skb(skb); + return 0; + } + } - dev_kfree_skb( skb ); - return 0; - } - } + SET_BUF_CNT(desc, /*HCF_DMA_FD_CNT */ HFS_ADDR_DEST); + SET_BUF_SIZE(desc, HCF_DMA_TX_BUF1_SIZE); - SET_BUF_CNT( desc, /*HCF_DMA_FD_CNT*/HFS_ADDR_DEST ); - SET_BUF_SIZE( desc, HCF_DMA_TX_BUF1_SIZE ); + desc_next = desc->next_desc_addr; - desc_next = desc->next_desc_addr; + if (desc_next->buf_addr == NULL) { + DBG_ERROR(DbgInfo, "DMA descriptor buf_addr is NULL\n"); + return FALSE; + } - if( desc_next->buf_addr == NULL ) { - DBG_ERROR( DbgInfo, "DMA descriptor buf_addr is NULL\n" ); - return FALSE; - } + /* Copy the payload into the DMA packet */ + memcpy(desc_next->buf_addr, skb->data, len); - /* Copy the payload into the DMA packet */ - memcpy( desc_next->buf_addr, skb->data, len ); + SET_BUF_CNT(desc_next, len); + SET_BUF_SIZE(desc_next, HCF_MAX_PACKET_SIZE); - SET_BUF_CNT( desc_next, len ); - SET_BUF_SIZE( desc_next, HCF_MAX_PACKET_SIZE ); + hcf_dma_tx_put(&(lp->hcfCtx), desc, 0); - hcf_dma_tx_put( &( lp->hcfCtx ), desc, 0 ); + /* Free the skb and perform queue cleanup, as the buffer was + transmitted successfully */ + dev_kfree_skb(skb); - /* Free the skb and perform queue cleanup, as the buffer was - transmitted successfully */ - dev_kfree_skb( skb ); + return TRUE; +} // wl_send_dma - return TRUE; -} // wl_send_dma /*============================================================================*/ /******************************************************************************* @@ -1779,147 +1824,151 @@ int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port ) * 1 on error * ******************************************************************************/ -int wl_rx_dma( struct net_device *dev ) +int wl_rx_dma(struct net_device *dev) { - int port; - hcf_16 pktlen; - hcf_16 hfs_stat; - struct sk_buff *skb; - struct wl_private *lp = NULL; - DESC_STRCT *desc, *desc_next; - //CFG_MB_INFO_RANGE2_STRCT x; + int port; + hcf_16 pktlen; + hcf_16 hfs_stat; + struct sk_buff *skb; + struct wl_private *lp = NULL; + DESC_STRCT *desc, *desc_next; + //CFG_MB_INFO_RANGE2_STRCT x; /*------------------------------------------------------------------------*/ - DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); + DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev); - if((( lp = dev->priv ) != NULL ) && - !( lp->flags & WVLAN2_UIL_BUSY )) { + if (((lp = dev->priv) != NULL) && !(lp->flags & WVLAN2_UIL_BUSY)) { #ifdef USE_RTS - if( lp->useRTS == 1 ) { - DBG_PRINT( "RTS: We're getting an Rx...\n" ); - return -EIO; - } -#endif /* USE_RTS */ - - //if( lp->dma.status == 0 ) - //{ - desc = hcf_dma_rx_get( &( lp->hcfCtx )); - - if( desc != NULL ) - { - /* Check and see if we rcvd. a WMP frame */ - /* - if((( *(hcf_8 *)&desc->buf_addr[HFS_STAT] ) & - ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR )) == HFS_STAT_WMP_MSG ) - { - DBG_TRACE( DbgInfo, "Got a WMP frame\n" ); - - x.len = sizeof( CFG_MB_INFO_RANGE2_STRCT ) / sizeof( hcf_16 ); - x.typ = CFG_MB_INFO; - x.base_typ = CFG_WMP; - x.frag_cnt = 2; - x.frag_buf[0].frag_len = GET_BUF_CNT( descp ) / sizeof( hcf_16 ); - x.frag_buf[0].frag_addr = (hcf_8 *) descp->buf_addr ; - x.frag_buf[1].frag_len = ( GET_BUF_CNT( descp->next_desc_addr ) + 1 ) / sizeof( hcf_16 ); - x.frag_buf[1].frag_addr = (hcf_8 *) descp->next_desc_addr->buf_addr ; - - hcf_put_info( &( lp->hcfCtx ), (LTVP)&x ); - } - */ - - desc_next = desc->next_desc_addr; - - /* Make sure the buffer isn't empty */ - if( GET_BUF_CNT( desc ) == 0 ) { - DBG_WARNING( DbgInfo, "Buffer is empty!\n" ); - - /* Give the descriptor back to the HCF */ - hcf_dma_rx_put( &( lp->hcfCtx ), desc ); - return -EIO; - } - - /* Read the HFS_STAT register from the lookahead buffer */ - hfs_stat = (hcf_16)( desc->buf_addr[HFS_STAT/2] ); - - /* Make sure the frame isn't bad */ - if(( hfs_stat & HFS_STAT_ERR ) != HCF_SUCCESS ) - { - DBG_WARNING( DbgInfo, "HFS_STAT_ERROR (0x%x) in Rx Packet\n", - desc->buf_addr[HFS_STAT/2] ); - - /* Give the descriptor back to the HCF */ - hcf_dma_rx_put( &( lp->hcfCtx ), desc ); - return -EIO; - } - - /* Determine what port this packet is for */ - port = ( hfs_stat >> 8 ) & 0x0007; - DBG_RX( DbgInfo, "Rx frame for port %d\n", port ); - - pktlen = GET_BUF_CNT(desc_next); - if (pktlen != 0) { - skb = ALLOC_SKB(pktlen); - if (skb != NULL) { - switch( port ) { + if (lp->useRTS == 1) { + DBG_PRINT("RTS: We're getting an Rx...\n"); + return -EIO; + } +#endif /* USE_RTS */ + + //if( lp->dma.status == 0 ) + //{ + desc = hcf_dma_rx_get(&(lp->hcfCtx)); + + if (desc != NULL) { + /* Check and see if we rcvd. a WMP frame */ + /* + if((( *(hcf_8 *)&desc->buf_addr[HFS_STAT] ) & + ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR )) == HFS_STAT_WMP_MSG ) + { + DBG_TRACE( DbgInfo, "Got a WMP frame\n" ); + + x.len = sizeof( CFG_MB_INFO_RANGE2_STRCT ) / sizeof( hcf_16 ); + x.typ = CFG_MB_INFO; + x.base_typ = CFG_WMP; + x.frag_cnt = 2; + x.frag_buf[0].frag_len = GET_BUF_CNT( descp ) / sizeof( hcf_16 ); + x.frag_buf[0].frag_addr = (hcf_8 *) descp->buf_addr ; + x.frag_buf[1].frag_len = ( GET_BUF_CNT( descp->next_desc_addr ) + 1 ) / sizeof( hcf_16 ); + x.frag_buf[1].frag_addr = (hcf_8 *) descp->next_desc_addr->buf_addr ; + + hcf_put_info( &( lp->hcfCtx ), (LTVP)&x ); + } + */ + + desc_next = desc->next_desc_addr; + + /* Make sure the buffer isn't empty */ + if (GET_BUF_CNT(desc) == 0) { + DBG_WARNING(DbgInfo, "Buffer is empty!\n"); + + /* Give the descriptor back to the HCF */ + hcf_dma_rx_put(&(lp->hcfCtx), desc); + return -EIO; + } + + /* Read the HFS_STAT register from the lookahead buffer */ + hfs_stat = (hcf_16) (desc->buf_addr[HFS_STAT / 2]); + + /* Make sure the frame isn't bad */ + if ((hfs_stat & HFS_STAT_ERR) != HCF_SUCCESS) { + DBG_WARNING(DbgInfo, + "HFS_STAT_ERROR (0x%x) in Rx Packet\n", + desc->buf_addr[HFS_STAT / 2]); + + /* Give the descriptor back to the HCF */ + hcf_dma_rx_put(&(lp->hcfCtx), desc); + return -EIO; + } + + /* Determine what port this packet is for */ + port = (hfs_stat >> 8) & 0x0007; + DBG_RX(DbgInfo, "Rx frame for port %d\n", port); + + pktlen = GET_BUF_CNT(desc_next); + if (pktlen != 0) { + skb = ALLOC_SKB(pktlen); + if (skb != NULL) { + switch (port) { #ifdef USE_WDS - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - skb->dev = lp->wds_port[port-1].dev; - break; -#endif /* USE_WDS */ - - case 0: - default: - skb->dev = dev; - break; - } - - GET_PACKET_DMA( skb->dev, skb, pktlen ); - - /* Give the descriptor back to the HCF */ - hcf_dma_rx_put( &( lp->hcfCtx ), desc ); - - netif_rx( skb ); - - if( port == 0 ) { - lp->stats.rx_packets++; - lp->stats.rx_bytes += pktlen; - } + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + skb->dev = + lp->wds_port[port - 1].dev; + break; +#endif /* USE_WDS */ + + case 0: + default: + skb->dev = dev; + break; + } + + GET_PACKET_DMA(skb->dev, skb, pktlen); + + /* Give the descriptor back to the HCF */ + hcf_dma_rx_put(&(lp->hcfCtx), desc); + + netif_rx(skb); + + if (port == 0) { + lp->stats.rx_packets++; + lp->stats.rx_bytes += pktlen; + } #ifdef USE_WDS - else - { - lp->wds_port[port-1].stats.rx_packets++; - lp->wds_port[port-1].stats.rx_bytes += pktlen; - } -#endif /* USE_WDS */ - - dev->last_rx = jiffies; - - } else { - DBG_ERROR( DbgInfo, "Could not alloc skb\n" ); - - if( port == 0 ) - { - lp->stats.rx_dropped++; - } + else { + lp->wds_port[port - + 1].stats. + rx_packets++; + lp->wds_port[port - + 1].stats. + rx_bytes += pktlen; + } +#endif /* USE_WDS */ + + dev->last_rx = jiffies; + + } else { + DBG_ERROR(DbgInfo, + "Could not alloc skb\n"); + + if (port == 0) { + lp->stats.rx_dropped++; + } #ifdef USE_WDS - else - { - lp->wds_port[port-1].stats.rx_dropped++; - } -#endif /* USE_WDS */ - } - } - } - //} - } - - return 0; -} // wl_rx_dma + else { + lp->wds_port[port - + 1].stats. + rx_dropped++; + } +#endif /* USE_WDS */ + } + } + } + //} + } + + return 0; +} // wl_rx_dma + /*============================================================================*/ -#endif // ENABLE_DMA +#endif // ENABLE_DMA |