diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c index 8ab340c6..b8423029 100644 --- a/arch/arm/mach-msm/smd.c +++ b/arch/arm/mach-msm/smd.c @@ -979,6 +979,7 @@ int smd_cur_packet_size(smd_channel_t *ch) { return ch->current_packet; } +EXPORT_SYMBOL(smd_cur_packet_size); /* ------------------------------------------------------------------------- */ diff --git a/drivers/net/Makefile b/drivers/net/Makefile index dde828ae..1c174f44 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -284,11 +284,7 @@ obj-$(CONFIG_FS_ENET) += fs_enet/ obj-$(CONFIG_NETXEN_NIC) += netxen/ -ifdef CONFIG_MACH_HTCLEO -obj-$(CONFIG_MSM_RMNET) += msm_rmnet_wince.o -else obj-$(CONFIG_MSM_RMNET) += msm_rmnet.o -endif obj-$(CONFIG_NIU) += niu.o obj-$(CONFIG_VIRTIO_NET) += virtio_net.o diff --git a/drivers/net/msm_rmnet_wince.c b/drivers/net/msm_rmnet_wince.c deleted file mode 100644 index ad1d1c93..00000000 --- a/drivers/net/msm_rmnet_wince.c +++ /dev/null @@ -1,542 +0,0 @@ -/* linux/drivers/net/msm_rmnet_wm.c - * - * Virtual Ethernet Interface for Networking - * - * Copyright (C) 2010 Cotulla - * Copyright (C) 2007 Google, Inc. - * Author: Brian Swetland - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif - -//#define ENABLE_LOGGING 1 - -// enabled for test -//#define CONFIG_MSM_RMNET_DEBUG 1 - -#define READ_BUF_SIZE 32768 - -#if 0 -#define DBG(x...) pr_info("RMNET: "x) -#else -#define DBG(x...) do{}while(0) -#endif - -#include - -/* XXX should come from smd headers */ -#define SMD_PORT_ETHER0 11 -#define POLL_DELAY 1000000 /* 1 second delay interval */ - -struct rmnet_private -{ - smd_channel_t *ch; - struct net_device_stats stats; - const char *chname; - struct wake_lock wake_lock; - uint8_t *buf; -#ifdef CONFIG_MSM_RMNET_DEBUG - ktime_t last_packet; - short active_countdown; /* Number of times left to check */ - short restart_count; /* Number of polls seems so far */ - unsigned long wakeups_xmit; - unsigned long wakeups_rcv; - unsigned long timeout_us; - unsigned long awake_time_ms; - struct delayed_work work; -#endif -}; - -static int count_this_packet(void *_hdr, int len) -{ - struct ethhdr *hdr = _hdr; - - if (len >= ETH_HLEN && hdr->h_proto == htons(ETH_P_ARP)) - return 0; - - return 1; -} - -#ifdef CONFIG_MSM_RMNET_DEBUG -static int in_suspend; -static unsigned long timeout_us; -static struct workqueue_struct *rmnet_wq; - -static void do_check_active(struct work_struct *work) -{ - struct rmnet_private *p = - container_of(work, struct rmnet_private, work.work); - - /* - * Soft timers do not wake the cpu from suspend. - * If we are in suspend, do_check_active is only called once at the - * timeout time instead of polling at POLL_DELAY interval. Otherwise the - * cpu will sleeps and the timer can fire much much later than POLL_DELAY - * casuing a skew in time calculations. - */ - if (in_suspend) { - /* - * Assume for N packets sent durring this session, they are - * uniformly distributed durring the timeout window. - */ - int tmp = p->timeout_us * 2 - - (p->timeout_us / (p->active_countdown + 1)); - tmp /= 1000; - p->awake_time_ms += tmp; - - p->active_countdown = p->restart_count = 0; - return; - } - - /* - * Poll if not in suspend, since this gives more accurate tracking of - * rmnet sessions. - */ - p->restart_count++; - if (--p->active_countdown == 0) { - p->awake_time_ms += p->restart_count * POLL_DELAY / 1000; - p->restart_count = 0; - } else { - queue_delayed_work(rmnet_wq, &p->work, - usecs_to_jiffies(POLL_DELAY)); - } -} - -#ifdef CONFIG_HAS_EARLYSUSPEND -/* - * If early suspend is enabled then we specify two timeout values, - * screen on (default), and screen is off. - */ -static unsigned long timeout_suspend_us; -static struct device *rmnet0; - -/* Set timeout in us when the screen is off. */ -static ssize_t timeout_suspend_store(struct device *d, struct device_attribute *attr, const char *buf, size_t n) -{ - timeout_suspend_us = simple_strtoul(buf, NULL, 10); - return n; -} - -static ssize_t timeout_suspend_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%lu\n", (unsigned long) timeout_suspend_us); -} - -static DEVICE_ATTR(timeout_suspend, 0664, timeout_suspend_show, timeout_suspend_store); - -static void rmnet_early_suspend(struct early_suspend *handler) { - if (rmnet0) { - struct rmnet_private *p = netdev_priv(to_net_dev(rmnet0)); - p->timeout_us = timeout_suspend_us; - } - in_suspend = 1; -} - -static void rmnet_late_resume(struct early_suspend *handler) { - if (rmnet0) { - struct rmnet_private *p = netdev_priv(to_net_dev(rmnet0)); - p->timeout_us = timeout_us; - } - in_suspend = 0; -} - -static struct early_suspend rmnet_power_suspend = { - .suspend = rmnet_early_suspend, - .resume = rmnet_late_resume, -}; - -static int __init rmnet_late_init(void) -{ - register_early_suspend(&rmnet_power_suspend); - return 0; -} - -late_initcall(rmnet_late_init); -#endif - -/* Returns 1 if packet caused rmnet to wakeup, 0 otherwise. */ -static int rmnet_cause_wakeup(struct rmnet_private *p) { - int ret = 0; - ktime_t now; - if (p->timeout_us == 0) /* Check if disabled */ - return 0; - - /* Start timer on a wakeup packet */ - if (p->active_countdown == 0) { - ret = 1; - now = ktime_get_real(); - p->last_packet = now; - if (in_suspend) - queue_delayed_work(rmnet_wq, &p->work, - usecs_to_jiffies(p->timeout_us)); - else - queue_delayed_work(rmnet_wq, &p->work, - usecs_to_jiffies(POLL_DELAY)); - } - - if (in_suspend) - p->active_countdown++; - else - p->active_countdown = p->timeout_us / POLL_DELAY; - - return ret; -} - -static ssize_t wakeups_xmit_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct rmnet_private *p = netdev_priv(to_net_dev(d)); - return sprintf(buf, "%lu\n", p->wakeups_xmit); -} - -DEVICE_ATTR(wakeups_xmit, 0444, wakeups_xmit_show, NULL); - -static ssize_t wakeups_rcv_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct rmnet_private *p = netdev_priv(to_net_dev(d)); - return sprintf(buf, "%lu\n", p->wakeups_rcv); -} - -DEVICE_ATTR(wakeups_rcv, 0444, wakeups_rcv_show, NULL); - -/* Set timeout in us. */ -static ssize_t timeout_store(struct device *d, struct device_attribute *attr, - const char *buf, size_t n) -{ -#ifndef CONFIG_HAS_EARLYSUSPEND - struct rmnet_private *p = netdev_priv(to_net_dev(d)); - p->timeout_us = timeout_us = simple_strtoul(buf, NULL, 10); -#else -/* If using early suspend/resume hooks do not write the value on store. */ - timeout_us = simple_strtoul(buf, NULL, 10); -#endif - return n; -} - -static ssize_t timeout_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct rmnet_private *p = netdev_priv(to_net_dev(d)); - p = netdev_priv(to_net_dev(d)); - return sprintf(buf, "%lu\n", timeout_us); -} - -DEVICE_ATTR(timeout, 0664, timeout_show, timeout_store); - -/* Show total radio awake time in ms */ -static ssize_t awake_time_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct rmnet_private *p = netdev_priv(to_net_dev(d)); - return sprintf(buf, "%lu\n", p->awake_time_ms); -} -DEVICE_ATTR(awake_time_ms, 0444, awake_time_show, NULL); - -#endif - -/* Called in soft-irq context */ -static void smd_net_data_handler(unsigned long arg) -{ - struct net_device *dev = (struct net_device *) arg; - struct rmnet_private *p = netdev_priv(dev); - struct sk_buff *skb; - void *ptr = 0; - uint8_t *curbuf = 0; - uint32_t offset; - uint32_t l, pksz; - int sz; - struct ethhdr *hdr; - - // DBG("+rx data\n"); - for (;;) - { - sz = smd_read_avail(p->ch); - DBG("RX: size %d\n", sz); - if (sz == 0) - break; - - if (sz > READ_BUF_SIZE) - { - pr_err("rmnet_recv() size too big %d?!\n", sz); - BUG(); - } - - wake_lock_timeout(&p->wake_lock, HZ / 2); - - if (smd_read(p->ch, p->buf, sz) != sz) - { - pr_err("rmnet_recv() smd lied about avail?!\n"); - continue; - } - offset = 0; - - while (offset < sz) - { - curbuf = p->buf + offset; - hdr = (struct ethhdr *)curbuf; - - if (curbuf[12] == 8 && curbuf[13] == 6) - { - struct arphdr *ah = (struct arphdr*)(curbuf + 14); - l = sizeof(struct arphdr) + (ah->ar_hln + ah->ar_pln) * 2; - pksz = l + 14; - } - else if (curbuf[12] == 8 && curbuf[13] == 0) - { - struct iphdr *ih = (struct iphdr *)(curbuf + 14); - l = ntohs(ih->tot_len); - pksz = l + 14; - } - else - { - pr_err("rmnet_recv() wrong header!\n"); - l = 0; - pksz = 0; - break; - } - - skb = dev_alloc_skb(pksz + NET_IP_ALIGN); - if (skb == NULL) - { - pr_err("rmnet_recv() cannot allocate skb\n"); - } - else - { - skb->dev = dev; - skb_reserve(skb, NET_IP_ALIGN); - ptr = skb_put(skb, pksz); - memcpy(ptr, curbuf, pksz); - - skb->protocol = eth_type_trans(skb, dev); -#ifdef ENABLE_LOGGING - printk("RX: packetdata: %d %x recv: %d\n", pksz, offset, skb->protocol); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, pksz); -#endif - - if (count_this_packet(ptr, skb->len)) - { -#ifdef CONFIG_MSM_RMNET_DEBUG - p->wakeups_rcv += rmnet_cause_wakeup(p); -#endif - p->stats.rx_packets++; - p->stats.rx_bytes += skb->len; - } - netif_rx(skb); - } - offset += pksz; - } - } - // DBG("-rx data\n"); -} - - -static DECLARE_TASKLET(smd_net_data_tasklet, smd_net_data_handler, 0); - -static void smd_net_notify(void *_dev, unsigned event) -{ - if (event != SMD_EVENT_DATA) - return; - - smd_net_data_tasklet.data = (unsigned long) _dev; - - tasklet_schedule(&smd_net_data_tasklet); -} - - -static int rmnet_open(struct net_device *dev) -{ - int r; - struct rmnet_private *p = netdev_priv(dev); - - pr_info("rmnet_open()\n"); - - if (!p->ch) - { - r = smd_open(p->chname, &p->ch, dev, smd_net_notify); - - if (r < 0) - return -ENODEV; - } - - p->buf = kmalloc(READ_BUF_SIZE, GFP_KERNEL); - netif_start_queue(dev); - return 0; -} - -static int rmnet_stop(struct net_device *dev) -{ - struct rmnet_private *p = netdev_priv(dev); - pr_info("rmnet_stop()\n"); - netif_stop_queue(dev); - kfree(p->buf); - return 0; -} - -static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rmnet_private *p = netdev_priv(dev); - smd_channel_t *ch = p->ch; - -#ifdef ENABLE_LOGGING - printk("TX: packetdata: %d\n", skb->len); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, skb->len); -#endif - - if (smd_write_atomic(ch, skb->data, skb->len) != skb->len) { - pr_err("rmnet fifo full, dropping packet\n"); - } else { - if (count_this_packet(skb->data, skb->len)) { - p->stats.tx_packets++; - p->stats.tx_bytes += skb->len; -#ifdef CONFIG_MSM_RMNET_DEBUG - p->wakeups_xmit += rmnet_cause_wakeup(p); -#endif - } - } - - dev_kfree_skb_irq(skb); - return 0; -} - -static struct net_device_stats *rmnet_get_stats(struct net_device *dev) -{ - struct rmnet_private *p = netdev_priv(dev); - return &p->stats; -} - -static void rmnet_set_multicast_list(struct net_device *dev) -{ -} - -static void rmnet_tx_timeout(struct net_device *dev) -{ - pr_info("rmnet_tx_timeout()\n"); -} - -static struct net_device_ops rmnet_ops = { - .ndo_open = rmnet_open, - .ndo_stop = rmnet_stop, - .ndo_start_xmit = rmnet_xmit, - .ndo_get_stats = rmnet_get_stats, - .ndo_set_multicast_list = rmnet_set_multicast_list, - .ndo_tx_timeout = rmnet_tx_timeout, -}; - -static void __init rmnet_setup(struct net_device *dev) -{ - dev->netdev_ops = &rmnet_ops; - - DBG("setup\n"); - dev->watchdog_timeo = 20; /* ??? */ - - ether_setup(dev); - - //dev->change_mtu = 0; /* ??? */ - - random_ether_addr(dev->dev_addr); -} - - -static const char *ch_name[3] = { - "SMD_DATA5", - "SMD_DATA6", - "SMD_DATA7", -}; - -static int __init rmnet_init(void) -{ - int ret; - struct device *d; - struct net_device *dev; - struct rmnet_private *p; - unsigned n; - -#ifdef CONFIG_MSM_RMNET_DEBUG - timeout_us = 0; -#ifdef CONFIG_HAS_EARLYSUSPEND - timeout_suspend_us = 0; -#endif -#endif - -#ifdef CONFIG_MSM_RMNET_DEBUG - rmnet_wq = create_workqueue("rmnet"); -#endif - - for (n = 0; n < 3; n++) - { - dev = alloc_netdev(sizeof(struct rmnet_private), - "rmnet%d", rmnet_setup); - - if (!dev) - return -ENOMEM; - - d = &(dev->dev); - p = netdev_priv(dev); - p->chname = ch_name[n]; - wake_lock_init(&p->wake_lock, WAKE_LOCK_SUSPEND, ch_name[n]); -#ifdef CONFIG_MSM_RMNET_DEBUG - p->timeout_us = timeout_us; - p->awake_time_ms = p->wakeups_xmit = p->wakeups_rcv = 0; - p->active_countdown = p->restart_count = 0; - INIT_DELAYED_WORK_DEFERRABLE(&p->work, do_check_active); -#endif - - ret = register_netdev(dev); - if (ret) { - free_netdev(dev); - return ret; - } - -#ifdef CONFIG_MSM_RMNET_DEBUG - if (device_create_file(d, &dev_attr_timeout)) - continue; - if (device_create_file(d, &dev_attr_wakeups_xmit)) - continue; - if (device_create_file(d, &dev_attr_wakeups_rcv)) - continue; - if (device_create_file(d, &dev_attr_awake_time_ms)) - continue; -#ifdef CONFIG_HAS_EARLYSUSPEND - if (device_create_file(d, &dev_attr_timeout_suspend)) - continue; - - /* Only care about rmnet0 for suspend/resume tiemout hooks. */ - if (n == 0) - rmnet0 = d; -#endif -#endif - } - return 0; -} - -module_init(rmnet_init);