Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 1 | #include "headers.h" |
| 2 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 3 | struct net_device *gblpnetdev; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 4 | |
| 5 | static INT bcm_open(struct net_device *dev) |
| 6 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 7 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Stephen Hemminger | 0ad008f | 2010-10-29 16:44:07 -0700 | [diff] [blame] | 8 | |
Lisa Nguyen | f70c8a9 | 2013-10-28 01:36:19 -0700 | [diff] [blame] | 9 | if (Adapter->fw_download_done == false) { |
Stephen Hemminger | 9ec4475 | 2010-11-01 12:18:36 -0400 | [diff] [blame] | 10 | pr_notice(PFX "%s: link up failed (download in progress)\n", |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 11 | dev->name); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 12 | return -EBUSY; |
| 13 | } |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 14 | |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 15 | if (netif_msg_ifup(Adapter)) |
Stephen Hemminger | 9ec4475 | 2010-11-01 12:18:36 -0400 | [diff] [blame] | 16 | pr_info(PFX "%s: enabling interface\n", dev->name); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 17 | |
| 18 | if (Adapter->LinkUpStatus) { |
| 19 | if (netif_msg_link(Adapter)) |
Stephen Hemminger | 9ec4475 | 2010-11-01 12:18:36 -0400 | [diff] [blame] | 20 | pr_info(PFX "%s: link up\n", dev->name); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 21 | |
| 22 | netif_carrier_on(Adapter->dev); |
| 23 | netif_start_queue(Adapter->dev); |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 24 | } |
| 25 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 26 | return 0; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 27 | } |
| 28 | |
| 29 | static INT bcm_close(struct net_device *dev) |
| 30 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 31 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 32 | |
| 33 | if (netif_msg_ifdown(Adapter)) |
Stephen Hemminger | 9ec4475 | 2010-11-01 12:18:36 -0400 | [diff] [blame] | 34 | pr_info(PFX "%s: disabling interface\n", dev->name); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 35 | |
| 36 | netif_carrier_off(dev); |
| 37 | netif_stop_queue(dev); |
| 38 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 39 | return 0; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 40 | } |
| 41 | |
Jason Wang | f663dd9 | 2014-01-10 16:18:26 +0800 | [diff] [blame] | 42 | static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb, |
| 43 | void *accel_priv) |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 44 | { |
| 45 | return ClassifyPacket(netdev_priv(dev), skb); |
| 46 | } |
| 47 | |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 48 | /******************************************************************* |
| 49 | * Function - bcm_transmit() |
| 50 | * |
| 51 | * Description - This is the main transmit function for our virtual |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 52 | * interface(eth0). It handles the ARP packets. It |
| 53 | * clones this packet and then Queue it to a suitable |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 54 | * Queue. Then calls the transmit_packet(). |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 55 | * |
| 56 | * Parameter - skb - Pointer to the socket buffer structure |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 57 | * dev - Pointer to the virtual net device structure |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 58 | * |
| 59 | *********************************************************************/ |
| 60 | |
| 61 | static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev) |
| 62 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 63 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 64 | u16 qindex = skb_get_queue_mapping(skb); |
| 65 | |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 66 | |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 67 | if (Adapter->device_removed || !Adapter->LinkUpStatus) |
| 68 | goto drop; |
| 69 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 70 | if (Adapter->TransferMode != IP_PACKET_ONLY_MODE) |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 71 | goto drop; |
| 72 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 73 | if (INVALID_QUEUE_INDEX == qindex) |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 74 | goto drop; |
| 75 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 76 | if (Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= |
| 77 | SF_MAX_ALLOWED_PACKETS_TO_BACKUP) |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 78 | return NETDEV_TX_BUSY; |
| 79 | |
| 80 | /* Now Enqueue the packet */ |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 81 | if (netif_msg_tx_queued(Adapter)) |
Stephen Hemminger | 9ec4475 | 2010-11-01 12:18:36 -0400 | [diff] [blame] | 82 | pr_info(PFX "%s: enqueueing packet to queue %d\n", |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 83 | dev->name, qindex); |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 84 | |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 85 | spin_lock(&Adapter->PackInfo[qindex].SFQueueLock); |
| 86 | Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len; |
| 87 | Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++; |
| 88 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 89 | *((B_UINT32 *) skb->cb + SKB_CB_LATENCY_OFFSET) = jiffies; |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 90 | ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue, |
| 91 | Adapter->PackInfo[qindex].LastTxQueue, skb); |
| 92 | atomic_inc(&Adapter->TotalPacketCount); |
| 93 | spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock); |
| 94 | |
Stephen Hemminger | 9371105 | 2010-10-31 23:55:21 -0400 | [diff] [blame] | 95 | /* FIXME - this is racy and incorrect, replace with work queue */ |
| 96 | if (!atomic_read(&Adapter->TxPktAvail)) { |
| 97 | atomic_set(&Adapter->TxPktAvail, 1); |
| 98 | wake_up(&Adapter->tx_packet_wait_queue); |
| 99 | } |
| 100 | return NETDEV_TX_OK; |
| 101 | |
| 102 | drop: |
| 103 | dev_kfree_skb(skb); |
| 104 | return NETDEV_TX_OK; |
| 105 | } |
| 106 | |
| 107 | |
| 108 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 109 | /** |
| 110 | @ingroup init_functions |
| 111 | Register other driver entry points with the kernel |
| 112 | */ |
Stephen Hemminger | 0ad008f | 2010-10-29 16:44:07 -0700 | [diff] [blame] | 113 | static const struct net_device_ops bcmNetDevOps = { |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 114 | .ndo_open = bcm_open, |
| 115 | .ndo_stop = bcm_close, |
| 116 | .ndo_start_xmit = bcm_transmit, |
| 117 | .ndo_change_mtu = eth_change_mtu, |
| 118 | .ndo_set_mac_address = eth_mac_addr, |
| 119 | .ndo_validate_addr = eth_validate_addr, |
| 120 | .ndo_select_queue = bcm_select_queue, |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 121 | }; |
Stephen Hemminger | 0ad008f | 2010-10-29 16:44:07 -0700 | [diff] [blame] | 122 | |
| 123 | static struct device_type wimax_type = { |
| 124 | .name = "wimax", |
| 125 | }; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 126 | |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 127 | static int bcm_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
| 128 | { |
| 129 | cmd->supported = 0; |
| 130 | cmd->advertising = 0; |
| 131 | cmd->speed = SPEED_10000; |
| 132 | cmd->duplex = DUPLEX_FULL; |
| 133 | cmd->port = PORT_TP; |
| 134 | cmd->phy_address = 0; |
| 135 | cmd->transceiver = XCVR_INTERNAL; |
| 136 | cmd->autoneg = AUTONEG_DISABLE; |
| 137 | cmd->maxtxpkt = 0; |
| 138 | cmd->maxrxpkt = 0; |
| 139 | return 0; |
| 140 | } |
| 141 | |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 142 | static void bcm_get_drvinfo(struct net_device *dev, |
| 143 | struct ethtool_drvinfo *info) |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 144 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 145 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Ebru Akagunduz | 95a7a86 | 2013-10-07 18:09:59 +0300 | [diff] [blame] | 146 | struct bcm_interface_adapter *psIntfAdapter = |
| 147 | Adapter->pvInterfaceAdapter; |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 148 | struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface); |
| 149 | |
Jiri Pirko | 7826d43 | 2013-01-06 00:44:26 +0000 | [diff] [blame] | 150 | strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); |
| 151 | strlcpy(info->version, DRV_VERSION, sizeof(info->version)); |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 152 | snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u", |
| 153 | Adapter->uiFlashLayoutMajorVersion, |
| 154 | Adapter->uiFlashLayoutMinorVersion); |
| 155 | |
| 156 | usb_make_path(udev, info->bus_info, sizeof(info->bus_info)); |
| 157 | } |
| 158 | |
| 159 | static u32 bcm_get_link(struct net_device *dev) |
| 160 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 161 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 162 | |
| 163 | return Adapter->LinkUpStatus; |
| 164 | } |
| 165 | |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 166 | static u32 bcm_get_msglevel(struct net_device *dev) |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 167 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 168 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 169 | |
| 170 | return Adapter->msg_enable; |
| 171 | } |
| 172 | |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 173 | static void bcm_set_msglevel(struct net_device *dev, u32 level) |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 174 | { |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 175 | struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 176 | |
| 177 | Adapter->msg_enable = level; |
| 178 | } |
| 179 | |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 180 | static const struct ethtool_ops bcm_ethtool_ops = { |
| 181 | .get_settings = bcm_get_settings, |
| 182 | .get_drvinfo = bcm_get_drvinfo, |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 183 | .get_link = bcm_get_link, |
Stephen Hemminger | 4fd64dd | 2010-11-01 12:12:31 -0400 | [diff] [blame] | 184 | .get_msglevel = bcm_get_msglevel, |
| 185 | .set_msglevel = bcm_set_msglevel, |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 186 | }; |
| 187 | |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 188 | int register_networkdev(struct bcm_mini_adapter *Adapter) |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 189 | { |
Stephen Hemminger | e614e28 | 2010-11-01 09:52:14 -0400 | [diff] [blame] | 190 | struct net_device *net = Adapter->dev; |
Kevin McKinney | d6861cf | 2012-11-01 23:42:21 -0400 | [diff] [blame] | 191 | struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter; |
Stephen Hemminger | 4ea4f7a | 2010-11-01 14:06:24 -0400 | [diff] [blame] | 192 | struct usb_interface *udev = IntfAdapter->interface; |
| 193 | struct usb_device *xdev = IntfAdapter->udev; |
| 194 | |
Stephen Hemminger | 0ad008f | 2010-10-29 16:44:07 -0700 | [diff] [blame] | 195 | int result; |
| 196 | |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 197 | net->netdev_ops = &bcmNetDevOps; |
Stephen Hemminger | d21d6dde | 2010-10-29 17:12:37 -0700 | [diff] [blame] | 198 | net->ethtool_ops = &bcm_ethtool_ops; |
Stephen Hemminger | 46c3790 | 2010-11-01 10:16:29 -0400 | [diff] [blame] | 199 | net->mtu = MTU_SIZE; /* 1400 Bytes */ |
Stephen Hemminger | d7affd0 | 2010-10-29 17:15:06 -0700 | [diff] [blame] | 200 | net->tx_queue_len = TX_QLEN; |
Stephen Hemminger | 7441698 | 2010-11-01 09:53:58 -0400 | [diff] [blame] | 201 | net->flags |= IFF_NOARP; |
Stephen Hemminger | 7441698 | 2010-11-01 09:53:58 -0400 | [diff] [blame] | 202 | |
Stephen Hemminger | 2515ab6 | 2010-10-29 21:39:54 -0700 | [diff] [blame] | 203 | netif_carrier_off(net); |
Stephen Hemminger | 0ad008f | 2010-10-29 16:44:07 -0700 | [diff] [blame] | 204 | |
Stephen Hemminger | 0ad008f | 2010-10-29 16:44:07 -0700 | [diff] [blame] | 205 | SET_NETDEV_DEVTYPE(net, &wimax_type); |
| 206 | |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 207 | /* Read the MAC Address from EEPROM */ |
Stephen Hemminger | 4ea4f7a | 2010-11-01 14:06:24 -0400 | [diff] [blame] | 208 | result = ReadMacAddressFromNVM(Adapter); |
| 209 | if (result != STATUS_SUCCESS) { |
| 210 | dev_err(&udev->dev, |
| 211 | PFX "Error in Reading the mac Address: %d", result); |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 212 | return -EIO; |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 213 | } |
| 214 | |
Stephen Hemminger | 4ea4f7a | 2010-11-01 14:06:24 -0400 | [diff] [blame] | 215 | result = register_netdev(net); |
| 216 | if (result) |
| 217 | return result; |
| 218 | |
| 219 | gblpnetdev = Adapter->dev; |
| 220 | |
| 221 | if (netif_msg_probe(Adapter)) |
| 222 | dev_info(&udev->dev, PFX "%s: register usb-%s-%s %pM\n", |
| 223 | net->name, xdev->bus->bus_name, xdev->devpath, |
| 224 | net->dev_addr); |
| 225 | |
| 226 | return 0; |
| 227 | } |
| 228 | |
Kevin McKinney | 2979460 | 2012-05-26 12:05:12 -0400 | [diff] [blame] | 229 | void unregister_networkdev(struct bcm_mini_adapter *Adapter) |
Stephen Hemminger | 4ea4f7a | 2010-11-01 14:06:24 -0400 | [diff] [blame] | 230 | { |
| 231 | struct net_device *net = Adapter->dev; |
Kevin McKinney | d6861cf | 2012-11-01 23:42:21 -0400 | [diff] [blame] | 232 | struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter; |
Stephen Hemminger | 4ea4f7a | 2010-11-01 14:06:24 -0400 | [diff] [blame] | 233 | struct usb_interface *udev = IntfAdapter->interface; |
| 234 | struct usb_device *xdev = IntfAdapter->udev; |
| 235 | |
| 236 | if (netif_msg_probe(Adapter)) |
| 237 | dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n", |
| 238 | net->name, xdev->bus->bus_name, xdev->devpath); |
Vinay Sawal | 00b6fb2 | 2011-03-09 13:47:35 -0800 | [diff] [blame] | 239 | |
Stephen Hemminger | 4ea4f7a | 2010-11-01 14:06:24 -0400 | [diff] [blame] | 240 | unregister_netdev(Adapter->dev); |
Stephen Hemminger | f8942e0 | 2010-09-08 14:46:36 -0700 | [diff] [blame] | 241 | } |