162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/* atmdev.h - ATM device driver declarations and various related items */
362306a36Sopenharmony_ci#ifndef LINUX_ATMDEV_H
462306a36Sopenharmony_ci#define LINUX_ATMDEV_H
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/wait.h> /* wait_queue_head_t */
862306a36Sopenharmony_ci#include <linux/time.h> /* struct timeval */
962306a36Sopenharmony_ci#include <linux/net.h>
1062306a36Sopenharmony_ci#include <linux/bug.h>
1162306a36Sopenharmony_ci#include <linux/skbuff.h> /* struct sk_buff */
1262306a36Sopenharmony_ci#include <linux/uio.h>
1362306a36Sopenharmony_ci#include <net/sock.h>
1462306a36Sopenharmony_ci#include <linux/atomic.h>
1562306a36Sopenharmony_ci#include <linux/refcount.h>
1662306a36Sopenharmony_ci#include <uapi/linux/atmdev.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
1962306a36Sopenharmony_ci#include <linux/proc_fs.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciextern struct proc_dir_entry *atm_proc_root;
2262306a36Sopenharmony_ci#endif
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
2562306a36Sopenharmony_ci#include <linux/compat.h>
2662306a36Sopenharmony_cistruct compat_atm_iobuf {
2762306a36Sopenharmony_ci	int length;
2862306a36Sopenharmony_ci	compat_uptr_t buffer;
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci#endif
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistruct k_atm_aal_stats {
3362306a36Sopenharmony_ci#define __HANDLE_ITEM(i) atomic_t i
3462306a36Sopenharmony_ci	__AAL_STAT_ITEMS
3562306a36Sopenharmony_ci#undef __HANDLE_ITEM
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistruct k_atm_dev_stats {
4062306a36Sopenharmony_ci	struct k_atm_aal_stats aal0;
4162306a36Sopenharmony_ci	struct k_atm_aal_stats aal34;
4262306a36Sopenharmony_ci	struct k_atm_aal_stats aal5;
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistruct device;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cienum {
4862306a36Sopenharmony_ci	ATM_VF_ADDR,		/* Address is in use. Set by anybody, cleared
4962306a36Sopenharmony_ci				   by device driver. */
5062306a36Sopenharmony_ci	ATM_VF_READY,		/* VC is ready to transfer data. Set by device
5162306a36Sopenharmony_ci				   driver, cleared by anybody. */
5262306a36Sopenharmony_ci	ATM_VF_PARTIAL,		/* resources are bound to PVC (partial PVC
5362306a36Sopenharmony_ci				   setup), controlled by socket layer */
5462306a36Sopenharmony_ci	ATM_VF_REGIS,		/* registered with demon, controlled by SVC
5562306a36Sopenharmony_ci				   socket layer */
5662306a36Sopenharmony_ci	ATM_VF_BOUND,		/* local SAP is set, controlled by SVC socket
5762306a36Sopenharmony_ci				   layer */
5862306a36Sopenharmony_ci	ATM_VF_RELEASED,	/* demon has indicated/requested release,
5962306a36Sopenharmony_ci				   controlled by SVC socket layer */
6062306a36Sopenharmony_ci	ATM_VF_HASQOS,		/* QOS parameters have been set */
6162306a36Sopenharmony_ci	ATM_VF_LISTEN,		/* socket is used for listening */
6262306a36Sopenharmony_ci	ATM_VF_META,		/* SVC socket isn't used for normal data
6362306a36Sopenharmony_ci				   traffic and doesn't depend on signaling
6462306a36Sopenharmony_ci				   to be available */
6562306a36Sopenharmony_ci	ATM_VF_SESSION,		/* VCC is p2mp session control descriptor */
6662306a36Sopenharmony_ci	ATM_VF_HASSAP,		/* SAP has been set */
6762306a36Sopenharmony_ci	ATM_VF_CLOSE,		/* asynchronous close - treat like VF_RELEASED*/
6862306a36Sopenharmony_ci	ATM_VF_WAITING,		/* waiting for reply from sigd */
6962306a36Sopenharmony_ci	ATM_VF_IS_CLIP,		/* in use by CLIP protocol */
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define ATM_VF2VS(flags) \
7462306a36Sopenharmony_ci    (test_bit(ATM_VF_READY,&(flags)) ? ATM_VS_CONNECTED : \
7562306a36Sopenharmony_ci     test_bit(ATM_VF_RELEASED,&(flags)) ? ATM_VS_CLOSING : \
7662306a36Sopenharmony_ci     test_bit(ATM_VF_LISTEN,&(flags)) ? ATM_VS_LISTEN : \
7762306a36Sopenharmony_ci     test_bit(ATM_VF_REGIS,&(flags)) ? ATM_VS_INUSE : \
7862306a36Sopenharmony_ci     test_bit(ATM_VF_BOUND,&(flags)) ? ATM_VS_BOUND : ATM_VS_IDLE)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cienum {
8262306a36Sopenharmony_ci	ATM_DF_REMOVED,		/* device was removed from atm_devs list */
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define ATM_PHY_SIG_LOST    0	/* no carrier/light */
8762306a36Sopenharmony_ci#define ATM_PHY_SIG_UNKNOWN 1	/* carrier/light status is unknown */
8862306a36Sopenharmony_ci#define ATM_PHY_SIG_FOUND   2	/* carrier/light okay */
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define ATM_ATMOPT_CLP	1	/* set CLP bit */
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistruct atm_vcc {
9362306a36Sopenharmony_ci	/* struct sock has to be the first member of atm_vcc */
9462306a36Sopenharmony_ci	struct sock	sk;
9562306a36Sopenharmony_ci	unsigned long	flags;		/* VCC flags (ATM_VF_*) */
9662306a36Sopenharmony_ci	short		vpi;		/* VPI and VCI (types must be equal */
9762306a36Sopenharmony_ci					/* with sockaddr) */
9862306a36Sopenharmony_ci	int 		vci;
9962306a36Sopenharmony_ci	unsigned long	aal_options;	/* AAL layer options */
10062306a36Sopenharmony_ci	unsigned long	atm_options;	/* ATM layer options */
10162306a36Sopenharmony_ci	struct atm_dev	*dev;		/* device back pointer */
10262306a36Sopenharmony_ci	struct atm_qos	qos;		/* QOS */
10362306a36Sopenharmony_ci	struct atm_sap	sap;		/* SAP */
10462306a36Sopenharmony_ci	void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
10562306a36Sopenharmony_ci	void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
10662306a36Sopenharmony_ci	void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
10762306a36Sopenharmony_ci	int (*push_oam)(struct atm_vcc *vcc,void *cell);
10862306a36Sopenharmony_ci	int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
10962306a36Sopenharmony_ci	void		*dev_data;	/* per-device data */
11062306a36Sopenharmony_ci	void		*proto_data;	/* per-protocol data */
11162306a36Sopenharmony_ci	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
11262306a36Sopenharmony_ci	struct module *owner;		/* owner of ->push function */
11362306a36Sopenharmony_ci	/* SVC part --- may move later ------------------------------------- */
11462306a36Sopenharmony_ci	short		itf;		/* interface number */
11562306a36Sopenharmony_ci	struct sockaddr_atmsvc local;
11662306a36Sopenharmony_ci	struct sockaddr_atmsvc remote;
11762306a36Sopenharmony_ci	/* Multipoint part ------------------------------------------------- */
11862306a36Sopenharmony_ci	struct atm_vcc	*session;	/* session VCC descriptor */
11962306a36Sopenharmony_ci	/* Other stuff ----------------------------------------------------- */
12062306a36Sopenharmony_ci	void		*user_back;	/* user backlink - not touched by */
12162306a36Sopenharmony_ci					/* native ATM stack. Currently used */
12262306a36Sopenharmony_ci					/* by CLIP and sch_atm. */
12362306a36Sopenharmony_ci};
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic inline struct atm_vcc *atm_sk(struct sock *sk)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	return (struct atm_vcc *)sk;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic inline struct atm_vcc *ATM_SD(struct socket *sock)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	return atm_sk(sock->sk);
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic inline struct sock *sk_atm(struct atm_vcc *vcc)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	return (struct sock *)vcc;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistruct atm_dev_addr {
14162306a36Sopenharmony_ci	struct sockaddr_atmsvc addr;	/* ATM address */
14262306a36Sopenharmony_ci	struct list_head entry;		/* next address */
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cienum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS };
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistruct atm_dev {
14862306a36Sopenharmony_ci	const struct atmdev_ops *ops;	/* device operations; NULL if unused */
14962306a36Sopenharmony_ci	const struct atmphy_ops *phy;	/* PHY operations, may be undefined */
15062306a36Sopenharmony_ci					/* (NULL) */
15162306a36Sopenharmony_ci	const char	*type;		/* device type name */
15262306a36Sopenharmony_ci	int		number;		/* device index */
15362306a36Sopenharmony_ci	void		*dev_data;	/* per-device data */
15462306a36Sopenharmony_ci	void		*phy_data;	/* private PHY data */
15562306a36Sopenharmony_ci	unsigned long	flags;		/* device flags (ATM_DF_*) */
15662306a36Sopenharmony_ci	struct list_head local;		/* local ATM addresses */
15762306a36Sopenharmony_ci	struct list_head lecs;		/* LECS ATM addresses learned via ILMI */
15862306a36Sopenharmony_ci	unsigned char	esi[ESI_LEN];	/* ESI ("MAC" addr) */
15962306a36Sopenharmony_ci	struct atm_cirange ci_range;	/* VPI/VCI range */
16062306a36Sopenharmony_ci	struct k_atm_dev_stats stats;	/* statistics */
16162306a36Sopenharmony_ci	char		signal;		/* signal status (ATM_PHY_SIG_*) */
16262306a36Sopenharmony_ci	int		link_rate;	/* link rate (default: OC3) */
16362306a36Sopenharmony_ci	refcount_t	refcnt;		/* reference count */
16462306a36Sopenharmony_ci	spinlock_t	lock;		/* protect internal members */
16562306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
16662306a36Sopenharmony_ci	struct proc_dir_entry *proc_entry; /* proc entry */
16762306a36Sopenharmony_ci	char *proc_name;		/* proc entry name */
16862306a36Sopenharmony_ci#endif
16962306a36Sopenharmony_ci	struct device class_dev;	/* sysfs device */
17062306a36Sopenharmony_ci	struct list_head dev_list;	/* linkage */
17162306a36Sopenharmony_ci};
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/* OF: send_Oam Flags */
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci#define ATM_OF_IMMED  1		/* Attempt immediate delivery */
17762306a36Sopenharmony_ci#define ATM_OF_INRATE 2		/* Attempt in-rate delivery */
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistruct atmdev_ops { /* only send is required */
18062306a36Sopenharmony_ci	void (*dev_close)(struct atm_dev *dev);
18162306a36Sopenharmony_ci	int (*open)(struct atm_vcc *vcc);
18262306a36Sopenharmony_ci	void (*close)(struct atm_vcc *vcc);
18362306a36Sopenharmony_ci	int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void __user *arg);
18462306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
18562306a36Sopenharmony_ci	int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd,
18662306a36Sopenharmony_ci			    void __user *arg);
18762306a36Sopenharmony_ci#endif
18862306a36Sopenharmony_ci	int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
18962306a36Sopenharmony_ci	int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb);
19062306a36Sopenharmony_ci	int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);
19162306a36Sopenharmony_ci	void (*phy_put)(struct atm_dev *dev,unsigned char value,
19262306a36Sopenharmony_ci	    unsigned long addr);
19362306a36Sopenharmony_ci	unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr);
19462306a36Sopenharmony_ci	int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags);
19562306a36Sopenharmony_ci	int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
19662306a36Sopenharmony_ci	struct module *owner;
19762306a36Sopenharmony_ci};
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistruct atmphy_ops {
20062306a36Sopenharmony_ci	int (*start)(struct atm_dev *dev);
20162306a36Sopenharmony_ci	int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void __user *arg);
20262306a36Sopenharmony_ci	void (*interrupt)(struct atm_dev *dev);
20362306a36Sopenharmony_ci	int (*stop)(struct atm_dev *dev);
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistruct atm_skb_data {
20762306a36Sopenharmony_ci	struct atm_vcc	*vcc;		/* ATM VCC */
20862306a36Sopenharmony_ci	unsigned long	atm_options;	/* ATM layer options */
20962306a36Sopenharmony_ci	unsigned int	acct_truesize;  /* truesize accounted to vcc */
21062306a36Sopenharmony_ci} __packed;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci#define VCC_HTABLE_SIZE 32
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ciextern struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
21562306a36Sopenharmony_ciextern rwlock_t vcc_sklist_lock;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci#define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistruct atm_dev *atm_dev_register(const char *type, struct device *parent,
22062306a36Sopenharmony_ci				 const struct atmdev_ops *ops,
22162306a36Sopenharmony_ci				 int number, /* -1 == pick first available */
22262306a36Sopenharmony_ci				 unsigned long *flags);
22362306a36Sopenharmony_cistruct atm_dev *atm_dev_lookup(int number);
22462306a36Sopenharmony_civoid atm_dev_deregister(struct atm_dev *dev);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci/* atm_dev_signal_change
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci * Propagate lower layer signal change in atm_dev->signal to netdevice.
22962306a36Sopenharmony_ci * The event will be sent via a notifier call chain.
23062306a36Sopenharmony_ci */
23162306a36Sopenharmony_civoid atm_dev_signal_change(struct atm_dev *dev, char signal);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_civoid vcc_insert_socket(struct sock *sk);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_civoid atm_dev_release_vccs(struct atm_dev *dev);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic inline void atm_account_tx(struct atm_vcc *vcc, struct sk_buff *skb)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	/*
24062306a36Sopenharmony_ci	 * Because ATM skbs may not belong to a sock (and we don't
24162306a36Sopenharmony_ci	 * necessarily want to), skb->truesize may be adjusted,
24262306a36Sopenharmony_ci	 * escaping the hack in pskb_expand_head() which avoids
24362306a36Sopenharmony_ci	 * doing so for some cases. So stash the value of truesize
24462306a36Sopenharmony_ci	 * at the time we accounted it, and atm_pop_raw() can use
24562306a36Sopenharmony_ci	 * that value later, in case it changes.
24662306a36Sopenharmony_ci	 */
24762306a36Sopenharmony_ci	refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
24862306a36Sopenharmony_ci	ATM_SKB(skb)->acct_truesize = skb->truesize;
24962306a36Sopenharmony_ci	ATM_SKB(skb)->atm_options = vcc->atm_options;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistatic inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	atomic_add(truesize, &sk_atm(vcc)->sk_rmem_alloc);
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic inline void atm_return(struct atm_vcc *vcc,int truesize)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	atomic_sub(truesize, &sk_atm(vcc)->sk_rmem_alloc);
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	return (size + refcount_read(&sk_atm(vcc)->sk_wmem_alloc)) <
26762306a36Sopenharmony_ci	       sk_atm(vcc)->sk_sndbuf;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic inline void atm_dev_hold(struct atm_dev *dev)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	refcount_inc(&dev->refcnt);
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_cistatic inline void atm_dev_put(struct atm_dev *dev)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	if (refcount_dec_and_test(&dev->refcnt)) {
28062306a36Sopenharmony_ci		BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags));
28162306a36Sopenharmony_ci		if (dev->ops->dev_close)
28262306a36Sopenharmony_ci			dev->ops->dev_close(dev);
28362306a36Sopenharmony_ci		put_device(&dev->class_dev);
28462306a36Sopenharmony_ci	}
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ciint atm_charge(struct atm_vcc *vcc,int truesize);
28962306a36Sopenharmony_cistruct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
29062306a36Sopenharmony_ci    gfp_t gfp_flags);
29162306a36Sopenharmony_ciint atm_pcr_goal(const struct atm_trafprm *tp);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_civoid vcc_release_async(struct atm_vcc *vcc, int reply);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistruct atm_ioctl {
29662306a36Sopenharmony_ci	struct module *owner;
29762306a36Sopenharmony_ci	/* A module reference is kept if appropriate over this call.
29862306a36Sopenharmony_ci	 * Return -ENOIOCTLCMD if you don't handle it. */
29962306a36Sopenharmony_ci	int (*ioctl)(struct socket *, unsigned int cmd, unsigned long arg);
30062306a36Sopenharmony_ci	struct list_head list;
30162306a36Sopenharmony_ci};
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/**
30462306a36Sopenharmony_ci * register_atm_ioctl - register handler for ioctl operations
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci * Special (non-device) handlers of ioctl's should
30762306a36Sopenharmony_ci * register here. If you're a normal device, you should
30862306a36Sopenharmony_ci * set .ioctl in your atmdev_ops instead.
30962306a36Sopenharmony_ci */
31062306a36Sopenharmony_civoid register_atm_ioctl(struct atm_ioctl *);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci/**
31362306a36Sopenharmony_ci * deregister_atm_ioctl - remove the ioctl handler
31462306a36Sopenharmony_ci */
31562306a36Sopenharmony_civoid deregister_atm_ioctl(struct atm_ioctl *);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci/* register_atmdevice_notifier - register atm_dev notify events
31962306a36Sopenharmony_ci *
32062306a36Sopenharmony_ci * Clients like br2684 will register notify events
32162306a36Sopenharmony_ci * Currently we notify of signal found/lost
32262306a36Sopenharmony_ci */
32362306a36Sopenharmony_ciint register_atmdevice_notifier(struct notifier_block *nb);
32462306a36Sopenharmony_civoid unregister_atmdevice_notifier(struct notifier_block *nb);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci#endif
327