--- zzzz-none-000/linux-4.4.60/drivers/net/ifb.c 2017-04-08 07:53:53.000000000 +0000 +++ scorpion-7490-727/linux-4.4.60/drivers/net/ifb.c 2021-02-04 17:41:59.000000000 +0000 @@ -37,6 +37,10 @@ #include #include +#if IS_ENABLED(CONFIG_AVM_PA) +#include +#endif + #define TX_Q_LIMIT 32 struct ifb_q_private { struct net_device *dev; @@ -105,7 +109,11 @@ dev_queue_xmit(skb); } else if (from & AT_INGRESS) { skb_pull(skb, skb->mac_len); - netif_receive_skb(skb); +#if IS_ENABLED(CONFIG_AVM_PA) + AVM_PKT_INFO(skb)->ingress_pid_handle = 0; + if (avm_pa_dev_pid_receive(AVM_PA_DEVINFO(txp->dev), skb) != AVM_PA_RX_STOLEN) +#endif + netif_receive_skb(skb); } else BUG(); } @@ -302,6 +310,61 @@ module_param(numifbs, int, 0); MODULE_PARM_DESC(numifbs, "Number of ifb devices"); + +#if IS_ENABLED(CONFIG_AVM_PA) +static void ifb_dev_transmit(void *arg, struct sk_buff *skb) +{ + int rc; + struct net_device *dev_ifb = (struct net_device *) arg; + struct net_device *orig_dev; + + orig_dev = __dev_get_by_index(dev_net(dev_ifb), skb->skb_iif); + if (unlikely(!orig_dev)) { + printk(KERN_ERR "ifb_dev_transmit(%s) orig_dev not found\n", + ((struct net_device *)arg)->name); + kfree_skb(skb); + return; + } + /* Clear pkt_info so that avm_pa can create one more session after + * going through ifb_xmit() */ + skb->dev = dev_ifb; + /* avm_pa already performs a push for certain ingress framing types */ + if (skb_mac_header(skb) != skb->data) + skb_push(skb, orig_dev->hard_header_len); + skb->pkt_type = PACKET_HOST; + rc = dev_queue_xmit(skb); + if (rc != 0 && net_ratelimit()) { + printk(KERN_ERR "ifb_dev_transmit(%s) %d\n", + ((struct net_device *)arg)->name, rc); + } +} + +static void register_avm_pa_pid(struct net_device *dev_ifb) +{ + struct avm_pa_pid_cfg cfg = { + .framing = avm_pa_framing_dev, + .default_mtu = 1500, + .tx_func = ifb_dev_transmit, + .tx_arg = dev_ifb, + 0 + }; + struct avm_pa_pid_ecfg ecfg = { + .version = AVM_PA_PID_ECFG_VERSION, + .flags = AVM_PA_PID_FLAG_NO_PID_CHANGED_CHECK, + 0, + }; + + strlcpy(cfg.name, dev_ifb->name, sizeof(cfg.name)); + if (avm_pa_dev_pid_register(AVM_PA_DEVINFO(dev_ifb), &cfg) < 0) + printk(KERN_ERR "%s: failed to register PA PID\n", cfg.name); + + if (avm_pa_pid_set_ecfg(AVM_PA_DEVINFO(dev_ifb)->pid_handle, &ecfg)) { + printk(KERN_ERR "%s: failed to set extended cfg for PA PID\n", cfg.name); + } +} +#endif + + static int __init ifb_init_one(int index) { struct net_device *dev_ifb; @@ -318,6 +381,10 @@ if (err < 0) goto err; +#if IS_ENABLED(CONFIG_AVM_PA) + register_avm_pa_pid(dev_ifb); +#endif + return 0; err: