/* * Copyright (C) 2012 Samsung Electronics. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #ifndef __MODEM_PRJ_H__ #define __MODEM_PRJ_H__ #include #include #include #include #include #include #include #define MAX_CPINFO_SIZE 512 #define MAX_LINK_DEVTYPE 3 #define MAX_FMT_DEVS 10 #define MAX_RAW_DEVS 32 #define MAX_RFS_DEVS 10 #define MAX_NUM_IO_DEV (MAX_FMT_DEVS + MAX_RAW_DEVS + MAX_RFS_DEVS) #define IOCTL_MODEM_ON _IO('o', 0x19) #define IOCTL_MODEM_OFF _IO('o', 0x20) #define IOCTL_MODEM_RESET _IO('o', 0x21) #define IOCTL_MODEM_BOOT_ON _IO('o', 0x22) #define IOCTL_MODEM_BOOT_OFF _IO('o', 0x23) #define IOCTL_MODEM_START _IO('o', 0x24) #define __UNUSED__IOCTL_MODEM_SEND _IO('o', 0x25) #define __UNUSED__IOCTL_MODEM_RECV _IO('o', 0x26) #define IOCTL_MODEM_STATUS _IO('o', 0x27) #define IOCTL_MODEM_DL_START _IO('o', 0x28) #define IOCTL_MODEM_FW_UPDATE _IO('o', 0x29) #define IOCTL_MODEM_NET_SUSPEND _IO('o', 0x30) #define IOCTL_MODEM_NET_RESUME _IO('o', 0x31) #define IOCTL_MODEM_DUMP_START _IO('o', 0x32) #define IOCTL_MODEM_DUMP_UPDATE _IO('o', 0x33) #define IOCTL_MODEM_FORCE_CRASH_EXIT _IO('o', 0x34) #define IOCTL_MODEM_CP_UPLOAD _IO('o', 0x35) #define IOCTL_MODEM_DUMP_RESET _IO('o', 0x36) #define IOCTL_DPRAM_SEND_BOOT _IO('o', 0x40) #define IOCTL_DPRAM_INIT_STATUS _IO('o', 0x43) /* * MAX_RXDATA_SIZE is used at making skb, when it called with page size * it need more bytes to allocate itself (Ex, cache byte, shared info, * padding...) * So, give restriction to allocation size below 1 page to prevent * big pages broken. */ #define MAX_RXDATA_SIZE 0x0E00 /* 4 * 1024 - 512 */ #define MAX_IPC_TX_SIZE 1024 #define MAX_MTU_TX_DATA_SIZE 1550 #define HDLC_HEADER_MAX_SIZE 6 /* fmt 3, raw 6, rfs 6 or sipc5 */ #define MAX_LINK_PADDING_SIZE 3 #define PSD_DATA_CHID_BEGIN 0x2A #define PSD_DATA_CHID_END 0x38 #define IP6VERSION 6 #define SOURCE_MAC_ADDR {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} #define FMT_WAKE_TIME (HZ/2) #define RFS_WAKE_TIME (HZ*3) #define RAW_WAKE_TIME (HZ*6) #define CP_LOOPBACK_CHANNEL 30 /* Does modem ctl structure will use state ? or status defined below ?*/ /* Be careful!! below sequence shouldn't be changed*/ enum modem_state { STATE_OFFLINE, STATE_CRASH_RESET, STATE_CRASH_EXIT, STATE_BOOTING, STATE_ONLINE, STATE_NV_REBUILDING, STATE_LOADER_DONE, STATE_SIM_ATTACH, STATE_SIM_DETACH, }; enum com_state { COM_NONE, COM_ONLINE, COM_HANDSHAKE, COM_BOOT, COM_CRASH, COM_BOOT_EBL, }; struct sim_state { bool online; /* SIM is online? */ bool changed; /* online is changed? */ }; struct header_data { char hdr[HDLC_HEADER_MAX_SIZE]; unsigned len; unsigned frag_len; char start; /* hdlc start header 0x7F or 0b11111000 */ }; struct fmt_hdr { u16 len; u8 control; } __packed; struct raw_hdr { u32 len; u8 channel; u8 control; } __packed; struct rfs_hdr { u32 len; u8 cmd; u8 id; } __packed; struct vnet { struct io_device *iod; }; /* for fragmented data from link devices */ struct fragmented_data { struct sk_buff *skb_recv; struct header_data h_data; /* page alloc fail retry*/ unsigned realloc_offset; }; #define fragdata(iod, ld) (&(iod)->fragments[(ld)->link_type]) /** struct skbuff_priv - private data of struct sk_buff * this is matched to char cb[48] of struct sk_buff */ struct skbuff_private { struct io_device *iod; struct link_device *ld; struct io_device *real_iod; /* for rx multipdp */ }; static inline struct skbuff_private *skbpriv(struct sk_buff *skb) { BUILD_BUG_ON(sizeof(struct skbuff_private) > sizeof(skb->cb)); return (struct skbuff_private *)&skb->cb; } struct io_device { /* rb_tree node for an io device */ struct rb_node node_chan; struct rb_node node_fmt; /* Name of the IO device */ char *name; atomic_t opened; /* Wait queue for the IO device */ wait_queue_head_t wq; /* Misc and net device structures for the IO device */ struct miscdevice miscdev; struct net_device *ndev; /* ID and Format for channel on the link */ unsigned id; enum modem_link link_types; enum dev_format format; enum modem_io io_typ; bool use_handover; /* handover 2+ link devices */ /* Rx queue of sk_buff */ struct sk_buff_head sk_rx_q; struct fragmented_data fragments[LINKDEV_MAX]; /* called from linkdevice when a packet arrives for this iodevice */ int (*recv)(struct io_device *iod, struct link_device *ld, const char *data, unsigned int len); /* inform the IO device that the modem is now online or offline or * crashing or whatever... */ void (*modem_state_changed)(struct io_device *iod, enum modem_state); /* inform the IO device that the SIM is not inserting or removing */ void (*sim_state_changed)(struct io_device *iod, bool sim_online); struct modem_ctl *mc; struct modem_shared *msd; struct wake_lock wakelock; long waketime; /* DO NOT use __current_link directly * you MUST use skbpriv(skb)->ld in mc, link, etc.. */ struct link_device *__current_link; }; #define to_io_device(misc) container_of(misc, struct io_device, miscdev) /* get_current_link, set_current_link don't need to use locks. * In ARM, set_current_link and get_current_link are compiled to * each one instruction (str, ldr) as atomic_set, atomic_read. * And, the order of set_current_link and get_current_link is not important. */ #define get_current_link(iod) ((iod)->__current_link) #define set_current_link(iod, ld) ((iod)->__current_link = (ld)) struct link_device { struct list_head list; char *name; enum modem_link link_type; unsigned aligned; /* Modem control */ struct modem_ctl *mc; /* Modem shared data */ struct modem_shared *msd; /* TX queue of socket buffers */ struct sk_buff_head sk_fmt_tx_q; struct sk_buff_head sk_raw_tx_q; struct sk_buff_head sk_rfs_tx_q; bool raw_tx_suspended; /* for misc dev */ struct completion raw_tx_resumed_by_cp; struct workqueue_struct *tx_wq; struct workqueue_struct *tx_raw_wq; struct work_struct tx_work; struct delayed_work tx_delayed_work; enum com_state com_state; /* init communication - setting link driver */ int (*init_comm)(struct link_device *ld, struct io_device *iod); /* terminate communication */ void (*terminate_comm)(struct link_device *ld, struct io_device *iod); /* called by an io_device when it has a packet to send over link * - the io device is passed so the link device can look at id and * format fields to determine how to route/format the packet */ int (*send)(struct link_device *ld, struct io_device *iod, struct sk_buff *skb); }; /** rx_alloc_skb - allocate an skbuff and set skb's iod, ld * @length: length to allocate * @iod: struct io_device * * @ld: struct link_device * * * %NULL is returned if there is no free memory. */ static inline struct sk_buff *rx_alloc_skb(unsigned int length, struct io_device *iod, struct link_device *ld) { struct sk_buff *skb; if (iod->format == IPC_MULTI_RAW || iod->format == IPC_RAW) skb = dev_alloc_skb(length); else skb = alloc_skb(length, GFP_ATOMIC); if (likely(skb)) { skbpriv(skb)->iod = iod; skbpriv(skb)->ld = ld; } return skb; } struct modemctl_ops { int (*modem_on) (struct modem_ctl *); int (*modem_off) (struct modem_ctl *); int (*modem_reset) (struct modem_ctl *); int (*modem_boot_on) (struct modem_ctl *); int (*modem_boot_off) (struct modem_ctl *); int (*modem_force_crash_exit) (struct modem_ctl *); int (*modem_dump_reset) (struct modem_ctl *); }; /* for IPC Logger */ struct mif_storage { char *addr; unsigned int cnt; }; /* modem_shared - shared data for all io/link devices and a modem ctl * msd : mc : iod : ld = 1 : 1 : M : N */ struct modem_shared { /* list of link devices */ struct list_head link_dev_list; /* rb_tree root of io devices. */ struct rb_root iodevs_tree_chan; /* group by channel */ struct rb_root iodevs_tree_fmt; /* group by dev_format */ /* for IPC Logger */ struct mif_storage storage; spinlock_t lock; }; struct modem_ctl { struct device *dev; char *name; struct modem_data *mdm_data; struct modem_shared *msd; enum modem_state phone_state; struct sim_state sim_state; unsigned gpio_cp_on; unsigned gpio_reset_req_n; unsigned gpio_cp_reset; unsigned gpio_pda_active; unsigned gpio_phone_active; unsigned gpio_cp_dump_int; unsigned gpio_ap_dump_int; unsigned gpio_sim_detect; int irq_phone_active; int irq_sim_detect; struct modemctl_ops ops; struct io_device *iod; struct io_device *bootd; }; int sipc4_init_io_device(struct io_device *iod); #endif