2 * Networking AIM - Networking Application Interface Module for MostCore
4 * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * This file is licensed under GPLv2.
14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 #include <linux/module.h>
17 #include <linux/netdevice.h>
18 #include <linux/etherdevice.h>
19 #include <linux/slab.h>
20 #include <linux/init.h>
21 #include <linux/list.h>
22 #include <linux/wait.h>
23 #include <linux/kobject.h>
25 #include "networking.h"
28 #define MDP_HDR_LEN 16
29 #define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
33 #define PMS_TELID_UNSEGM_MAMAC 0x0A
34 #define PMS_FIFONO_MDP 0x01
35 #define PMS_FIFONO_MEP 0x04
36 #define PMS_MSGTYPE_DATA 0x04
37 #define PMS_DEF_PRIO 0
38 #define MEP_DEF_RETRY 15
40 #define PMS_FIFONO_MASK 0x07
41 #define PMS_FIFONO_SHIFT 3
42 #define PMS_RETRY_SHIFT 4
43 #define PMS_TELID_MASK 0x0F
44 #define PMS_TELID_SHIFT 4
46 #define HB(value) ((u8)((u16)(value) >> 8))
47 #define LB(value) ((u8)(value))
49 #define EXTRACT_BIT_SET(bitset_name, value) \
50 (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
52 #define PMS_IS_MEP(buf, len) \
53 ((len) > MEP_HDR_LEN && \
54 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
56 #define PMS_IS_MAMAC(buf, len) \
57 ((len) > MDP_HDR_LEN && \
58 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
59 EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)
61 struct net_dev_channel {
66 struct net_dev_context {
67 struct most_interface *iface;
70 unsigned char link_stat;
71 struct net_device *dev;
72 struct net_dev_channel rx;
73 struct net_dev_channel tx;
74 struct list_head list;
77 static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
78 static struct spinlock list_lock;
79 static struct most_aim aim;
81 static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
83 u8 *buff = mbo->virt_address;
84 const u8 broadcast[] = { 0x03, 0xFF };
85 const u8 *dest_addr = skb->data + 4;
86 const u8 *eth_type = skb->data + 12;
87 unsigned int payload_len = skb->len - ETH_HLEN;
88 unsigned int mdp_len = payload_len + MDP_HDR_LEN;
90 if (mdp_len < skb->len) {
91 pr_err("drop: too large packet! (%u)\n", skb->len);
95 if (mbo->buffer_length < mdp_len) {
96 pr_err("drop: too small buffer! (%d for %d)\n",
97 mbo->buffer_length, mdp_len);
101 if (skb->len < ETH_HLEN) {
102 pr_err("drop: too small packet! (%d)\n", skb->len);
106 if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
107 dest_addr = broadcast;
109 *buff++ = HB(mdp_len - 2);
110 *buff++ = LB(mdp_len - 2);
113 *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
114 *buff++ = PMS_DEF_PRIO;
115 *buff++ = dest_addr[0];
116 *buff++ = dest_addr[1];
119 *buff++ = HB(payload_len + 6);
120 *buff++ = LB(payload_len + 6);
122 /* end of FPH here */
124 *buff++ = eth_type[0];
125 *buff++ = eth_type[1];
129 *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
130 *buff++ = LB(payload_len);
132 memcpy(buff, skb->data + ETH_HLEN, payload_len);
133 mbo->buffer_length = mdp_len;
137 static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
139 u8 *buff = mbo->virt_address;
140 unsigned int mep_len = skb->len + MEP_HDR_LEN;
142 if (mep_len < skb->len) {
143 pr_err("drop: too large packet! (%u)\n", skb->len);
147 if (mbo->buffer_length < mep_len) {
148 pr_err("drop: too small buffer! (%d for %d)\n",
149 mbo->buffer_length, mep_len);
153 *buff++ = HB(mep_len - 2);
154 *buff++ = LB(mep_len - 2);
157 *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
158 *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
163 memcpy(buff, skb->data, skb->len);
164 mbo->buffer_length = mep_len;
168 static int most_nd_set_mac_address(struct net_device *dev, void *p)
170 struct net_dev_context *nd = dev->ml_priv;
171 int err = eth_mac_addr(dev, p);
176 BUG_ON(nd->dev != dev);
179 (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
180 dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
183 * Set default MTU for the given packet type.
184 * It is still possible to change MTU using ip tools afterwards.
186 dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
191 static int most_nd_open(struct net_device *dev)
193 struct net_dev_context *nd = dev->ml_priv;
195 netdev_info(dev, "open net device\n");
197 BUG_ON(nd->dev != dev);
199 if (nd->channels_opened)
202 BUG_ON(!nd->tx.linked || !nd->rx.linked);
204 if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
205 netdev_err(dev, "most_start_channel() failed\n");
209 if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
210 netdev_err(dev, "most_start_channel() failed\n");
211 most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
215 nd->channels_opened = true;
219 netif_wake_queue(dev);
221 nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
227 static int most_nd_stop(struct net_device *dev)
229 struct net_dev_context *nd = dev->ml_priv;
231 netdev_info(dev, "stop net device\n");
233 BUG_ON(nd->dev != dev);
234 netif_stop_queue(dev);
236 if (nd->channels_opened) {
237 most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
238 most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
239 nd->channels_opened = false;
245 static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
246 struct net_device *dev)
248 struct net_dev_context *nd = dev->ml_priv;
252 BUG_ON(nd->dev != dev);
254 mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
257 netif_stop_queue(dev);
258 dev->stats.tx_fifo_errors++;
259 return NETDEV_TX_BUSY;
263 ret = skb_to_mamac(skb, mbo);
265 ret = skb_to_mep(skb, mbo);
269 dev->stats.tx_dropped++;
274 most_submit_mbo(mbo);
275 dev->stats.tx_packets++;
276 dev->stats.tx_bytes += skb->len;
281 static const struct net_device_ops most_nd_ops = {
282 .ndo_open = most_nd_open,
283 .ndo_stop = most_nd_stop,
284 .ndo_start_xmit = most_nd_start_xmit,
285 .ndo_set_mac_address = most_nd_set_mac_address,
288 static void most_nd_setup(struct net_device *dev)
290 netdev_info(dev, "setup net device\n");
292 dev->netdev_ops = &most_nd_ops;
295 static void most_net_rm_netdev_safe(struct net_dev_context *nd)
300 pr_info("remove net device %p\n", nd->dev);
302 unregister_netdev(nd->dev);
303 free_netdev(nd->dev);
307 static struct net_dev_context *get_net_dev_context(
308 struct most_interface *iface)
310 struct net_dev_context *nd, *tmp;
312 spin_lock(&list_lock);
313 list_for_each_entry_safe(nd, tmp, &net_devices, list) {
314 if (nd->iface == iface) {
315 spin_unlock(&list_lock);
319 spin_unlock(&list_lock);
323 static int aim_probe_channel(struct most_interface *iface, int channel_idx,
324 struct most_channel_config *ccfg,
325 struct kobject *parent, char *name)
327 struct net_dev_context *nd;
328 struct net_dev_channel *ch;
333 if (ccfg->data_type != MOST_CH_ASYNC)
336 nd = get_net_dev_context(iface);
339 nd = kzalloc(sizeof(*nd), GFP_KERNEL);
345 spin_lock(&list_lock);
346 list_add(&nd->list, &net_devices);
347 spin_unlock(&list_lock);
350 ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
352 pr_err("only one channel per instance & direction allowed\n");
356 if (nd->tx.linked || nd->rx.linked) {
357 struct net_device *dev =
358 alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN,
362 pr_err("no memory for net_device\n");
367 ch->ch_id = channel_idx;
371 if (register_netdev(dev)) {
372 pr_err("registering net device failed\n");
379 ch->ch_id = channel_idx;
385 static int aim_disconnect_channel(struct most_interface *iface,
388 struct net_dev_context *nd;
389 struct net_dev_channel *ch;
391 nd = get_net_dev_context(iface);
395 if (nd->rx.linked && channel_idx == nd->rx.ch_id)
397 else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
405 * do not call most_stop_channel() here, because channels are
406 * going to be closed in ndo_stop() after unregister_netdev()
408 most_net_rm_netdev_safe(nd);
410 if (!nd->rx.linked && !nd->tx.linked) {
411 spin_lock(&list_lock);
413 spin_unlock(&list_lock);
420 static int aim_resume_tx_channel(struct most_interface *iface,
423 struct net_dev_context *nd;
425 nd = get_net_dev_context(iface);
426 if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx)
432 netif_wake_queue(nd->dev);
436 static int aim_rx_data(struct mbo *mbo)
439 struct net_dev_context *nd;
440 char *buf = mbo->virt_address;
441 u32 len = mbo->processed_length;
443 struct net_device *dev;
445 nd = get_net_dev_context(mbo->ifp);
446 if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
451 pr_err_once("drop packet: missing net_device\n");
456 if (!PMS_IS_MAMAC(buf, len))
459 skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
461 if (!PMS_IS_MEP(buf, len))
464 skb = dev_alloc_skb(len - MEP_HDR_LEN);
468 dev->stats.rx_dropped++;
469 pr_err_once("drop packet: no memory for skb\n");
477 ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
480 memcpy(skb_put(skb, 4), &zero, 4);
481 memcpy(skb_put(skb, 2), buf + 5, 2);
484 memcpy(skb_put(skb, 2), buf + 10, 2);
493 memcpy(skb_put(skb, len), buf, len);
494 skb->protocol = eth_type_trans(skb, dev);
495 dev->stats.rx_packets++;
496 dev->stats.rx_bytes += skb->len;
504 static struct most_aim aim = {
505 .name = "networking",
506 .probe_channel = aim_probe_channel,
507 .disconnect_channel = aim_disconnect_channel,
508 .tx_completion = aim_resume_tx_channel,
509 .rx_completion = aim_rx_data,
512 static int __init most_net_init(void)
514 pr_info("most_net_init()\n");
515 spin_lock_init(&list_lock);
516 return most_register_aim(&aim);
519 static void __exit most_net_exit(void)
521 struct net_dev_context *nd, *tmp;
523 spin_lock(&list_lock);
524 list_for_each_entry_safe(nd, tmp, &net_devices, list) {
526 spin_unlock(&list_lock);
528 * do not call most_stop_channel() here, because channels are
529 * going to be closed in ndo_stop() after unregister_netdev()
531 most_net_rm_netdev_safe(nd);
533 spin_lock(&list_lock);
535 spin_unlock(&list_lock);
537 most_deregister_aim(&aim);
538 pr_info("most_net_exit()\n");
542 * most_deliver_netinfo - callback for HDM to be informed about HW's MAC
543 * @param iface - most interface instance
544 * @param link_stat - link status
545 * @param mac_addr - MAC address
547 void most_deliver_netinfo(struct most_interface *iface,
548 unsigned char link_stat, unsigned char *mac_addr)
550 struct net_dev_context *nd;
551 struct net_device *dev;
553 pr_info("Received netinfo from %s\n", iface->description);
555 nd = get_net_dev_context(iface);
564 ether_addr_copy(dev->dev_addr, mac_addr);
566 if (nd->link_stat != link_stat) {
567 nd->link_stat = link_stat;
569 netif_wake_queue(dev);
571 netif_stop_queue(dev);
574 EXPORT_SYMBOL(most_deliver_netinfo);
576 module_init(most_net_init);
577 module_exit(most_net_exit);
578 MODULE_LICENSE("GPL");
579 MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
580 MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");