From f0a34615add3912bf8f5354c02998aa506f4d15b Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 18 Nov 2013 11:05:52 +0400 Subject: xtensa: clean up include/asm/vectors.h - drop unused PHYSICAL_MEMORY_ADDRESS and XC_PADDR - fix NMI_VECTOR_VADDR and INTLEVEL7_VECTOR_VADDR definitions: there should be no XCHAL_ prefix in them; - fix the following warning seen with gcc-4.8.1: arch/xtensa/include/asm/vectors.h:71:5: warning: "XCHAL_HAVE_VECBASE" is not defined [-Wundef] Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/vectors.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/include/asm/vectors.h b/arch/xtensa/include/asm/vectors.h index c52b656d031..37e073b21a5 100644 --- a/arch/xtensa/include/asm/vectors.h +++ b/arch/xtensa/include/asm/vectors.h @@ -30,11 +30,9 @@ #if defined(XCHAL_HAVE_PTP_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY /* MMU v3 - XCHAL_HAVE_PTP_MMU == 1 */ - #define PHYSICAL_MEMORY_ADDRESS 0x00000000 #define LOAD_MEMORY_ADDRESS 0x00003000 #else /* MMU V2 - XCHAL_HAVE_PTP_MMU == 0 */ - #define PHYSICAL_MEMORY_ADDRESS 0xD0000000 #define LOAD_MEMORY_ADDRESS 0xD0003000 #endif @@ -46,7 +44,6 @@ /* Location of the start of the kernel text, _start */ #define KERNELOFFSET 0x00003000 - #define PHYSICAL_MEMORY_ADDRESS 0x00000000 /* Loaded just above possibly live vectors */ #define LOAD_MEMORY_ADDRESS 0x00003000 @@ -54,7 +51,6 @@ #endif /* CONFIG_MMU */ #define XC_VADDR(offset) (VIRTUAL_MEMORY_ADDRESS + offset) -#define XC_PADDR(offset) (PHYSICAL_MEMORY_ADDRESS + offset) /* Used to set VECBASE register */ #define VECBASE_RESET_VADDR VIRTUAL_MEMORY_ADDRESS @@ -67,7 +63,7 @@ VECBASE_RESET_VADDR) #define RESET_VECTOR1_VADDR XC_VADDR(RESET_VECTOR1_VECOFS) -#if XCHAL_HAVE_VECBASE +#if defined(XCHAL_HAVE_VECBASE) && XCHAL_HAVE_VECBASE #define USER_VECTOR_VADDR XC_VADDR(XCHAL_USER_VECOFS) #define KERNEL_VECTOR_VADDR XC_VADDR(XCHAL_KERNEL_VECOFS) @@ -81,11 +77,9 @@ #define DEBUG_VECTOR_VADDR XC_VADDR(XCHAL_DEBUG_VECOFS) -#undef XCHAL_NMI_VECTOR_VADDR -#define XCHAL_NMI_VECTOR_VADDR XC_VADDR(XCHAL_NMI_VECOFS) +#define NMI_VECTOR_VADDR XC_VADDR(XCHAL_NMI_VECOFS) -#undef XCHAL_INTLEVEL7_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL7_VECOFS) +#define INTLEVEL7_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL7_VECOFS) /* * These XCHAL_* #defines from varian/core.h -- cgit v1.2.3-18-g5258 From ea1d3ed3cfde34914a517f97320b80d9ccee7507 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 18 Nov 2013 11:05:53 +0400 Subject: xtensa: remove trailing colons in asm statement Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/ftrace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h index 73cc3f48230..736b9d214d8 100644 --- a/arch/xtensa/include/asm/ftrace.h +++ b/arch/xtensa/include/asm/ftrace.h @@ -18,7 +18,7 @@ __asm__ __volatile__ ( \ "mov %0, a0\n" \ "mov %1, a1\n" \ - : "=r"(a0), "=r"(a1) : : ); \ + : "=r"(a0), "=r"(a1)); \ MAKE_PC_FROM_RA(a0, a1); }) #ifdef CONFIG_FRAME_POINTER extern unsigned long return_address(unsigned level); -- cgit v1.2.3-18-g5258 From 3f3cd60bbd376e52ef91c92d0dba95b8942ebfcc Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 16:05:44 +0400 Subject: xtensa: ISS: clean up iss-network driver No functional changes, remove dead/unused code, clean checkpatch warnings, replace strlen of constant strings with sizeof. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 176 +++++++++++------------------------- 1 file changed, 52 insertions(+), 124 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index e9e1aad8c27..6d9cc455eae 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -57,7 +57,6 @@ static LIST_HEAD(devices); struct tuntap_info { char dev_name[IFNAMSIZ]; int fixed_config; - unsigned char gw[ETH_ALEN]; int fd; }; @@ -67,7 +66,6 @@ struct tuntap_info { /* This structure contains out private information for the driver. */ struct iss_net_private { - struct list_head device_list; struct list_head opened_list; @@ -118,7 +116,7 @@ static char *split_if_spec(char *str, ...) *arg = str; if (end == NULL) return NULL; - *end ++ = '\0'; + *end++ = '\0'; str = end; } va_end(ap); @@ -126,25 +124,6 @@ static char *split_if_spec(char *str, ...) } -#if 0 -/* Adjust SKB. */ - -struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) -{ - if ((skb != NULL) && (skb_tailroom(skb) < extra)) { - struct sk_buff *skb2; - - skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); - dev_kfree_skb(skb); - skb = skb2; - } - if (skb != NULL) - skb_put(skb, extra); - - return skb; -} -#endif - /* Return the IP address as a string for a given device. */ static void dev_ip_addr(void *d, char *buf, char *bin_buf) @@ -154,11 +133,13 @@ static void dev_ip_addr(void *d, char *buf, char *bin_buf) struct in_ifaddr *in; __be32 addr; - if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) { - printk(KERN_WARNING "Device not assigned an IP address!\n"); + if (ip == NULL || ip->ifa_list == NULL) { + pr_warn("Device not assigned an IP address!\n"); return; } + in = ip->ifa_list; + addr = in->ifa_address; sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, addr >> 24); @@ -173,7 +154,7 @@ static void dev_ip_addr(void *d, char *buf, char *bin_buf) /* Set Ethernet address of the specified device. */ -static void inline set_ether_mac(void *d, unsigned char *addr) +static inline void set_ether_mac(void *d, unsigned char *addr) { struct net_device *dev = d; memcpy(dev->dev_addr, addr, ETH_ALEN); @@ -194,19 +175,21 @@ static int tuntap_open(struct iss_net_private *lp) if (!lp->tp.info.tuntap.fixed_config) return -EINVAL; - if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) { /* O_RDWR */ - printk("Failed to open /dev/net/tun, returned %d " - "(errno = %d)\n", fd, errno); + fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */ + if (fd < 0) { + pr_err("Failed to open /dev/net/tun, returned %d (errno = %d)\n", + fd, errno); return fd; } - memset(&ifr, 0, sizeof ifr); + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name); + strlcpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)); - if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) { - printk("Failed to set interface, returned %d " - "(errno = %d)\n", err, errno); + err = simc_ioctl(fd, TUNSETIFF, &ifr); + if (err < 0) { + pr_err("Failed to set interface, returned %d (errno = %d)\n", + err, errno); simc_close(fd); return err; } @@ -217,27 +200,17 @@ static int tuntap_open(struct iss_net_private *lp) static void tuntap_close(struct iss_net_private *lp) { -#if 0 - if (lp->tp.info.tuntap.fixed_config) - iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name); -#endif simc_close(lp->tp.info.tuntap.fd); lp->tp.info.tuntap.fd = -1; } -static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb) +static int tuntap_read(struct iss_net_private *lp, struct sk_buff **skb) { -#if 0 - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if (*skb == NULL) - return -ENOMEM; -#endif - return simc_read(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER); } -static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb) +static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb) { return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len); } @@ -259,40 +232,36 @@ static int tuntap_poll(struct iss_net_private *lp) static int tuntap_probe(struct iss_net_private *lp, int index, char *init) { - const int len = strlen(TRANSPORT_TUNTAP_NAME); char *dev_name = NULL, *mac_str = NULL, *rem = NULL; /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */ - if (strncmp(init, TRANSPORT_TUNTAP_NAME, len)) + if (strncmp(init, TRANSPORT_TUNTAP_NAME, + sizeof(TRANSPORT_TUNTAP_NAME) - 1)) return 0; - if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') { - if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) { - printk("Extra garbage on specification : '%s'\n", rem); + init += sizeof(TRANSPORT_TUNTAP_NAME) - 1; + if (*init == ',') { + rem = split_if_spec(init + 1, &mac_str, &dev_name); + if (rem != NULL) { + pr_err("Extra garbage on specification : '%s'\n", rem); return 0; } } else if (*init != '\0') { - printk("Invalid argument: %s. Skipping device!\n", init); + pr_err("Invalid argument: %s. Skipping device!\n", init); return 0; } if (dev_name) { - strncpy(lp->tp.info.tuntap.dev_name, dev_name, - sizeof lp->tp.info.tuntap.dev_name); + strlcpy(lp->tp.info.tuntap.dev_name, dev_name, + sizeof(lp->tp.info.tuntap.dev_name)); lp->tp.info.tuntap.fixed_config = 1; } else strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME); -#if 0 - if (setup_etheraddr(mac_str, lp->mac)) - lp->have_mac = 1; -#endif lp->mtu = TRANSPORT_TUNTAP_MTU; - //lp->info.tuntap.gate_addr = gate_addr; - lp->tp.info.tuntap.fd = -1; lp->tp.open = tuntap_open; @@ -302,12 +271,7 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) lp->tp.protocol = tuntap_protocol; lp->tp.poll = tuntap_poll; - printk("TUN/TAP backend - "); -#if 0 - if (lp->host.gate_addr != NULL) - printk("IP = %s", lp->host.gate_addr); -#endif - printk("\n"); + pr_info("TUN/TAP backend -\n"); return 1; } @@ -327,7 +291,8 @@ static int iss_net_rx(struct net_device *dev) /* Try to allocate memory, if it fails, try again next round. */ - if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) { + skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER); + if (skb == NULL) { lp->stats.rx_dropped++; return 0; } @@ -347,7 +312,6 @@ static int iss_net_rx(struct net_device *dev) lp->stats.rx_bytes += skb->len; lp->stats.rx_packets++; - // netif_rx(skb); netif_rx_ni(skb); return pkt_len; } @@ -378,11 +342,11 @@ static int iss_net_poll(void) spin_unlock(&lp->lock); if (err < 0) { - printk(KERN_ERR "Device '%s' read returned %d, " - "shutting it down\n", lp->dev->name, err); + pr_err("Device '%s' read returned %d, shutting it down\n", + lp->dev->name, err); dev_close(lp->dev); } else { - // FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); + /* FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); */ } } @@ -393,14 +357,11 @@ static int iss_net_poll(void) static void iss_net_timer(unsigned long priv) { - struct iss_net_private* lp = (struct iss_net_private*) priv; + struct iss_net_private *lp = (struct iss_net_private *)priv; spin_lock(&lp->lock); - iss_net_poll(); - mod_timer(&lp->timer, jiffies + lp->timer_val); - spin_unlock(&lp->lock); } @@ -408,12 +369,13 @@ static void iss_net_timer(unsigned long priv) static int iss_net_open(struct net_device *dev) { struct iss_net_private *lp = netdev_priv(dev); - char addr[sizeof "255.255.255.255\0"]; + char addr[sizeof("255.255.255.255\0")]; int err; spin_lock(&lp->lock); - if ((err = lp->tp.open(lp)) < 0) + err = lp->tp.open(lp); + if (err < 0) goto out; if (!lp->have_mac) { @@ -448,7 +410,6 @@ out: static int iss_net_close(struct net_device *dev) { struct iss_net_private *lp = netdev_priv(dev); -printk("iss_net_close!\n"); netif_stop_queue(dev); spin_lock(&lp->lock); @@ -490,7 +451,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) } else { netif_start_queue(dev); - printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len); + pr_err("iss_net_start_xmit: failed(%d)\n", len); } spin_unlock_irqrestore(&lp->lock, flags); @@ -508,22 +469,10 @@ static struct net_device_stats *iss_net_get_stats(struct net_device *dev) static void iss_net_set_multicast_list(struct net_device *dev) { -#if 0 - if (dev->flags & IFF_PROMISC) - return; - else if (!netdev_mc_empty(dev)) - dev->flags |= IFF_ALLMULTI; - else - dev->flags &= ~IFF_ALLMULTI; -#endif } static void iss_net_tx_timeout(struct net_device *dev) { -#if 0 - dev->trans_start = jiffies; - netif_wake_queue(dev); -#endif } static int iss_net_set_mac(struct net_device *dev, void *addr) @@ -542,22 +491,6 @@ static int iss_net_set_mac(struct net_device *dev, void *addr) static int iss_net_change_mtu(struct net_device *dev, int new_mtu) { -#if 0 - struct iss_net_private *lp = netdev_priv(dev); - int err = 0; - - spin_lock(&lp->lock); - - // FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user); - - if (new_mtu < 0) - err = new_mtu; - else - dev->mtu = new_mtu; - - spin_unlock(&lp->lock); - return err; -#endif return -EINVAL; } @@ -582,7 +515,6 @@ static const struct net_device_ops iss_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = iss_net_change_mtu, .ndo_set_mac_address = iss_net_set_mac, - //.ndo_do_ioctl = iss_net_ioctl, .ndo_tx_timeout = iss_net_tx_timeout, .ndo_set_rx_mode = iss_net_set_multicast_list, }; @@ -593,24 +525,24 @@ static int iss_net_configure(int index, char *init) struct iss_net_private *lp; int err; - if ((dev = alloc_etherdev(sizeof *lp)) == NULL) { - printk(KERN_ERR "eth_configure: failed to allocate device\n"); + dev = alloc_etherdev(sizeof(*lp)); + if (dev == NULL) { + pr_err("eth_configure: failed to allocate device\n"); return 1; } /* Initialize private element. */ lp = netdev_priv(dev); - *lp = ((struct iss_net_private) { + *lp = (struct iss_net_private) { .device_list = LIST_HEAD_INIT(lp->device_list), .opened_list = LIST_HEAD_INIT(lp->opened_list), .lock = __SPIN_LOCK_UNLOCKED(lp.lock), .dev = dev, .index = index, - //.fd = -1, .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 }, .have_mac = 0, - }); + }; /* * Try all transport protocols. @@ -618,7 +550,7 @@ static int iss_net_configure(int index, char *init) */ if (!tuntap_probe(lp, index, init)) { - printk("Invalid arguments. Skipping device!\n"); + pr_err("Invalid arguments. Skipping device!\n"); goto errout; } @@ -641,14 +573,14 @@ static int iss_net_configure(int index, char *init) lp->pdev.id = index; lp->pdev.name = DRIVER_NAME; platform_device_register(&lp->pdev); - SET_NETDEV_DEV(dev,&lp->pdev.dev); + SET_NETDEV_DEV(dev, &lp->pdev.dev); /* * If this name ends up conflicting with an existing registered * netdevice, that is OK, register_netdev{,ice}() will notice this * and fail. */ - snprintf(dev->name, sizeof dev->name, "eth%d", index); + snprintf(dev->name, sizeof(dev->name), "eth%d", index); dev->netdev_ops = &iss_netdev_ops; dev->mtu = lp->mtu; @@ -660,7 +592,7 @@ static int iss_net_configure(int index, char *init) rtnl_unlock(); if (err) { - printk("Error registering net device!\n"); + pr_err("Error registering net device!\n"); /* XXX: should we call ->remove() here? */ free_netdev(dev); return 1; @@ -669,16 +601,11 @@ static int iss_net_configure(int index, char *init) init_timer(&lp->tl); lp->tl.function = iss_net_user_timer_expire; -#if 0 - if (lp->have_mac) - set_ether_mac(dev, lp->mac); -#endif return 0; errout: - // FIXME: unregister; free, etc.. + /* FIXME: unregister; free, etc.. */ return -EIO; - } /* ------------------------------------------------------------------------- */ @@ -717,7 +644,8 @@ static int __init iss_net_setup(char *str) printk(ERR "Device %d is negative\n", n); return 1; } - if (*(str = end) != '=') { + str = end; + if (*str != '=') { printk(ERR "Expected '=' after device number\n"); return 1; } @@ -739,7 +667,7 @@ static int __init iss_net_setup(char *str) new = alloc_bootmem(sizeof(*new)); if (new == NULL) { - printk("Alloc_bootmem failed\n"); + printk(ERR "Alloc_bootmem failed\n"); return 1; } -- cgit v1.2.3-18-g5258 From 8c8ad85f1f3ee1c2096a6b7b0892cabe4a956e31 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 16:05:45 +0400 Subject: xtensa: ISS: fix command line parameter name Now 'ethX=...' syntax can actually be used in kernel command line to specify network interfaces. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 6d9cc455eae..0c7c1d4141d 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -681,7 +681,7 @@ static int __init iss_net_setup(char *str) #undef ERR -__setup("eth=", iss_net_setup); +__setup("eth", iss_net_setup); /* * Initialize all ISS Ethernet devices previously registered in iss_net_setup. -- cgit v1.2.3-18-g5258 From 358b181003dbb30985331a77e753e1b05c05d87d Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 16:05:46 +0400 Subject: xtensa: ISS: init network interface name before the probe Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 0c7c1d4141d..3718cff3909 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -544,6 +544,13 @@ static int iss_net_configure(int index, char *init) .have_mac = 0, }; + /* + * If this name ends up conflicting with an existing registered + * netdevice, that is OK, register_netdev{,ice}() will notice this + * and fail. + */ + snprintf(dev->name, sizeof(dev->name), "eth%d", index); + /* * Try all transport protocols. * Note: more protocols can be added by adding '&& !X_init(lp, eth)'. @@ -575,13 +582,6 @@ static int iss_net_configure(int index, char *init) platform_device_register(&lp->pdev); SET_NETDEV_DEV(dev, &lp->pdev.dev); - /* - * If this name ends up conflicting with an existing registered - * netdevice, that is OK, register_netdev{,ice}() will notice this - * and fail. - */ - snprintf(dev->name, sizeof(dev->name), "eth%d", index); - dev->netdev_ops = &iss_netdev_ops; dev->mtu = lp->mtu; dev->watchdog_timeo = (HZ >> 1); -- cgit v1.2.3-18-g5258 From 8991fd88354f924cc3f4e6386c619fc39fb48f21 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 08:48:34 +0400 Subject: xtensa: ISS: drop IP setup, clean up MAC setup Without proper MAC setup network device doesn't work. IP setup is redundant and may be done with 'ip=...' kernel parameter. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 77 +++++++++++++++---------------------- 1 file changed, 31 insertions(+), 46 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 3718cff3909..f7709c7efca 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -81,9 +81,6 @@ struct iss_net_private { int index; int mtu; - unsigned char mac[ETH_ALEN]; - int have_mac; - struct { union { struct tuntap_info tuntap; @@ -123,44 +120,41 @@ static char *split_if_spec(char *str, ...) return str; } +/* Set Ethernet address of the specified device. */ -/* Return the IP address as a string for a given device. */ - -static void dev_ip_addr(void *d, char *buf, char *bin_buf) +static void setup_etheraddr(struct net_device *dev, char *str) { - struct net_device *dev = d; - struct in_device *ip = dev->ip_ptr; - struct in_ifaddr *in; - __be32 addr; - - if (ip == NULL || ip->ifa_list == NULL) { - pr_warn("Device not assigned an IP address!\n"); - return; - } + unsigned char *addr = dev->dev_addr; - in = ip->ifa_list; + if (str == NULL) + goto random; - addr = in->ifa_address; - sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, - (addr >> 16) & 0xff, addr >> 24); - - if (bin_buf) { - bin_buf[0] = addr & 0xff; - bin_buf[1] = (addr >> 8) & 0xff; - bin_buf[2] = (addr >> 16) & 0xff; - bin_buf[3] = addr >> 24; + if (!mac_pton(str, addr)) { + pr_err("%s: failed to parse '%s' as an ethernet address\n", + dev->name, str); + goto random; } + if (is_multicast_ether_addr(addr)) { + pr_err("%s: attempt to assign a multicast ethernet address\n", + dev->name); + goto random; + } + if (!is_valid_ether_addr(addr)) { + pr_err("%s: attempt to assign an invalid ethernet address\n", + dev->name); + goto random; + } + if (!is_local_ether_addr(addr)) + pr_warn("%s: assigning a globally valid ethernet address\n", + dev->name); + return; + +random: + pr_info("%s: choosing a random ethernet address\n", + dev->name); + eth_hw_addr_random(dev); } -/* Set Ethernet address of the specified device. */ - -static inline void set_ether_mac(void *d, unsigned char *addr) -{ - struct net_device *dev = d; - memcpy(dev->dev_addr, addr, ETH_ALEN); -} - - /* ======================= TUNTAP TRANSPORT INTERFACE ====================== */ static int tuntap_open(struct iss_net_private *lp) @@ -232,6 +226,7 @@ static int tuntap_poll(struct iss_net_private *lp) static int tuntap_probe(struct iss_net_private *lp, int index, char *init) { + struct net_device *dev = lp->dev; char *dev_name = NULL, *mac_str = NULL, *rem = NULL; /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */ @@ -259,6 +254,7 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) } else strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME); + setup_etheraddr(dev, mac_str); lp->mtu = TRANSPORT_TUNTAP_MTU; @@ -369,7 +365,6 @@ static void iss_net_timer(unsigned long priv) static int iss_net_open(struct net_device *dev) { struct iss_net_private *lp = netdev_priv(dev); - char addr[sizeof("255.255.255.255\0")]; int err; spin_lock(&lp->lock); @@ -378,11 +373,6 @@ static int iss_net_open(struct net_device *dev) if (err < 0) goto out; - if (!lp->have_mac) { - dev_ip_addr(dev, addr, &lp->mac[2]); - set_ether_mac(dev, lp->mac); - } - netif_start_queue(dev); /* clear buffer - it can happen that the host side of the interface @@ -540,8 +530,6 @@ static int iss_net_configure(int index, char *init) .lock = __SPIN_LOCK_UNLOCKED(lp.lock), .dev = dev, .index = index, - .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 }, - .have_mac = 0, }; /* @@ -561,10 +549,7 @@ static int iss_net_configure(int index, char *init) goto errout; } - printk(KERN_INFO "Netdevice %d ", index); - if (lp->have_mac) - printk("(%pM) ", lp->mac); - printk(": "); + pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr); /* sysfs register */ -- cgit v1.2.3-18-g5258 From f6ac5a177db24379e7a7a7d44b1ae7d1036042ec Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 16:05:48 +0400 Subject: xtensa: ISS: enable iss_net_set_mac This allows changing MAC address of the device. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index f7709c7efca..b33ed0c5354 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -467,15 +467,14 @@ static void iss_net_tx_timeout(struct net_device *dev) static int iss_net_set_mac(struct net_device *dev, void *addr) { -#if 0 struct iss_net_private *lp = netdev_priv(dev); struct sockaddr *hwaddr = addr; + if (!is_valid_ether_addr(hwaddr->sa_data)) + return -EADDRNOTAVAIL; spin_lock(&lp->lock); memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); spin_unlock(&lp->lock); -#endif - return 0; } -- cgit v1.2.3-18-g5258 From 35e14b443aa906ffb4ff8bd884e393c1bbdb6670 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 16:05:49 +0400 Subject: xtensa: ISS: always use fixed tuntap config The code doesn't handle dynamic TAP interface allocation, so there's no point tracking this case. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index b33ed0c5354..668ed624b2c 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -56,7 +56,6 @@ static LIST_HEAD(devices); struct tuntap_info { char dev_name[IFNAMSIZ]; - int fixed_config; int fd; }; @@ -164,11 +163,6 @@ static int tuntap_open(struct iss_net_private *lp) int err = -EINVAL; int fd; - /* We currently only support a fixed configuration. */ - - if (!lp->tp.info.tuntap.fixed_config) - return -EINVAL; - fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */ if (fd < 0) { pr_err("Failed to open /dev/net/tun, returned %d (errno = %d)\n", @@ -220,8 +214,7 @@ static int tuntap_poll(struct iss_net_private *lp) } /* - * Currently only a device name is supported. - * ethX=tuntap[,[mac address][,[device name]]] + * ethX=tuntap,[mac address],device name */ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) @@ -247,12 +240,13 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) return 0; } - if (dev_name) { - strlcpy(lp->tp.info.tuntap.dev_name, dev_name, - sizeof(lp->tp.info.tuntap.dev_name)); - lp->tp.info.tuntap.fixed_config = 1; - } else - strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME); + if (!dev_name) { + pr_err("%s: missing tuntap device name\n", dev->name); + return 0; + } + + strlcpy(lp->tp.info.tuntap.dev_name, dev_name, + sizeof(lp->tp.info.tuntap.dev_name)); setup_etheraddr(dev, mac_str); -- cgit v1.2.3-18-g5258 From a6e16b9aaf0df4b1de8853cad97f387ade9fa8f5 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 10 Nov 2013 16:05:51 +0400 Subject: xtensa: ISS: clean up diagnostic, increase verbosity Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 668ed624b2c..3aff4302f93 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -165,8 +165,8 @@ static int tuntap_open(struct iss_net_private *lp) fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */ if (fd < 0) { - pr_err("Failed to open /dev/net/tun, returned %d (errno = %d)\n", - fd, errno); + pr_err("%s: failed to open /dev/net/tun, returned %d (errno = %d)\n", + lp->dev->name, fd, errno); return fd; } @@ -176,8 +176,8 @@ static int tuntap_open(struct iss_net_private *lp) err = simc_ioctl(fd, TUNSETIFF, &ifr); if (err < 0) { - pr_err("Failed to set interface, returned %d (errno = %d)\n", - err, errno); + pr_err("%s: failed to set interface %s, returned %d (errno = %d)\n", + lp->dev->name, dev_name, err, errno); simc_close(fd); return err; } @@ -232,11 +232,13 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) if (*init == ',') { rem = split_if_spec(init + 1, &mac_str, &dev_name); if (rem != NULL) { - pr_err("Extra garbage on specification : '%s'\n", rem); + pr_err("%s: extra garbage on specification : '%s'\n", + dev->name, rem); return 0; } } else if (*init != '\0') { - pr_err("Invalid argument: %s. Skipping device!\n", init); + pr_err("%s: invalid argument: %s. Skipping device!\n", + dev->name, init); return 0; } @@ -261,8 +263,6 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) lp->tp.protocol = tuntap_protocol; lp->tp.poll = tuntap_poll; - pr_info("TUN/TAP backend -\n"); - return 1; } @@ -435,7 +435,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) } else { netif_start_queue(dev); - pr_err("iss_net_start_xmit: failed(%d)\n", len); + pr_err("%s: %s failed(%d)\n", dev->name, __func__, len); } spin_unlock_irqrestore(&lp->lock, flags); @@ -538,7 +538,8 @@ static int iss_net_configure(int index, char *init) */ if (!tuntap_probe(lp, index, init)) { - pr_err("Invalid arguments. Skipping device!\n"); + pr_err("%s: invalid arguments. Skipping device!\n", + dev->name); goto errout; } @@ -570,7 +571,7 @@ static int iss_net_configure(int index, char *init) rtnl_unlock(); if (err) { - pr_err("Error registering net device!\n"); + pr_err("%s: error registering net device!\n", dev->name); /* XXX: should we call ->remove() here? */ free_netdev(dev); return 1; -- cgit v1.2.3-18-g5258 From 220c062688c31bbf992921fca172ddd1e609f8f6 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 18 Nov 2013 06:46:43 +0200 Subject: xtensa: implement robust futex atomic uaccess ops This enables the set_robust_list(2) system call. Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/Kbuild | 1 - arch/xtensa/include/asm/futex.h | 147 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 arch/xtensa/include/asm/futex.h (limited to 'arch') diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 228d6aee3a1..5851db29158 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -8,7 +8,6 @@ generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h generic-y += fcntl.h -generic-y += futex.h generic-y += hardirq.h generic-y += ioctl.h generic-y += irq_regs.h diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h new file mode 100644 index 00000000000..b39531babec --- /dev/null +++ b/arch/xtensa/include/asm/futex.h @@ -0,0 +1,147 @@ +/* + * Atomic futex routines + * + * Based on the PowerPC implementataion + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Copyright (C) 2013 TangoTec Ltd. + * + * Baruch Siach + */ + +#ifndef _ASM_XTENSA_FUTEX_H +#define _ASM_XTENSA_FUTEX_H + +#ifdef __KERNEL__ + +#include +#include +#include + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile( \ + "1: l32i %0, %2, 0\n" \ + insn "\n" \ + " wsr %0, scompare1\n" \ + "2: s32c1i %1, %2, 0\n" \ + " bne %1, %0, 1b\n" \ + " movi %1, 0\n" \ + "3:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 4\n" \ + "4: .long 3b\n" \ + "5: l32r %0, 4b\n" \ + " movi %1, %3\n" \ + " jx %0\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .long 1b,5b,2b,5b\n" \ + " .previous\n" \ + : "=&r" (oldval), "=&r" (ret) \ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "memory") + +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + +#if !XCHAL_HAVE_S32C1I + return -ENOSYS; +#endif + + pagefault_disable(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("mov %1, %4", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %1, %0, %4", ret, oldval, uaddr, + oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %1, %0, %4", ret, oldval, uaddr, + oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("and %1, %0, %4", ret, oldval, uaddr, + ~oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %1, %0, %4", ret, oldval, uaddr, + oparg); + break; + default: + ret = -ENOSYS; + } + + pagefault_enable(); + + if (ret) + return ret; + + switch (cmp) { + case FUTEX_OP_CMP_EQ: return (oldval == cmparg); + case FUTEX_OP_CMP_NE: return (oldval != cmparg); + case FUTEX_OP_CMP_LT: return (oldval < cmparg); + case FUTEX_OP_CMP_GE: return (oldval >= cmparg); + case FUTEX_OP_CMP_LE: return (oldval <= cmparg); + case FUTEX_OP_CMP_GT: return (oldval > cmparg); + } + + return -ENOSYS; +} + +static inline int +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + u32 oldval, u32 newval) +{ + int ret = 0; + u32 prev; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + +#if !XCHAL_HAVE_S32C1I + return -ENOSYS; +#endif + + __asm__ __volatile__ ( + " # futex_atomic_cmpxchg_inatomic\n" + "1: l32i %1, %3, 0\n" + " mov %0, %5\n" + " wsr %1, scompare1\n" + "2: s32c1i %0, %3, 0\n" + "3:\n" + " .section .fixup,\"ax\"\n" + " .align 4\n" + "4: .long 3b\n" + "5: l32r %1, 4b\n" + " movi %0, %6\n" + " jx %1\n" + " .previous\n" + " .section __ex_table,\"a\"\n" + " .long 1b,5b,2b,5b\n" + " .previous\n" + : "+r" (ret), "=&r" (prev), "+m" (*uaddr) + : "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT) + : "memory"); + + *uval = prev; + return ret; +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_XTENSA_FUTEX_H */ -- cgit v1.2.3-18-g5258 From c4ee0af3fa0dc65f690fc908f02b8355f9576ea0 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:12 +0400 Subject: xtensa: remove NO_IRQ definitions These definitions (-1) were correct when used as a hardware IRQ number, but are incorrect as a mapped IRQ number. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/xtfpga/include/platform/hardware.h | 4 ---- arch/xtensa/variants/s6000/include/variant/irq.h | 1 - 2 files changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h index 4416773cbde..4b43ff133be 100644 --- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h +++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h @@ -15,10 +15,6 @@ #ifndef __XTENSA_XTAVNET_HARDWARE_H #define __XTENSA_XTAVNET_HARDWARE_H -/* By default NO_IRQ is defined to 0 in Linux, but we use the - interrupt 0 for UART... */ -#define NO_IRQ -1 - /* Memory configuration. */ #define PLATFORM_DEFAULT_MEM_START 0x00000000 diff --git a/arch/xtensa/variants/s6000/include/variant/irq.h b/arch/xtensa/variants/s6000/include/variant/irq.h index 97d6fc48def..39ca751a625 100644 --- a/arch/xtensa/variants/s6000/include/variant/irq.h +++ b/arch/xtensa/variants/s6000/include/variant/irq.h @@ -1,7 +1,6 @@ #ifndef _XTENSA_S6000_IRQ_H #define _XTENSA_S6000_IRQ_H -#define NO_IRQ (-1) #define VARIANT_NR_IRQS 8 /* GPIO interrupts */ extern void variant_irq_enable(unsigned int irq); -- cgit v1.2.3-18-g5258 From ff3849059d787ab2072032800e553c9022c9ab54 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:13 +0400 Subject: xtensa: fix build warning in 64-bit build environment This fixes the following build warnings: arch/xtensa/mm/misc.S: Assembler messages: arch/xtensa/mm/misc.S:143: Warning: value 0xffffffff30000106 truncated to 0x30000106 arch/xtensa/mm/misc.S:197: Warning: value 0xffffffff30000106 truncated to 0x30000106 Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/mm/misc.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index d97ed1ba7b0..1f68558dbcc 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S @@ -140,7 +140,7 @@ ENTRY(clear_user_page) /* Setup a temporary DTLB with the color of the VPN */ - movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE) + movi a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff movi a5, TLBTEMP_BASE_1 # virt add a6, a2, a4 # ppn add a2, a5, a3 # add 'color' @@ -194,7 +194,7 @@ ENTRY(copy_user_page) or a9, a9, a8 slli a4, a4, PAGE_SHIFT s32i a9, a5, PAGE_FLAGS - movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE) + movi a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff beqz a6, 1f -- cgit v1.2.3-18-g5258 From 5515daa9ca5a0992cc1c55d4c6c7ddb116e829b4 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:15 +0400 Subject: xtensa: fix arch spinlock function names Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/spinlock.h | 31 +++++++++++++++++-------------- arch/xtensa/include/asm/spinlock_types.h | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 arch/xtensa/include/asm/spinlock_types.h (limited to 'arch') diff --git a/arch/xtensa/include/asm/spinlock.h b/arch/xtensa/include/asm/spinlock.h index 03975906b36..1d95fa5dcd1 100644 --- a/arch/xtensa/include/asm/spinlock.h +++ b/arch/xtensa/include/asm/spinlock.h @@ -28,13 +28,13 @@ * 1 somebody owns the spinlock */ -#define __raw_spin_is_locked(x) ((x)->slock != 0) -#define __raw_spin_unlock_wait(lock) \ - do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) +#define arch_spin_is_locked(x) ((x)->slock != 0) +#define arch_spin_unlock_wait(lock) \ + do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0) -#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) -static inline void __raw_spin_lock(raw_spinlock_t *lock) +static inline void arch_spin_lock(arch_spinlock_t *lock) { unsigned long tmp; @@ -51,7 +51,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) /* Returns 1 if the lock is obtained, 0 otherwise. */ -static inline int __raw_spin_trylock(raw_spinlock_t *lock) +static inline int arch_spin_trylock(arch_spinlock_t *lock) { unsigned long tmp; @@ -67,7 +67,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock) return tmp == 0 ? 1 : 0; } -static inline void __raw_spin_unlock(raw_spinlock_t *lock) +static inline void arch_spin_unlock(arch_spinlock_t *lock) { unsigned long tmp; @@ -96,9 +96,9 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock) * 0x80000000 one writer owns the rwlock, no other writers, no readers */ -#define __raw_write_can_lock(x) ((x)->lock == 0) +#define arch_write_can_lock(x) ((x)->lock == 0) -static inline void __raw_write_lock(raw_rwlock_t *rw) +static inline void arch_write_lock(arch_rwlock_t *rw) { unsigned long tmp; @@ -116,7 +116,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw) /* Returns 1 if the lock is obtained, 0 otherwise. */ -static inline int __raw_write_trylock(raw_rwlock_t *rw) +static inline int arch_write_trylock(arch_rwlock_t *rw) { unsigned long tmp; @@ -133,7 +133,7 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw) return tmp == 0 ? 1 : 0; } -static inline void __raw_write_unlock(raw_rwlock_t *rw) +static inline void arch_write_unlock(arch_rwlock_t *rw) { unsigned long tmp; @@ -145,7 +145,7 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) : "memory"); } -static inline void __raw_read_lock(raw_rwlock_t *rw) +static inline void arch_read_lock(arch_rwlock_t *rw) { unsigned long tmp; unsigned long result; @@ -164,7 +164,7 @@ static inline void __raw_read_lock(raw_rwlock_t *rw) /* Returns 1 if the lock is obtained, 0 otherwise. */ -static inline int __raw_read_trylock(raw_rwlock_t *rw) +static inline int arch_read_trylock(arch_rwlock_t *rw) { unsigned long result; unsigned long tmp; @@ -184,7 +184,7 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw) return result == 0; } -static inline void __raw_read_unlock(raw_rwlock_t *rw) +static inline void arch_read_unlock(arch_rwlock_t *rw) { unsigned long tmp1, tmp2; @@ -199,4 +199,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw) : "memory"); } +#define arch_read_lock_flags(lock, flags) arch_read_lock(lock) +#define arch_write_lock_flags(lock, flags) arch_write_lock(lock) + #endif /* _XTENSA_SPINLOCK_H */ diff --git a/arch/xtensa/include/asm/spinlock_types.h b/arch/xtensa/include/asm/spinlock_types.h new file mode 100644 index 00000000000..7ec5ce10c9e --- /dev/null +++ b/arch/xtensa/include/asm/spinlock_types.h @@ -0,0 +1,20 @@ +#ifndef __ASM_SPINLOCK_TYPES_H +#define __ASM_SPINLOCK_TYPES_H + +#ifndef __LINUX_SPINLOCK_TYPES_H +# error "please don't include this file directly" +#endif + +typedef struct { + volatile unsigned int slock; +} arch_spinlock_t; + +#define __ARCH_SPIN_LOCK_UNLOCKED { 0 } + +typedef struct { + volatile unsigned int lock; +} arch_rwlock_t; + +#define __ARCH_RW_LOCK_UNLOCKED { 0 } + +#endif -- cgit v1.2.3-18-g5258 From 01e3b3cb2d70ca9d95769e863ca71a85f84c3917 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:16 +0400 Subject: xtensa: fix __delay for small loop count Avoid __delay counter underflow for loop counts < 2. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/delay.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/include/asm/delay.h b/arch/xtensa/include/asm/delay.h index 3899610c1df..742b89f3ca2 100644 --- a/arch/xtensa/include/asm/delay.h +++ b/arch/xtensa/include/asm/delay.h @@ -19,9 +19,12 @@ extern unsigned long loops_per_jiffy; static inline void __delay(unsigned long loops) { - /* 2 cycles per loop. */ - __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b" - : "=r" (loops) : "0" (loops)); + if (__builtin_constant_p(loops) && loops < 2) + __asm__ __volatile__ ("nop"); + else if (loops >= 2) + /* 2 cycles per loop. */ + __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b" + : "+r" (loops)); } /* For SMP/NUMA systems, change boot_cpu_data to something like -- cgit v1.2.3-18-g5258 From 496543c4f1afd0eb1548054838058bf30464ccc9 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:17 +0400 Subject: xtensa: enable HAVE_IRQ_TIME_ACCOUNTING Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8d24dcb7cda..fb140ae3860 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -19,6 +19,7 @@ config XTENSA select IRQ_DOMAIN select HAVE_OPROFILE select HAVE_FUNCTION_TRACER + select HAVE_IRQ_TIME_ACCOUNTING help Xtensa processors are 32-bit RISC machines designed by Tensilica primarily for embedded systems. These processors are both -- cgit v1.2.3-18-g5258 From 0fb4040e6ed69b62e64ec781694882309edbf33c Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 17 Oct 2013 02:42:18 +0400 Subject: xtensa: mark ccount as continuous clocksource This allows ccount to be used as highres timer. Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/time.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 9af3dd88ad7..26eb6a9e8d4 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -46,6 +46,7 @@ static struct clocksource ccount_clocksource = { .rating = 200, .read = ccount_read, .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; static int ccount_timer_set_next_event(unsigned long delta, -- cgit v1.2.3-18-g5258 From 6235153170db777296b6a47181056dd30a027d03 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:19 +0400 Subject: xtensa: update clockevent setup for SMP Provide per-cpu ccount_timer objects and use them appropriately. Extract per-cpu clockevent setup function. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/time.c | 54 +++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 26eb6a9e8d4..4ce7aae39e6 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -53,18 +53,12 @@ static int ccount_timer_set_next_event(unsigned long delta, struct clock_event_device *dev); static void ccount_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt); -static struct ccount_timer_t { +struct ccount_timer { struct clock_event_device evt; int irq_enabled; -} ccount_timer = { - .evt = { - .name = "ccount_clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 300, - .set_next_event = ccount_timer_set_next_event, - .set_mode = ccount_timer_set_mode, - }, + char name[24]; }; +static DEFINE_PER_CPU(struct ccount_timer, ccount_timer); static int ccount_timer_set_next_event(unsigned long delta, struct clock_event_device *dev) @@ -85,8 +79,8 @@ static int ccount_timer_set_next_event(unsigned long delta, static void ccount_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - struct ccount_timer_t *timer = - container_of(evt, struct ccount_timer_t, evt); + struct ccount_timer *timer = + container_of(evt, struct ccount_timer, evt); /* * There is no way to disable the timer interrupt at the device level, @@ -118,9 +112,28 @@ static struct irqaction timer_irqaction = { .handler = timer_interrupt, .flags = IRQF_TIMER, .name = "timer", - .dev_id = &ccount_timer, }; +void local_timer_setup(unsigned cpu) +{ + struct ccount_timer *timer = &per_cpu(ccount_timer, cpu); + struct clock_event_device *clockevent = &timer->evt; + + timer->irq_enabled = 1; + clockevent->name = timer->name; + snprintf(timer->name, sizeof(timer->name), "ccount_clockevent_%u", cpu); + clockevent->features = CLOCK_EVT_FEAT_ONESHOT; + clockevent->rating = 300; + clockevent->set_next_event = ccount_timer_set_next_event; + clockevent->set_mode = ccount_timer_set_mode; + clockevent->cpumask = cpumask_of(cpu); + clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); + if (WARN(!clockevent->irq, "error: can't map timer irq")) + return; + clockevents_config_and_register(clockevent, ccount_freq, + 0xf, 0xffffffff); +} + void __init time_init(void) { #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT @@ -132,16 +145,8 @@ void __init time_init(void) ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL; #endif clocksource_register_hz(&ccount_clocksource, ccount_freq); - - ccount_timer.evt.cpumask = cpumask_of(0); - ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT); - if (WARN(!ccount_timer.evt.irq, "error: can't map timer irq")) - return; - clockevents_config_and_register(&ccount_timer.evt, ccount_freq, 0xf, - 0xffffffff); - setup_irq(ccount_timer.evt.irq, &timer_irqaction); - ccount_timer.irq_enabled = 1; - + local_timer_setup(0); + setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction); setup_sched_clock(ccount_sched_clock_read, 32, ccount_freq); } @@ -149,10 +154,9 @@ void __init time_init(void) * The timer interrupt is called HZ times per second. */ -irqreturn_t timer_interrupt (int irq, void *dev_id) +irqreturn_t timer_interrupt(int irq, void *dev_id) { - struct ccount_timer_t *timer = dev_id; - struct clock_event_device *evt = &timer->evt; + struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; evt->event_handler(evt); -- cgit v1.2.3-18-g5258 From 59970753536d98d33efcbe4f119ad8e3e399a46b Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:20 +0400 Subject: xtensa: call check_s32c1i after trap_init Otherwise exceptions may occur prior to exception handling mechanism initialization, resulting in silently dead system. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/setup.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 6e2b6638122..9bc6f064489 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -354,7 +354,8 @@ static inline int probed_compare_swap(int *v, int cmp, int set) /* Handle probed exception */ -void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) +static void __init do_probed_exception(struct pt_regs *regs, + unsigned long exccause) { if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ regs->pc += 3; /* skip the s32c1i instruction */ @@ -366,7 +367,7 @@ void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) /* Simple test of S32C1I (soc bringup assist) */ -void __init check_s32c1i(void) +static int __init check_s32c1i(void) { int n, cause1, cause2; void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ @@ -421,24 +422,21 @@ void __init check_s32c1i(void) trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); + return 0; } #else /* XCHAL_HAVE_S32C1I */ /* This condition should not occur with a commercially deployed processor. Display reminder for early engr test or demo chips / FPGA bitstreams */ -void __init check_s32c1i(void) +static int __init check_s32c1i(void) { pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); + return 0; } #endif /* XCHAL_HAVE_S32C1I */ -#else /* CONFIG_S32C1I_SELFTEST */ - -void __init check_s32c1i(void) -{ -} - +early_initcall(check_s32c1i); #endif /* CONFIG_S32C1I_SELFTEST */ @@ -447,8 +445,6 @@ void __init setup_arch(char **cmdline_p) strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; - check_s32c1i(); - /* Reserve some memory regions */ #ifdef CONFIG_BLK_DEV_INITRD -- cgit v1.2.3-18-g5258 From c8f3a7dc0102fc9f89cc373c6dd7beb49916a695 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:21 +0400 Subject: xtensa: move init_mmu declaration to mmu_context.h Secondary CPUs need this declaration to initialize their MMUs. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/mmu_context.h | 6 ++++++ arch/xtensa/kernel/setup.c | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/include/asm/mmu_context.h b/arch/xtensa/include/asm/mmu_context.h index d43525a286b..86292c28674 100644 --- a/arch/xtensa/include/asm/mmu_context.h +++ b/arch/xtensa/include/asm/mmu_context.h @@ -49,6 +49,12 @@ extern unsigned long asid_cache; #define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1) #define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8)) +#ifdef CONFIG_MMU +void init_mmu(void); +#else +static inline void init_mmu(void) { } +#endif + static inline void set_rasid_register (unsigned long val) { __asm__ __volatile__ (" wsr %0, rasid\n\t" diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 9bc6f064489..3d353140c2d 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -37,6 +37,7 @@ #endif #include +#include #include #include #include @@ -85,12 +86,6 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; sysmem_info_t __initdata sysmem; -#ifdef CONFIG_MMU -extern void init_mmu(void); -#else -static inline void init_mmu(void) { } -#endif - extern int mem_reserve(unsigned long, unsigned long, int); extern void bootmem_init(void); extern void zones_init(void); -- cgit v1.2.3-18-g5258 From cbd1de2e8e46207cead11034f92ea8a018b11189 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 1 Dec 2013 12:59:49 +0400 Subject: xtensa: move built-in PIC to drivers/irqchip Extract xtensa built-in interrupt controller implementation from xtensa/kernel/irq.c and move it to other irqchips, providing way to instantiate it from the device tree. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/boot/dts/xtfpga.dtsi | 2 +- arch/xtensa/include/asm/irq.h | 7 ++ arch/xtensa/kernel/irq.c | 137 +++++++++------------------------------ 3 files changed, 38 insertions(+), 108 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi index 7eda6ecf7ee..b042c3f508e 100644 --- a/arch/xtensa/boot/dts/xtfpga.dtsi +++ b/arch/xtensa/boot/dts/xtfpga.dtsi @@ -26,7 +26,7 @@ }; pic: pic { - compatible = "xtensa,pic"; + compatible = "cdns,xtensa-pic"; /* one cell: internal irq number, * two cells: second cell == 0: internal irq number * second cell == 1: external irq number diff --git a/arch/xtensa/include/asm/irq.h b/arch/xtensa/include/asm/irq.h index 4c0ccc9c4f4..16464f2f8ec 100644 --- a/arch/xtensa/include/asm/irq.h +++ b/arch/xtensa/include/asm/irq.h @@ -43,5 +43,12 @@ static __inline__ int irq_canonicalize(int irq) } struct irqaction; +struct irq_domain; + +int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize, + unsigned long int_irq, unsigned long ext_irq, + unsigned long *out_hwirq, unsigned int *out_type); +int xtensa_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw); +unsigned xtensa_map_ext_irq(unsigned ext_irq); #endif /* _XTENSA_IRQ_H */ diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 6f4f9749cff..ada1e4893dd 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -18,28 +18,20 @@ #include #include #include +#include +#include #include #include #include #include -static unsigned int cached_irq_mask; - atomic_t irq_err_count; -static struct irq_domain *root_domain; - -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ - asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - int irq = irq_find_mapping(root_domain, hwirq); + int irq = irq_find_mapping(NULL, hwirq); if (hwirq >= NR_IRQS) { printk(KERN_EMERG "%s: cannot handle IRQ %d\n", @@ -74,83 +66,57 @@ int arch_show_interrupts(struct seq_file *p, int prec) return 0; } -static void xtensa_irq_mask(struct irq_data *d) -{ - cached_irq_mask &= ~(1 << d->hwirq); - set_sr (cached_irq_mask, intenable); -} - -static void xtensa_irq_unmask(struct irq_data *d) -{ - cached_irq_mask |= 1 << d->hwirq; - set_sr (cached_irq_mask, intenable); -} - -static void xtensa_irq_enable(struct irq_data *d) -{ - variant_irq_enable(d->hwirq); - xtensa_irq_unmask(d); -} - -static void xtensa_irq_disable(struct irq_data *d) -{ - xtensa_irq_mask(d); - variant_irq_disable(d->hwirq); -} - -static void xtensa_irq_ack(struct irq_data *d) -{ - set_sr(1 << d->hwirq, intclear); -} - -static int xtensa_irq_retrigger(struct irq_data *d) +int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize, + unsigned long int_irq, unsigned long ext_irq, + unsigned long *out_hwirq, unsigned int *out_type) { - set_sr(1 << d->hwirq, intset); - return 1; + if (WARN_ON(intsize < 1 || intsize > 2)) + return -EINVAL; + if (intsize == 2 && intspec[1] == 1) { + int_irq = xtensa_map_ext_irq(ext_irq); + if (int_irq < XCHAL_NUM_INTERRUPTS) + *out_hwirq = int_irq; + else + return -EINVAL; + } else { + *out_hwirq = int_irq; + } + *out_type = IRQ_TYPE_NONE; + return 0; } -static struct irq_chip xtensa_irq_chip = { - .name = "xtensa", - .irq_enable = xtensa_irq_enable, - .irq_disable = xtensa_irq_disable, - .irq_mask = xtensa_irq_mask, - .irq_unmask = xtensa_irq_unmask, - .irq_ack = xtensa_irq_ack, - .irq_retrigger = xtensa_irq_retrigger, -}; - -static int xtensa_irq_map(struct irq_domain *d, unsigned int irq, +int xtensa_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { + struct irq_chip *irq_chip = d->host_data; u32 mask = 1 << hw; if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) { - irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, + irq_set_chip_and_handler_name(irq, irq_chip, handle_simple_irq, "level"); irq_set_status_flags(irq, IRQ_LEVEL); } else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) { - irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, + irq_set_chip_and_handler_name(irq, irq_chip, handle_edge_irq, "edge"); irq_clear_status_flags(irq, IRQ_LEVEL); } else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) { - irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, + irq_set_chip_and_handler_name(irq, irq_chip, handle_level_irq, "level"); irq_set_status_flags(irq, IRQ_LEVEL); } else if (mask & XCHAL_INTTYPE_MASK_TIMER) { - irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, - handle_edge_irq, "edge"); + irq_set_chip_and_handler_name(irq, irq_chip, + handle_percpu_irq, "timer"); irq_clear_status_flags(irq, IRQ_LEVEL); } else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */ /* XCHAL_INTTYPE_MASK_NMI */ - - irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, + irq_set_chip_and_handler_name(irq, irq_chip, handle_level_irq, "level"); irq_set_status_flags(irq, IRQ_LEVEL); } return 0; } -static unsigned map_ext_irq(unsigned ext_irq) +unsigned xtensa_map_ext_irq(unsigned ext_irq) { unsigned mask = XCHAL_INTTYPE_MASK_EXTERN_EDGE | XCHAL_INTTYPE_MASK_EXTERN_LEVEL; @@ -163,55 +129,12 @@ static unsigned map_ext_irq(unsigned ext_irq) return XCHAL_NUM_INTERRUPTS; } -/* - * Device Tree IRQ specifier translation function which works with one or - * two cell bindings. First cell value maps directly to the hwirq number. - * Second cell if present specifies whether hwirq number is external (1) or - * internal (0). - */ -int xtensa_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, - const u32 *intspec, unsigned int intsize, - unsigned long *out_hwirq, unsigned int *out_type) -{ - if (WARN_ON(intsize < 1 || intsize > 2)) - return -EINVAL; - if (intsize == 2 && intspec[1] == 1) { - unsigned int_irq = map_ext_irq(intspec[0]); - if (int_irq < XCHAL_NUM_INTERRUPTS) - *out_hwirq = int_irq; - else - return -EINVAL; - } else { - *out_hwirq = intspec[0]; - } - *out_type = IRQ_TYPE_NONE; - return 0; -} - -static const struct irq_domain_ops xtensa_irq_domain_ops = { - .xlate = xtensa_irq_domain_xlate, - .map = xtensa_irq_map, -}; - void __init init_IRQ(void) { - struct device_node *intc = NULL; - - cached_irq_mask = 0; - set_sr(~0, intclear); - #ifdef CONFIG_OF - /* The interrupt controller device node is mandatory */ - intc = of_find_compatible_node(NULL, NULL, "xtensa,pic"); - BUG_ON(!intc); - - root_domain = irq_domain_add_linear(intc, NR_IRQS, - &xtensa_irq_domain_ops, NULL); + irqchip_init(); #else - root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0, - &xtensa_irq_domain_ops, NULL); + xtensa_pic_init_legacy(NULL); #endif - irq_set_default_host(root_domain); - variant_init_irq(); } -- cgit v1.2.3-18-g5258 From 996232393bcdfff49de31e1bc1c431fd8bce9ccb Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:23 +0400 Subject: xtensa: clean up do_interrupt/do_IRQ - set up irq registers and call irq_enter/irq_exit once for each kernel entry due to interrupt; - don't attempt to clear current IRQ in the do_interrupt, IRQ handler will take care of it; - find pending interrupt with highest priority before every ISR invocation. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/irq.c | 6 ------ arch/xtensa/kernel/traps.c | 23 +++++++++-------------- 2 files changed, 9 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index ada1e4893dd..3cef58e2833 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -30,7 +30,6 @@ atomic_t irq_err_count; asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) { - struct pt_regs *old_regs = set_irq_regs(regs); int irq = irq_find_mapping(NULL, hwirq); if (hwirq >= NR_IRQS) { @@ -38,8 +37,6 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) __func__, hwirq); } - irq_enter(); - #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than 1KB free? */ { @@ -54,9 +51,6 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) } #endif generic_handle_irq(irq); - - irq_exit(); - set_irq_regs(old_regs); } int arch_show_interrupts(struct seq_file *p, int prec) diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 3e8a05c874c..3dbe8648df1 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -212,6 +212,9 @@ void do_interrupt(struct pt_regs *regs) XCHAL_INTLEVEL6_MASK, XCHAL_INTLEVEL7_MASK, }; + struct pt_regs *old_regs = set_irq_regs(regs); + + irq_enter(); for (;;) { unsigned intread = get_sr(interrupt); @@ -227,21 +230,13 @@ void do_interrupt(struct pt_regs *regs) } if (level == 0) - return; - - /* - * Clear the interrupt before processing, in case it's - * edge-triggered or software-generated - */ - while (int_at_level) { - unsigned i = __ffs(int_at_level); - unsigned mask = 1 << i; - - int_at_level ^= mask; - set_sr(mask, intclear); - do_IRQ(i, regs); - } + break; + + do_IRQ(__ffs(int_at_level), regs); } + + irq_exit(); + set_irq_regs(old_regs); } /* -- cgit v1.2.3-18-g5258 From bae07f8a9dfaf6268f2fba5522b70bce6fc7d718 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 17 Oct 2013 02:42:24 +0400 Subject: xtensa: clear timer IRQ unconditionally in its handler PIC irq_ack doesn't clear timer IRQ, because timer interrupt handler usually set up new timer by writing to ccompare register and thus clearing timer IRQ. However timer may not be set up in the IRQ handler, e.g. with tickless idle on SMP, or when CPU is going offline, leaving timer IRQ raised and making do_interrupt attempting to handle it forever. To fix this always write current value of ccompare SR chosen to be linux timer back to that SR on entry to timer interrupt handler. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/time.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 4ce7aae39e6..60dcb3fcaea 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -158,6 +158,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; + set_linux_timer(get_linux_timer()); evt->event_handler(evt); /* Allow platform to do something useful (Wdog). */ -- cgit v1.2.3-18-g5258 From 26a8e96a8b37e8070fa9dcb1b7490cf4d4492d50 Mon Sep 17 00:00:00 2001 From: Max Filippov