Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) /* We are an ethernet device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <net/checksum.h>   /* for ip_fast_csum() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <net/arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <net/dst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) /* And atm device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/atmdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/atmlec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/atmmpc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) /* Modular too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include "lec.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include "mpc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include "resources.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  * mpc.c: Implementation of MPOA client kernel part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define dprintk(format, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define dprintk_cont(format, args...) printk(KERN_CONT format, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #define dprintk(format, args...)					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	do { if (0)							\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 		printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #define dprintk_cont(format, args...)			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	do { if (0) printk(KERN_CONT format, ##args); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define ddprintk(format, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define ddprintk_cont(format, args...) printk(KERN_CONT format, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define ddprintk(format, args...)					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	do { if (0)							\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 		printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define ddprintk_cont(format, args...)			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	do { if (0) printk(KERN_CONT format, ##args); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) /* mpc_daemon -> kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) static void mps_death(struct k_message *msg, struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) static void clean_up(struct k_message *msg, struct mpoa_client *mpc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 		     int action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) static void MPOA_cache_impos_rcvd(struct k_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 				  struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 				   struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) static void set_mps_mac_addr_rcvd(struct k_message *mesg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 				  struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) static const uint8_t *copy_macs(struct mpoa_client *mpc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 				const uint8_t *router_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 				const uint8_t *tlvs, uint8_t mps_macs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 				uint8_t device_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) static void mpoad_close(struct atm_vcc *vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 				   struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 			       unsigned long event, void *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) static void mpc_timer_refresh(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static void mpc_cache_check(struct timer_list *unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	0xaa, 0xaa, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	{0x00, 0x00, 0x5e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	{0x00, 0x03}         /* For MPOA control PDUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) static struct llc_snap_hdr llc_snap_mpoa_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	0xaa, 0xaa, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	{0x00, 0x00, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	{0x08, 0x00}         /* This is for IP PDUs only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	0xaa, 0xaa, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	{0x00, 0x00, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	{0x88, 0x4c}         /* This is for tagged data PDUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) static struct notifier_block mpoa_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	mpoa_event_listener,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) struct mpoa_client *mpcs = NULL; /* FIXME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) static struct atm_mpoa_qos *qos_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) static DEFINE_TIMER(mpc_timer, mpc_cache_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) static struct mpoa_client *find_mpc_by_itfnum(int itf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	mpc = mpcs;  /* our global linked list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	while (mpc != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		if (mpc->dev_num == itf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 			return mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 		mpc = mpc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	return NULL;   /* not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	mpc = mpcs;  /* our global linked list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	while (mpc != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		if (mpc->mpoad_vcc == vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 			return mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 		mpc = mpc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	return NULL;   /* not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	mpc = mpcs;  /* our global linked list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	while (mpc != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 		if (mpc->dev == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 			return mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 		mpc = mpc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	return NULL;   /* not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171)  * Functions for managing QoS list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175)  * Overwrites the old entry or makes a new one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	struct atm_mpoa_qos *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	entry = atm_mpoa_search_qos(dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	if (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		entry->qos = *qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 		return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	entry = kmalloc(sizeof(struct atm_mpoa_qos), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 		pr_info("mpoa: out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 		return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	entry->ipaddr = dst_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	entry->qos = *qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	entry->next = qos_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	qos_head = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	struct atm_mpoa_qos *qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	qos = qos_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	while (qos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		if (qos->ipaddr == dst_ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 		qos = qos->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	return qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217)  * Returns 0 for failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	struct atm_mpoa_qos *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	if (entry == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	if (entry == qos_head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		qos_head = qos_head->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	curr = qos_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	while (curr != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 		if (curr->next == entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 			curr->next = entry->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 			kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 		curr = curr->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) /* this is buggered - we need locking for qos_head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) void atm_mpoa_disp_qos(struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	struct atm_mpoa_qos *qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	qos = qos_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	seq_printf(m, "QoS entries for shortcuts:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	seq_printf(m, "IP address\n  TX:max_pcr pcr     min_pcr max_cdv max_sdu\n  RX:max_pcr pcr     min_pcr max_cdv max_sdu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	while (qos != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		seq_printf(m, "%pI4\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 			   &qos->ipaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 			   qos->qos.txtp.max_pcr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 			   qos->qos.txtp.pcr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 			   qos->qos.txtp.min_pcr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 			   qos->qos.txtp.max_cdv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 			   qos->qos.txtp.max_sdu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 			   qos->qos.rxtp.max_pcr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 			   qos->qos.rxtp.pcr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 			   qos->qos.rxtp.min_pcr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 			   qos->qos.rxtp.max_cdv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 			   qos->qos.rxtp.max_sdu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		qos = qos->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) static struct net_device *find_lec_by_itfnum(int itf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	char name[IFNAMSIZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	sprintf(name, "lec%d", itf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	dev = dev_get_by_name(&init_net, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) static struct mpoa_client *alloc_mpc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	mpc = kzalloc(sizeof(struct mpoa_client), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	if (mpc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	rwlock_init(&mpc->ingress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	rwlock_init(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	mpc->next = mpcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	atm_mpoa_init_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	mpc->parameters.mpc_p1 = MPC_P1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	mpc->parameters.mpc_p2 = MPC_P2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	memset(mpc->parameters.mpc_p3, 0, sizeof(mpc->parameters.mpc_p3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	mpc->parameters.mpc_p4 = MPC_P4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	mpc->parameters.mpc_p5 = MPC_P5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	mpc->parameters.mpc_p6 = MPC_P6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	mpcs = mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	return mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307)  * start_mpc() puts the MPC on line. All the packets destined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308)  * to the lec underneath us are now being monitored and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309)  * shortcuts will be established.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	dprintk("(%s)\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	if (!dev->netdev_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 		pr_info("(%s) not starting\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		mpc->old_ops = dev->netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 		mpc->new_ops = *mpc->old_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		mpc->new_ops.ndo_start_xmit = mpc_send_packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 		dev->netdev_ops = &mpc->new_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) static void stop_mpc(struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	struct net_device *dev = mpc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	dprintk("(%s)", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	/* Lets not nullify lec device's dev->hard_start_xmit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	if (dev->netdev_ops != &mpc->new_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		dprintk_cont(" mpc already stopped, not fatal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	dprintk_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	dev->netdev_ops = mpc->old_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	mpc->old_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	/* close_shortcuts(mpc);    ??? FIXME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) static const char *mpoa_device_type_string(char type) __attribute__ ((unused));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) static const char *mpoa_device_type_string(char type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	case NON_MPOA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		return "non-MPOA device";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	case MPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		return "MPS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	case MPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		return "MPC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	case MPS_AND_MPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 		return "both MPS and MPC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	return "unspecified (non-MPOA) device";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363)  * lec device calls this via its netdev_priv(dev)->lane2_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364)  * ->associate_indicator() when it sees a TLV in LE_ARP packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365)  * We fill in the pointer above when we see a LANE2 lec initializing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366)  * See LANE2 spec 3.1.5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368)  * Quite a big and ugly function but when you look at it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369)  * all it does is to try to locate and parse MPOA Device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370)  * Type TLV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371)  * We give our lec a pointer to this function and when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)  * lec sees a TLV it uses the pointer to call this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 			    const u8 *tlvs, u32 sizeoftlvs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	uint32_t type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	uint8_t length, mpoa_device_type, number_of_mps_macs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	const uint8_t *end_of_tlvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	dprintk("(%s) received TLV(s), ", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	dprintk("total length of all TLVs %d\n", sizeoftlvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		pr_info("(%s) no mpc\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	end_of_tlvs = tlvs + sizeoftlvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	while (end_of_tlvs - tlvs >= 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 		type = ((tlvs[0] << 24) | (tlvs[1] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 			(tlvs[2] << 8) | tlvs[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		length = tlvs[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		tlvs += 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		dprintk("    type 0x%x length %02x\n", type, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		if (tlvs + length > end_of_tlvs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 			pr_info("TLV value extends past its buffer, aborting parse\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		if (type == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 			pr_info("mpoa: (%s) TLV type was 0, returning\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 				dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		if (type != TLV_MPOA_DEVICE_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 			tlvs += length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 			continue;  /* skip other TLVs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		mpoa_device_type = *tlvs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		number_of_mps_macs = *tlvs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		dprintk("(%s) MPOA device type '%s', ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 			dev->name, mpoa_device_type_string(mpoa_device_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		if (mpoa_device_type == MPS_AND_MPC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		    length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 			pr_info("(%s) short MPOA Device Type TLV\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 				dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		if ((mpoa_device_type == MPS || mpoa_device_type == MPC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		    length < 22 + number_of_mps_macs*ETH_ALEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 			pr_info("(%s) short MPOA Device Type TLV\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		if (mpoa_device_type != MPS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		    mpoa_device_type != MPS_AND_MPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 			dprintk("ignoring non-MPS device ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 			if (mpoa_device_type == MPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 				tlvs += 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 			continue;  /* we are only interested in MPSs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		if (number_of_mps_macs == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		    mpoa_device_type == MPS_AND_MPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 			pr_info("(%s) MPS_AND_MPC has zero MACs\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 			continue;  /* someone should read the spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		dprintk_cont("this MPS has %d MAC addresses\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 			     number_of_mps_macs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		 * ok, now we can go and tell our daemon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		 * the control address of MPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		send_set_mps_ctrl_addr(tlvs, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		tlvs = copy_macs(mpc, mac_addr, tlvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 				 number_of_mps_macs, mpoa_device_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		if (tlvs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	if (end_of_tlvs - tlvs != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		pr_info("(%s) ignoring %zd bytes of trailing TLV garbage\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 			dev->name, end_of_tlvs - tlvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460)  * Store at least advertizing router's MAC address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461)  * plus the possible MAC address(es) to mpc->mps_macs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462)  * For a freshly allocated MPOA client mpc->mps_macs == 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) static const uint8_t *copy_macs(struct mpoa_client *mpc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 				const uint8_t *router_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 				const uint8_t *tlvs, uint8_t mps_macs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 				uint8_t device_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	int num_macs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	num_macs = (mps_macs > 1) ? mps_macs : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		if (mpc->number_of_mps_macs != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 			kfree(mpc->mps_macs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		mpc->number_of_mps_macs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		mpc->mps_macs = kmalloc_array(ETH_ALEN, num_macs, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		if (mpc->mps_macs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 			pr_info("(%s) out of mem\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	ether_addr_copy(mpc->mps_macs, router_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	if (mps_macs > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	tlvs += mps_macs*ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	mpc->number_of_mps_macs = num_macs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	return tlvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	in_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	struct iphdr *iph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	char *buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	__be32 ipaddr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		struct llc_snap_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		__be32 tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	} tagged_llc_snap_hdr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 		{0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	buff = skb->data + mpc->dev->hard_header_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	iph = (struct iphdr *)buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	ipaddr = iph->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	ddprintk("(%s) ipaddr 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		 mpc->dev->name, ipaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	entry = mpc->in_ops->get(ipaddr, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		entry = mpc->in_ops->add_entry(ipaddr, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		if (entry != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 			mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	/* threshold not exceeded or VCC not ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	if (mpc->in_ops->cache_hit(entry, mpc) != OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		ddprintk("(%s) cache_hit: returns != OPEN\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 			 mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	ddprintk("(%s) using shortcut\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		 mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	/* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	if (iph->ttl <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		ddprintk("(%s) IP ttl = %u, using LANE\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 			 mpc->dev->name, iph->ttl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	iph->ttl--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	iph->check = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	if (entry->ctrl_info.tag != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		ddprintk("(%s) adding tag 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 			 mpc->dev->name, entry->ctrl_info.tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		skb_pull(skb, ETH_HLEN);	/* get rid of Eth header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		skb_push(skb, sizeof(tagged_llc_snap_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 						/* add LLC/SNAP header   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		skb_copy_to_linear_data(skb, &tagged_llc_snap_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 					sizeof(tagged_llc_snap_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		skb_pull(skb, ETH_HLEN);	/* get rid of Eth header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 		skb_push(skb, sizeof(struct llc_snap_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 						/* add LLC/SNAP header + tag  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		skb_copy_to_linear_data(skb, &llc_snap_mpoa_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 					sizeof(struct llc_snap_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	atm_account_tx(entry->shortcut, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	entry->shortcut->send(entry->shortcut, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	entry->packets_fwded++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568)  * Probably needs some error checks and locking, not sure...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 					 struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	struct ethhdr *eth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		pr_info("(%s) no MPC found\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		goto non_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	eth = (struct ethhdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	if (eth->h_proto != htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		goto non_ip; /* Multi-Protocol Over ATM :-) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	/* Weed out funny packets (e.g., AF_PACKET or raw). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	if (skb->len < ETH_HLEN + sizeof(struct iphdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		goto non_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	skb_set_network_header(skb, ETH_HLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	if (skb->len < ETH_HLEN + ip_hdr(skb)->ihl * 4 || ip_hdr(skb)->ihl < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		goto non_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	while (i < mpc->number_of_mps_macs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		if (ether_addr_equal(eth->h_dest, mpc->mps_macs + i * ETH_ALEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 			if (send_via_shortcut(skb, mpc) == 0) /* try shortcut */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 				return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) non_ip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	return __netdev_start_xmit(mpc->old_ops, skb, dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	int bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	struct atmmpc_ioc ioc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	in_cache_entry *in_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	__be32  ipaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	if (bytes_left != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		pr_info("mpoa:Short read (missed %d bytes) from userland\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 			bytes_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	ipaddr = ioc_data.ipaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	mpc = find_mpc_by_itfnum(ioc_data.dev_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	if (mpc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	if (ioc_data.type == MPC_SOCKET_INGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		in_entry = mpc->in_ops->get(ipaddr, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 		if (in_entry == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		    in_entry->entry_state < INGRESS_RESOLVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 			pr_info("(%s) did not find RESOLVED entry from ingress cache\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 				mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 			if (in_entry != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 				mpc->in_ops->put(in_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		pr_info("(%s) attaching ingress SVC, entry = %pI4\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 			mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		in_entry->shortcut = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		mpc->in_ops->put(in_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		pr_info("(%s) attaching egress SVC\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	vcc->proto_data = mpc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	vcc->push = mpc_push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	in_cache_entry *in_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	eg_cache_entry *eg_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	mpc = find_mpc_by_lec(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		pr_info("(%s) close for unknown MPC\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	dprintk("(%s)\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	if (in_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		dprintk("(%s) ingress SVC closed ip = %pI4\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 			mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		in_entry->shortcut = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		mpc->in_ops->put(in_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	if (eg_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		dprintk("(%s) egress SVC closed\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		eg_entry->shortcut = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		mpc->eg_ops->put(eg_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	if (in_entry == NULL && eg_entry == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 		dprintk("(%s) unused vcc closed\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	struct net_device *dev = (struct net_device *)vcc->proto_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	struct sk_buff *new_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	eg_cache_entry *eg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	__be32 tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	ddprintk("(%s)\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	if (skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		dprintk("(%s) null skb, closing VCC\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		mpc_vcc_close(vcc, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	if (memcmp(skb->data, &llc_snap_mpoa_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		   sizeof(struct llc_snap_hdr)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		struct sock *sk = sk_atm(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		dprintk("(%s) control packet arrived\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		/* Pass control packets to daemon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		skb_queue_tail(&sk->sk_receive_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		sk->sk_data_ready(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	/* data coming over the shortcut */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	atm_return(vcc, skb->truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	mpc = find_mpc_by_lec(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		pr_info("(%s) unknown MPC\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	if (memcmp(skb->data, &llc_snap_mpoa_data_tagged,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		   sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		ddprintk("(%s) tagged data packet arrived\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	} else if (memcmp(skb->data, &llc_snap_mpoa_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 			  sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		pr_info("(%s) Unsupported non-tagged data packet arrived.  Purging\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 			dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		pr_info("(%s) garbage arrived, purging\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	tmp = skb->data + sizeof(struct llc_snap_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	tag = *(__be32 *)tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	eg = mpc->eg_ops->get_by_tag(tag, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	if (eg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		pr_info("mpoa: (%s) Didn't find egress cache entry, tag = %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 			dev->name, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 		purge_egress_shortcut(vcc, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	 * See if ingress MPC is using shortcut we opened as a return channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	 * This means we have a bi-directional vcc opened by us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	if (eg->shortcut == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 		eg->shortcut = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		pr_info("(%s) egress SVC in use\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 					/* get rid of LLC/SNAP header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 					/* LLC/SNAP is shorter than MAC header :( */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	if (new_skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		mpc->eg_ops->put(eg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	skb_push(new_skb, eg->ctrl_info.DH_length);     /* add MAC header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	skb_copy_to_linear_data(new_skb, eg->ctrl_info.DLL_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 				eg->ctrl_info.DH_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	new_skb->protocol = eth_type_trans(new_skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	skb_reset_network_header(new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	eg->latest_ip_addr = ip_hdr(new_skb)->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	eg->packets_rcvd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	mpc->eg_ops->put(eg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	memset(ATM_SKB(new_skb), 0, sizeof(struct atm_skb_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	netif_rx(new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) static const struct atmdev_ops mpc_ops = { /* only send is required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	.close	= mpoad_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	.send	= msg_from_mpoad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) static struct atm_dev mpc_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	.ops	= &mpc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	.type	= "mpc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	.number	= 42,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	.lock	= __SPIN_LOCK_UNLOCKED(mpc_dev.lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	/* members not explicitly initialised will be 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	struct lec_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	if (mpcs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		mpc_timer_refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		/* This lets us now how our LECs are doing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		err = register_netdevice_notifier(&mpoa_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 			del_timer(&mpc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	mpc = find_mpc_by_itfnum(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		dprintk("allocating new mpc for itf %d\n", arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		mpc = alloc_mpc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		if (mpc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 		mpc->dev_num = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		mpc->dev = find_lec_by_itfnum(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 					/* NULL if there was no lec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	if (mpc->mpoad_vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		pr_info("mpoad is already present for itf %d\n", arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		return -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	if (mpc->dev) { /* check if the lec is LANE2 capable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		priv = netdev_priv(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 		if (priv->lane_version < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 			dev_put(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 			mpc->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			priv->lane2_ops->associate_indicator = lane2_assoc_ind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	mpc->mpoad_vcc = vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	vcc->dev = &mpc_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	vcc_insert_socket(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	set_bit(ATM_VF_META, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	set_bit(ATM_VF_READY, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	if (mpc->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		char empty[ATM_ESA_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		memset(empty, 0, ATM_ESA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		start_mpc(mpc, mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		/* set address if mpcd e.g. gets killed and restarted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		 * If we do not do it now we have to wait for the next LE_ARP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		if (memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	__module_get(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	return arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	struct k_message mesg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	memcpy(mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	mesg.type = SET_MPS_CTRL_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	msg_to_mpoad(&mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) static void mpoad_close(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	mpc = find_mpc_by_vcc(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		pr_info("did not find MPC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	if (!mpc->mpoad_vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		pr_info("close for non-present mpoad\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	mpc->mpoad_vcc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	if (mpc->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		struct lec_priv *priv = netdev_priv(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 		priv->lane2_ops->associate_indicator = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		stop_mpc(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		dev_put(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	mpc->in_ops->destroy_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	mpc->eg_ops->destroy_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 		atm_return(vcc, skb->truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 		kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	pr_info("(%s) going down\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		(mpc->dev) ? mpc->dev->name : "<unknown>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	module_put(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	struct k_message *mesg = (struct k_message *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		pr_info("no mpc found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	dprintk("(%s)", mpc->dev ? mpc->dev->name : "<unknown>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	switch (mesg->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	case MPOA_RES_REPLY_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		dprintk_cont("mpoa_res_reply_rcvd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		MPOA_res_reply_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	case MPOA_TRIGGER_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		dprintk_cont("mpoa_trigger_rcvd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		MPOA_trigger_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	case INGRESS_PURGE_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		dprintk_cont("nhrp_purge_rcvd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		ingress_purge_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	case EGRESS_PURGE_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		dprintk_cont("egress_purge_reply_rcvd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		egress_purge_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	case MPS_DEATH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		dprintk_cont("mps_death\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		mps_death(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	case CACHE_IMPOS_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		dprintk_cont("cache_impos_rcvd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		MPOA_cache_impos_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	case SET_MPC_CTRL_ADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		dprintk_cont("set_mpc_ctrl_addr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		set_mpc_ctrl_addr_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	case SET_MPS_MAC_ADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		dprintk_cont("set_mps_mac_addr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		set_mps_mac_addr_rcvd(mesg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	case CLEAN_UP_AND_EXIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		dprintk_cont("clean_up_and_exit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		clean_up(mesg, mpc, DIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	case RELOAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		dprintk_cont("reload\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		clean_up(mesg, mpc, RELOAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	case SET_MPC_PARAMS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		dprintk_cont("set_mpc_params\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		mpc->parameters = mesg->content.params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		dprintk_cont("unknown message %d\n", mesg->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) /* Remember that this function may not do things that sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	if (mpc == NULL || !mpc->mpoad_vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		pr_info("mesg %d to a non-existent mpoad\n", mesg->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	skb_put(skb, sizeof(struct k_message));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	skb_copy_to_linear_data(skb, mesg, sizeof(*mesg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	atm_force_charge(mpc->mpoad_vcc, skb->truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	sk = sk_atm(mpc->mpoad_vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	skb_queue_tail(&sk->sk_receive_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	sk->sk_data_ready(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 			       unsigned long event, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	struct mpoa_client *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	struct lec_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	if (!net_eq(dev_net(dev), &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 		return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	if (strncmp(dev->name, "lec", 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		return NOTIFY_DONE; /* we are only interested in lec:s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	case NETDEV_REGISTER:       /* a new lec device was allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 		priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		if (priv->lane_version < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		priv->lane2_ops->associate_indicator = lane2_assoc_ind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		mpc = find_mpc_by_itfnum(priv->itfnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 			dprintk("allocating new mpc for %s\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 			mpc = alloc_mpc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 			if (mpc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 				pr_info("no new mpc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		mpc->dev_num = priv->itfnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		mpc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		dprintk("(%s) was initialized\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	case NETDEV_UNREGISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		/* the lec device was deallocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		mpc = find_mpc_by_lec(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		if (mpc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		dprintk("device (%s) was deallocated\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		stop_mpc(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		dev_put(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		mpc->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	case NETDEV_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		/* the dev was ifconfig'ed up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		mpc = find_mpc_by_lec(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 		if (mpc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 		if (mpc->mpoad_vcc != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 			start_mpc(mpc, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	case NETDEV_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 		/* the dev was ifconfig'ed down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 		/* this means that the flow of packets from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		 * upper layer stops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 		mpc = find_mpc_by_lec(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		if (mpc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		if (mpc->mpoad_vcc != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 			stop_mpc(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	case NETDEV_REBOOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	case NETDEV_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	case NETDEV_CHANGEMTU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	case NETDEV_CHANGEADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	case NETDEV_GOING_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)  * Functions which are called after a message is received from mpcd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)  * Msg is reused on purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	__be32 dst_ip = msg->content.in_info.in_dst_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	in_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	entry = mpc->in_ops->get(dst_ip, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		entry = mpc->in_ops->add_entry(dst_ip, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		entry->entry_state = INGRESS_RESOLVING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		msg->type = SND_MPOA_RES_RQST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 		msg->content.in_info = entry->ctrl_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		msg_to_mpoad(msg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		entry->reply_wait = ktime_get_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	if (entry->entry_state == INGRESS_INVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		entry->entry_state = INGRESS_RESOLVING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 		msg->type = SND_MPOA_RES_RQST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 		msg->content.in_info = entry->ctrl_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		msg_to_mpoad(msg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		entry->reply_wait = ktime_get_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	pr_info("(%s) entry already in resolving state\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		(mpc->dev) ? mpc->dev->name : "<unknown>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)  * Things get complicated because we have to check if there's an egress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)  * shortcut with suitable traffic parameters we could use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) static void check_qos_and_open_shortcut(struct k_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 					struct mpoa_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 					in_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	__be32 dst_ip = msg->content.in_info.in_dst_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	if (eg_entry && eg_entry->shortcut) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		if (eg_entry->shortcut->qos.txtp.traffic_class &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		    msg->qos.txtp.traffic_class &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		    (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 			if (eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 				entry->shortcut = eg_entry->shortcut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 			else if (eg_entry->shortcut->qos.txtp.max_pcr > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 				entry->shortcut = eg_entry->shortcut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		if (entry->shortcut) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 			dprintk("(%s) using egress SVC to reach %pI4\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 				client->dev->name, &dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 			client->eg_ops->put(eg_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	if (eg_entry != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		client->eg_ops->put(eg_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	/* No luck in the egress cache we must open an ingress SVC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	msg->type = OPEN_INGRESS_SVC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	if (qos &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	    (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		msg->qos = qos->qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 		pr_info("(%s) trying to get a CBR shortcut\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 			client->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 		memset(&msg->qos, 0, sizeof(struct atm_qos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	msg_to_mpoad(msg, client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	__be32 dst_ip = msg->content.in_info.in_dst_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	dprintk("(%s) ip %pI4\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		mpc->dev->name, &dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	ddprintk("(%s) entry = %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 		 mpc->dev->name, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		pr_info("(%s) ARGH, received res. reply for an entry that doesn't exist.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 			mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	ddprintk_cont(" entry_state = %d ", entry->entry_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	if (entry->entry_state == INGRESS_RESOLVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		pr_info("(%s) RESOLVED entry!\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	entry->ctrl_info = msg->content.in_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	entry->time = ktime_get_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	/* Used in refreshing func from now on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	entry->reply_wait = ktime_get_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	entry->refresh_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	ddprintk_cont("entry->shortcut = %p\n", entry->shortcut);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	if (entry->entry_state == INGRESS_RESOLVING &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	    entry->shortcut != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 		entry->entry_state = INGRESS_RESOLVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		return; /* Shortcut already open... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	if (entry->shortcut != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		pr_info("(%s) entry->shortcut != NULL, impossible!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 			mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	check_qos_and_open_shortcut(msg, mpc, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	entry->entry_state = INGRESS_RESOLVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	__be32 dst_ip = msg->content.in_info.in_dst_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	__be32 mask = msg->ip_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		pr_info("(%s) purge for a non-existing entry, ip = %pI4\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 			mpc->dev->name, &dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		dprintk("(%s) removing an ingress entry, ip = %pI4\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 			mpc->dev->name, &dst_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 		write_lock_bh(&mpc->ingress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 		mpc->in_ops->remove_entry(entry, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 		write_unlock_bh(&mpc->ingress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		mpc->in_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	} while (entry != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	__be32 cache_id = msg->content.eg_info.cache_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		dprintk("(%s) purge for a non-existing entry\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 			mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	write_lock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	mpc->eg_ops->remove_entry(entry, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	write_unlock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	mpc->eg_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	struct k_message *purge_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	dprintk("entering\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	if (vcc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		pr_info("vcc == NULL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	if (skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 		pr_info("out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	skb_put(skb, sizeof(struct k_message));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	memset(skb->data, 0, sizeof(struct k_message));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	purge_msg = (struct k_message *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	purge_msg->type = DATA_PLANE_PURGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	if (entry != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		purge_msg->content.eg_info = entry->ctrl_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	atm_force_charge(vcc, skb->truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	sk = sk_atm(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	skb_queue_tail(&sk->sk_receive_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	sk->sk_data_ready(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	dprintk("exiting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)  * Our MPS died. Tell our daemon to send NHRP data plane purge to each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)  * of the egress shortcuts we have.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) static void mps_death(struct k_message *msg, struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	eg_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	dprintk("(%s)\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	if (memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 		pr_info("(%s) wrong MPS\n", mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	/* FIXME: This knows too much of the cache structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	read_lock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	entry = mpc->eg_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	while (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 		purge_egress_shortcut(entry->shortcut, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 		entry = entry->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	read_unlock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	mpc->in_ops->destroy_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	mpc->eg_ops->destroy_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) static void MPOA_cache_impos_rcvd(struct k_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 				  struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	uint16_t holding_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	holding_time = msg->content.eg_info.holding_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 	dprintk("(%s) entry = %p, holding_time = %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		mpc->dev->name, entry, holding_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	if (entry == NULL && holding_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		entry = mpc->eg_ops->add_entry(msg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		mpc->eg_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	if (holding_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 		mpc->eg_ops->update(entry, holding_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	write_lock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	mpc->eg_ops->remove_entry(entry, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	write_unlock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	mpc->eg_ops->put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 				   struct mpoa_client *mpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	struct lec_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 	int i, retval ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 	tlv[4] = 1 + 1 + ATM_ESA_LEN;  /* length                           */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 	tlv[5] = 0x02;                 /* MPOA client                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	tlv[6] = 0x00;                 /* number of MPS MAC addresses      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 	memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	dprintk("(%s) setting MPC ctrl ATM address to",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 		mpc->dev ? mpc->dev->name : "<unknown>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	for (i = 7; i < sizeof(tlv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 		dprintk_cont(" %02x", tlv[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	dprintk_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 	if (mpc->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 		priv = netdev_priv(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 		retval = priv->lane2_ops->associate_req(mpc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 							mpc->dev->dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 							tlv, sizeof(tlv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		if (retval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 			pr_info("(%s) MPOA device type TLV association failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 				mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 		retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 		if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 			pr_info("(%s) targetless LE_ARP request failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 				mpc->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) static void set_mps_mac_addr_rcvd(struct k_message *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 				  struct mpoa_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 	if (client->number_of_mps_macs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 		kfree(client->mps_macs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 	client->number_of_mps_macs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	if (client->mps_macs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 		pr_info("out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	client->number_of_mps_macs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)  * purge egress cache and tell daemon to 'action' (DIE, RELOAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	eg_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	msg->type = SND_EGRESS_PURGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 	/* FIXME: This knows too much of the cache structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	read_lock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	entry = mpc->eg_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 	while (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		msg->content.eg_info = entry->ctrl_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		dprintk("cache_id %u\n", entry->ctrl_info.cache_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		msg_to_mpoad(msg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		entry = entry->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 	read_unlock_irq(&mpc->egress_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 	msg->type = action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 	msg_to_mpoad(msg, mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) static unsigned long checking_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) static void mpc_timer_refresh(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	mpc_timer.expires = jiffies + (MPC_P2 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	checking_time = mpc_timer.expires;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	add_timer(&mpc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) static void mpc_cache_check(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 	struct mpoa_client *mpc = mpcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 	static unsigned long previous_resolving_check_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	static unsigned long previous_refresh_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	while (mpc != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 		mpc->in_ops->clear_count(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		mpc->eg_ops->clear_expired(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 		if (checking_time - previous_resolving_check_time >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 		    mpc->parameters.mpc_p4 * HZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 			mpc->in_ops->check_resolving(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 			previous_resolving_check_time = checking_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 		if (checking_time - previous_refresh_time >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		    mpc->parameters.mpc_p5 * HZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 			mpc->in_ops->refresh(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 			previous_refresh_time = checking_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		mpc = mpc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 	mpc_timer_refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 			  unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 	if (cmd != ATMMPC_CTRL && cmd != ATMMPC_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 		return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	case ATMMPC_CTRL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 		err = atm_mpoa_mpoad_attach(vcc, (int)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 		if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 			sock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	case ATMMPC_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 		err = atm_mpoa_vcc_attach(vcc, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) static struct atm_ioctl atm_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	.owner	= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 	.ioctl	= atm_mpoa_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) static __init int atm_mpoa_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 	register_atm_ioctl(&atm_ioctl_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 	if (mpc_proc_init() != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 		pr_info("failed to initialize /proc/mpoa\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 	pr_info("mpc.c: initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) static void __exit atm_mpoa_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 	struct mpoa_client *mpc, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	struct atm_mpoa_qos *qos, *nextqos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 	struct lec_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	mpc_proc_clean();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 	del_timer_sync(&mpc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 	unregister_netdevice_notifier(&mpoa_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 	deregister_atm_ioctl(&atm_ioctl_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	mpc = mpcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	mpcs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	while (mpc != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 		tmp = mpc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 		if (mpc->dev != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 			stop_mpc(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 			priv = netdev_priv(mpc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 			if (priv->lane2_ops != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 				priv->lane2_ops->associate_indicator = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 		ddprintk("about to clear caches\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 		mpc->in_ops->destroy_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 		mpc->eg_ops->destroy_cache(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 		ddprintk("caches cleared\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 		kfree(mpc->mps_macs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 		memset(mpc, 0, sizeof(struct mpoa_client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 		ddprintk("about to kfree %p\n", mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 		kfree(mpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 		ddprintk("next mpc is at %p\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 		mpc = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 	qos = qos_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	qos_head = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 	while (qos != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 		nextqos = qos->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 		dprintk("freeing qos entry %p\n", qos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		kfree(qos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 		qos = nextqos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) module_init(atm_mpoa_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) module_exit(atm_mpoa_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) MODULE_LICENSE("GPL");