1 /*-
2 * GPL LICENSE SUMMARY
3 *
4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution
19 * in the file called LICENSE.GPL.
20 *
21 * Contact Information:
22 * Intel Corporation
23 */
24 /*--------------------------------------------------------------------------*/
25 #include <linux/device.h>
26 #include <linux/module.h>
27 #include <linux/version.h>
28 #include <linux/slab.h>
29 #include <linux/uaccess.h>
30 #include <linux/if_ether.h>
31 #include <linux/etherdevice.h>
32 #include "dpdk_iface.h"
33 /*--------------------------------------------------------------------------*/
34 struct stats_struct sarrays[MAX_DEVICES][MAX_QID] = {{{0, 0, 0, 0, 0, 0, 0, 0, 0}}};
35 struct stats_struct old_sarrays[MAX_DEVICES][MAX_QID] = {{{0, 0, 0, 0, 0, 0, 0, 0, 0}}};
36 static int major_no = -1;
37 /*--------------------------------------------------------------------------*/
38 static int
update_stats(struct stats_struct * stats)39 update_stats(struct stats_struct *stats)
40 {
41 uint8_t qid = stats->qid;
42 uint8_t device = stats->dev;
43 struct stats_struct *old_sarray = &old_sarrays[device][qid];
44 struct stats_struct *sarray = &sarrays[device][qid];
45
46 if (unlikely(sarrays[device][qid].rx_bytes > stats->rx_bytes ||
47 sarrays[device][qid].tx_bytes > stats->tx_bytes)) {
48 /* mTCP app restarted?? */
49 old_sarray->rx_bytes += sarray->rx_bytes;
50 old_sarray->rx_pkts += sarray->rx_pkts;
51 old_sarray->tx_bytes += sarray->tx_bytes;
52 old_sarray->tx_pkts += sarray->tx_pkts;
53 old_sarray->rmiss += sarray->rmiss;
54 old_sarray->rerr += sarray->rerr;
55 old_sarray->terr += sarray->terr;
56 }
57
58 sarray->rx_bytes = stats->rx_bytes;
59 sarray->rx_pkts = stats->rx_pkts;
60 sarray->tx_bytes = stats->tx_bytes;
61 sarray->tx_pkts = stats->tx_pkts;
62 sarray->rmiss = stats->rmiss;
63 sarray->rerr = stats->rerr;
64 sarray->terr = stats->terr;
65
66 #if 0
67 printk(KERN_ALERT "%s: Dev: %d, Qid: %d, RXP: %llu, "
68 "RXB: %llu, TXP: %llu, TXB: %llu\n",
69 device, qid,
70 THIS_MODULE->name,
71 (long long unsigned int)sarray->rx_pkts,
72 (long long unsigned int)sarray->rx_bytes,
73 (long long unsigned int)sarray->tx_pkts,
74 (long long unsigned int)sarray->tx_bytes);
75 #endif
76 return 0;
77 }
78 /*--------------------------------------------------------------------------*/
79 static void
clear_all_netdevices(void)80 clear_all_netdevices(void)
81 {
82 struct net_device *netdev, *dpdk_netdev;
83 uint8_t freed;
84
85 do {
86 dpdk_netdev = NULL;
87 freed = 0;
88 write_lock(&dev_base_lock);
89 netdev = first_net_device(&init_net);
90 while (netdev) {
91 if (strncmp(netdev->name, IFACE_PREFIX,
92 strlen(IFACE_PREFIX)) == 0) {
93 dpdk_netdev = netdev;
94 break;
95 }
96 netdev = next_net_device(netdev);
97 }
98 write_unlock(&dev_base_lock);
99 if (dpdk_netdev) {
100 unregister_netdev(dpdk_netdev);
101 free_netdev(dpdk_netdev);
102 freed = 1;
103 }
104 } while (freed);
105 }
106 /*--------------------------------------------------------------------------*/
107 int
igb_net_open(struct inode * inode,struct file * filp)108 igb_net_open(struct inode *inode, struct file *filp)
109 {
110 return 0;
111 }
112 /*--------------------------------------------------------------------------*/
113 int
igb_net_release(struct inode * inode,struct file * filp)114 igb_net_release(struct inode *inode, struct file *filp)
115 {
116 return 0;
117 }
118 /*--------------------------------------------------------------------------*/
119 long
igb_net_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)120 igb_net_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
121 {
122 int ret = 0;
123 unsigned char mac_addr[ETH_ALEN];
124 struct net_device *netdev;
125 struct stats_struct ss;
126 struct net_adapter *adapter = NULL;
127 struct PciDevice pd;
128
129 switch (cmd) {
130 case SEND_STATS:
131 ret = copy_from_user(&ss,
132 (struct stats_struct __user *)arg,
133 sizeof(struct stats_struct));
134 if (ret)
135 return -EFAULT;
136 ret = update_stats(&ss);
137 break;
138 case CREATE_IFACE:
139 ret = copy_from_user(&pd,
140 (PciDevice __user *)arg,
141 sizeof(PciDevice));
142 ret = copy_from_user(mac_addr,
143 (unsigned char __user *)pd.ports_eth_addr,
144 ETH_ALEN);
145 if (!ret) {
146 /* first check whether the entry does not exist */
147 read_lock(&dev_base_lock);
148 netdev = first_net_device(&init_net);
149 while (netdev) {
150 if (memcmp(netdev->dev_addr, mac_addr, ETH_ALEN) == 0) {
151 read_unlock(&dev_base_lock);
152 printk(KERN_ERR "%s: port already registered!\n", THIS_MODULE->name);
153 return -EINVAL;
154 }
155 netdev = next_net_device(netdev);
156 }
157 read_unlock(&dev_base_lock);
158
159 /* initialize the corresponding netdev */
160 netdev = alloc_etherdev(sizeof(struct net_adapter));
161 if (!netdev) {
162 ret = -ENOMEM;
163 } else {
164 SET_NETDEV_DEV(netdev, NULL);
165 adapter = netdev_priv(netdev);
166 adapter->netdev = netdev;
167 netdev_assign_netdev_ops(netdev);
168 memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
169 strcpy(netdev->name, IFACE_PREFIX"%d");
170 ret = register_netdev(netdev);
171 if (ret)
172 goto fail_ioremap;
173 adapter->netdev_registered = true;
174
175 if ((ret=sscanf(netdev->name, IFACE_PREFIX"%hu", &adapter->bd_number)) <= 0)
176 goto fail_bdnumber;
177
178 printk(KERN_INFO "%s: ifindex picked: %hu\n",
179 THIS_MODULE->name, adapter->bd_number);
180 /* reset nstats */
181 memset(&adapter->nstats, 0, sizeof(struct net_device_stats));
182 /* set 'fake' pci address */
183 memcpy(&adapter->pa, &pd.pa, sizeof(struct PciAddress));
184 ret = copy_to_user((unsigned char __user *)arg,
185 netdev->name,
186 IFNAMSIZ);
187 if (ret) {
188 printk(KERN_INFO "%s: Interface %s copy to user failed!\n",
189 THIS_MODULE->name, netdev->name);
190 ret = -1;
191 goto fail_pciaddr;
192 }
193 /* set numa locality */
194 adapter->numa_socket = pd.numa_socket;
195 }
196 }
197 break;
198 case CLEAR_IFACE:
199 clear_all_netdevices();
200 break;
201
202 case FETCH_PCI_ADDRESS:
203 ret = copy_from_user(&pd,
204 (PciDevice __user *)arg,
205 sizeof(PciDevice));
206 if (!ret) {
207 read_lock(&dev_base_lock);
208 netdev = first_net_device(&init_net);
209 while (netdev) {
210 if (strcmp(netdev->name, pd.ifname) == 0) {
211 read_unlock(&dev_base_lock);
212 printk(KERN_INFO "%s: Passing PCI info of %s to user\n",
213 THIS_MODULE->name, pd.ifname);
214 adapter = netdev_priv(netdev);
215 ret = copy_to_user(&((PciDevice __user *)arg)->pa,
216 &adapter->pa,
217 sizeof(struct PciAddress));
218 if (ret) return -1;
219 ret = copy_to_user(&((PciDevice __user *)arg)->numa_socket,
220 &adapter->numa_socket,
221 sizeof(adapter->numa_socket));
222 if (ret) return -1;
223 return 0;
224 }
225 netdev = next_net_device(netdev);
226 }
227 read_unlock(&dev_base_lock);
228 ret = -1;
229 }
230 break;
231 default:
232 ret = -ENOTTY;
233 break;
234 }
235
236
237 return ret;
238 fail_pciaddr:
239 fail_bdnumber:
240 unregister_netdev(netdev);
241 fail_ioremap:
242 free_netdev(netdev);
243 return ret;
244 }
245 /*--------------------------------------------------------------------------*/
246 static struct file_operations igb_net_fops = {
247 .open = igb_net_open,
248 .release = igb_net_release,
249 .unlocked_ioctl = igb_net_ioctl,
250 };
251 /*--------------------------------------------------------------------------*/
252 static int __init
iface_pci_init_module(void)253 iface_pci_init_module(void)
254 {
255 int ret;
256
257 ret = register_chrdev(0 /* MAJOR */,
258 DEV_NAME /*NAME*/,
259 &igb_net_fops);
260 if (ret < 0) {
261 printk(KERN_ERR "%s: register_chrdev failed\n",
262 THIS_MODULE->name);
263 return ret;
264 }
265
266 printk(KERN_INFO "%s: Loaded\n",
267 THIS_MODULE->name);
268
269 /* record major number */
270 major_no = ret;
271
272 return 0;
273 }
274 /*--------------------------------------------------------------------------*/
275 static void __exit
iface_pci_exit_module(void)276 iface_pci_exit_module(void)
277 {
278 clear_all_netdevices();
279 unregister_chrdev(major_no, DEV_NAME);
280 }
281 /*--------------------------------------------------------------------------*/
282 module_init(iface_pci_init_module);
283 module_exit(iface_pci_exit_module);
284
285 MODULE_DESCRIPTION("Interface driver for DPDK devices");
286 MODULE_LICENSE("BSD");
287 MODULE_AUTHOR("[email protected]");
288 /*--------------------------------------------------------------------------*/
289