2010-09-08 15:46:36 -06:00
|
|
|
#include "headers.h"
|
|
|
|
|
|
|
|
struct net_device *gblpnetdev;
|
|
|
|
|
|
|
|
static INT bcm_open(struct net_device *dev)
|
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-11-01 08:16:29 -06:00
|
|
|
|
2010-11-01 10:12:31 -06:00
|
|
|
if (Adapter->fw_download_done == FALSE) {
|
2010-11-01 10:18:36 -06:00
|
|
|
pr_notice(PFX "%s: link up failed (download in progress)\n",
|
2011-03-09 14:47:35 -07:00
|
|
|
dev->name);
|
2010-11-01 10:12:31 -06:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netif_msg_ifup(Adapter))
|
2010-11-01 10:18:36 -06:00
|
|
|
pr_info(PFX "%s: enabling interface\n", dev->name);
|
2010-11-01 10:12:31 -06:00
|
|
|
|
|
|
|
if (Adapter->LinkUpStatus) {
|
|
|
|
if (netif_msg_link(Adapter))
|
2010-11-01 10:18:36 -06:00
|
|
|
pr_info(PFX "%s: link up\n", dev->name);
|
2010-10-29 17:44:07 -06:00
|
|
|
|
2010-11-01 10:12:31 -06:00
|
|
|
netif_carrier_on(Adapter->dev);
|
|
|
|
netif_start_queue(Adapter->dev);
|
2010-09-08 15:46:36 -06:00
|
|
|
}
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
return 0;
|
2010-09-08 15:46:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static INT bcm_close(struct net_device *dev)
|
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-11-01 10:12:31 -06:00
|
|
|
|
|
|
|
if (netif_msg_ifdown(Adapter))
|
2010-11-01 10:18:36 -06:00
|
|
|
pr_info(PFX "%s: disabling interface\n", dev->name);
|
2010-11-01 10:12:31 -06:00
|
|
|
|
|
|
|
netif_carrier_off(dev);
|
|
|
|
netif_stop_queue(dev);
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
return 0;
|
2010-09-08 15:46:36 -06:00
|
|
|
}
|
|
|
|
|
2010-10-31 21:55:21 -06:00
|
|
|
static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
return ClassifyPacket(netdev_priv(dev), skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
* Function - bcm_transmit()
|
|
|
|
*
|
|
|
|
* Description - This is the main transmit function for our virtual
|
2010-11-01 08:16:29 -06:00
|
|
|
* interface(eth0). It handles the ARP packets. It
|
|
|
|
* clones this packet and then Queue it to a suitable
|
2011-03-09 14:47:35 -07:00
|
|
|
* Queue. Then calls the transmit_packet().
|
2010-10-31 21:55:21 -06:00
|
|
|
*
|
|
|
|
* Parameter - skb - Pointer to the socket buffer structure
|
2010-11-01 08:16:29 -06:00
|
|
|
* dev - Pointer to the virtual net device structure
|
2010-10-31 21:55:21 -06:00
|
|
|
*
|
|
|
|
*********************************************************************/
|
|
|
|
|
|
|
|
static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-10-31 21:55:21 -06:00
|
|
|
u16 qindex = skb_get_queue_mapping(skb);
|
|
|
|
|
2010-11-01 10:12:31 -06:00
|
|
|
|
2010-10-31 21:55:21 -06:00
|
|
|
if (Adapter->device_removed || !Adapter->LinkUpStatus)
|
|
|
|
goto drop;
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
if (Adapter->TransferMode != IP_PACKET_ONLY_MODE)
|
2010-10-31 21:55:21 -06:00
|
|
|
goto drop;
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
if (INVALID_QUEUE_INDEX == qindex)
|
2010-10-31 21:55:21 -06:00
|
|
|
goto drop;
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
if (Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >=
|
|
|
|
SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
|
2010-10-31 21:55:21 -06:00
|
|
|
return NETDEV_TX_BUSY;
|
|
|
|
|
|
|
|
/* Now Enqueue the packet */
|
2010-11-01 10:12:31 -06:00
|
|
|
if (netif_msg_tx_queued(Adapter))
|
2010-11-01 10:18:36 -06:00
|
|
|
pr_info(PFX "%s: enqueueing packet to queue %d\n",
|
2010-11-01 10:12:31 -06:00
|
|
|
dev->name, qindex);
|
2010-11-01 08:16:29 -06:00
|
|
|
|
2010-10-31 21:55:21 -06:00
|
|
|
spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
|
|
|
|
Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
|
|
|
|
Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
*((B_UINT32 *) skb->cb + SKB_CB_LATENCY_OFFSET) = jiffies;
|
2010-10-31 21:55:21 -06:00
|
|
|
ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
|
|
|
|
Adapter->PackInfo[qindex].LastTxQueue, skb);
|
|
|
|
atomic_inc(&Adapter->TotalPacketCount);
|
|
|
|
spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);
|
|
|
|
|
|
|
|
/* FIXME - this is racy and incorrect, replace with work queue */
|
|
|
|
if (!atomic_read(&Adapter->TxPktAvail)) {
|
|
|
|
atomic_set(&Adapter->TxPktAvail, 1);
|
|
|
|
wake_up(&Adapter->tx_packet_wait_queue);
|
|
|
|
}
|
|
|
|
return NETDEV_TX_OK;
|
|
|
|
|
|
|
|
drop:
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
return NETDEV_TX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-09-08 15:46:36 -06:00
|
|
|
/**
|
|
|
|
@ingroup init_functions
|
|
|
|
Register other driver entry points with the kernel
|
|
|
|
*/
|
2010-10-29 17:44:07 -06:00
|
|
|
static const struct net_device_ops bcmNetDevOps = {
|
2011-03-09 14:47:35 -07:00
|
|
|
.ndo_open = bcm_open,
|
|
|
|
.ndo_stop = bcm_close,
|
|
|
|
.ndo_start_xmit = bcm_transmit,
|
|
|
|
.ndo_change_mtu = eth_change_mtu,
|
|
|
|
.ndo_set_mac_address = eth_mac_addr,
|
|
|
|
.ndo_validate_addr = eth_validate_addr,
|
|
|
|
.ndo_select_queue = bcm_select_queue,
|
2010-09-08 15:46:36 -06:00
|
|
|
};
|
2010-10-29 17:44:07 -06:00
|
|
|
|
|
|
|
static struct device_type wimax_type = {
|
|
|
|
.name = "wimax",
|
|
|
|
};
|
2010-09-08 15:46:36 -06:00
|
|
|
|
2010-10-29 18:12:37 -06:00
|
|
|
static int bcm_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
|
|
|
{
|
|
|
|
cmd->supported = 0;
|
|
|
|
cmd->advertising = 0;
|
|
|
|
cmd->speed = SPEED_10000;
|
|
|
|
cmd->duplex = DUPLEX_FULL;
|
|
|
|
cmd->port = PORT_TP;
|
|
|
|
cmd->phy_address = 0;
|
|
|
|
cmd->transceiver = XCVR_INTERNAL;
|
|
|
|
cmd->autoneg = AUTONEG_DISABLE;
|
|
|
|
cmd->maxtxpkt = 0;
|
|
|
|
cmd->maxrxpkt = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-09 14:47:35 -07:00
|
|
|
static void bcm_get_drvinfo(struct net_device *dev,
|
|
|
|
struct ethtool_drvinfo *info)
|
2010-10-29 18:12:37 -06:00
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-10-29 18:12:37 -06:00
|
|
|
PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter;
|
|
|
|
struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface);
|
|
|
|
|
|
|
|
strcpy(info->driver, DRV_NAME);
|
|
|
|
strcpy(info->version, DRV_VERSION);
|
|
|
|
snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u",
|
|
|
|
Adapter->uiFlashLayoutMajorVersion,
|
|
|
|
Adapter->uiFlashLayoutMinorVersion);
|
|
|
|
|
|
|
|
usb_make_path(udev, info->bus_info, sizeof(info->bus_info));
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32 bcm_get_link(struct net_device *dev)
|
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-10-29 18:12:37 -06:00
|
|
|
|
|
|
|
return Adapter->LinkUpStatus;
|
|
|
|
}
|
|
|
|
|
2011-03-09 14:47:35 -07:00
|
|
|
static u32 bcm_get_msglevel(struct net_device *dev)
|
2010-11-01 10:12:31 -06:00
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-11-01 10:12:31 -06:00
|
|
|
|
|
|
|
return Adapter->msg_enable;
|
|
|
|
}
|
|
|
|
|
2011-03-09 14:47:35 -07:00
|
|
|
static void bcm_set_msglevel(struct net_device *dev, u32 level)
|
2010-11-01 10:12:31 -06:00
|
|
|
{
|
2012-05-26 10:05:12 -06:00
|
|
|
struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
|
2010-11-01 10:12:31 -06:00
|
|
|
|
|
|
|
Adapter->msg_enable = level;
|
|
|
|
}
|
|
|
|
|
2010-10-29 18:12:37 -06:00
|
|
|
static const struct ethtool_ops bcm_ethtool_ops = {
|
|
|
|
.get_settings = bcm_get_settings,
|
|
|
|
.get_drvinfo = bcm_get_drvinfo,
|
2011-03-09 14:47:35 -07:00
|
|
|
.get_link = bcm_get_link,
|
2010-11-01 10:12:31 -06:00
|
|
|
.get_msglevel = bcm_get_msglevel,
|
|
|
|
.set_msglevel = bcm_set_msglevel,
|
2010-10-29 18:12:37 -06:00
|
|
|
};
|
|
|
|
|
2012-05-26 10:05:12 -06:00
|
|
|
int register_networkdev(struct bcm_mini_adapter *Adapter)
|
2010-09-08 15:46:36 -06:00
|
|
|
{
|
2010-11-01 07:52:14 -06:00
|
|
|
struct net_device *net = Adapter->dev;
|
2010-11-01 12:06:24 -06:00
|
|
|
PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter;
|
|
|
|
struct usb_interface *udev = IntfAdapter->interface;
|
|
|
|
struct usb_device *xdev = IntfAdapter->udev;
|
|
|
|
|
2010-10-29 17:44:07 -06:00
|
|
|
int result;
|
|
|
|
|
2010-11-01 08:16:29 -06:00
|
|
|
net->netdev_ops = &bcmNetDevOps;
|
2010-10-29 18:12:37 -06:00
|
|
|
net->ethtool_ops = &bcm_ethtool_ops;
|
2010-11-01 08:16:29 -06:00
|
|
|
net->mtu = MTU_SIZE; /* 1400 Bytes */
|
2010-10-29 18:15:06 -06:00
|
|
|
net->tx_queue_len = TX_QLEN;
|
2010-11-01 07:53:58 -06:00
|
|
|
net->flags |= IFF_NOARP;
|
|
|
|
|
2010-10-29 22:39:54 -06:00
|
|
|
netif_carrier_off(net);
|
2010-10-29 17:44:07 -06:00
|
|
|
|
|
|
|
SET_NETDEV_DEVTYPE(net, &wimax_type);
|
|
|
|
|
2010-09-08 15:46:36 -06:00
|
|
|
/* Read the MAC Address from EEPROM */
|
2010-11-01 12:06:24 -06:00
|
|
|
result = ReadMacAddressFromNVM(Adapter);
|
|
|
|
if (result != STATUS_SUCCESS) {
|
|
|
|
dev_err(&udev->dev,
|
|
|
|
PFX "Error in Reading the mac Address: %d", result);
|
2011-03-09 14:47:35 -07:00
|
|
|
return -EIO;
|
2010-11-01 12:06:24 -06:00
|
|
|
}
|
2010-09-08 15:46:36 -06:00
|
|
|
|
2010-10-29 17:44:07 -06:00
|
|
|
result = register_netdev(net);
|
2010-11-01 12:06:24 -06:00
|
|
|
if (result)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
gblpnetdev = Adapter->dev;
|
2010-09-08 15:46:36 -06:00
|
|
|
|
2010-11-01 12:06:24 -06:00
|
|
|
if (netif_msg_probe(Adapter))
|
|
|
|
dev_info(&udev->dev, PFX "%s: register usb-%s-%s %pM\n",
|
|
|
|
net->name, xdev->bus->bus_name, xdev->devpath,
|
|
|
|
net->dev_addr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 10:05:12 -06:00
|
|
|
void unregister_networkdev(struct bcm_mini_adapter *Adapter)
|
2010-11-01 12:06:24 -06:00
|
|
|
{
|
|
|
|
struct net_device *net = Adapter->dev;
|
|
|
|
PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter;
|
|
|
|
struct usb_interface *udev = IntfAdapter->interface;
|
|
|
|
struct usb_device *xdev = IntfAdapter->udev;
|
|
|
|
|
|
|
|
if (netif_msg_probe(Adapter))
|
|
|
|
dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n",
|
|
|
|
net->name, xdev->bus->bus_name, xdev->devpath);
|
2011-03-09 14:47:35 -07:00
|
|
|
|
2010-11-01 12:06:24 -06:00
|
|
|
unregister_netdev(Adapter->dev);
|
2010-09-08 15:46:36 -06:00
|
|
|
}
|