1#include "headers.h"
2
3struct net_device *gblpnetdev;
4
5static INT bcm_open(struct net_device *dev)
6{
7	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
8
9	if (ad->fw_download_done == false) {
10		pr_notice(PFX "%s: link up failed (download in progress)\n",
11			  dev->name);
12		return -EBUSY;
13	}
14
15	if (netif_msg_ifup(ad))
16		pr_info(PFX "%s: enabling interface\n", dev->name);
17
18	if (ad->LinkUpStatus) {
19		if (netif_msg_link(ad))
20			pr_info(PFX "%s: link up\n", dev->name);
21
22		netif_carrier_on(ad->dev);
23		netif_start_queue(ad->dev);
24	}
25
26	return 0;
27}
28
29static INT bcm_close(struct net_device *dev)
30{
31	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
32
33	if (netif_msg_ifdown(ad))
34		pr_info(PFX "%s: disabling interface\n", dev->name);
35
36	netif_carrier_off(dev);
37	netif_stop_queue(dev);
38
39	return 0;
40}
41
42static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
43			    void *accel_priv, select_queue_fallback_t fallback)
44{
45	return ClassifyPacket(netdev_priv(dev), skb);
46}
47
48/*******************************************************************
49* Function    -	bcm_transmit()
50*
51* Description - This is the main transmit function for our virtual
52*		interface(eth0). It handles the ARP packets. It
53*		clones this packet and then Queue it to a suitable
54*		Queue. Then calls the transmit_packet().
55*
56* Parameter   -	 skb - Pointer to the socket buffer structure
57*		 dev - Pointer to the virtual net device structure
58*
59*********************************************************************/
60
61static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev)
62{
63	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
64	u16 qindex = skb_get_queue_mapping(skb);
65
66
67	if (ad->device_removed || !ad->LinkUpStatus)
68		goto drop;
69
70	if (ad->TransferMode != IP_PACKET_ONLY_MODE)
71		goto drop;
72
73	if (INVALID_QUEUE_INDEX == qindex)
74		goto drop;
75
76	if (ad->PackInfo[qindex].uiCurrentPacketsOnHost >=
77	    SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
78		return NETDEV_TX_BUSY;
79
80	/* Now Enqueue the packet */
81	if (netif_msg_tx_queued(ad))
82		pr_info(PFX "%s: enqueueing packet to queue %d\n",
83			dev->name, qindex);
84
85	spin_lock(&ad->PackInfo[qindex].SFQueueLock);
86	ad->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
87	ad->PackInfo[qindex].uiCurrentPacketsOnHost++;
88
89	*((B_UINT32 *) skb->cb + SKB_CB_LATENCY_OFFSET) = jiffies;
90	ENQUEUEPACKET(ad->PackInfo[qindex].FirstTxQueue,
91		      ad->PackInfo[qindex].LastTxQueue, skb);
92	atomic_inc(&ad->TotalPacketCount);
93	spin_unlock(&ad->PackInfo[qindex].SFQueueLock);
94
95	/* FIXME - this is racy and incorrect, replace with work queue */
96	if (!atomic_read(&ad->TxPktAvail)) {
97		atomic_set(&ad->TxPktAvail, 1);
98		wake_up(&ad->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
109/**
110@ingroup init_functions
111Register other driver entry points with the kernel
112*/
113static const struct net_device_ops bcmNetDevOps = {
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,
121};
122
123static struct device_type wimax_type = {
124	.name	= "wimax",
125};
126
127static 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
142static void bcm_get_drvinfo(struct net_device *dev,
143			    struct ethtool_drvinfo *info)
144{
145	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
146	struct bcm_interface_adapter *intf_ad = ad->pvInterfaceAdapter;
147	struct usb_device *udev = interface_to_usbdev(intf_ad->interface);
148
149	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
150	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
151	snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u",
152		 ad->uiFlashLayoutMajorVersion,
153		 ad->uiFlashLayoutMinorVersion);
154
155	usb_make_path(udev, info->bus_info, sizeof(info->bus_info));
156}
157
158static u32 bcm_get_link(struct net_device *dev)
159{
160	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
161
162	return ad->LinkUpStatus;
163}
164
165static u32 bcm_get_msglevel(struct net_device *dev)
166{
167	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
168
169	return ad->msg_enable;
170}
171
172static void bcm_set_msglevel(struct net_device *dev, u32 level)
173{
174	struct bcm_mini_adapter *ad = GET_BCM_ADAPTER(dev);
175
176	ad->msg_enable = level;
177}
178
179static const struct ethtool_ops bcm_ethtool_ops = {
180	.get_settings	= bcm_get_settings,
181	.get_drvinfo	= bcm_get_drvinfo,
182	.get_link	= bcm_get_link,
183	.get_msglevel	= bcm_get_msglevel,
184	.set_msglevel	= bcm_set_msglevel,
185};
186
187int register_networkdev(struct bcm_mini_adapter *ad)
188{
189	struct net_device *net = ad->dev;
190	struct bcm_interface_adapter *intf_ad = ad->pvInterfaceAdapter;
191	struct usb_interface *udev = intf_ad->interface;
192	struct usb_device *xdev = intf_ad->udev;
193
194	int result;
195
196	net->netdev_ops = &bcmNetDevOps;
197	net->ethtool_ops = &bcm_ethtool_ops;
198	net->mtu = MTU_SIZE;	/* 1400 Bytes */
199	net->tx_queue_len = TX_QLEN;
200	net->flags |= IFF_NOARP;
201
202	netif_carrier_off(net);
203
204	SET_NETDEV_DEVTYPE(net, &wimax_type);
205
206	/* Read the MAC Address from EEPROM */
207	result = ReadMacAddressFromNVM(ad);
208	if (result != STATUS_SUCCESS) {
209		dev_err(&udev->dev,
210			PFX "Error in Reading the mac Address: %d", result);
211		return -EIO;
212	}
213
214	result = register_netdev(net);
215	if (result)
216		return result;
217
218	gblpnetdev = ad->dev;
219
220	if (netif_msg_probe(ad))
221		dev_info(&udev->dev, PFX "%s: register usb-%s-%s %pM\n",
222			 net->name, xdev->bus->bus_name, xdev->devpath,
223			 net->dev_addr);
224
225	return 0;
226}
227
228void unregister_networkdev(struct bcm_mini_adapter *ad)
229{
230	struct net_device *net = ad->dev;
231	struct bcm_interface_adapter *intf_ad = ad->pvInterfaceAdapter;
232	struct usb_interface *udev = intf_ad->interface;
233	struct usb_device *xdev = intf_ad->udev;
234
235	if (netif_msg_probe(ad))
236		dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n",
237			 net->name, xdev->bus->bus_name, xdev->devpath);
238
239	unregister_netdev(ad->dev);
240}
241