1 #include "headers.h"
2
3 struct net_device *gblpnetdev;
4
bcm_open(struct net_device * dev)5 static 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
bcm_close(struct net_device * dev)29 static 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
bcm_select_queue(struct net_device * dev,struct sk_buff * skb,void * accel_priv,select_queue_fallback_t fallback)42 static 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
bcm_transmit(struct sk_buff * skb,struct net_device * dev)61 static 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
111 Register other driver entry points with the kernel
112 */
113 static 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
123 static struct device_type wimax_type = {
124 .name = "wimax",
125 };
126
bcm_get_settings(struct net_device * dev,struct ethtool_cmd * cmd)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
bcm_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)142 static 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
bcm_get_link(struct net_device * dev)158 static 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
bcm_get_msglevel(struct net_device * dev)165 static 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
bcm_set_msglevel(struct net_device * dev,u32 level)172 static 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
179 static 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
register_networkdev(struct bcm_mini_adapter * ad)187 int 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
unregister_networkdev(struct bcm_mini_adapter * ad)228 void 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