From 87db73aebf55554fefaa3eade0a28f282a1511b8 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 7 Aug 2015 09:36:54 +0100 Subject: efi: Add support for EFI_MEMORY_RO attribute introduced by UEFIv2.5 The UEFI spec v2.5 introduces a new memory attribute EFI_MEMORY_RO, which is now the preferred attribute to convey that the nature of the contents of such a region allows it to be mapped read-only (i.e., it contains .text and .rodata only). The specification of the existing EFI_MEMORY_WP attribute has been updated to align more closely with its common use as a cacheability attribute rather than a permission attribute. Add the #define and add the attribute to the memory map dumping routine. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Reviewed-by: Laszlo Ersek Cc: H. Peter Anvin Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1438936621-5215-1-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- include/linux/efi.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/efi.h b/include/linux/efi.h index 85ef051ac6fb..26ca9e2fd30e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -99,6 +99,7 @@ typedef struct { #define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ #define EFI_MEMORY_MORE_RELIABLE \ ((u64)0x0000000000010000ULL) /* higher reliability */ +#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ #define EFI_MEMORY_DESCRIPTOR_VERSION 1 -- cgit v1.3-6-gb490 From a0175b9c76f59c1f5706f986d690e27ba06363dd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 12 Aug 2015 10:22:41 +0200 Subject: iio: st_sensors: add debugfs register read hook This adds a debugfs hook to read/write registers in the ST sensors using debugfs. Proved to be awesome help when trying to debug why IRQs do not arrive. Signed-off-by: Linus Walleij Acked-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 1 + drivers/iio/common/st_sensors/st_sensors_core.c | 22 ++++++++++++++++++++++ drivers/iio/gyro/st_gyro_core.c | 1 + drivers/iio/magnetometer/st_magn_core.c | 1 + drivers/iio/pressure/st_pressure_core.c | 1 + include/linux/iio/common/st_sensors.h | 4 ++++ 6 files changed, 30 insertions(+) (limited to 'include') diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index ff30f8806880..dab8b76c1427 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -618,6 +618,7 @@ static const struct iio_info accel_info = { .attrs = &st_accel_attribute_group, .read_raw = &st_accel_read_raw, .write_raw = &st_accel_write_raw, + .debugfs_reg_access = &st_sensors_debugfs_reg_access, }; #ifdef CONFIG_IIO_TRIGGER diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 2e7fdb502645..25258e2c1a82 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -44,6 +44,28 @@ st_sensors_write_data_with_mask_error: return err; } +int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct st_sensor_data *sdata = iio_priv(indio_dev); + u8 readdata; + int err; + + if (!readval) + return sdata->tf->write_byte(&sdata->tb, sdata->dev, + (u8)reg, (u8)writeval); + + err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata); + if (err < 0) + return err; + + *readval = (unsigned)readdata; + + return 0; +} +EXPORT_SYMBOL(st_sensors_debugfs_reg_access); + static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings, unsigned int odr, struct st_sensor_odr_avl *odr_out) { diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 4b993a5bc9a1..02eddcebeea3 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -383,6 +383,7 @@ static const struct iio_info gyro_info = { .attrs = &st_gyro_attribute_group, .read_raw = &st_gyro_read_raw, .write_raw = &st_gyro_write_raw, + .debugfs_reg_access = &st_sensors_debugfs_reg_access, }; #ifdef CONFIG_IIO_TRIGGER diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index f8dc4b85d70c..b27f0146647b 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -560,6 +560,7 @@ static const struct iio_info magn_info = { .attrs = &st_magn_attribute_group, .read_raw = &st_magn_read_raw, .write_raw = &st_magn_write_raw, + .debugfs_reg_access = &st_sensors_debugfs_reg_access, }; #ifdef CONFIG_IIO_TRIGGER diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index eb41d2b92c24..b39a2fb0671c 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -400,6 +400,7 @@ static const struct iio_info press_info = { .attrs = &st_press_attribute_group, .read_raw = &st_press_read_raw, .write_raw = &st_press_write_raw, + .debugfs_reg_access = &st_sensors_debugfs_reg_access, }; #ifdef CONFIG_IIO_TRIGGER diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 3c17cd7fdf06..2fe939c73cd2 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -271,6 +271,10 @@ void st_sensors_power_enable(struct iio_dev *indio_dev); void st_sensors_power_disable(struct iio_dev *indio_dev); +int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval); + int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr); int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable); -- cgit v1.3-6-gb490 From 735ad074ffa72ccc4fdba8e54eb024df95545e7d Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Thu, 20 Aug 2015 22:37:39 +0300 Subject: iio: Support triggered events Support triggered events. This is useful for chips that don't have their own interrupt sources. It allows to use generic/standalone iio triggers for those drivers. Signed-off-by: Vladimir Barinov Signed-off-by: Jonathan Cameron --- drivers/iio/Kconfig | 6 +++ drivers/iio/Makefile | 2 + drivers/iio/industrialio-core.c | 4 +- drivers/iio/industrialio-trigger.c | 12 +++++- drivers/iio/industrialio-triggered-event.c | 68 ++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 3 ++ include/linux/iio/triggered_event.h | 11 +++++ 7 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 drivers/iio/industrialio-triggered-event.c create mode 100644 include/linux/iio/triggered_event.h (limited to 'include') diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 3c6c6e28a60a..6fe0d6524c9c 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -38,6 +38,12 @@ config IIO_CONSUMERS_PER_TRIGGER This value controls the maximum number of consumers that a given trigger may handle. Default is 2. +config IIO_TRIGGERED_EVENT + tristate + select IIO_TRIGGER + help + Provides helper functions for setting up triggered events. + source "drivers/iio/accel/Kconfig" source "drivers/iio/adc/Kconfig" source "drivers/iio/amplifiers/Kconfig" diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 7ddb988338ec..40995f366843 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -7,6 +7,8 @@ industrialio-y := industrialio-core.o industrialio-event.o inkern.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o +obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o + obj-y += accel/ obj-y += adc/ obj-y += amplifiers/ diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index b347524d1b6d..bef690ed0480 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -962,7 +962,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) static void iio_dev_release(struct device *device) { struct iio_dev *indio_dev = dev_to_iio_dev(device); - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) + if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED)) iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_eventset(indio_dev); iio_device_unregister_sysfs(indio_dev); @@ -1243,7 +1243,7 @@ int iio_device_register(struct iio_dev *indio_dev) "Failed to register event set\n"); goto error_free_sysfs; } - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) + if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED)) iio_device_register_trigger_consumer(indio_dev); if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 570606c2adbd..ae2806aafb72 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -366,10 +366,18 @@ static ssize_t iio_trigger_write_current(struct device *dev, indio_dev->trig = trig; - if (oldtrig) + if (oldtrig) { + if (indio_dev->modes & INDIO_EVENT_TRIGGERED) + iio_trigger_detach_poll_func(oldtrig, + indio_dev->pollfunc_event); iio_trigger_put(oldtrig); - if (indio_dev->trig) + } + if (indio_dev->trig) { iio_trigger_get(indio_dev->trig); + if (indio_dev->modes & INDIO_EVENT_TRIGGERED) + iio_trigger_attach_poll_func(indio_dev->trig, + indio_dev->pollfunc_event); + } return len; } diff --git a/drivers/iio/industrialio-triggered-event.c b/drivers/iio/industrialio-triggered-event.c new file mode 100644 index 000000000000..8cc254fac16a --- /dev/null +++ b/drivers/iio/industrialio-triggered-event.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 Cogent Embedded, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +/** + * iio_triggered_event_setup() - Setup pollfunc_event for triggered event + * @indio_dev: IIO device structure + * @h: Function which will be used as pollfunc_event top half + * @thread: Function which will be used as pollfunc_event bottom half + * + * This function combines some common tasks which will normally be performed + * when setting up a triggered event. It will allocate the pollfunc_event and + * set mode to use it for triggered event. + * + * Before calling this function the indio_dev structure should already be + * completely initialized, but not yet registered. In practice this means that + * this function should be called right before iio_device_register(). + * + * To free the resources allocated by this function call + * iio_triggered_event_cleanup(). + */ +int iio_triggered_event_setup(struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p)) +{ + indio_dev->pollfunc_event = iio_alloc_pollfunc(h, + thread, + IRQF_ONESHOT, + indio_dev, + "%s_consumer%d", + indio_dev->name, + indio_dev->id); + if (indio_dev->pollfunc_event == NULL) + return -ENOMEM; + + /* Flag that events polling is possible */ + indio_dev->modes |= INDIO_EVENT_TRIGGERED; + + return 0; +} +EXPORT_SYMBOL(iio_triggered_event_setup); + +/** + * iio_triggered_event_cleanup() - Free resources allocated by iio_triggered_event_setup() + * @indio_dev: IIO device structure + */ +void iio_triggered_event_cleanup(struct iio_dev *indio_dev) +{ + indio_dev->modes &= ~INDIO_EVENT_TRIGGERED; + iio_dealloc_pollfunc(indio_dev->pollfunc_event); +} +EXPORT_SYMBOL(iio_triggered_event_cleanup); + +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_DESCRIPTION("IIO helper functions for setting up triggered events"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 7bb7f673cb3f..19c94c9acc81 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -294,6 +294,7 @@ static inline s64 iio_get_time_ns(void) #define INDIO_BUFFER_TRIGGERED 0x02 #define INDIO_BUFFER_SOFTWARE 0x04 #define INDIO_BUFFER_HARDWARE 0x08 +#define INDIO_EVENT_TRIGGERED 0x10 #define INDIO_ALL_BUFFER_MODES \ (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE) @@ -457,6 +458,7 @@ struct iio_buffer_setup_ops { * @scan_index_timestamp:[INTERN] cache of the index to the timestamp * @trig: [INTERN] current device trigger (buffer modes) * @pollfunc: [DRIVER] function run on trigger being received + * @pollfunc_event: [DRIVER] function run on events trigger being received * @channels: [DRIVER] channel specification structure table * @num_channels: [DRIVER] number of channels specified in @channels. * @channel_attr_list: [INTERN] keep track of automatically created channel @@ -495,6 +497,7 @@ struct iio_dev { unsigned scan_index_timestamp; struct iio_trigger *trig; struct iio_poll_func *pollfunc; + struct iio_poll_func *pollfunc_event; struct iio_chan_spec const *channels; int num_channels; diff --git a/include/linux/iio/triggered_event.h b/include/linux/iio/triggered_event.h new file mode 100644 index 000000000000..8fe8537085bb --- /dev/null +++ b/include/linux/iio/triggered_event.h @@ -0,0 +1,11 @@ +#ifndef _LINUX_IIO_TRIGGERED_EVENT_H_ +#define _LINUX_IIO_TRIGGERED_EVENT_H_ + +#include + +int iio_triggered_event_setup(struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p)); +void iio_triggered_event_cleanup(struct iio_dev *indio_dev); + +#endif -- cgit v1.3-6-gb490 From b0e010c527de742cb18e8d50a06dfd1a995b5382 Mon Sep 17 00:00:00 2001 From: Alex Gartrell Date: Wed, 26 Aug 2015 09:40:28 -0700 Subject: ipvs: replace ip_vs_fill_ip4hdr with ip_vs_fill_iph_skb_off This removes some duplicated code and makes the ICMPv6 path look more like the ICMP path. Signed-off-by: Alex Gartrell Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 49 +++++++++++++++++------------ net/netfilter/ipvs/ip_vs_core.c | 70 +++++++++++++++-------------------------- net/netfilter/ipvs/ip_vs_xmit.c | 15 ++++----- 3 files changed, 63 insertions(+), 71 deletions(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 9b9ca87a4210..0c8309f34982 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -104,6 +104,7 @@ static inline struct net *seq_file_single_net(struct seq_file *seq) extern int ip_vs_conn_tab_size; struct ip_vs_iphdr { + __u32 off; /* Where IP or IPv4 header starts */ __u32 len; /* IPv4 simply where L4 starts * IPv6 where L4 Transport Header starts */ __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ @@ -120,48 +121,56 @@ static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, return skb_header_pointer(skb, offset, len, buffer); } -static inline void -ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) -{ - const struct iphdr *iph = nh; - - iphdr->len = iph->ihl * 4; - iphdr->fragoffs = 0; - iphdr->protocol = iph->protocol; - iphdr->saddr.ip = iph->saddr; - iphdr->daddr.ip = iph->daddr; -} - /* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6. * IPv6 requires some extra work, as finding proper header position, * depend on the IPv6 extension headers. */ -static inline void -ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) +static inline int +ip_vs_fill_iph_skb_off(int af, const struct sk_buff *skb, int offset, + struct ip_vs_iphdr *iphdr) { + iphdr->off = offset; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { - const struct ipv6hdr *iph = - (struct ipv6hdr *)skb_network_header(skb); + struct ipv6hdr _iph; + const struct ipv6hdr *iph = skb_header_pointer( + skb, offset, sizeof(_iph), &_iph); + if (!iph) + return 0; + iphdr->saddr.in6 = iph->saddr; iphdr->daddr.in6 = iph->daddr; /* ipv6_find_hdr() updates len, flags */ - iphdr->len = 0; + iphdr->len = offset; iphdr->flags = 0; iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, &iphdr->fragoffs, &iphdr->flags); + if (iphdr->protocol < 0) + return 0; } else #endif { - const struct iphdr *iph = - (struct iphdr *)skb_network_header(skb); - iphdr->len = iph->ihl * 4; + struct iphdr _iph; + const struct iphdr *iph = skb_header_pointer( + skb, offset, sizeof(_iph), &_iph); + if (!iph) + return 0; + + iphdr->len = offset + iph->ihl * 4; iphdr->fragoffs = 0; iphdr->protocol = iph->protocol; iphdr->saddr.ip = iph->saddr; iphdr->daddr.ip = iph->daddr; } + + return 1; +} + +static inline int +ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) +{ + return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb), iphdr); } static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst, diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 38fbc194b9cb..b831fe84bff7 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -436,7 +436,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, * with persistence the connection is created on SYN+ACK. */ if (pptr[0] == FTPDATA) { - IP_VS_DBG_PKT(12, svc->af, pp, skb, 0, + IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, "Not scheduling FTPDATA"); return NULL; } @@ -446,7 +446,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, */ if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) && (cp = pp->conn_in_get(svc->af, skb, iph, 1))) { - IP_VS_DBG_PKT(12, svc->af, pp, skb, 0, + IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, "Not scheduling reply for existing connection"); __ip_vs_conn_put(cp); return NULL; @@ -934,8 +934,8 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, "Checking outgoing ICMP for"); - ip_vs_fill_ip4hdr(cih, &ciph); - ciph.len += offset; + ip_vs_fill_iph_skb_off(AF_INET, skb, offset, &ciph); + /* The embedded headers contain source and dest in reverse order */ cp = pp->conn_out_get(AF_INET, skb, &ciph, 1); if (!cp) @@ -951,12 +951,11 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum, struct ip_vs_iphdr *ipvsh) { struct icmp6hdr _icmph, *ic; - struct ipv6hdr _ip6h, *ip6h; /* The ip header contained within ICMP */ struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */ struct ip_vs_conn *cp; struct ip_vs_protocol *pp; union nf_inet_addr snet; - unsigned int writable; + unsigned int offset; *related = 1; ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph, ipvsh); @@ -984,17 +983,9 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, ic->icmp6_type, ntohs(icmpv6_id(ic)), &ipvsh->saddr, &ipvsh->daddr); - /* Now find the contained IP header */ - ciph.len = ipvsh->len + sizeof(_icmph); - ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h); - if (ip6h == NULL) + if (!ip_vs_fill_iph_skb_off(AF_INET6, skb, ipvsh->len + sizeof(_icmph), + &ciph)) return NF_ACCEPT; /* The packet looks wrong, ignore */ - ciph.saddr.in6 = ip6h->saddr; /* conn_out_get() handles reverse order */ - ciph.daddr.in6 = ip6h->daddr; - /* skip possible IPv6 exthdrs of contained IPv6 packet */ - ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL); - if (ciph.protocol < 0) - return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */ pp = ip_vs_proto_get(ciph.protocol); if (!pp) @@ -1006,9 +997,9 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, return NF_ACCEPT; snet.in6 = ciph.saddr.in6; - writable = ciph.len; + offset = ciph.len; return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, - pp, writable, sizeof(struct ipv6hdr), + pp, offset, sizeof(struct ipv6hdr), hooknum); } #endif @@ -1093,7 +1084,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, { struct ip_vs_protocol *pp = pd->pp; - IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet"); + IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet"); if (!skb_make_writable(skb, iph->len)) goto drop; @@ -1130,7 +1121,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, if (ip_vs_route_me_harder(af, skb, hooknum)) goto drop; - IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); + IP_VS_DBG_PKT(10, af, pp, skb, iph->off, "After SNAT"); ip_vs_out_stats(cp, skb); ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd); @@ -1221,7 +1212,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ip_vs_defrag_user(hooknum))) return NF_STOLEN; - ip_vs_fill_ip4hdr(skb_network_header(skb), &iph); + ip_vs_fill_iph_skb(AF_INET, skb, &iph); } /* @@ -1272,7 +1263,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) } } } - IP_VS_DBG_PKT(12, af, pp, skb, 0, + IP_VS_DBG_PKT(12, af, pp, skb, iph.off, "ip_vs_out: packet continues traversal as normal"); return NF_ACCEPT; } @@ -1416,9 +1407,9 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) "Checking incoming ICMP for"); offset2 = offset; - ip_vs_fill_ip4hdr(cih, &ciph); - ciph.len += offset; + ip_vs_fill_iph_skb_off(AF_INET, skb, offset, &ciph); offset = ciph.len; + /* The embedded headers contain source and dest in reverse order. * For IPIP this is error for request, not for reply. */ @@ -1511,13 +1502,12 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum, struct ip_vs_iphdr *iph) { struct net *net = NULL; - struct ipv6hdr _ip6h, *ip6h; struct icmp6hdr _icmph, *ic; struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */ struct ip_vs_conn *cp; struct ip_vs_protocol *pp; struct ip_vs_proto_data *pd; - unsigned int offs_ciph, writable, verdict; + unsigned int offset, verdict; *related = 1; @@ -1546,18 +1536,9 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, ic->icmp6_type, ntohs(icmpv6_id(ic)), &iph->saddr, &iph->daddr); - /* Now find the contained IP header */ - ciph.len = iph->len + sizeof(_icmph); - offs_ciph = ciph.len; /* Save ip header offset */ - ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h); - if (ip6h == NULL) - return NF_ACCEPT; /* The packet looks wrong, ignore */ - ciph.saddr.in6 = ip6h->saddr; /* conn_in_get() handles reverse order */ - ciph.daddr.in6 = ip6h->daddr; - /* skip possible IPv6 exthdrs of contained IPv6 packet */ - ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL); - if (ciph.protocol < 0) - return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */ + offset = iph->len + sizeof(_icmph); + if (!ip_vs_fill_iph_skb_off(AF_INET6, skb, offset, &ciph)) + return NF_ACCEPT; net = skb_net(skb); pd = ip_vs_proto_data_get(net, ciph.protocol); @@ -1569,7 +1550,7 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, if (ciph.fragoffs) return NF_ACCEPT; - IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offs_ciph, + IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset, "Checking incoming ICMPv6 for"); /* The embedded headers contain source and dest in reverse order @@ -1591,12 +1572,12 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, ip_vs_in_stats(cp, skb); /* Need to mangle contained IPv6 header in ICMPv6 packet */ - writable = ciph.len; + offset = ciph.len; if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol || IPPROTO_SCTP == ciph.protocol) - writable += 2 * sizeof(__u16); /* Also mangle ports */ + offset += 2 * sizeof(__u16); /* Also mangle ports */ - verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, writable, hooknum, &ciph); + verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum, &ciph); __ip_vs_conn_put(cp); @@ -1720,12 +1701,13 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) * is missing module nf_defrag_ipv6 */ IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n"); - IP_VS_DBG_PKT(7, af, pp, skb, 0, "unhandled fragment"); + IP_VS_DBG_PKT(7, af, pp, skb, iph.off, + "unhandled fragment"); } return NF_ACCEPT; } - IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); + IP_VS_DBG_PKT(11, af, pp, skb, iph.off, "Incoming packet"); /* Check the server status */ if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { /* the destination server is not available */ diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 258a0b0e82a2..9a26f2ea86d9 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -723,7 +723,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct nf_conn *ct = nf_ct_get(skb, &ctinfo); if (ct && !nf_ct_is_untracked(ct)) { - IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0, + IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, ipvsh->off, "ip_vs_nat_xmit(): " "stopping DNAT to local address"); goto tx_error; @@ -733,8 +733,9 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, /* From world but DNAT to loopback address? */ if (local && ipv4_is_loopback(cp->daddr.ip) && was_input) { - IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " - "stopping DNAT to loopback address"); + IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, ipvsh->off, + "ip_vs_nat_xmit(): stopping DNAT to loopback " + "address"); goto tx_error; } @@ -751,7 +752,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, ip_hdr(skb)->daddr = cp->daddr.ip; ip_send_check(ip_hdr(skb)); - IP_VS_DBG_PKT(10, AF_INET, pp, skb, 0, "After DNAT"); + IP_VS_DBG_PKT(10, AF_INET, pp, skb, ipvsh->off, "After DNAT"); /* FIXME: when application helper enlarges the packet and the length is larger than the MTU of outgoing device, there will be still @@ -812,7 +813,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, struct nf_conn *ct = nf_ct_get(skb, &ctinfo); if (ct && !nf_ct_is_untracked(ct)) { - IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0, + IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, ipvsh->off, "ip_vs_nat_xmit_v6(): " "stopping DNAT to local address"); goto tx_error; @@ -823,7 +824,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, /* From world but DNAT to loopback address? */ if (local && skb->dev && !(skb->dev->flags & IFF_LOOPBACK) && ipv6_addr_type(&cp->daddr.in6) & IPV6_ADDR_LOOPBACK) { - IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, 0, + IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, ipvsh->off, "ip_vs_nat_xmit_v6(): " "stopping DNAT to loopback address"); goto tx_error; @@ -841,7 +842,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error; ipv6_hdr(skb)->daddr = cp->daddr.in6; - IP_VS_DBG_PKT(10, AF_INET6, pp, skb, 0, "After DNAT"); + IP_VS_DBG_PKT(10, AF_INET6, pp, skb, ipvsh->off, "After DNAT"); /* FIXME: when application helper enlarges the packet and the length is larger than the MTU of outgoing device, there will be still -- cgit v1.3-6-gb490 From 4fd9beef37f3a14aa34cb025479a0e431dc9e58b Mon Sep 17 00:00:00 2001 From: Alex Gartrell Date: Wed, 26 Aug 2015 09:40:29 -0700 Subject: ipvs: Add hdr_flags to iphdr These flags contain information like whether or not the addresses are inverted or from icmp. The first will allow us to drop an inverse param all over the place, and the second will later be useful in scheduling icmp. Signed-off-by: Alex Gartrell Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 43 ++++++++++++++++++++++++++++++++++++--- net/netfilter/ipvs/ip_vs_core.c | 20 +++++++++--------- net/netfilter/ipvs/ip_vs_pe_sip.c | 2 +- net/netfilter/xt_ipvs.c | 2 +- 4 files changed, 52 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 0c8309f34982..ac336a79ad3d 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -29,6 +29,9 @@ #endif #include /* Netw namespace */ +#define IP_VS_HDR_INVERSE 1 +#define IP_VS_HDR_ICMP 2 + /* Generic access of ipvs struct */ static inline struct netns_ipvs *net_ipvs(struct net* net) { @@ -104,6 +107,7 @@ static inline struct net *seq_file_single_net(struct seq_file *seq) extern int ip_vs_conn_tab_size; struct ip_vs_iphdr { + int hdr_flags; /* ipvs flags */ __u32 off; /* Where IP or IPv4 header starts */ __u32 len; /* IPv4 simply where L4 starts * IPv6 where L4 Transport Header starts */ @@ -127,9 +131,11 @@ static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, */ static inline int ip_vs_fill_iph_skb_off(int af, const struct sk_buff *skb, int offset, - struct ip_vs_iphdr *iphdr) + int hdr_flags, struct ip_vs_iphdr *iphdr) { + iphdr->hdr_flags = hdr_flags; iphdr->off = offset; + #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { struct ipv6hdr _iph; @@ -168,9 +174,40 @@ ip_vs_fill_iph_skb_off(int af, const struct sk_buff *skb, int offset, } static inline int -ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) +ip_vs_fill_iph_skb_icmp(int af, const struct sk_buff *skb, int offset, + bool inverse, struct ip_vs_iphdr *iphdr) +{ + int hdr_flags = IP_VS_HDR_ICMP; + + if (inverse) + hdr_flags |= IP_VS_HDR_INVERSE; + + return ip_vs_fill_iph_skb_off(af, skb, offset, hdr_flags, iphdr); +} + +static inline int +ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, bool inverse, + struct ip_vs_iphdr *iphdr) +{ + int hdr_flags = 0; + + if (inverse) + hdr_flags |= IP_VS_HDR_INVERSE; + + return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb), + hdr_flags, iphdr); +} + +static inline bool +ip_vs_iph_inverse(const struct ip_vs_iphdr *iph) +{ + return !!(iph->hdr_flags & IP_VS_HDR_INVERSE); +} + +static inline bool +ip_vs_iph_icmp(const struct ip_vs_iphdr *iph) { - return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb), iphdr); + return !!(iph->hdr_flags & IP_VS_HDR_ICMP); } static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst, diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index b831fe84bff7..4f5d3d174517 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -934,7 +934,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, "Checking outgoing ICMP for"); - ip_vs_fill_iph_skb_off(AF_INET, skb, offset, &ciph); + ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph); /* The embedded headers contain source and dest in reverse order */ cp = pp->conn_out_get(AF_INET, skb, &ciph, 1); @@ -983,8 +983,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, ic->icmp6_type, ntohs(icmpv6_id(ic)), &ipvsh->saddr, &ipvsh->daddr); - if (!ip_vs_fill_iph_skb_off(AF_INET6, skb, ipvsh->len + sizeof(_icmph), - &ciph)) + if (!ip_vs_fill_iph_skb_icmp(AF_INET6, skb, ipvsh->len + sizeof(_icmph), + true, &ciph)) return NF_ACCEPT; /* The packet looks wrong, ignore */ pp = ip_vs_proto_get(ciph.protocol); @@ -1177,7 +1177,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) if (!net_ipvs(net)->enable) return NF_ACCEPT; - ip_vs_fill_iph_skb(af, skb, &iph); + ip_vs_fill_iph_skb(af, skb, false, &iph); #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { @@ -1212,7 +1212,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ip_vs_defrag_user(hooknum))) return NF_STOLEN; - ip_vs_fill_iph_skb(AF_INET, skb, &iph); + ip_vs_fill_iph_skb(AF_INET, skb, false, &iph); } /* @@ -1407,7 +1407,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) "Checking incoming ICMP for"); offset2 = offset; - ip_vs_fill_iph_skb_off(AF_INET, skb, offset, &ciph); + ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !ipip, &ciph); offset = ciph.len; /* The embedded headers contain source and dest in reverse order. @@ -1537,7 +1537,7 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, &iph->saddr, &iph->daddr); offset = iph->len + sizeof(_icmph); - if (!ip_vs_fill_iph_skb_off(AF_INET6, skb, offset, &ciph)) + if (!ip_vs_fill_iph_skb_icmp(AF_INET6, skb, offset, true, &ciph)) return NF_ACCEPT; net = skb_net(skb); @@ -1614,7 +1614,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) if (unlikely((skb->pkt_type != PACKET_HOST && hooknum != NF_INET_LOCAL_OUT) || !skb_dst(skb))) { - ip_vs_fill_iph_skb(af, skb, &iph); + ip_vs_fill_iph_skb(af, skb, false, &iph); IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s" " ignored in hook %u\n", skb->pkt_type, iph.protocol, @@ -1627,7 +1627,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable)) return NF_ACCEPT; - ip_vs_fill_iph_skb(af, skb, &iph); + ip_vs_fill_iph_skb(af, skb, false, &iph); /* Bad... Do not break raw sockets */ if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT && @@ -1841,7 +1841,7 @@ ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb, struct netns_ipvs *ipvs; struct ip_vs_iphdr iphdr; - ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr); + ip_vs_fill_iph_skb(AF_INET6, skb, false, &iphdr); if (iphdr.protocol != IPPROTO_ICMPV6) return NF_ACCEPT; diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c index bed5f7042529..1b8d594e493a 100644 --- a/net/netfilter/ipvs/ip_vs_pe_sip.c +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c @@ -70,7 +70,7 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) const char *dptr; int retc; - ip_vs_fill_iph_skb(p->af, skb, &iph); + ip_vs_fill_iph_skb(p->af, skb, false, &iph); /* Only useful with UDP */ if (iph.protocol != IPPROTO_UDP) diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c index 8d47c3780fda..370462572d84 100644 --- a/net/netfilter/xt_ipvs.c +++ b/net/netfilter/xt_ipvs.c @@ -67,7 +67,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par) goto out; } - ip_vs_fill_iph_skb(family, skb, &iph); + ip_vs_fill_iph_skb(family, skb, true, &iph); if (data->bitmask & XT_IPVS_PROTO) if ((iph.protocol == data->l4proto) ^ -- cgit v1.3-6-gb490 From 802c41adcf3be63f351c302c9665865d705cada9 Mon Sep 17 00:00:00 2001 From: Alex Gartrell Date: Wed, 26 Aug 2015 09:40:32 -0700 Subject: ipvs: drop inverse argument to conn_{in,out}_get No longer necessary since the information is included in the ip_vs_iphdr itself. Signed-off-by: Alex Gartrell Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 12 ++++-------- net/netfilter/ipvs/ip_vs_conn.c | 12 ++++++------ net/netfilter/ipvs/ip_vs_core.c | 31 ++++++++++++++++++------------- net/netfilter/ipvs/ip_vs_proto_ah_esp.c | 17 ++++++++--------- net/netfilter/xt_ipvs.c | 2 +- 5 files changed, 37 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index ac336a79ad3d..ba90729d1111 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -495,14 +495,12 @@ struct ip_vs_protocol { struct ip_vs_conn * (*conn_in_get)(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, - int inverse); + const struct ip_vs_iphdr *iph); struct ip_vs_conn * (*conn_out_get)(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, - int inverse); + const struct ip_vs_iphdr *iph); int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); @@ -1232,14 +1230,12 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p); struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p); struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, - int inverse); + const struct ip_vs_iphdr *iph); struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p); struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, - int inverse); + const struct ip_vs_iphdr *iph); /* Get reference to gain full access to conn. * By default, RCU read-side critical sections have access only to diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index b0f7b626b56d..f71b3146a5a1 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -316,7 +316,7 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p) static int ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb, const struct ip_vs_iphdr *iph, - int inverse, struct ip_vs_conn_param *p) + struct ip_vs_conn_param *p) { __be16 _ports[2], *pptr; struct net *net = skb_net(skb); @@ -325,7 +325,7 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb, if (pptr == NULL) return 1; - if (likely(!inverse)) + if (likely(!ip_vs_iph_inverse(iph))) ip_vs_conn_fill_param(net, af, iph->protocol, &iph->saddr, pptr[0], &iph->daddr, pptr[1], p); else @@ -336,11 +336,11 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb, struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, int inverse) + const struct ip_vs_iphdr *iph) { struct ip_vs_conn_param p; - if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p)) + if (ip_vs_conn_fill_param_proto(af, skb, iph, &p)) return NULL; return ip_vs_conn_in_get(&p); @@ -440,11 +440,11 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p) struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, int inverse) + const struct ip_vs_iphdr *iph) { struct ip_vs_conn_param p; - if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p)) + if (ip_vs_conn_fill_param_proto(af, skb, iph, &p)) return NULL; return ip_vs_conn_out_get(&p); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 2c44e34314c2..ebfb371daa3b 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -444,12 +444,18 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, /* * Do not schedule replies from local real server. */ - if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) && - (cp = pp->conn_in_get(svc->af, skb, iph, 1))) { - IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, - "Not scheduling reply for existing connection"); - __ip_vs_conn_put(cp); - return NULL; + if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK)) { + iph->hdr_flags ^= IP_VS_HDR_INVERSE; + cp = pp->conn_in_get(svc->af, skb, iph); + iph->hdr_flags ^= IP_VS_HDR_INVERSE; + + if (cp) { + IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, + "Not scheduling reply for existing" + " connection"); + __ip_vs_conn_put(cp); + return NULL; + } } /* @@ -946,7 +952,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph); /* The embedded headers contain source and dest in reverse order */ - cp = pp->conn_out_get(AF_INET, skb, &ciph, 1); + cp = pp->conn_out_get(AF_INET, skb, &ciph); if (!cp) return NF_ACCEPT; @@ -1001,7 +1007,7 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, return NF_ACCEPT; /* The embedded headers contain source and dest in reverse order */ - cp = pp->conn_out_get(AF_INET6, skb, &ciph, 1); + cp = pp->conn_out_get(AF_INET6, skb, &ciph); if (!cp) return NF_ACCEPT; @@ -1227,7 +1233,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) /* * Check if the packet belongs to an existing entry */ - cp = pp->conn_out_get(af, skb, &iph, 0); + cp = pp->conn_out_get(af, skb, &iph); if (likely(cp)) return handle_response(af, skb, pd, cp, &iph, hooknum); @@ -1458,7 +1464,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) /* The embedded headers contain source and dest in reverse order. * For IPIP this is error for request, not for reply. */ - cp = pp->conn_in_get(AF_INET, skb, &ciph, ipip ? 0 : 1); + cp = pp->conn_in_get(AF_INET, skb, &ciph); if (!cp) return NF_ACCEPT; @@ -1601,8 +1607,7 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, /* The embedded headers contain source and dest in reverse order * if not from localhost */ - cp = pp->conn_in_get(AF_INET6, skb, &ciph, - (hooknum == NF_INET_LOCAL_OUT) ? 0 : 1); + cp = pp->conn_in_get(AF_INET6, skb, &ciph); if (!cp) return NF_ACCEPT; @@ -1712,7 +1717,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) /* * Check if the packet belongs to an existing connection entry */ - cp = pp->conn_in_get(af, skb, &iph, 0); + cp = pp->conn_in_get(af, skb, &iph); conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); if (conn_reuse_mode && !iph.fragoffs && diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c index 5de3dd312c0f..be1791d1c03f 100644 --- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c +++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c @@ -42,10 +42,10 @@ struct isakmp_hdr { static void ah_esp_conn_fill_param_proto(struct net *net, int af, - const struct ip_vs_iphdr *iph, int inverse, + const struct ip_vs_iphdr *iph, struct ip_vs_conn_param *p) { - if (likely(!inverse)) + if (likely(!ip_vs_iph_inverse(iph))) ip_vs_conn_fill_param(net, af, IPPROTO_UDP, &iph->saddr, htons(PORT_ISAKMP), &iph->daddr, htons(PORT_ISAKMP), p); @@ -57,14 +57,13 @@ ah_esp_conn_fill_param_proto(struct net *net, int af, static struct ip_vs_conn * ah_esp_conn_in_get(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, - int inverse) + const struct ip_vs_iphdr *iph) { struct ip_vs_conn *cp; struct ip_vs_conn_param p; struct net *net = skb_net(skb); - ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p); + ah_esp_conn_fill_param_proto(net, af, iph, &p); cp = ip_vs_conn_in_get(&p); if (!cp) { /* @@ -73,7 +72,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, */ IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " "%s%s %s->%s\n", - inverse ? "ICMP+" : "", + ip_vs_iph_icmp(iph) ? "ICMP+" : "", ip_vs_proto_get(iph->protocol)->name, IP_VS_DBG_ADDR(af, &iph->saddr), IP_VS_DBG_ADDR(af, &iph->daddr)); @@ -85,18 +84,18 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, static struct ip_vs_conn * ah_esp_conn_out_get(int af, const struct sk_buff *skb, - const struct ip_vs_iphdr *iph, int inverse) + const struct ip_vs_iphdr *iph) { struct ip_vs_conn *cp; struct ip_vs_conn_param p; struct net *net = skb_net(skb); - ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p); + ah_esp_conn_fill_param_proto(net, af, iph, &p); cp = ip_vs_conn_out_get(&p); if (!cp) { IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " "%s%s %s->%s\n", - inverse ? "ICMP+" : "", + ip_vs_iph_icmp(iph) ? "ICMP+" : "", ip_vs_proto_get(iph->protocol)->name, IP_VS_DBG_ADDR(af, &iph->saddr), IP_VS_DBG_ADDR(af, &iph->daddr)); diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c index 370462572d84..452ba2a3e7ae 100644 --- a/net/netfilter/xt_ipvs.c +++ b/net/netfilter/xt_ipvs.c @@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par) /* * Check if the packet belongs to an existing entry */ - cp = pp->conn_out_get(family, skb, &iph, 1 /* inverse */); + cp = pp->conn_out_get(family, skb, &iph); if (unlikely(cp == NULL)) { match = false; goto out; -- cgit v1.3-6-gb490 From 94485fedcb176a9105961e47bd9dda23801c1906 Mon Sep 17 00:00:00 2001 From: Alex Gartrell Date: Wed, 26 Aug 2015 09:40:34 -0700 Subject: ipvs: add schedule_icmp sysctl This sysctl will be used to enable the scheduling of icmp packets. Signed-off-by: Alex Gartrell Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 11 +++++++++++ net/netfilter/ipvs/ip_vs_ctl.c | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index ba90729d1111..47677f0493c7 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -997,6 +997,7 @@ struct netns_ipvs { int sysctl_pmtu_disc; int sysctl_backup_only; int sysctl_conn_reuse_mode; + int sysctl_schedule_icmp; /* ip_vs_lblc */ int sysctl_lblc_expiration; @@ -1115,6 +1116,11 @@ static inline int sysctl_conn_reuse_mode(struct netns_ipvs *ipvs) return ipvs->sysctl_conn_reuse_mode; } +static inline int sysctl_schedule_icmp(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_schedule_icmp; +} + #else static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) @@ -1187,6 +1193,11 @@ static inline int sysctl_conn_reuse_mode(struct netns_ipvs *ipvs) return 1; } +static inline int sysctl_schedule_icmp(struct netns_ipvs *ipvs) +{ + return 0; +} + #endif /* IPVS core functions diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 1a23e91d50d8..31d80e203863 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1844,6 +1844,12 @@ static struct ctl_table vs_vars[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "schedule_icmp", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #ifdef CONFIG_IP_VS_DEBUG { .procname = "debug_level", @@ -3895,7 +3901,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) tbl[idx++].data = &ipvs->sysctl_backup_only; ipvs->sysctl_conn_reuse_mode = 1; tbl[idx++].data = &ipvs->sysctl_conn_reuse_mode; - + tbl[idx++].data = &ipvs->sysctl_schedule_icmp; ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); if (ipvs->sysctl_hdr == NULL) { -- cgit v1.3-6-gb490 From 7cc53cf01e61bd1a774d2ba492bbe3e93e58ca79 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Aug 2015 14:33:31 +0300 Subject: drm/dp: add drm_dp_tps3_supported helper Cc: Thierry Reding Signed-off-by: Jani Nikula Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- include/drm/drm_dp_helper.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 94898f6ea02a..6aa59b9c7335 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -633,6 +633,13 @@ drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP); } +static inline bool +drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + return dpcd[DP_DPCD_REV] >= 0x12 && + dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED; +} + /* * DisplayPort AUX channel */ -- cgit v1.3-6-gb490 From a39f1d5e4303f535840a44eee87326fd9743de7c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 13 Aug 2015 15:46:04 -0700 Subject: mtd: spi-nor: add forward declaration for mtd_info This header can't actually stand alone, as it relies on the declaration (but not definition) of struct mtd_info. Let's fix that. Signed-off-by: Brian Norris Tested-by: Joachim Eastwood --- include/linux/mtd/spi-nor.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index e5409524bb0a..85a24baea093 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -127,6 +127,8 @@ enum spi_nor_option_flags { SNOR_F_USE_FSR = BIT(0), }; +struct mtd_info; + /** * struct spi_nor - Structure for defining a the SPI NOR layer * @mtd: point to a mtd_info structure -- cgit v1.3-6-gb490 From 1976367173a47f801c67b5f456922d79c60d0d42 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 13 Aug 2015 15:46:05 -0700 Subject: mtd: spi-nor: embed struct mtd_info within struct spi_nor This reflects the proper layering, so let's do it. Signed-off-by: Brian Norris Tested-by: Joachim Eastwood --- drivers/mtd/devices/m25p80.c | 10 ++++------ drivers/mtd/spi-nor/fsl-quadspi.c | 10 ++++------ drivers/mtd/spi-nor/nxp-spifi.c | 6 ++---- drivers/mtd/spi-nor/spi-nor.c | 8 ++++---- include/linux/mtd/spi-nor.h | 2 +- 5 files changed, 15 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 24965ae9f7aa..b6bc9a2a5f87 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -31,7 +31,6 @@ struct m25p { struct spi_device *spi; struct spi_nor spi_nor; - struct mtd_info mtd; u8 command[MAX_CMD_SIZE]; }; @@ -159,7 +158,7 @@ static int m25p80_erase(struct spi_nor *nor, loff_t offset) struct m25p *flash = nor->priv; dev_dbg(nor->dev, "%dKiB at 0x%08x\n", - flash->mtd.erasesize / 1024, (u32)offset); + flash->spi_nor.mtd.erasesize / 1024, (u32)offset); /* Set up command buffer. */ flash->command[0] = nor->erase_opcode; @@ -201,7 +200,6 @@ static int m25p_probe(struct spi_device *spi) nor->read_reg = m25p80_read_reg; nor->dev = &spi->dev; - nor->mtd = &flash->mtd; nor->priv = flash; spi_set_drvdata(spi, flash); @@ -213,7 +211,7 @@ static int m25p_probe(struct spi_device *spi) mode = SPI_NOR_DUAL; if (data && data->name) - flash->mtd.name = data->name; + nor->mtd.name = data->name; /* For some (historical?) reason many platforms provide two different * names in flash_platform_data: "name" and "type". Quite often name is @@ -231,7 +229,7 @@ static int m25p_probe(struct spi_device *spi) ppdata.of_node = spi->dev.of_node; - return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, + return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, data ? data->parts : NULL, data ? data->nr_parts : 0); } @@ -242,7 +240,7 @@ static int m25p_remove(struct spi_device *spi) struct m25p *flash = spi_get_drvdata(spi); /* Clean up MTD stuff. */ - return mtd_device_unregister(&flash->mtd); + return mtd_device_unregister(&flash->spi_nor.mtd); } /* diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index ad9f73ae6eea..19f61783cb56 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -259,7 +259,6 @@ static struct fsl_qspi_devtype_data imx6ul_data = { #define FSL_QSPI_MAX_CHIP 4 struct fsl_qspi { - struct mtd_info mtd[FSL_QSPI_MAX_CHIP]; struct spi_nor nor[FSL_QSPI_MAX_CHIP]; void __iomem *iobase; void __iomem *ahb_addr; @@ -888,7 +887,7 @@ static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs) int ret; dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", - nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs); + nor->mtd.erasesize / 1024, q->chip_base_addr, (u32)offs); ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); if (ret) @@ -1013,9 +1012,8 @@ static int fsl_qspi_probe(struct platform_device *pdev) i *= 2; nor = &q->nor[i]; - mtd = &q->mtd[i]; + mtd = &nor->mtd; - nor->mtd = mtd; nor->dev = dev; nor->priv = q; @@ -1086,7 +1084,7 @@ last_init_failed: /* skip the holes */ if (!q->has_second_chip) i *= 2; - mtd_device_unregister(&q->mtd[i]); + mtd_device_unregister(&q->nor[i].mtd); } mutex_failed: mutex_destroy(&q->lock); @@ -1106,7 +1104,7 @@ static int fsl_qspi_remove(struct platform_device *pdev) /* skip the holes */ if (!q->has_second_chip) i *= 2; - mtd_device_unregister(&q->mtd[i]); + mtd_device_unregister(&q->nor[i].mtd); } /* disable the hardware */ diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c index ce6a478a02a5..0f6b452574bd 100644 --- a/drivers/mtd/spi-nor/nxp-spifi.c +++ b/drivers/mtd/spi-nor/nxp-spifi.c @@ -60,7 +60,6 @@ struct nxp_spifi { struct clk *clk_reg; void __iomem *io_base; void __iomem *flash_base; - struct mtd_info mtd; struct spi_nor nor; bool memory_mode; u32 mcmd; @@ -331,7 +330,6 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, writel(ctrl, spifi->io_base + SPIFI_CTRL); - spifi->nor.mtd = &spifi->mtd; spifi->nor.dev = spifi->dev; spifi->nor.priv = spifi; spifi->nor.read = nxp_spifi_read; @@ -364,7 +362,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, } ppdata.of_node = np; - ret = mtd_device_parse_register(&spifi->mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_parse_register(&spifi->nor.mtd, NULL, &ppdata, NULL, 0); if (ret) { dev_err(spifi->dev, "mtd device parse failed\n"); return ret; @@ -453,7 +451,7 @@ static int nxp_spifi_remove(struct platform_device *pdev) { struct nxp_spifi *spifi = platform_get_drvdata(pdev); - mtd_device_unregister(&spifi->mtd); + mtd_device_unregister(&spifi->nor.mtd); clk_disable_unprepare(spifi->clk_spifi); clk_disable_unprepare(spifi->clk_reg); diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index d98180e73307..834a06049ca2 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -265,7 +265,7 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor) */ static int erase_chip(struct spi_nor *nor) { - dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); + dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); } @@ -373,7 +373,7 @@ erase_err: static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) { - struct mtd_info *mtd = nor->mtd; + struct mtd_info *mtd = &nor->mtd; uint32_t offset = ofs; uint8_t status_old, status_new; int ret = 0; @@ -407,7 +407,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) { - struct mtd_info *mtd = nor->mtd; + struct mtd_info *mtd = &nor->mtd; uint32_t offset = ofs; uint8_t status_old, status_new; int ret = 0; @@ -1004,7 +1004,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) { const struct flash_info *info = NULL; struct device *dev = nor->dev; - struct mtd_info *mtd = nor->mtd; + struct mtd_info *mtd = &nor->mtd; struct device_node *np = dev->of_node; int ret; int i; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 85a24baea093..495433d3f56d 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -162,7 +162,7 @@ struct mtd_info; * @priv: the private data */ struct spi_nor { - struct mtd_info *mtd; + struct mtd_info mtd; struct mutex lock; struct device *dev; u32 page_size; -- cgit v1.3-6-gb490 From a9cadf72bfb7185a680eb7599b9bda65d1515b9f Mon Sep 17 00:00:00 2001 From: Ezequiel García Date: Fri, 21 Aug 2015 15:47:28 -0300 Subject: mtd: pxa3xx_nand: Remove unused platform-data flash specification The driver supports board files specificating the flash device, by passing a pxa3xx_nand_flash struct (with flash parameters) in the platform data struct. Currently this support is not being used by any board file. Moreover, we'd like to deprecate such usage in favor of using the device table in nand_ids.c. So let's remove the ad-hoc flash specification. Signed-off-by: Ezequiel Garcia Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 33 ++++++++++++++++++++++----- include/linux/platform_data/mtd-nand-pxa3xx.h | 27 ---------------------- 2 files changed, 27 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 740983a34626..165112c1a7d1 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -252,6 +252,30 @@ static bool use_dma = 1; module_param(use_dma, bool, 0444); MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW"); +struct pxa3xx_nand_timing { + unsigned int tCH; /* Enable signal hold time */ + unsigned int tCS; /* Enable signal setup time */ + unsigned int tWH; /* ND_nWE high duration */ + unsigned int tWP; /* ND_nWE pulse time */ + unsigned int tRH; /* ND_nRE high duration */ + unsigned int tRP; /* ND_nRE pulse width */ + unsigned int tR; /* ND_nWE high to ND_nRE low for read */ + unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */ + unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ +}; + +struct pxa3xx_nand_flash { + char *name; + uint32_t chip_id; + unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */ + unsigned int page_size; /* Page size in bytes (PAGE_SZ) */ + unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */ + unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */ + unsigned int num_blocks; /* Number of physical blocks in Flash */ + + struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ +}; + static struct pxa3xx_nand_timing timing[] = { { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, @@ -1491,19 +1515,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) return -EINVAL; } - num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; + num = ARRAY_SIZE(builtin_flash_types) - 1; for (i = 0; i < num; i++) { - if (i < pdata->num_flash) - f = pdata->flash + i; - else - f = &builtin_flash_types[i - pdata->num_flash + 1]; + f = &builtin_flash_types[i + 1]; /* find the chip in default list */ if (f->chip_id == id) break; } - if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) { + if (i >= (ARRAY_SIZE(builtin_flash_types) - 1)) { dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n"); return -EINVAL; diff --git a/include/linux/platform_data/mtd-nand-pxa3xx.h b/include/linux/platform_data/mtd-nand-pxa3xx.h index ac4ea2e641c7..394d15597dc7 100644 --- a/include/linux/platform_data/mtd-nand-pxa3xx.h +++ b/include/linux/platform_data/mtd-nand-pxa3xx.h @@ -4,30 +4,6 @@ #include #include -struct pxa3xx_nand_timing { - unsigned int tCH; /* Enable signal hold time */ - unsigned int tCS; /* Enable signal setup time */ - unsigned int tWH; /* ND_nWE high duration */ - unsigned int tWP; /* ND_nWE pulse time */ - unsigned int tRH; /* ND_nRE high duration */ - unsigned int tRP; /* ND_nRE pulse width */ - unsigned int tR; /* ND_nWE high to ND_nRE low for read */ - unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */ - unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ -}; - -struct pxa3xx_nand_flash { - char *name; - uint32_t chip_id; - unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */ - unsigned int page_size; /* Page size in bytes (PAGE_SZ) */ - unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */ - unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */ - unsigned int num_blocks; /* Number of physical blocks in Flash */ - - struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ -}; - /* * Current pxa3xx_nand controller has two chip select which * both be workable. @@ -63,9 +39,6 @@ struct pxa3xx_nand_platform_data { const struct mtd_partition *parts[NUM_CHIP_SELECT]; unsigned int nr_parts[NUM_CHIP_SELECT]; - - const struct pxa3xx_nand_flash * flash; - size_t num_flash; }; extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); -- cgit v1.3-6-gb490 From bbda9c1f170e4b31f5d827372ee9a3fb8389f7fa Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 19 Aug 2015 19:21:14 -0400 Subject: drm: cleanup modesetting ioctls, one param per line Since this already confused me once when adding addfb2.1, let's clean up the header to split params one per line. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- include/uapi/drm/drm_mode.h | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 359107ab629e..6c11ca401de8 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -105,8 +105,16 @@ struct drm_mode_modeinfo { __u32 clock; - __u16 hdisplay, hsync_start, hsync_end, htotal, hskew; - __u16 vdisplay, vsync_start, vsync_end, vtotal, vscan; + __u16 hdisplay; + __u16 hsync_start; + __u16 hsync_end; + __u16 htotal; + __u16 hskew; + __u16 vdisplay; + __u16 vsync_start; + __u16 vsync_end; + __u16 vtotal; + __u16 vscan; __u32 vrefresh; @@ -124,8 +132,10 @@ struct drm_mode_card_res { __u32 count_crtcs; __u32 count_connectors; __u32 count_encoders; - __u32 min_width, max_width; - __u32 min_height, max_height; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; }; struct drm_mode_crtc { @@ -135,7 +145,8 @@ struct drm_mode_crtc { __u32 crtc_id; /**< Id */ __u32 fb_id; /**< Id of framebuffer */ - __u32 x, y; /**< Position on the frameuffer */ + __u32 x; /**< x Position on the framebuffer */ + __u32 y; /**< y Position on the framebuffer */ __u32 gamma_size; __u32 mode_valid; @@ -153,12 +164,16 @@ struct drm_mode_set_plane { __u32 flags; /* see above flags */ /* Signed dest location allows it to be partially off screen */ - __s32 crtc_x, crtc_y; - __u32 crtc_w, crtc_h; + __s32 crtc_x; + __s32 crtc_y; + __u32 crtc_w; + __u32 crtc_h; /* Source values are 16.16 fixed point */ - __u32 src_x, src_y; - __u32 src_h, src_w; + __u32 src_x; + __u32 src_y; + __u32 src_h; + __u32 src_w; }; struct drm_mode_get_plane { @@ -244,7 +259,8 @@ struct drm_mode_get_connector { __u32 connector_type_id; __u32 connection; - __u32 mm_width, mm_height; /**< HxW in millimeters */ + __u32 mm_width; /**< width in millimeters */ + __u32 mm_height; /**< height in millimeters */ __u32 subpixel; __u32 pad; @@ -327,7 +343,8 @@ struct drm_mode_get_blob { struct drm_mode_fb_cmd { __u32 fb_id; - __u32 width, height; + __u32 width; + __u32 height; __u32 pitch; __u32 bpp; __u32 depth; @@ -340,7 +357,8 @@ struct drm_mode_fb_cmd { struct drm_mode_fb_cmd2 { __u32 fb_id; - __u32 width, height; + __u32 width; + __u32 height; __u32 pixel_format; /* fourcc code from drm_fourcc.h */ __u32 flags; /* see above flags */ -- cgit v1.3-6-gb490 From fe8660acd8853ad9f95b94a04cce384949ddecfe Mon Sep 17 00:00:00 2001 From: Danilo Cesar Lemes de Paula Date: Fri, 21 Aug 2015 16:46:14 -0300 Subject: drm/doc: Fixing xml documentation warning "/**" should be used for kernel-doc documentation only. It causes a warning with the new "in struct body" format. Signed-off-by: Danilo Cesar Lemes de Paula Cc: Randy Dunlap Cc: Daniel Vetter Cc: Laurent Pinchart Cc: Jonathan Corbet Cc: Herbert Xu Cc: Stephan Mueller Cc: Michal Marek Cc: linux-kernel@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: intel-gfx Cc: dri-devel Cc: Graham Whaley Signed-off-by: Daniel Vetter --- include/drm/drm_modeset_lock.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index 5dd18bfdf601..94938d89347c 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h @@ -43,19 +43,19 @@ struct drm_modeset_acquire_ctx { struct ww_acquire_ctx ww_ctx; - /** + /* * Contended lock: if a lock is contended you should only call * drm_modeset_backoff() which drops locks and slow-locks the * contended lock. */ struct drm_modeset_lock *contended; - /** + /* * list of held locks (drm_modeset_lock) */ struct list_head locked; - /** + /* * Trylock mode, use only for panic handlers! */ bool trylock_only; @@ -70,12 +70,12 @@ struct drm_modeset_acquire_ctx { * Used for locking CRTCs and other modeset resources. */ struct drm_modeset_lock { - /** + /* * modeset lock */ struct ww_mutex mutex; - /** + /* * Resources that are locked as part of an atomic update are added * to a list (so we know what to unlock at the end). */ -- cgit v1.3-6-gb490 From b7bdf0a87add0fead1550533e328a290d8f9da6c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Aug 2015 17:20:28 +0200 Subject: drm/fb-helper: Use -errno return in restore_mode_unlocked Using bool and returning true upon error is very uncommon. Also an int return value is actually what all the callers which did check it seem to have expected. v2: Restore hunk misplaced in a rebase, spotted by Rob. Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 19 +++++++++++-------- include/drm/drm_fb_helper.h | 6 +++--- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 418d299f3b12..859134e0d72d 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -320,11 +320,10 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) +static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; struct drm_plane *plane; - bool error = false; int i; drm_warn_on_modeset_not_all_locked(dev); @@ -348,14 +347,15 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) if (crtc->funcs->cursor_set) { ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); if (ret) - error = true; + return ret; } ret = drm_mode_set_config_internal(mode_set); if (ret) - error = true; + return ret; } - return error; + + return 0; } /** @@ -365,12 +365,15 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) * This should be called from driver's drm ->lastclose callback * when implementing an fbcon on top of kms using this helper. This ensures that * the user isn't greeted with a black screen when e.g. X dies. + * + * RETURNS: + * Zero if everything went ok, negative error code otherwise. */ -bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) +int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; - bool ret; - bool do_delayed = false; + bool do_delayed; + int ret; drm_modeset_lock_all(dev); ret = restore_fbdev_mode(fb_helper); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index dbab4622b58f..67de1f10008e 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -136,7 +136,7 @@ int drm_fb_helper_set_par(struct fb_info *info); int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info); -bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); +int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper); void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper); @@ -226,10 +226,10 @@ static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return 0; } -static inline bool +static inline int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) { - return true; + return 0; } static inline struct fb_info * -- cgit v1.3-6-gb490 From b7c914b3d94e93bd9b442226231b0bba84c9fa2c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 31 Aug 2015 15:09:26 +0300 Subject: drm: Constify TV mode names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the mode names passed to drm_mode_create_tv_properties() const. drivers/gpu/drm/i2c/ch7006.ko: -.rodata 596 +.rodata 664 -.data 7064 +.data 6992 drivers/gpu/drm/nouveau/nouveau.ko: -.rodata 146808 +.rodata 146904 -.data 178624 +.data 178528 Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/i2c/ch7006_drv.c | 6 +++--- drivers/gpu/drm/i2c/ch7006_mode.c | 4 ++-- drivers/gpu/drm/i2c/ch7006_priv.h | 2 +- drivers/gpu/drm/i915/intel_tv.c | 4 ++-- drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.h | 2 +- include/drm/drm_crtc.h | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 884690c81094..474f328535a1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1519,7 +1519,7 @@ EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); */ int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, - char *modes[]) + const char * const modes[]) { struct drm_property *tv_selector; struct drm_property *tv_subconnector; diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 51fa32392029..d9a72c96e56c 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -119,8 +119,8 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder, struct ch7006_encoder_params *params = &priv->params; struct ch7006_state *state = &priv->state; uint8_t *regs = state->regs; - struct ch7006_mode *mode = priv->mode; - struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_mode *mode = priv->mode; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; int start_active; ch7006_dbg(client, "\n"); @@ -226,7 +226,7 @@ static int ch7006_encoder_get_modes(struct drm_encoder *encoder, struct drm_connector *connector) { struct ch7006_priv *priv = to_ch7006_priv(encoder); - struct ch7006_mode *mode; + const struct ch7006_mode *mode; int n = 0; for (mode = ch7006_modes; mode->mode.clock; mode++) { diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index 9b83574141a6..f4dca53f5752 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c @@ -26,7 +26,7 @@ #include "ch7006_priv.h" -char *ch7006_tv_norm_names[] = { +const char * const ch7006_tv_norm_names[] = { [TV_NORM_PAL] = "PAL", [TV_NORM_PAL_M] = "PAL-M", [TV_NORM_PAL_N] = "PAL-N", @@ -202,7 +202,7 @@ void ch7006_setup_levels(struct drm_encoder *encoder) struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder); uint8_t *regs = priv->state.regs; - struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; + const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; int gain; int black_level; diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index ce577841f931..cef6ce7c79d1 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h @@ -106,7 +106,7 @@ extern int ch7006_debug; extern char *ch7006_tv_norm; extern int ch7006_scale; -extern char *ch7006_tv_norm_names[]; +extern const char * const ch7006_tv_norm_names[]; extern struct ch7006_tv_norm_info ch7006_tv_norms[]; extern struct ch7006_mode ch7006_modes[]; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 0568ae6ec9dd..590ceabe2d5e 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1579,7 +1579,7 @@ intel_tv_init(struct drm_device *dev) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; u32 tv_dac_on, tv_dac_off, save_tv_dac; - char *tv_format_names[ARRAY_SIZE(tv_modes)]; + const char *tv_format_names[ARRAY_SIZE(tv_modes)]; int i, initial_mode = 0; if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) @@ -1677,7 +1677,7 @@ intel_tv_init(struct drm_device *dev) /* Create TV properties then attach current values */ for (i = 0; i < ARRAY_SIZE(tv_modes); i++) - tv_format_names[i] = (char *)tv_modes[i].name; + tv_format_names[i] = tv_modes[i].name; drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c index 08c6f5e50610..903c473d266f 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c @@ -32,7 +32,7 @@ #include "hw.h" #include "tvnv17.h" -char *nv17_tv_norm_names[NUM_TV_NORMS] = { +const char * const nv17_tv_norm_names[NUM_TV_NORMS] = { [TV_NORM_PAL] = "PAL", [TV_NORM_PAL_M] = "PAL-M", [TV_NORM_PAL_N] = "PAL-N", diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h index 459910b6bb32..1b07521cde0d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h @@ -85,7 +85,7 @@ struct nv17_tv_encoder { #define to_tv_enc(x) container_of(nouveau_encoder(x), \ struct nv17_tv_encoder, base) -extern char *nv17_tv_norm_names[NUM_TV_NORMS]; +extern const char * const nv17_tv_norm_names[NUM_TV_NORMS]; extern struct nv17_tv_norm_params { enum { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index faaeff7db684..75f49c1ef8bb 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1390,7 +1390,7 @@ extern int drm_property_add_enum(struct drm_property *property, int index, extern int drm_mode_create_dvi_i_properties(struct drm_device *dev); extern int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, - char *modes[]); + const char * const modes[]); extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); extern int drm_mode_create_dirty_info_property(struct drm_device *dev); -- cgit v1.3-6-gb490 From 844f9111f6f54f88eb2f0fac121b82ce77193866 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 2 Sep 2015 10:42:40 +0200 Subject: drm/atomic: Make prepare_fb/cleanup_fb only take state, v3. This removes the need to separately track fb changes i915. That will be done as a separate commit, however. Changes since v1: - Add dri-devel to cc. - Fix a check in intel's prepare and cleanup fb to take rotation into account. Changes since v2: - Split out i915 changes to a separate commit. Cc: dri-devel@lists.freedesktop.org Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Stone [danvet: Squash in msm fixup from Maarten.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 4 +++- drivers/gpu/drm/drm_atomic_helper.c | 21 ++++++--------------- drivers/gpu/drm/drm_plane_helper.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 9 ++++----- drivers/gpu/drm/i915/intel_drv.h | 2 -- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 10 ++++++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 10 ++++++++-- drivers/gpu/drm/omapdrm/omap_plane.c | 10 ++++++---- drivers/gpu/drm/tegra/dc.c | 2 -- include/drm/drm_plane_helper.h | 2 -- 10 files changed, 38 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index be9fa8220499..36fda86b3518 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -712,11 +712,13 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, } static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); + if (!new_state->fb) + return 0; + return atmel_hlcdc_layer_update_start(&plane->layer); } diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index a2629ee133ba..9b0c47690ae8 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1111,17 +1111,14 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; - struct drm_framebuffer *fb; if (!plane) continue; funcs = plane->helper_private; - fb = plane_state->fb; - - if (fb && funcs->prepare_fb) { - ret = funcs->prepare_fb(plane, fb, plane_state); + if (funcs->prepare_fb) { + ret = funcs->prepare_fb(plane, plane_state); if (ret) goto fail; } @@ -1134,17 +1131,14 @@ fail: const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; - struct drm_framebuffer *fb; if (!plane) continue; funcs = plane->helper_private; - fb = state->plane_states[i]->fb; - - if (fb && funcs->cleanup_fb) - funcs->cleanup_fb(plane, fb, plane_state); + if (funcs->cleanup_fb) + funcs->cleanup_fb(plane, plane_state); } @@ -1300,14 +1294,11 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, for_each_plane_in_state(old_state, plane, plane_state, i) { const struct drm_plane_helper_funcs *funcs; - struct drm_framebuffer *old_fb; funcs = plane->helper_private; - old_fb = plane_state->fb; - - if (old_fb && funcs->cleanup_fb) - funcs->cleanup_fb(plane, old_fb, plane_state); + if (funcs->cleanup_fb) + funcs->cleanup_fb(plane, plane_state); } } EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 5e5a07af02c8..d384ebcf0aaf 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -426,7 +426,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, if (plane_funcs->prepare_fb && plane_state->fb && plane_state->fb != old_fb) { - ret = plane_funcs->prepare_fb(plane, plane_state->fb, + ret = plane_funcs->prepare_fb(plane, plane_state); if (ret) goto out; @@ -479,8 +479,8 @@ int drm_plane_helper_commit(struct drm_plane *plane, ret = 0; } - if (plane_funcs->cleanup_fb && old_fb) - plane_funcs->cleanup_fb(plane, old_fb, plane_state); + if (plane_funcs->cleanup_fb) + plane_funcs->cleanup_fb(plane, plane_state); out: if (plane_state) { if (plane->funcs->atomic_destroy_state) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ca9278be49f7..4eb03b4f91db 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13313,10 +13313,10 @@ static void intel_shared_dpll_init(struct drm_device *dev) */ int intel_prepare_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct drm_device *dev = plane->dev; + struct drm_framebuffer *fb = new_state->fb; struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); @@ -13354,19 +13354,18 @@ intel_prepare_plane_fb(struct drm_plane *plane, */ void intel_cleanup_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { struct drm_device *dev = plane->dev; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb); - if (WARN_ON(!obj)) + if (!obj) return; if (plane->type != DRM_PLANE_TYPE_CURSOR || !INTEL_INFO(dev)->cursor_needs_physical) { mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(fb, old_state); + intel_unpin_fb_obj(old_state->fb, old_state); mutex_unlock(&dev->struct_mutex); } } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2b9e6f9775c5..bfd1204217e2 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1038,10 +1038,8 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe); void intel_finish_page_flip_plane(struct drm_device *dev, int plane); void intel_check_page_flip(struct drm_device *dev, int pipe); int intel_prepare_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state); void intel_cleanup_plane_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state); int intel_plane_atomic_get_property(struct drm_plane *plane, const struct drm_plane_state *state, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index e9dee367b597..30d57e74c42f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -99,22 +99,28 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { }; static int mdp4_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); struct mdp4_kms *mdp4_kms = get_kms(plane); + struct drm_framebuffer *fb = new_state->fb; + + if (!fb) + return 0; DBG("%s: prepare: FB[%u]", mdp4_plane->name, fb->base.id); return msm_framebuffer_prepare(fb, mdp4_kms->id); } static void mdp4_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); struct mdp4_kms *mdp4_kms = get_kms(plane); + struct drm_framebuffer *fb = old_state->fb; + + if (!fb) + return; DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id); msm_framebuffer_cleanup(fb, mdp4_kms->id); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 07fb62fea6dc..a0f5ff0ce8dc 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -250,22 +250,28 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { }; static int mdp5_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct mdp5_kms *mdp5_kms = get_kms(plane); + struct drm_framebuffer *fb = new_state->fb; + + if (!new_state->fb) + return 0; DBG("%s: prepare: FB[%u]", mdp5_plane->name, fb->base.id); return msm_framebuffer_prepare(fb, mdp5_kms->id); } static void mdp5_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct mdp5_kms *mdp5_kms = get_kms(plane); + struct drm_framebuffer *fb = old_state->fb; + + if (!fb) + return; DBG("%s: cleanup: FB[%u]", mdp5_plane->name, fb->base.id); msm_framebuffer_cleanup(fb, mdp5_kms->id); diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 098904696a5c..09e363bb55f2 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -60,17 +60,19 @@ to_omap_plane_state(struct drm_plane_state *state) } static int omap_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { - return omap_framebuffer_pin(fb); + if (!new_state->fb) + return 0; + + return omap_framebuffer_pin(new_state->fb); } static void omap_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state) { - omap_framebuffer_unpin(fb); + if (old_state->fb) + omap_framebuffer_unpin(old_state->fb); } static void omap_plane_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index ddefb85dc4f7..b4af4ab9ce6b 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -480,14 +480,12 @@ static const struct drm_plane_funcs tegra_primary_plane_funcs = { }; static int tegra_plane_prepare_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state) { return 0; } static void tegra_plane_cleanup_fb(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_fb) { } diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index dda401bf910e..5a7f9d4efb1d 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -58,10 +58,8 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, */ struct drm_plane_helper_funcs { int (*prepare_fb)(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *new_state); void (*cleanup_fb)(struct drm_plane *plane, - struct drm_framebuffer *fb, const struct drm_plane_state *old_state); int (*atomic_check)(struct drm_plane *plane, -- cgit v1.3-6-gb490 From aef9dbb8f779ae0ffb46313b07700cac72b58ff4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Sep 2015 12:02:07 +0200 Subject: drm/atomic-helper: Add option to update planes only on active crtc With drivers supporting runtime pm it's generally not a good idea to touch the hardware when it's off. Add an option to the commit_planes helper to support this case. Note that the helpers already add all planes on a crtc when a modeset happens, hence plane updates will not be lost if drivers set this to true. v2: Check for NULL state->crtc before chasing the pointer. Also check both old and new crtc if there's a switch. Finally just outright disallow switching crtcs for a plane if the plane is in active use, on most hardware that doesn't make sense. v3: Since commit_planes(active_only = true) is for enabling things only after all the crtc are on we should only look at the new crtc to decide whether to call the plane hooks - if the current CRTC isn't on then skip. If the old crtc (when moving a plane) went down then the plane should have been disabled as part of the pipe shutdown work already. For which there's currently no helper really unfortunately. Also move the check for wether a plane gets a new CRTC assigned while still in active use out of this patch. v4: Rebase over exynos changes. Cc: Maarten Lankhorst Cc: Thierry Reding Cc: Laurent Pinchart Reviewed-by: Thierry Reding Tested-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 20 ++++++++++++++++++-- drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 +- drivers/gpu/drm/msm/msm_atomic.c | 2 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 +- drivers/gpu/drm/sti/sti_drv.c | 2 +- drivers/gpu/drm/tegra/drm.c | 2 +- include/drm/drm_atomic_helper.h | 3 ++- 8 files changed, 26 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9b0c47690ae8..12c25c54309f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1037,7 +1037,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); drm_atomic_helper_commit_modeset_enables(dev, state); @@ -1146,10 +1146,16 @@ fail: } EXPORT_SYMBOL(drm_atomic_helper_prepare_planes); +bool plane_crtc_active(struct drm_plane_state *state) +{ + return state->crtc && state->crtc->state->active; +} + /** * drm_atomic_helper_commit_planes - commit plane state * @dev: DRM device * @old_state: atomic state object with old state structures + * @active_only: Only commit on active CRTC if set * * This function commits the new plane state using the plane and atomic helper * functions for planes and crtcs. It assumes that the atomic state has already @@ -1164,7 +1170,8 @@ EXPORT_SYMBOL(drm_atomic_helper_prepare_planes); * drm_atomic_helper_commit_planes_on_crtc() instead. */ void drm_atomic_helper_commit_planes(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *old_state, + bool active_only) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; @@ -1180,6 +1187,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_begin) continue; + if (active_only && !crtc->state->active) + continue; + funcs->atomic_begin(crtc, old_crtc_state); } @@ -1191,6 +1201,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs) continue; + if (active_only && !plane_crtc_active(plane->state)) + continue; + /* * Special-case disabling the plane if drivers support it. */ @@ -1210,6 +1223,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_flush) continue; + if (active_only && !crtc->state->active) + continue; + funcs->atomic_flush(crtc, old_crtc_state); } } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 831d2e4cacf9..f0a5839bd226 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -105,7 +105,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit) atomic_inc(&exynos_crtc->pending_update); } - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); exynos_atomic_wait_for_commit(state); diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 1ceb4f22dd89..7eb253bc24df 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -125,7 +125,7 @@ static void complete_commit(struct msm_commit *c) drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); drm_atomic_helper_commit_modeset_enables(dev, state); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 419c2e49adf5..a5f9d8bf75ed 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -96,7 +96,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) dispc_runtime_get(); drm_atomic_helper_commit_modeset_disables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, false); drm_atomic_helper_commit_modeset_enables(dev, old_state); omap_atomic_wait_for_completion(dev, old_state); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 56518eb1269a..ca12e8ca5552 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -456,7 +456,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit) /* Apply the atomic update. */ drm_atomic_helper_commit_modeset_disables(dev, old_state); drm_atomic_helper_commit_modeset_enables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, false); drm_atomic_helper_wait_for_vblanks(dev, old_state); diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 6f4af6a8ba1b..9f85988a43ce 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -59,7 +59,7 @@ static void sti_atomic_complete(struct sti_private *private, */ drm_atomic_helper_commit_modeset_disables(drm, state); - drm_atomic_helper_commit_planes(drm, state); + drm_atomic_helper_commit_planes(drm, state, false); drm_atomic_helper_commit_modeset_enables(drm, state); drm_atomic_helper_wait_for_vblanks(drm, state); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 6d88cf1fcd1c..2486bc24bff6 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -56,7 +56,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra, */ drm_atomic_helper_commit_modeset_disables(drm, state); - drm_atomic_helper_commit_planes(drm, state); + drm_atomic_helper_commit_planes(drm, state, false); drm_atomic_helper_commit_modeset_enables(drm, state); drm_atomic_helper_wait_for_vblanks(drm, state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 11266d147a29..4ffe9dca07c4 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -55,7 +55,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, int drm_atomic_helper_prepare_planes(struct drm_device *dev, struct drm_atomic_state *state); void drm_atomic_helper_commit_planes(struct drm_device *dev, - struct drm_atomic_state *state); + struct drm_atomic_state *state, + bool active_only); void drm_atomic_helper_cleanup_planes(struct drm_device *dev, struct drm_atomic_state *old_state); void drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state); -- cgit v1.3-6-gb490 From 397fd77c0491ceb0ed4783eb88fc05d0222e2030 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 8 Sep 2015 15:00:45 +0200 Subject: drm/atomic-helper: Implement drm_atomic_helper_duplicate_state() This function can be used to duplicate an atomic state object. This is useful for example to implement suspend/resume, where the state before suspend can be saved and restored upon resume. v2: move locking to caller, be more explicit about prerequisites v3: explicitly pass lock acquisition context, improve kerneldoc Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 78 +++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 3 ++ 2 files changed, 81 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 77d55a935793..99411679312e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2371,6 +2371,84 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) } EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); +/** + * drm_atomic_helper_duplicate_state - duplicate an atomic state object + * @dev: DRM device + * @ctx: lock acquisition context + * + * Makes a copy of the current atomic state by looping over all objects and + * duplicating their respective states. + * + * Note that this treats atomic state as persistent between save and restore. + * Drivers must make sure that this is possible and won't result in confusion + * or erroneous behaviour. + * + * Note that if callers haven't already acquired all modeset locks this might + * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). + * + * Returns: + * A pointer to the copy of the atomic state object on success or an + * ERR_PTR()-encoded error code on failure. + */ +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct drm_connector *conn; + struct drm_plane *plane; + struct drm_crtc *crtc; + int err = 0; + + state = drm_atomic_state_alloc(dev); + if (!state) + return ERR_PTR(-ENOMEM); + + state->acquire_ctx = ctx; + + drm_for_each_crtc(crtc, dev) { + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + err = PTR_ERR(crtc_state); + goto free; + } + } + + drm_for_each_plane(plane, dev) { + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + err = PTR_ERR(plane_state); + goto free; + } + } + + drm_for_each_connector(conn, dev) { + struct drm_connector_state *conn_state; + + conn_state = drm_atomic_get_connector_state(state, conn); + if (IS_ERR(conn_state)) { + err = PTR_ERR(conn_state); + goto free; + } + } + + /* clear the acquire context so that it isn't accidentally reused */ + state->acquire_ctx = NULL; + +free: + if (err < 0) { + drm_atomic_state_free(state); + state = ERR_PTR(err); + } + + return state; +} +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state); + /** * __drm_atomic_helper_connector_destroy_state - release connector state * @connector: connector object diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 4ffe9dca07c4..1547eb43c14a 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -118,6 +118,9 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, struct drm_connector_state *state); struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +struct drm_atomic_state * +drm_atomic_helper_duplicate_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx); void __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); -- cgit v1.3-6-gb490 From 2b712be72fddc74ac12c2857af24a20a93d9e9c0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 27 Aug 2015 17:23:26 +0300 Subject: drm/dp: s/I2C_STATUS/I2C_WRITE_STATUS_UPDATE/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the I2C_STATUS request to I2C_WRITE_STATUS_UPDATE to match the spec. Acked-by: Alex Deucher Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/tegra/dpaux.c | 2 +- include/drm/drm_dp_helper.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 224a7dc8e4ed..1cc09ff14a4f 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -149,7 +149,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, break; - case DP_AUX_I2C_STATUS: + case DP_AUX_I2C_WRITE_STATUS_UPDATE: if (msg->request & DP_AUX_I2C_MOT) value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; else diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 499e9f625aef..d0c88107996a 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -46,7 +46,7 @@ #define DP_AUX_I2C_WRITE 0x0 #define DP_AUX_I2C_READ 0x1 -#define DP_AUX_I2C_STATUS 0x2 +#define DP_AUX_I2C_WRITE_STATUS_UPDATE 0x2 #define DP_AUX_I2C_MOT 0x4 #define DP_AUX_NATIVE_WRITE 0x8 #define DP_AUX_NATIVE_READ 0x9 -- cgit v1.3-6-gb490 From 9e5a3b529e8419db1dd2b32c86a1fb42fc07347d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 7 Sep 2015 18:22:57 +0300 Subject: drm: Remove the 'mode' argument from drm_select_eld() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_select_eld() doesn't look at the passed in mode, so don't pass it in. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_edid.c | 4 +--- drivers/gpu/drm/i915/intel_audio.c | 2 +- include/drm/drm_edid.h | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9afb1fc15b34..e32218f03584 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3396,7 +3396,6 @@ EXPORT_SYMBOL(drm_av_sync_delay); /** * drm_select_eld - select one ELD from multiple HDMI/DP sinks * @encoder: the encoder just changed display mode - * @mode: the adjusted display mode * * It's possible for one encoder to be associated with multiple HDMI/DP sinks. * The policy is now hard coded to simply use the first HDMI/DP sink's ELD. @@ -3404,8 +3403,7 @@ EXPORT_SYMBOL(drm_av_sync_delay); * Return: The connector associated with the first HDMI/DP sink that has ELD * attached to it. */ -struct drm_connector *drm_select_eld(struct drm_encoder *encoder, - struct drm_display_mode *mode) +struct drm_connector *drm_select_eld(struct drm_encoder *encoder) { struct drm_connector *connector; struct drm_device *dev = encoder->dev; diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index dc32cf4585f8..1314ebb282e4 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -401,7 +401,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - connector = drm_select_eld(encoder, mode); + connector = drm_select_eld(encoder); if (!connector) return; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 53c53c459b15..31528d957331 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -327,8 +327,7 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); int drm_av_sync_delay(struct drm_connector *connector, struct drm_display_mode *mode); -struct drm_connector *drm_select_eld(struct drm_encoder *encoder, - struct drm_display_mode *mode); +struct drm_connector *drm_select_eld(struct drm_encoder *encoder); int drm_load_edid_firmware(struct drm_connector *connector); int -- cgit v1.3-6-gb490 From 3a818d350f6b5ad542175ab1f71c027787ce952e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 7 Sep 2015 18:22:58 +0300 Subject: drm: Make drm_av_sync_delay() 'mode' argument const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_av_sync_delay() doesn't change the passed in mode, so make it const. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_edid.c | 2 +- include/drm/drm_edid.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index e32218f03584..d895556be4f0 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3361,7 +3361,7 @@ EXPORT_SYMBOL(drm_edid_to_speaker_allocation); * the sink doesn't support audio or video. */ int drm_av_sync_delay(struct drm_connector *connector, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); int a, v; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 31528d957331..2af97691e878 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -326,7 +326,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid); int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); int drm_av_sync_delay(struct drm_connector *connector, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); struct drm_connector *drm_select_eld(struct drm_encoder *encoder); int drm_load_edid_firmware(struct drm_connector *connector); -- cgit v1.3-6-gb490 From c86fb9d997428e0d55ab5a47488b6ba3bc4b5c5b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 10 Sep 2015 22:39:22 +0200 Subject: drm: Nuke drm_framebuffer->helper_private It's completely unused and there's really no reason for this: - drm_framebuffer structures are invariant after creation, no need for helpers to manipulate them. - drm_framebuffer structures should just be embedded (and that's what all the drivers do). Stumbled over this since some folks are apparently concerned with the overhead of struct drm_framebuffer and this is an easy 8 byte saving. More could be gained by ditching the legacy fields and recomputing stuff from the fourcc value. But that would require some drm-wide cocci and real justification. Cc: gary.k.smith@intel.com Reviewed-by: David Herrmann Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 75f49c1ef8bb..c0366e9152e2 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -210,8 +210,6 @@ struct drm_framebuffer { int flags; uint32_t pixel_format; /* fourcc format */ struct list_head filp_head; - /* if you are using the helper */ - void *helper_private; }; struct drm_property_blob { -- cgit v1.3-6-gb490 From 11bff0b70cc003b995cf4c2acec4adab90957b02 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Sep 2015 18:35:36 +0200 Subject: mtd: spi-nor: Decouple SPI NOR's device_node from controller device The problem this patch is trying to address is such, that SPI NOR flash devices attached to a dedicated SPI NOR controller cannot read their properties from the associated struct device_node. A couple of facts first: 1) Each SPI NOR flash has a struct spi_nor associated with it. 2) Each SPI NOR flash has certain device properties associated with it, for example the OF property 'm25p,fast-read' is a good pick. These properties are used by the SPI NOR core to select which opcodes are sent to such SPI NOR flash. These properties are coming from spi_nor .dev->of_node . The problem is, that for SPI NOR controllers, the struct spi_nor .dev element points to the struct device of the SPI NOR controller, not the SPI NOR flash. Therefore, the associated dev->of_node also is the one of the controller and therefore the SPI NOR core code is trying to parse the SPI NOR controller's properties, not the properties of the SPI NOR flash. Note: The m25p80 driver is not affected, because the controller and the flash are the same device, so the associated device_node of the controller and the flash are the same. This patch adjusts the SPI NOR core such that the device_node is not picked from spi_nor .dev directly, but from a new separate spi_nor .flash_node element. This let's the SPI NOR controller drivers set up a different spi_nor .flash_node element for each SPI NOR flash. This patch also fixes the controller drivers to be compatible with this modification and correctly set the spi_nor .flash_node element. This patch is inspired by 5844feeaa4154d1c46d3462c7a4653d22356d8b4 mtd: nand: add common DT init code Signed-off-by: Marek Vasut Signed-off-by: Brian Norris --- drivers/mtd/devices/m25p80.c | 1 + drivers/mtd/spi-nor/fsl-quadspi.c | 1 + drivers/mtd/spi-nor/nxp-spifi.c | 1 + drivers/mtd/spi-nor/spi-nor.c | 2 +- include/linux/mtd/spi-nor.h | 2 ++ 5 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index b6bc9a2a5f87..05bf0d71abea 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -200,6 +200,7 @@ static int m25p_probe(struct spi_device *spi) nor->read_reg = m25p80_read_reg; nor->dev = &spi->dev; + nor->flash_node = spi->dev.of_node; nor->priv = flash; spi_set_drvdata(spi, flash); diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index f28dcc1cd63f..f72483247c75 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -1013,6 +1013,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) mtd = &nor->mtd; nor->dev = dev; + nor->flash_node = np; nor->priv = q; /* fill the hooks */ diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c index 0f6b452574bd..ce7bf6b2916b 100644 --- a/drivers/mtd/spi-nor/nxp-spifi.c +++ b/drivers/mtd/spi-nor/nxp-spifi.c @@ -331,6 +331,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, writel(ctrl, spifi->io_base + SPIFI_CTRL); spifi->nor.dev = spifi->dev; + spifi->nor.flash_node = np; spifi->nor.priv = spifi; spifi->nor.read = nxp_spifi_read; spifi->nor.write = nxp_spifi_write; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 55c67a4ea231..22cca87db9ca 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1005,7 +1005,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) const struct flash_info *info = NULL; struct device *dev = nor->dev; struct mtd_info *mtd = &nor->mtd; - struct device_node *np = dev->of_node; + struct device_node *np = nor->flash_node; int ret; int i; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 495433d3f56d..6379e107f2e5 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -134,6 +134,7 @@ struct mtd_info; * @mtd: point to a mtd_info structure * @lock: the lock for the read/write/erase/lock/unlock operations * @dev: point to a spi device, or a spi nor controller device. + * @flash_node: point to a device node describing this flash instance. * @page_size: the page size of the SPI NOR * @addr_width: number of address bytes * @erase_opcode: the opcode for erasing a sector @@ -165,6 +166,7 @@ struct spi_nor { struct mtd_info mtd; struct mutex lock; struct device *dev; + struct device_node *flash_node; u32 page_size; u8 addr_width; u8 erase_opcode; -- cgit v1.3-6-gb490 From 61528d888adf9470db73aaadf1ff9ca35942262a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Sep 2015 18:35:37 +0200 Subject: mtd: nand: Rename nand_chip .dn to .flash_node Use a more descriptive name for the device_node element in struct nand_chip . This name matches the element name used for device_node property of a flash in the spi-nor framework. Signed-off-by: Marek Vasut Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 5 +++-- drivers/mtd/nand/nand_base.c | 4 ++-- include/linux/mtd/nand.h | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index fddb795eeb71..048e4e030fc8 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1792,7 +1792,8 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) memset(cfg, 0, sizeof(*cfg)); - ret = of_property_read_u32(chip->dn, "brcm,nand-oob-sector-size", + ret = of_property_read_u32(chip->flash_node, + "brcm,nand-oob-sector-size", &oob_sector); if (ret) { /* Use detected size */ @@ -1899,7 +1900,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host) mtd = &host->mtd; chip = &host->chip; - chip->dn = dn; + chip->flash_node = dn; chip->priv = host; mtd->priv = chip; mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ceb68ca8277a..51f7816d67c9 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3846,8 +3846,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *type; int ret; - if (chip->dn) { - ret = nand_dt_init(mtd, chip, chip->dn); + if (chip->flash_node) { + ret = nand_dt_init(mtd, chip, chip->flash_node); if (ret) return ret; } diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 272f42952f34..3140b3d94838 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -544,7 +544,7 @@ struct nand_buffers { * flash device * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the * flash device. - * @dn: [BOARDSPECIFIC] device node describing this instance + * @flash_node: [BOARDSPECIFIC] device node describing this instance * @read_byte: [REPLACEABLE] read one byte from the chip * @read_word: [REPLACEABLE] read one word from the chip * @write_byte: [REPLACEABLE] write a single byte to the chip on the @@ -647,7 +647,7 @@ struct nand_chip { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; - struct device_node *dn; + struct device_node *flash_node; uint8_t (*read_byte)(struct mtd_info *mtd); u16 (*read_word)(struct mtd_info *mtd); -- cgit v1.3-6-gb490 From f9f3ce835ddce3c669eee869253105f88819888b Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Wed, 19 Aug 2015 15:26:44 +0530 Subject: mtd: spi-nor: Zap unneeded write_enable from write_reg The 'write_enable' argument is unused and unneeded, so remove it from the API. Signed-off-by: Jagan Teki Cc: David Woodhouse Cc: Han Xu [Brian: fixed for nxp-spifi.c] Signed-off-by: Brian Norris --- drivers/mtd/devices/m25p80.c | 3 +-- drivers/mtd/spi-nor/fsl-quadspi.c | 3 +-- drivers/mtd/spi-nor/nxp-spifi.c | 3 +-- drivers/mtd/spi-nor/spi-nor.c | 16 ++++++++-------- include/linux/mtd/spi-nor.h | 3 +-- 5 files changed, 12 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 05bf0d71abea..4b5d7a4655fd 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -61,8 +61,7 @@ static int m25p_cmdsz(struct spi_nor *nor) return 1 + nor->addr_width; } -static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, - int wr_en) +static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) { struct m25p *flash = nor->priv; struct spi_device *spi = flash->spi; diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index f72483247c75..2954f89fc8be 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -797,8 +797,7 @@ static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) return 0; } -static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, - int write_enable) +static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) { struct fsl_qspi *q = nor->priv; int ret; diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c index ce7bf6b2916b..9e82098ae644 100644 --- a/drivers/mtd/spi-nor/nxp-spifi.c +++ b/drivers/mtd/spi-nor/nxp-spifi.c @@ -149,8 +149,7 @@ static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) return nxp_spifi_wait_for_cmd(spifi); } -static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, - int len, int write_enable) +static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) { struct nxp_spifi *spifi = nor->priv; u32 cmd; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3694f6697344..8818d4325d20 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -145,7 +145,7 @@ static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) static inline int write_sr(struct spi_nor *nor, u8 val) { nor->cmd_buf[0] = val; - return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); + return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); } /* @@ -154,7 +154,7 @@ static inline int write_sr(struct spi_nor *nor, u8 val) */ static inline int write_enable(struct spi_nor *nor) { - return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); + return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); } /* @@ -162,7 +162,7 @@ static inline int write_enable(struct spi_nor *nor) */ static inline int write_disable(struct spi_nor *nor) { - return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0); + return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); } static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) @@ -188,7 +188,7 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, write_enable(nor); cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; - status = nor->write_reg(nor, cmd, NULL, 0, 0); + status = nor->write_reg(nor, cmd, NULL, 0); if (need_wren) write_disable(nor); @@ -196,7 +196,7 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, default: /* Spansion style */ nor->cmd_buf[0] = enable << 7; - return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); + return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); } } static inline int spi_nor_sr_ready(struct spi_nor *nor) @@ -267,7 +267,7 @@ static int erase_chip(struct spi_nor *nor) { dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); - return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); + return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); } static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) @@ -893,7 +893,7 @@ static int write_sr_cr(struct spi_nor *nor, u16 val) nor->cmd_buf[0] = val & 0xff; nor->cmd_buf[1] = (val >> 8); - return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0); + return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2); } static int spansion_quad_enable(struct spi_nor *nor) @@ -935,7 +935,7 @@ static int micron_quad_enable(struct spi_nor *nor) /* set EVCR, enable quad I/O */ nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; - ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0); + ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1); if (ret < 0) { dev_err(nor->dev, "error while writing EVCR register\n"); return ret; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 6379e107f2e5..e9c912d73141 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -186,8 +186,7 @@ struct spi_nor { int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, u8 *buf, size_t len); int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); - int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, - int write_enable); + int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); int (*read)(struct spi_nor *nor, loff_t from, size_t len, size_t *retlen, u_char *read_buf); -- cgit v1.3-6-gb490 From e0f5f3afd2cffa96291cd852056d83ff4e2e99c7 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Fri, 14 Aug 2015 17:23:09 +0100 Subject: sched/fair: Make load tracking frequency scale-invariant Apply frequency scaling correction factor to per-entity load tracking to make it frequency invariant. Currently, load appears bigger when the CPU is running slower which affects load-balancing decisions. Each segment of the sched_avg.load_sum geometric series is now scaled by the current frequency so that the sched_avg.load_avg of each sched entity will be invariant from frequency scaling. Moreover, cfs_rq.runnable_load_sum is scaled by the current frequency as well. Signed-off-by: Dietmar Eggemann Signed-off-by: Morten Rasmussen Signed-off-by: Peter Zijlstra (Intel) Acked-by: Vincent Guittot Cc: Dietmar Eggemann Cc: Juri Lelli Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: daniel.lezcano@linaro.org Cc: mturquette@baylibre.com Cc: pang.xunlei@zte.com.cn Cc: rjw@rjwysocki.net Cc: sgurrappadi@nvidia.com Cc: yuyang.du@intel.com Link: http://lkml.kernel.org/r/1439569394-11974-2-git-send-email-morten.rasmussen@arm.com Signed-off-by: Ingo Molnar --- include/linux/sched.h | 6 +++--- kernel/sched/fair.c | 27 +++++++++++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index a4ab9daa387c..c8d923ba429d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1177,9 +1177,9 @@ struct load_weight { /* * The load_avg/util_avg accumulates an infinite geometric series. - * 1) load_avg factors the amount of time that a sched_entity is - * runnable on a rq into its weight. For cfs_rq, it is the aggregated - * such weights of all runnable and blocked sched_entities. + * 1) load_avg factors frequency scaling into the amount of time that a + * sched_entity is runnable on a rq into its weight. For cfs_rq, it is the + * aggregated such weights of all runnable and blocked sched_entities. * 2) util_avg factors frequency scaling into the amount of time * that a sched_entity is running on a CPU, in the range [0..SCHED_LOAD_SCALE]. * For cfs_rq, it is the aggregated such times of all runnable and diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 47ece22e7ae1..86cb27cae4b7 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2515,6 +2515,8 @@ static u32 __compute_runnable_contrib(u64 n) return contrib + runnable_avg_yN_sum[n]; } +#define scale(v, s) ((v)*(s) >> SCHED_CAPACITY_SHIFT) + /* * We can represent the historical contribution to runnable average as the * coefficients of a geometric series. To do this we sub-divide our runnable @@ -2547,9 +2549,9 @@ static __always_inline int __update_load_avg(u64 now, int cpu, struct sched_avg *sa, unsigned long weight, int running, struct cfs_rq *cfs_rq) { - u64 delta, periods; + u64 delta, scaled_delta, periods; u32 contrib; - int delta_w, decayed = 0; + int delta_w, scaled_delta_w, decayed = 0; unsigned long scale_freq = arch_scale_freq_capacity(NULL, cpu); delta = now - sa->last_update_time; @@ -2585,13 +2587,16 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa, * period and accrue it. */ delta_w = 1024 - delta_w; + scaled_delta_w = scale(delta_w, scale_freq); if (weight) { - sa->load_sum += weight * delta_w; - if (cfs_rq) - cfs_rq->runnable_load_sum += weight * delta_w; + sa->load_sum += weight * scaled_delta_w; + if (cfs_rq) { + cfs_rq->runnable_load_sum += + weight * scaled_delta_w; + } } if (running) - sa->util_sum += delta_w * scale_freq >> SCHED_CAPACITY_SHIFT; + sa->util_sum += scaled_delta_w; delta -= delta_w; @@ -2608,23 +2613,25 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa, /* Efficiently calculate \sum (1..n_period) 1024*y^i */ contrib = __compute_runnable_contrib(periods); + contrib = scale(contrib, scale_freq); if (weight) { sa->load_sum += weight * contrib; if (cfs_rq) cfs_rq->runnable_load_sum += weight * contrib; } if (running) - sa->util_sum += contrib * scale_freq >> SCHED_CAPACITY_SHIFT; + sa->util_sum += contrib; } /* Remainder of delta accrued against u_0` */ + scaled_delta = scale(delta, scale_freq); if (weight) { - sa->load_sum += weight * delta; + sa->load_sum += weight * scaled_delta; if (cfs_rq) - cfs_rq->runnable_load_sum += weight * delta; + cfs_rq->runnable_load_sum += weight * scaled_delta; } if (running) - sa->util_sum += delta * scale_freq >> SCHED_CAPACITY_SHIFT; + sa->util_sum += scaled_delta; sa->period_contrib += delta; -- cgit v1.3-6-gb490 From e3279a2e6d697e00e74f905851ee7cf532f72b2d Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Sat, 15 Aug 2015 00:04:41 +0100 Subject: sched/fair: Make utilization tracking CPU scale-invariant Besides the existing frequency scale-invariance correction factor, apply CPU scale-invariance correction factor to utilization tracking to compensate for any differences in compute capacity. This could be due to micro-architectural differences (i.e. instructions per seconds) between cpus in HMP systems (e.g. big.LITTLE), and/or differences in the current maximum frequency supported by individual cpus in SMP systems. In the existing implementation utilization isn't comparable between cpus as it is relative to the capacity of each individual CPU. Each segment of the sched_avg.util_sum geometric series is now scaled by the CPU performance factor too so the sched_avg.util_avg of each sched entity will be invariant from the particular CPU of the HMP/SMP system on which the sched entity is scheduled. With this patch, the utilization of a CPU stays relative to the max CPU performance of the fastest CPU in the system. In contrast to utilization (sched_avg.util_sum), load (sched_avg.load_sum) should not be scaled by compute capacity. The utilization metric is based on running time which only makes sense when cpus are _not_ fully utilized (utilization cannot go beyond 100% even if more tasks are added), where load is runnable time which isn't limited by the capacity of the CPU and therefore is a better metric for overloaded scenarios. If we run two nice-0 busy loops on two cpus with different compute capacity their load should be similar since their compute demands are the same. We have to assume that the compute demand of any task running on a fully utilized CPU (no spare cycles = 100% utilization) is high and the same no matter of the compute capacity of its current CPU, hence we shouldn't scale load by CPU capacity. Signed-off-by: Dietmar Eggemann Signed-off-by: Morten Rasmussen Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/55CE7409.1000700@arm.com Signed-off-by: Ingo Molnar --- include/linux/sched.h | 2 +- kernel/sched/fair.c | 7 ++++--- kernel/sched/sched.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index c8d923ba429d..bd38b3ee9e83 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1180,7 +1180,7 @@ struct load_weight { * 1) load_avg factors frequency scaling into the amount of time that a * sched_entity is runnable on a rq into its weight. For cfs_rq, it is the * aggregated such weights of all runnable and blocked sched_entities. - * 2) util_avg factors frequency scaling into the amount of time + * 2) util_avg factors frequency and cpu scaling into the amount of time * that a sched_entity is running on a CPU, in the range [0..SCHED_LOAD_SCALE]. * For cfs_rq, it is the aggregated such times of all runnable and * blocked sched_entities. diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 102cdf1e4e97..573dc98c6248 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2553,6 +2553,7 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa, u32 contrib; int delta_w, scaled_delta_w, decayed = 0; unsigned long scale_freq = arch_scale_freq_capacity(NULL, cpu); + unsigned long scale_cpu = arch_scale_cpu_capacity(NULL, cpu); delta = now - sa->last_update_time; /* @@ -2596,7 +2597,7 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa, } } if (running) - sa->util_sum += scaled_delta_w; + sa->util_sum += scale(scaled_delta_w, scale_cpu); delta -= delta_w; @@ -2620,7 +2621,7 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa, cfs_rq->runnable_load_sum += weight * contrib; } if (running) - sa->util_sum += contrib; + sa->util_sum += scale(contrib, scale_cpu); } /* Remainder of delta accrued against u_0` */ @@ -2631,7 +2632,7 @@ __update_load_avg(u64 now, int cpu, struct sched_avg *sa, cfs_rq->runnable_load_sum += weight * scaled_delta; } if (running) - sa->util_sum += scaled_delta; + sa->util_sum += scale(scaled_delta, scale_cpu); sa->period_contrib += delta; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c0726d5fd6a3..167ab4844ee6 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1398,7 +1398,7 @@ unsigned long arch_scale_freq_capacity(struct sched_domain *sd, int cpu) static __always_inline unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu) { - if ((sd->flags & SD_SHARE_CPUCAPACITY) && (sd->span_weight > 1)) + if (sd && (sd->flags & SD_SHARE_CPUCAPACITY) && (sd->span_weight > 1)) return sd->smt_gain / sd->span_weight; return SCHED_CAPACITY_SCALE; -- cgit v1.3-6-gb490 From b0e878759452314676fbdd71df4ac67e7d08de5d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 28 Aug 2015 14:06:07 +0200 Subject: perf/abi: Document some more aspects of the perf ABI Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 105 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 092a0e8a479a..d61ee4459eee 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -140,27 +140,60 @@ struct hw_perf_event { }; #endif }; + /* + * If the event is a per task event, this will point to the task in + * question. See the comment in perf_event_alloc(). + */ struct task_struct *target; + +/* + * hw_perf_event::state flags; used to track the PERF_EF_* state. + */ +#define PERF_HES_STOPPED 0x01 /* the counter is stopped */ +#define PERF_HES_UPTODATE 0x02 /* event->count up-to-date */ +#define PERF_HES_ARCH 0x04 + int state; + + /* + * The last observed hardware counter value, updated with a + * local64_cmpxchg() such that pmu::read() can be called nested. + */ local64_t prev_count; + + /* + * The period to start the next sample with. + */ u64 sample_period; + + /* + * The period we started this sample with. + */ u64 last_period; + + /* + * However much is left of the current period; note that this is + * a full 64bit value and allows for generation of periods longer + * than hardware might allow. + */ local64_t period_left; + + /* + * State for throttling the event, see __perf_event_overflow() and + * perf_adjust_freq_unthr_context(). + */ u64 interrupts_seq; u64 interrupts; + /* + * State for freq target events, see __perf_event_overflow() and + * perf_adjust_freq_unthr_context(). + */ u64 freq_time_stamp; u64 freq_count_stamp; #endif }; -/* - * hw_perf_event::state flags - */ -#define PERF_HES_STOPPED 0x01 /* the counter is stopped */ -#define PERF_HES_UPTODATE 0x02 /* event->count up-to-date */ -#define PERF_HES_ARCH 0x04 - struct perf_event; /* @@ -210,7 +243,19 @@ struct pmu { /* * Try and initialize the event for this PMU. - * Should return -ENOENT when the @event doesn't match this PMU. + * + * Returns: + * -ENOENT -- @event is not for this PMU + * + * -ENODEV -- @event is for this PMU but PMU not present + * -EBUSY -- @event is for this PMU but PMU temporarily unavailable + * -EINVAL -- @event is for this PMU but @event is not valid + * -EOPNOTSUPP -- @event is for this PMU, @event is valid, but not supported + * -EACCESS -- @event is for this PMU, @event is valid, but no privilidges + * + * 0 -- @event is for this PMU and valid + * + * Other error return values are allowed. */ int (*event_init) (struct perf_event *event); @@ -221,27 +266,61 @@ struct pmu { void (*event_mapped) (struct perf_event *event); /*optional*/ void (*event_unmapped) (struct perf_event *event); /*optional*/ + /* + * Flags for ->add()/->del()/ ->start()/->stop(). There are + * matching hw_perf_event::state flags. + */ #define PERF_EF_START 0x01 /* start the counter when adding */ #define PERF_EF_RELOAD 0x02 /* reload the counter when starting */ #define PERF_EF_UPDATE 0x04 /* update the counter when stopping */ /* - * Adds/Removes a counter to/from the PMU, can be done inside - * a transaction, see the ->*_txn() methods. + * Adds/Removes a counter to/from the PMU, can be done inside a + * transaction, see the ->*_txn() methods. + * + * The add/del callbacks will reserve all hardware resources required + * to service the event, this includes any counter constraint + * scheduling etc. + * + * Called with IRQs disabled and the PMU disabled on the CPU the event + * is on. + * + * ->add() called without PERF_EF_START should result in the same state + * as ->add() followed by ->stop(). + * + * ->del() must always PERF_EF_UPDATE stop an event. If it calls + * ->stop() that must deal with already being stopped without + * PERF_EF_UPDATE. */ int (*add) (struct perf_event *event, int flags); void (*del) (struct perf_event *event, int flags); /* - * Starts/Stops a counter present on the PMU. The PMI handler - * should stop the counter when perf_event_overflow() returns - * !0. ->start() will be used to continue. + * Starts/Stops a counter present on the PMU. + * + * The PMI handler should stop the counter when perf_event_overflow() + * returns !0. ->start() will be used to continue. + * + * Also used to change the sample period. + * + * Called with IRQs disabled and the PMU disabled on the CPU the event + * is on -- will be called from NMI context with the PMU generates + * NMIs. + * + * ->stop() with PERF_EF_UPDATE will read the counter and update + * period/count values like ->read() would. + * + * ->start() with PERF_EF_RELOAD will reprogram the the counter + * value, must be preceded by a ->stop() with PERF_EF_UPDATE. */ void (*start) (struct perf_event *event, int flags); void (*stop) (struct perf_event *event, int flags); /* * Updates the counter value of the event. + * + * For sampling capable PMUs this will also update the software period + * hw_perf_event::period_left field. */ void (*read) (struct perf_event *event); -- cgit v1.3-6-gb490 From fbbe07011581990ef74dfac06dc8511b1a14badb Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Thu, 3 Sep 2015 20:07:45 -0700 Subject: perf/core: Add a 'flags' parameter to the PMU transactional interfaces Currently, the PMU interface allows reading only one counter at a time. But some PMUs like the 24x7 counters in Power, support reading several counters at once. To leveage this functionality, extend the transaction interface to support a "transaction type". The first type, PERF_PMU_TXN_ADD, refers to the existing transactions, i.e. used to _schedule_ all the events on the PMU as a group. A second transaction type, PERF_PMU_TXN_READ, will be used in a follow-on patch, by the 24x7 counters to read several counters at once. Extend the transaction interfaces to the PMU to accept a 'txn_flags' parameter and use this parameter to ignore any transactions that are not of type PERF_PMU_TXN_ADD. Thanks to Peter Zijlstra for his input. Signed-off-by: Sukadev Bhattiprolu [peterz: s390 compile fix] Signed-off-by: Peter Zijlstra (Intel) Acked-by: Michael Ellerman Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1441336073-22750-3-git-send-email-sukadev@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- arch/powerpc/perf/core-book3s.c | 30 +++++++++++++++++++++++++++++- arch/s390/kernel/perf_cpum_cf.c | 30 +++++++++++++++++++++++++++++- arch/sparc/kernel/perf_event.c | 25 ++++++++++++++++++++++++- arch/x86/kernel/cpu/perf_event.c | 32 +++++++++++++++++++++++++++++++- arch/x86/kernel/cpu/perf_event.h | 1 + include/linux/perf_event.h | 14 +++++++++++--- kernel/events/core.c | 31 ++++++++++++++++++++++++++++--- 7 files changed, 153 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index b0382f3f1095..c84074185c80 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -49,6 +49,7 @@ struct cpu_hw_events { unsigned long avalues[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; unsigned int group_flag; + unsigned int txn_flags; int n_txn_start; /* BHRB bits */ @@ -1586,11 +1587,21 @@ static void power_pmu_stop(struct perf_event *event, int ef_flags) * Start group events scheduling transaction * Set the flag to make pmu::enable() not perform the * schedulability test, it will be performed at commit time + * + * We only support PERF_PMU_TXN_ADD transactions. Save the + * transaction flags but otherwise ignore non-PERF_PMU_TXN_ADD + * transactions. */ -static void power_pmu_start_txn(struct pmu *pmu) +static void power_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) { struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); + WARN_ON_ONCE(cpuhw->txn_flags); /* txn already in flight */ + + cpuhw->txn_flags = txn_flags; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; + perf_pmu_disable(pmu); cpuhw->group_flag |= PERF_EVENT_TXN; cpuhw->n_txn_start = cpuhw->n_events; @@ -1604,6 +1615,14 @@ static void power_pmu_start_txn(struct pmu *pmu) static void power_pmu_cancel_txn(struct pmu *pmu) { struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); + unsigned int txn_flags; + + WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */ + + txn_flags = cpuhw->txn_flags; + cpuhw->txn_flags = 0; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; cpuhw->group_flag &= ~PERF_EVENT_TXN; perf_pmu_enable(pmu); @@ -1621,7 +1640,15 @@ static int power_pmu_commit_txn(struct pmu *pmu) if (!ppmu) return -EAGAIN; + cpuhw = this_cpu_ptr(&cpu_hw_events); + WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */ + + if (cpuhw->txn_flags & ~PERF_PMU_TXN_ADD) { + cpuhw->txn_flags = 0; + return 0; + } + n = cpuhw->n_events; if (check_excludes(cpuhw->event, cpuhw->flags, 0, n)) return -EAGAIN; @@ -1633,6 +1660,7 @@ static int power_pmu_commit_txn(struct pmu *pmu) cpuhw->event[i]->hw.config = cpuhw->events[i]; cpuhw->group_flag &= ~PERF_EVENT_TXN; + cpuhw->txn_flags = 0; perf_pmu_enable(pmu); return 0; } diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 56fdad479115..19138be412d6 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -72,6 +72,7 @@ struct cpu_hw_events { atomic_t ctr_set[CPUMF_CTR_SET_MAX]; u64 state, tx_state; unsigned int flags; + unsigned int txn_flags; }; static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .ctr_set = { @@ -82,6 +83,7 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { }, .state = 0, .flags = 0, + .txn_flags = 0, }; static int get_counter_set(u64 event) @@ -572,11 +574,21 @@ static void cpumf_pmu_del(struct perf_event *event, int flags) /* * Start group events scheduling transaction. * Set flags to perform a single test at commit time. + * + * We only support PERF_PMU_TXN_ADD transactions. Save the + * transaction flags but otherwise ignore non-PERF_PMU_TXN_ADD + * transactions. */ -static void cpumf_pmu_start_txn(struct pmu *pmu) +static void cpumf_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) { struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); + WARN_ON_ONCE(cpuhw->txn_flags); /* txn already in flight */ + + cpuhw->txn_flags = txn_flags; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; + perf_pmu_disable(pmu); cpuhw->flags |= PERF_EVENT_TXN; cpuhw->tx_state = cpuhw->state; @@ -589,8 +601,16 @@ static void cpumf_pmu_start_txn(struct pmu *pmu) */ static void cpumf_pmu_cancel_txn(struct pmu *pmu) { + unsigned int txn_flags; struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); + WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */ + + txn_flags = cpuhw->txn_flags; + cpuhw->txn_flags = 0; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; + WARN_ON(cpuhw->tx_state != cpuhw->state); cpuhw->flags &= ~PERF_EVENT_TXN; @@ -607,6 +627,13 @@ static int cpumf_pmu_commit_txn(struct pmu *pmu) struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); u64 state; + WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */ + + if (cpuhw->txn_flags & ~PERF_PMU_TXN_ADD) { + cpuhw->txn_flags = 0; + return 0; + } + /* check if the updated state can be scheduled */ state = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1); state >>= CPUMF_LCCTL_ENABLE_SHIFT; @@ -614,6 +641,7 @@ static int cpumf_pmu_commit_txn(struct pmu *pmu) return -EPERM; cpuhw->flags &= ~PERF_EVENT_TXN; + cpuhw->txn_flags = 0; perf_pmu_enable(pmu); return 0; } diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index e3f89c7e5062..2c0984d146ec 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -109,6 +109,7 @@ struct cpu_hw_events { int enabled; unsigned int group_flag; + unsigned int txn_flags; }; static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, }; @@ -1494,10 +1495,16 @@ static int sparc_pmu_event_init(struct perf_event *event) * Set the flag to make pmu::enable() not perform the * schedulability test, it will be performed at commit time */ -static void sparc_pmu_start_txn(struct pmu *pmu) +static void sparc_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) { struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); + WARN_ON_ONCE(cpuhw->txn_flags); /* txn already in flight */ + + cpuhw->txn_flags = txn_flags; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; + perf_pmu_disable(pmu); cpuhw->group_flag |= PERF_EVENT_TXN; } @@ -1510,6 +1517,14 @@ static void sparc_pmu_start_txn(struct pmu *pmu) static void sparc_pmu_cancel_txn(struct pmu *pmu) { struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); + unsigned int txn_flags; + + WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */ + + txn_flags = cpuhw->txn_flags; + cpuhw->txn_flags = 0; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; cpuhw->group_flag &= ~PERF_EVENT_TXN; perf_pmu_enable(pmu); @@ -1528,6 +1543,13 @@ static int sparc_pmu_commit_txn(struct pmu *pmu) if (!sparc_pmu) return -EINVAL; + WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */ + + if (cpuc->txn_flags & ~PERF_PMU_TXN_ADD) { + cpuc->txn_flags = 0; + return 0; + } + n = cpuc->n_events; if (check_excludes(cpuc->event, 0, n)) return -EINVAL; @@ -1535,6 +1557,7 @@ static int sparc_pmu_commit_txn(struct pmu *pmu) return -EAGAIN; cpuc->group_flag &= ~PERF_EVENT_TXN; + cpuc->txn_flags = 0; perf_pmu_enable(pmu); return 0; } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 66dd3fe99b82..dc77ef470e0e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1748,9 +1748,21 @@ static inline void x86_pmu_read(struct perf_event *event) * Start group events scheduling transaction * Set the flag to make pmu::enable() not perform the * schedulability test, it will be performed at commit time + * + * We only support PERF_PMU_TXN_ADD transactions. Save the + * transaction flags but otherwise ignore non-PERF_PMU_TXN_ADD + * transactions. */ -static void x86_pmu_start_txn(struct pmu *pmu) +static void x86_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + + WARN_ON_ONCE(cpuc->txn_flags); /* txn already in flight */ + + cpuc->txn_flags = txn_flags; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; + perf_pmu_disable(pmu); __this_cpu_or(cpu_hw_events.group_flag, PERF_EVENT_TXN); __this_cpu_write(cpu_hw_events.n_txn, 0); @@ -1763,6 +1775,16 @@ static void x86_pmu_start_txn(struct pmu *pmu) */ static void x86_pmu_cancel_txn(struct pmu *pmu) { + unsigned int txn_flags; + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + + WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */ + + txn_flags = cpuc->txn_flags; + cpuc->txn_flags = 0; + if (txn_flags & ~PERF_PMU_TXN_ADD) + return; + __this_cpu_and(cpu_hw_events.group_flag, ~PERF_EVENT_TXN); /* * Truncate collected array by the number of events added in this @@ -1786,6 +1808,13 @@ static int x86_pmu_commit_txn(struct pmu *pmu) int assign[X86_PMC_IDX_MAX]; int n, ret; + WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */ + + if (cpuc->txn_flags & ~PERF_PMU_TXN_ADD) { + cpuc->txn_flags = 0; + return 0; + } + n = cpuc->n_events; if (!x86_pmu_initialized()) @@ -1802,6 +1831,7 @@ static int x86_pmu_commit_txn(struct pmu *pmu) memcpy(cpuc->assign, assign, n*sizeof(int)); cpuc->group_flag &= ~PERF_EVENT_TXN; + cpuc->txn_flags = 0; perf_pmu_enable(pmu); return 0; } diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 5edf6d868fc1..c99c93b9e348 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -196,6 +196,7 @@ struct cpu_hw_events { int n_excl; /* the number of exclusive events */ unsigned int group_flag; + unsigned int txn_flags; int is_fake; /* diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index d61ee4459eee..ea3b5dd21a4c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -201,6 +201,8 @@ struct perf_event; */ #define PERF_EVENT_TXN 0x1 +#define PERF_PMU_TXN_ADD 0x1 /* txn to add/schedule event on PMU */ + /** * pmu::capabilities flags */ @@ -331,20 +333,26 @@ struct pmu { * * Start the transaction, after this ->add() doesn't need to * do schedulability tests. + * + * Optional. */ - void (*start_txn) (struct pmu *pmu); /* optional */ + void (*start_txn) (struct pmu *pmu, unsigned int txn_flags); /* * If ->start_txn() disabled the ->add() schedulability test * then ->commit_txn() is required to perform one. On success * the transaction is closed. On error the transaction is kept * open until ->cancel_txn() is called. + * + * Optional. */ - int (*commit_txn) (struct pmu *pmu); /* optional */ + int (*commit_txn) (struct pmu *pmu); /* * Will cancel the transaction, assumes ->del() is called * for each successful ->add() during the transaction. + * + * Optional. */ - void (*cancel_txn) (struct pmu *pmu); /* optional */ + void (*cancel_txn) (struct pmu *pmu); /* * Will return the value for perf_event_mmap_page::index for this event, diff --git a/kernel/events/core.c b/kernel/events/core.c index 76e64be9bfb5..c80cee82959f 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1914,7 +1914,7 @@ group_sched_in(struct perf_event *group_event, if (group_event->state == PERF_EVENT_STATE_OFF) return 0; - pmu->start_txn(pmu); + pmu->start_txn(pmu, PERF_PMU_TXN_ADD); if (event_sched_in(group_event, cpuctx, ctx)) { pmu->cancel_txn(pmu); @@ -7267,24 +7267,49 @@ static void perf_pmu_nop_void(struct pmu *pmu) { } +static void perf_pmu_nop_txn(struct pmu *pmu, unsigned int flags) +{ +} + static int perf_pmu_nop_int(struct pmu *pmu) { return 0; } -static void perf_pmu_start_txn(struct pmu *pmu) +DEFINE_PER_CPU(unsigned int, nop_txn_flags); + +static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags) { + __this_cpu_write(nop_txn_flags, flags); + + if (flags & ~PERF_PMU_TXN_ADD) + return; + perf_pmu_disable(pmu); } static int perf_pmu_commit_txn(struct pmu *pmu) { + unsigned int flags = __this_cpu_read(nop_txn_flags); + + __this_cpu_write(nop_txn_flags, 0); + + if (flags & ~PERF_PMU_TXN_ADD) + return 0; + perf_pmu_enable(pmu); return 0; } static void perf_pmu_cancel_txn(struct pmu *pmu) { + unsigned int flags = __this_cpu_read(nop_txn_flags); + + __this_cpu_write(nop_txn_flags, 0); + + if (flags & ~PERF_PMU_TXN_ADD) + return; + perf_pmu_enable(pmu); } @@ -7523,7 +7548,7 @@ got_cpu_context: pmu->commit_txn = perf_pmu_commit_txn; pmu->cancel_txn = perf_pmu_cancel_txn; } else { - pmu->start_txn = perf_pmu_nop_void; + pmu->start_txn = perf_pmu_nop_txn; pmu->commit_txn = perf_pmu_nop_int; pmu->cancel_txn = perf_pmu_nop_void; } -- cgit v1.3-6-gb490 From 4a00c16e552ea5e71756cd29cd2df7557ec9cac4 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Thu, 3 Sep 2015 20:07:51 -0700 Subject: perf/core: Define PERF_PMU_TXN_READ interface Define a new PERF_PMU_TXN_READ interface to read a group of counters at once. pmu->start_txn() // Initialize before first event for each event in group pmu->read(event); // Queue each event to be read rc = pmu->commit_txn() // Read/update all queued counters Note that we use this interface with all PMUs. PMUs that implement this interface use the ->read() operation to _queue_ the counters to be read and use ->commit_txn() to actually read all the queued counters at once. PMUs that don't implement PERF_PMU_TXN_READ ignore ->start_txn() and ->commit_txn() and continue to read counters one at a time. Thanks to input from Peter Zijlstra. Signed-off-by: Sukadev Bhattiprolu Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Michael Ellerman Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1441336073-22750-9-git-send-email-sukadev@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 1 + kernel/events/core.c | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ea3b5dd21a4c..b83cea932f74 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -202,6 +202,7 @@ struct perf_event; #define PERF_EVENT_TXN 0x1 #define PERF_PMU_TXN_ADD 0x1 /* txn to add/schedule event on PMU */ +#define PERF_PMU_TXN_READ 0x2 /* txn to read event group from PMU */ /** * pmu::capabilities flags diff --git a/kernel/events/core.c b/kernel/events/core.c index ade04dfab368..55b0f7cf2614 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3199,6 +3199,7 @@ static void __perf_event_read(void *info) struct perf_event *sub, *event = data->event; struct perf_event_context *ctx = event->ctx; struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); + struct pmu *pmu = event->pmu; /* * If this is a task context, we need to check whether it is @@ -3217,18 +3218,31 @@ static void __perf_event_read(void *info) } update_event_times(event); - if (event->state == PERF_EVENT_STATE_ACTIVE) - event->pmu->read(event); + if (event->state != PERF_EVENT_STATE_ACTIVE) + goto unlock; - if (!data->group) + if (!data->group) { + pmu->read(event); + data->ret = 0; goto unlock; + } + + pmu->start_txn(pmu, PERF_PMU_TXN_READ); + + pmu->read(event); list_for_each_entry(sub, &event->sibling_list, group_entry) { update_event_times(sub); - if (sub->state == PERF_EVENT_STATE_ACTIVE) + if (sub->state == PERF_EVENT_STATE_ACTIVE) { + /* + * Use sibling's PMU rather than @event's since + * sibling could be on different (eg: software) PMU. + */ sub->pmu->read(sub); + } } - data->ret = 0; + + data->ret = pmu->commit_txn(pmu); unlock: raw_spin_unlock(&ctx->lock); -- cgit v1.3-6-gb490 From 8f3e5684d3fbd91ead283916676fa3dac22615e5 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Thu, 3 Sep 2015 20:07:53 -0700 Subject: perf/core: Drop PERF_EVENT_TXN We currently use PERF_EVENT_TXN flag to determine if we are in the middle of a transaction. If in a transaction, we defer the schedulability checks from pmu->add() operation to the pmu->commit() operation. Now that we have "transaction types" (PERF_PMU_TXN_ADD, PERF_PMU_TXN_READ) we can use the type to determine if we are in a transaction and drop the PERF_EVENT_TXN flag. When PERF_EVENT_TXN is dropped, the cpuhw->group_flag on some architectures becomes unused, so drop that field as well. This is an extension of the Powerpc patch from Peter Zijlstra to s390, Sparc and x86 architectures. Signed-off-by: Sukadev Bhattiprolu Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Michael Ellerman Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Link: http://lkml.kernel.org/r/1441336073-22750-11-git-send-email-sukadev@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- arch/powerpc/perf/core-book3s.c | 6 +----- arch/s390/kernel/perf_cpum_cf.c | 5 +---- arch/sparc/kernel/perf_event.c | 6 +----- arch/x86/kernel/cpu/perf_event.c | 7 ++----- arch/x86/kernel/cpu/perf_event.h | 1 - include/linux/perf_event.h | 2 -- 6 files changed, 5 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index c84074185c80..d1e65ce545b3 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -48,7 +48,6 @@ struct cpu_hw_events { unsigned long amasks[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; unsigned long avalues[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; - unsigned int group_flag; unsigned int txn_flags; int n_txn_start; @@ -1442,7 +1441,7 @@ static int power_pmu_add(struct perf_event *event, int ef_flags) * skip the schedulability test here, it will be performed * at commit time(->commit_txn) as a whole */ - if (cpuhw->group_flag & PERF_EVENT_TXN) + if (cpuhw->txn_flags & PERF_PMU_TXN_ADD) goto nocheck; if (check_excludes(cpuhw->event, cpuhw->flags, n0, 1)) @@ -1603,7 +1602,6 @@ static void power_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) return; perf_pmu_disable(pmu); - cpuhw->group_flag |= PERF_EVENT_TXN; cpuhw->n_txn_start = cpuhw->n_events; } @@ -1624,7 +1622,6 @@ static void power_pmu_cancel_txn(struct pmu *pmu) if (txn_flags & ~PERF_PMU_TXN_ADD) return; - cpuhw->group_flag &= ~PERF_EVENT_TXN; perf_pmu_enable(pmu); } @@ -1659,7 +1656,6 @@ static int power_pmu_commit_txn(struct pmu *pmu) for (i = cpuhw->n_txn_start; i < n; ++i) cpuhw->event[i]->hw.config = cpuhw->events[i]; - cpuhw->group_flag &= ~PERF_EVENT_TXN; cpuhw->txn_flags = 0; perf_pmu_enable(pmu); return 0; diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 19138be412d6..cb774ff6e749 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -536,7 +536,7 @@ static int cpumf_pmu_add(struct perf_event *event, int flags) * For group events transaction, the authorization check is * done in cpumf_pmu_commit_txn(). */ - if (!(cpuhw->flags & PERF_EVENT_TXN)) + if (!(cpuhw->txn_flags & PERF_PMU_TXN_ADD)) if (validate_ctr_auth(&event->hw)) return -EPERM; @@ -590,7 +590,6 @@ static void cpumf_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) return; perf_pmu_disable(pmu); - cpuhw->flags |= PERF_EVENT_TXN; cpuhw->tx_state = cpuhw->state; } @@ -613,7 +612,6 @@ static void cpumf_pmu_cancel_txn(struct pmu *pmu) WARN_ON(cpuhw->tx_state != cpuhw->state); - cpuhw->flags &= ~PERF_EVENT_TXN; perf_pmu_enable(pmu); } @@ -640,7 +638,6 @@ static int cpumf_pmu_commit_txn(struct pmu *pmu) if ((state & cpuhw->info.auth_ctl) != state) return -EPERM; - cpuhw->flags &= ~PERF_EVENT_TXN; cpuhw->txn_flags = 0; perf_pmu_enable(pmu); return 0; diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 2c0984d146ec..b0da5aedb336 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -108,7 +108,6 @@ struct cpu_hw_events { /* Enabled/disable state. */ int enabled; - unsigned int group_flag; unsigned int txn_flags; }; static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, }; @@ -1380,7 +1379,7 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags) * skip the schedulability test here, it will be performed * at commit time(->commit_txn) as a whole */ - if (cpuc->group_flag & PERF_EVENT_TXN) + if (cpuc->txn_flags & PERF_PMU_TXN_ADD) goto nocheck; if (check_excludes(cpuc->event, n0, 1)) @@ -1506,7 +1505,6 @@ static void sparc_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) return; perf_pmu_disable(pmu); - cpuhw->group_flag |= PERF_EVENT_TXN; } /* @@ -1526,7 +1524,6 @@ static void sparc_pmu_cancel_txn(struct pmu *pmu) if (txn_flags & ~PERF_PMU_TXN_ADD) return; - cpuhw->group_flag &= ~PERF_EVENT_TXN; perf_pmu_enable(pmu); } @@ -1556,7 +1553,6 @@ static int sparc_pmu_commit_txn(struct pmu *pmu) if (sparc_check_constraints(cpuc->event, cpuc->events, n)) return -EAGAIN; - cpuc->group_flag &= ~PERF_EVENT_TXN; cpuc->txn_flags = 0; perf_pmu_enable(pmu); return 0; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index dc77ef470e0e..4562cf070c27 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1175,7 +1175,7 @@ static int x86_pmu_add(struct perf_event *event, int flags) * skip the schedulability test here, it will be performed * at commit time (->commit_txn) as a whole. */ - if (cpuc->group_flag & PERF_EVENT_TXN) + if (cpuc->txn_flags & PERF_PMU_TXN_ADD) goto done_collect; ret = x86_pmu.schedule_events(cpuc, n, assign); @@ -1326,7 +1326,7 @@ static void x86_pmu_del(struct perf_event *event, int flags) * XXX assumes any ->del() called during a TXN will only be on * an event added during that same TXN. */ - if (cpuc->group_flag & PERF_EVENT_TXN) + if (cpuc->txn_flags & PERF_PMU_TXN_ADD) return; /* @@ -1764,7 +1764,6 @@ static void x86_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags) return; perf_pmu_disable(pmu); - __this_cpu_or(cpu_hw_events.group_flag, PERF_EVENT_TXN); __this_cpu_write(cpu_hw_events.n_txn, 0); } @@ -1785,7 +1784,6 @@ static void x86_pmu_cancel_txn(struct pmu *pmu) if (txn_flags & ~PERF_PMU_TXN_ADD) return; - __this_cpu_and(cpu_hw_events.group_flag, ~PERF_EVENT_TXN); /* * Truncate collected array by the number of events added in this * transaction. See x86_pmu_add() and x86_pmu_*_txn(). @@ -1830,7 +1828,6 @@ static int x86_pmu_commit_txn(struct pmu *pmu) */ memcpy(cpuc->assign, assign, n*sizeof(int)); - cpuc->group_flag &= ~PERF_EVENT_TXN; cpuc->txn_flags = 0; perf_pmu_enable(pmu); return 0; diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index c99c93b9e348..953a0e4e3284 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -195,7 +195,6 @@ struct cpu_hw_events { int n_excl; /* the number of exclusive events */ - unsigned int group_flag; unsigned int txn_flags; int is_fake; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index b83cea932f74..d841d33bcdc9 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -199,8 +199,6 @@ struct perf_event; /* * Common implementation detail of pmu::{start,commit,cancel}_txn */ -#define PERF_EVENT_TXN 0x1 - #define PERF_PMU_TXN_ADD 0x1 /* txn to add/schedule event on PMU */ #define PERF_PMU_TXN_READ 0x2 /* txn to read event group from PMU */ -- cgit v1.3-6-gb490 From 0052b7dcf9d9ec6be4fc3fe815a2ceda623bb9d1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 13 Sep 2015 19:00:05 +0900 Subject: ALSA: pcm: remove structure member of 'struct snd_pcm_hwptr_log *' type because this structure had been removed This structure was added by 4d96eb255c53 ('ALSA: pcm_lib - add possibility to log last 10 DMA ring buffer positions') to store PCM pointers information of latest 10 pointer movements (=XRUN_LOG_CNT). When CONFIG_SND_PCM_XRUN_DEBUG is configured, 'struct snd_pcm_runtime' has 'hwptr_log' member with a pointer to the structure. When calling xrun_log() in pcm_lib.c, the structure was allocated to the pointer. When calling snd_pcm_detach_substream() in pcm.c, the allocated pointer is released. In f5914908a5b7 ('ALSA: pcm: Replace PCM hwptr tracking with tracepoints'), the pointer logging is replaced with using Linux Kernel Tracepoints. The structure was also removed, while it's just declared. The member and kfree still remains. This commit removes the member and related codes. I think this was overlooked because it brings no errors/warnings to C compilers. Fixes: f5914908a5b7 ('ALSA: pcm: Replace PCM hwptr tracking with tracepoints') Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 6 ------ sound/core/pcm.c | 3 --- 2 files changed, 9 deletions(-) (limited to 'include') diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 691e7ee0a510..a4fcc9456194 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -285,8 +285,6 @@ struct snd_pcm_hw_constraint_ranges { unsigned int mask; }; -struct snd_pcm_hwptr_log; - /* * userspace-provided audio timestamp config to kernel, * structure is for internal use only and filled with dedicated unpack routine @@ -428,10 +426,6 @@ struct snd_pcm_runtime { /* -- OSS things -- */ struct snd_pcm_oss_runtime oss; #endif - -#ifdef CONFIG_SND_PCM_XRUN_DEBUG - struct snd_pcm_hwptr_log *hwptr_log; -#endif }; struct snd_pcm_group { /* keep linked substreams */ diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 02bd96954dc4..308c9ecf73db 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1014,9 +1014,6 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) snd_free_pages((void*)runtime->control, PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))); kfree(runtime->hw_constraints.rules); -#ifdef CONFIG_SND_PCM_XRUN_DEBUG - kfree(runtime->hwptr_log); -#endif kfree(runtime); substream->runtime = NULL; put_pid(substream->pid); -- cgit v1.3-6-gb490 From 7486d80f7d853f50088124824bf62d9a4d14de75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 10 Sep 2015 06:49:29 +0000 Subject: ASoC: rsnd: remove unneeded sh_clk header sh_clk header is not needed, and it will create confusion. Let's remove it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 1 - sound/soc/sh/rcar/adg.c | 1 - 2 files changed, 2 deletions(-) (limited to 'include') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index bb7b2ebfee7b..d8e33d38da43 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -12,7 +12,6 @@ #ifndef RCAR_SND_H #define RCAR_SND_H -#include #define RSND_GEN1_SRU 0 #define RSND_GEN1_ADG 1 diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index fefc881dbac2..b512be82306e 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -7,7 +7,6 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ -#include #include "rsnd.h" #define CLKA 0 -- cgit v1.3-6-gb490 From d52fad262041217be0a0e7049253186ec9cfb2a6 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 18 Jun 2015 17:11:32 -0700 Subject: soc: add stubs for brcmstb SoC's Used on BCM7xxx Set-Top Box chips (e.g., BCM7445). Signed-off-by: Brian Norris Signed-off-by: Florian Fainelli --- arch/arm/mach-bcm/Kconfig | 1 + drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/brcmstb/Kconfig | 9 +++++++++ drivers/soc/brcmstb/Makefile | 1 + drivers/soc/brcmstb/common.c | 33 +++++++++++++++++++++++++++++++++ include/soc/brcmstb/common.h | 15 +++++++++++++++ 7 files changed, 61 insertions(+) create mode 100644 drivers/soc/brcmstb/Kconfig create mode 100644 drivers/soc/brcmstb/Makefile create mode 100644 drivers/soc/brcmstb/common.c create mode 100644 include/soc/brcmstb/common.h (limited to 'include') diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 1679fa4fb700..0be09af9dec7 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -161,6 +161,7 @@ config ARCH_BRCMSTB select BCM7120_L2_IRQ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_WANT_OPTIONAL_GPIOLIB + select SOC_BRCMSTB help Say Y if you intend to run the kernel on a Broadcom ARM-based STB chipset. diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index 96ddecb92254..c9c0fcce98a7 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -1,5 +1,6 @@ menu "SOC (System On Chip) specific Drivers" +source "drivers/soc/brcmstb/Kconfig" source "drivers/soc/mediatek/Kconfig" source "drivers/soc/qcom/Kconfig" source "drivers/soc/sunxi/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 0b12d777d3c4..4e27f10367f0 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -2,6 +2,7 @@ # Makefile for the Linux Kernel SOC specific device drivers. # +obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ obj-$(CONFIG_MACH_DOVE) += dove/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_QCOM) += qcom/ diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig new file mode 100644 index 000000000000..39cab3bd544d --- /dev/null +++ b/drivers/soc/brcmstb/Kconfig @@ -0,0 +1,9 @@ +menuconfig SOC_BRCMSTB + bool "Broadcom STB SoC drivers" + depends on ARM + help + Enables drivers for the Broadcom Set-Top Box (STB) series of chips. + This option alone enables only some support code, while the drivers + can be enabled individually within this menu. + + If unsure, say N. diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile new file mode 100644 index 000000000000..183280e39f80 --- /dev/null +++ b/drivers/soc/brcmstb/Makefile @@ -0,0 +1 @@ +obj-y += common.o diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c new file mode 100644 index 000000000000..c262c029b1b8 --- /dev/null +++ b/drivers/soc/brcmstb/common.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * Copyright © 2015 Broadcom Corporation + * + * 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. + * + * 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 + +static const struct of_device_id brcmstb_machine_match[] = { + { .compatible = "brcm,brcmstb", }, + { } +}; + +bool soc_is_brcmstb(void) +{ + struct device_node *root; + + root = of_find_node_by_path("/"); + if (!root) + return false; + + return of_match_node(brcmstb_machine_match, root) != NULL; +} diff --git a/include/soc/brcmstb/common.h b/include/soc/brcmstb/common.h new file mode 100644 index 000000000000..cfb5335f2a15 --- /dev/null +++ b/include/soc/brcmstb/common.h @@ -0,0 +1,15 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * Copyright © 2015 Broadcom Corporation + * + * 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. + */ + +#ifndef __SOC_BRCMSTB_COMMON_H__ +#define __SOC_BRCMSTB_COMMON_H__ + +bool soc_is_brcmstb(void); + +#endif /* __SOC_BRCMSTB_COMMON_H__ */ -- cgit v1.3-6-gb490 From 445b0eb058f5f31c844a731cb82e7441d0d9e578 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 27 Aug 2015 04:36:14 +0200 Subject: ACPI / property: Add support for data-only subnodes In some cases, the information expressed via device properties is hierarchical by nature. For example, the properties of a composite device consisting of multiple semi-dependent components may need to be represented in the form of a tree of property data sets corresponding to specific components of the device. Unfortunately, using ACPI device objects for this purpose turns out to be problematic, mostly due to the assumption made by some operating systems (that platform firmware generally needs to work with) that each device object in the ACPI namespace represents a device requiring a separate driver. That assumption leads to complications which reportedly are impractically difficult to overcome and a different approach is needed for the sake of interoperability. The approach implemented here is based on extending _DSD via pointers (links) to additional ACPI objects returning data packages formatted in accordance with the _DSD formatting rules defined by Section 6.2.5 of ACPI 6. Those additional objects are referred to as data-only subnodes of the device object containing the _DSD pointing to them. The links to them need to be located in a separate section of the _DSD data package following UUID dbb8e3e6-5886-4ba6-8795-1319f52a966b referred to as the Hierarchical Data Extension UUID as defined in [1]. Each of them is represented by a package of two strings. The first string in that package (the key) is regarded as the name of the data-only subnode pointed to by the link. The second string in it (the target) is expected to hold the ACPI namespace path (possibly utilizing the usual ACPI namespace search rules) of an ACPI object evaluating to a data package extending the _DSD. The device properties initialization code follows those links, creates a struct acpi_data_node object for each of them to store the data returned by the ACPI object pointed to by it and processes those data recursively (which may lead to the creation of more struct acpi_data_node objects if the returned data package contains the Hierarchical Data Extension UUID section with more links in it). All of the struct acpi_data_node objects are present until the the ACPI device object containing the _DSD with links to them is deleted and they are deleted along with that object. [1]: http://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.pdf Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/property.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++- include/acpi/acpi_bus.h | 9 ++++ include/linux/fwnode.h | 1 + 3 files changed, 142 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 8163b4bd7a61..17c436de376b 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -24,6 +24,115 @@ static const u8 prp_uuid[16] = { 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 }; +/* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ +static const u8 ads_uuid[16] = { + 0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b, + 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b +}; + +static bool acpi_enumerate_nondev_subnodes(acpi_handle scope, + const union acpi_object *desc, + struct acpi_device_data *data); +static bool acpi_extract_properties(const union acpi_object *desc, + struct acpi_device_data *data); + +static bool acpi_nondev_subnode_ok(acpi_handle scope, + const union acpi_object *link, + struct list_head *list) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; + struct acpi_data_node *dn; + acpi_handle handle; + acpi_status status; + + dn = kzalloc(sizeof(*dn), GFP_KERNEL); + if (!dn) + return false; + + dn->name = link->package.elements[0].string.pointer; + dn->fwnode.type = FWNODE_ACPI_DATA; + INIT_LIST_HEAD(&dn->data.subnodes); + + status = acpi_get_handle(scope, link->package.elements[1].string.pointer, + &handle); + if (ACPI_FAILURE(status)) + goto fail; + + status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + goto fail; + + if (acpi_extract_properties(buf.pointer, &dn->data)) + dn->data.pointer = buf.pointer; + + if (acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data)) + dn->data.pointer = buf.pointer; + + if (dn->data.pointer) { + list_add_tail(&dn->sibling, list); + return true; + } + + acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n"); + + fail: + ACPI_FREE(buf.pointer); + kfree(dn); + return false; +} + +static int acpi_add_nondev_subnodes(acpi_handle scope, + const union acpi_object *links, + struct list_head *list) +{ + bool ret = false; + int i; + + for (i = 0; i < links->package.count; i++) { + const union acpi_object *link; + + link = &links->package.elements[i]; + /* Only two elements allowed, both must be strings. */ + if (link->package.count == 2 + && link->package.elements[0].type == ACPI_TYPE_STRING + && link->package.elements[1].type == ACPI_TYPE_STRING + && acpi_nondev_subnode_ok(scope, link, list)) + ret = true; + } + + return ret; +} + +static bool acpi_enumerate_nondev_subnodes(acpi_handle scope, + const union acpi_object *desc, + struct acpi_device_data *data) +{ + int i; + + /* Look for the ACPI data subnodes UUID. */ + for (i = 0; i < desc->package.count; i += 2) { + const union acpi_object *uuid, *links; + + uuid = &desc->package.elements[i]; + links = &desc->package.elements[i + 1]; + + /* + * The first element must be a UUID and the second one must be + * a package. + */ + if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16 + || links->type != ACPI_TYPE_PACKAGE) + break; + + if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid))) + continue; + + return acpi_add_nondev_subnodes(scope, links, &data->subnodes); + } + + return false; +} static bool acpi_property_value_ok(const union acpi_object *value) { @@ -147,6 +256,8 @@ void acpi_init_properties(struct acpi_device *adev) acpi_status status; bool acpi_of = false; + INIT_LIST_HEAD(&adev->data.subnodes); + /* * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in * Device Tree compatible properties for this device. @@ -167,7 +278,11 @@ void acpi_init_properties(struct acpi_device *adev) adev->data.pointer = buf.pointer; if (acpi_of) acpi_init_of_compatible(adev); - } else { + } + if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer, &adev->data)) + adev->data.pointer = buf.pointer; + + if (!adev->data.pointer) { acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n"); ACPI_FREE(buf.pointer); } @@ -178,8 +293,24 @@ void acpi_init_properties(struct acpi_device *adev) ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n"); } +static void acpi_destroy_nondev_subnodes(struct list_head *list) +{ + struct acpi_data_node *dn, *next; + + if (list_empty(list)) + return; + + list_for_each_entry_safe_reverse(dn, next, list, sibling) { + acpi_destroy_nondev_subnodes(&dn->data.subnodes); + list_del(&dn->sibling); + ACPI_FREE((void *)dn->data.pointer); + kfree(dn); + } +} + void acpi_free_properties(struct acpi_device *adev) { + acpi_destroy_nondev_subnodes(&adev->data.subnodes); ACPI_FREE((void *)adev->data.pointer); adev->data.of_compatible = NULL; adev->data.pointer = NULL; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5ba8fb64f664..79cfee646d6b 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -343,6 +343,7 @@ struct acpi_device_data { const union acpi_object *pointer; const union acpi_object *properties; const union acpi_object *of_compatible; + struct list_head subnodes; }; struct acpi_gpio_mapping; @@ -378,6 +379,14 @@ struct acpi_device { void (*remove)(struct acpi_device *); }; +/* Non-device subnode */ +struct acpi_data_node { + const char *name; + struct fwnode_handle fwnode; + struct acpi_device_data data; + struct list_head sibling; +}; + static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent) { bool ret = false; diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 0408545bce42..b08d6ba5c1e6 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -16,6 +16,7 @@ enum fwnode_type { FWNODE_INVALID = 0, FWNODE_OF, FWNODE_ACPI, + FWNODE_ACPI_DATA, FWNODE_PDATA, }; -- cgit v1.3-6-gb490 From 263b4c1a64bc12470684aeaf7c44f03d31716819 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 27 Aug 2015 04:37:19 +0200 Subject: ACPI / property: Expose data-only subnodes via sysfs Add infrastructure needed to expose data-only subnodes of ACPI device objects introduced previously via sysfs. Each data-only subnode is represented as a sysfs directory under the directory corresponding to its parent object (a device or a data-only subnode). Each of them has a "path" attribute (containing the full ACPI namespace path to the object the subnode data come from) at this time. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/device_sysfs.c | 120 +++++++++++++++++++++++++++++++++++++++----- drivers/acpi/property.c | 8 +-- include/acpi/acpi_bus.h | 3 ++ 3 files changed, 116 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 4ab4582e586b..707cf6213bc2 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -26,6 +26,106 @@ #include "internal.h" +static ssize_t acpi_object_path(acpi_handle handle, char *buf) +{ + struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; + int result; + + result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path); + if (result) + return result; + + result = sprintf(buf, "%s\n", (char*)path.pointer); + kfree(path.pointer); + return result; +} + +struct acpi_data_node_attr { + struct attribute attr; + ssize_t (*show)(struct acpi_data_node *, char *); + ssize_t (*store)(struct acpi_data_node *, const char *, size_t count); +}; + +#define DATA_NODE_ATTR(_name) \ + static struct acpi_data_node_attr data_node_##_name = \ + __ATTR(_name, 0444, data_node_show_##_name, NULL) + +static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf) +{ + return acpi_object_path(dn->handle, buf); +} + +DATA_NODE_ATTR(path); + +static struct attribute *acpi_data_node_default_attrs[] = { + &data_node_path.attr, + NULL +}; + +#define to_data_node(k) container_of(k, struct acpi_data_node, kobj) +#define to_attr(a) container_of(a, struct acpi_data_node_attr, attr) + +static ssize_t acpi_data_node_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct acpi_data_node *dn = to_data_node(kobj); + struct acpi_data_node_attr *dn_attr = to_attr(attr); + + return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO; +} + +static const struct sysfs_ops acpi_data_node_sysfs_ops = { + .show = acpi_data_node_attr_show, +}; + +static void acpi_data_node_release(struct kobject *kobj) +{ + struct acpi_data_node *dn = to_data_node(kobj); + complete(&dn->kobj_done); +} + +static struct kobj_type acpi_data_node_ktype = { + .sysfs_ops = &acpi_data_node_sysfs_ops, + .default_attrs = acpi_data_node_default_attrs, + .release = acpi_data_node_release, +}; + +static void acpi_expose_nondev_subnodes(struct kobject *kobj, + struct acpi_device_data *data) +{ + struct list_head *list = &data->subnodes; + struct acpi_data_node *dn; + + if (list_empty(list)) + return; + + list_for_each_entry(dn, list, sibling) { + int ret; + + init_completion(&dn->kobj_done); + ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype, + kobj, dn->name); + if (ret) + acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret); + else + acpi_expose_nondev_subnodes(&dn->kobj, &dn->data); + } +} + +static void acpi_hide_nondev_subnodes(struct acpi_device_data *data) +{ + struct list_head *list = &data->subnodes; + struct acpi_data_node *dn; + + if (list_empty(list)) + return; + + list_for_each_entry_reverse(dn, list, sibling) { + acpi_hide_nondev_subnodes(&dn->data); + kobject_put(&dn->kobj); + } +} + /** * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent * @acpi_dev: ACPI device object. @@ -323,20 +423,12 @@ static ssize_t acpi_device_adr_show(struct device *dev, } static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL); -static ssize_t -acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) { +static ssize_t acpi_device_path_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; - int result; - - result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); - if (result) - goto end; - result = sprintf(buf, "%s\n", (char*)path.pointer); - kfree(path.pointer); -end: - return result; + return acpi_object_path(acpi_dev->handle, buf); } static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); @@ -475,6 +567,8 @@ int acpi_device_setup_files(struct acpi_device *dev) &dev_attr_real_power_state); } + acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data); + end: return result; } @@ -485,6 +579,8 @@ end: */ void acpi_device_remove_files(struct acpi_device *dev) { + acpi_hide_nondev_subnodes(&dev->data); + if (dev->flags.power_manageable) { device_remove_file(&dev->dev, &dev_attr_power_state); if (dev->power.flags.power_resources) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 17c436de376b..333f9146d19e 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -64,12 +64,13 @@ static bool acpi_nondev_subnode_ok(acpi_handle scope, goto fail; if (acpi_extract_properties(buf.pointer, &dn->data)) - dn->data.pointer = buf.pointer; + dn->handle = handle; if (acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data)) - dn->data.pointer = buf.pointer; + dn->handle = handle; - if (dn->data.pointer) { + if (dn->handle) { + dn->data.pointer = buf.pointer; list_add_tail(&dn->sibling, list); return true; } @@ -302,6 +303,7 @@ static void acpi_destroy_nondev_subnodes(struct list_head *list) list_for_each_entry_safe_reverse(dn, next, list, sibling) { acpi_destroy_nondev_subnodes(&dn->data.subnodes); + wait_for_completion(&dn->kobj_done); list_del(&dn->sibling); ACPI_FREE((void *)dn->data.pointer); kfree(dn); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 79cfee646d6b..e0d7c193d6e0 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -382,9 +382,12 @@ struct acpi_device { /* Non-device subnode */ struct acpi_data_node { const char *name; + acpi_handle handle; struct fwnode_handle fwnode; struct acpi_device_data data; struct list_head sibling; + struct kobject kobj; + struct completion kobj_done; }; static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent) -- cgit v1.3-6-gb490 From 3a7a2ab839ad18c2d542b40f4a647c98d068e55a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 27 Aug 2015 04:40:05 +0200 Subject: ACPI / property: Extend fwnode_property_* to data-only subnodes Modify is_acpi_node() to return "true" for ACPI data-only subnodes as well as for ACPI device objects and change the name of to_acpi_node() to to_acpi_device_node() so it is clear that it covers ACPI device objects only. Accordingly, introduce to_acpi_data_node() to cover data-only subnodes in an analogous way. With that, make the fwnode_property_* family of functions work with ACPI data-only subnodes introduced previously. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/property.c | 138 ++++++++++++++++++++++++++++++++++++------------ drivers/base/property.c | 16 +++--- drivers/gpio/gpiolib.c | 6 +-- include/acpi/acpi_bus.h | 21 +++++++- include/linux/acpi.h | 53 +++++++++++++------ 5 files changed, 173 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 333f9146d19e..e78551726acb 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -19,6 +19,11 @@ #include "internal.h" +static int acpi_data_get_property_array(struct acpi_device_data *data, + const char *name, + acpi_object_type type, + const union acpi_object **obj); + /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ static const u8 prp_uuid[16] = { 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, @@ -191,8 +196,8 @@ static void acpi_init_of_compatible(struct acpi_device *adev) const union acpi_object *of_compatible; int ret; - ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, - &of_compatible); + ret = acpi_data_get_property_array(&adev->data, "compatible", + ACPI_TYPE_STRING, &of_compatible); if (ret) { ret = acpi_dev_get_property(adev, "compatible", ACPI_TYPE_STRING, &of_compatible); @@ -320,8 +325,8 @@ void acpi_free_properties(struct acpi_device *adev) } /** - * acpi_dev_get_property - return an ACPI property with given name - * @adev: ACPI device to get property + * acpi_data_get_property - return an ACPI property with given name + * @data: ACPI device deta object to get the property from * @name: Name of the property * @type: Expected property type * @obj: Location to store the property value (if not %NULL) @@ -330,26 +335,27 @@ void acpi_free_properties(struct acpi_device *adev) * object at the location pointed to by @obj if found. * * Callers must not attempt to free the returned objects. These objects will be - * freed by the ACPI core automatically during the removal of @adev. + * freed by the ACPI core automatically during the removal of @data. * * Return: %0 if property with @name has been found (success), * %-EINVAL if the arguments are invalid, * %-ENODATA if the property doesn't exist, * %-EPROTO if the property value type doesn't match @type. */ -int acpi_dev_get_property(struct acpi_device *adev, const char *name, - acpi_object_type type, const union acpi_object **obj) +static int acpi_data_get_property(struct acpi_device_data *data, + const char *name, acpi_object_type type, + const union acpi_object **obj) { const union acpi_object *properties; int i; - if (!adev || !name) + if (!data || !name) return -EINVAL; - if (!adev->data.pointer || !adev->data.properties) + if (!data->pointer || !data->properties) return -ENODATA; - properties = adev->data.properties; + properties = data->properties; for (i = 0; i < properties->package.count; i++) { const union acpi_object *propname, *propvalue; const union acpi_object *property; @@ -370,11 +376,50 @@ int acpi_dev_get_property(struct acpi_device *adev, const char *name, } return -ENODATA; } + +/** + * acpi_dev_get_property - return an ACPI property with given name. + * @adev: ACPI device to get the property from. + * @name: Name of the property. + * @type: Expected property type. + * @obj: Location to store the property value (if not %NULL). + */ +int acpi_dev_get_property(struct acpi_device *adev, const char *name, + acpi_object_type type, const union acpi_object **obj) +{ + return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL; +} EXPORT_SYMBOL_GPL(acpi_dev_get_property); +static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode) +{ + if (fwnode->type == FWNODE_ACPI) { + struct acpi_device *adev = to_acpi_device_node(fwnode); + return &adev->data; + } else if (fwnode->type == FWNODE_ACPI_DATA) { + struct acpi_data_node *dn = to_acpi_data_node(fwnode); + return &dn->data; + } + return NULL; +} + /** - * acpi_dev_get_property_array - return an ACPI array property with given name - * @adev: ACPI device to get property + * acpi_node_prop_get - return an ACPI property with given name. + * @fwnode: Firmware node to get the property from. + * @propname: Name of the property. + * @valptr: Location to store a pointer to the property value (if not %NULL). + */ +int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, + void **valptr) +{ + return acpi_data_get_property(acpi_device_data_of_node(fwnode), + propname, ACPI_TYPE_ANY, + (const union acpi_object **)valptr); +} + +/** + * acpi_data_get_property_array - return an ACPI array property with given name + * @adev: ACPI data object to get the property from * @name: Name of the property * @type: Expected type of array elements * @obj: Location to store a pointer to the property value (if not NULL) @@ -383,7 +428,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property); * ACPI object at the location pointed to by @obj if found. * * Callers must not attempt to free the returned objects. Those objects will be - * freed by the ACPI core automatically during the removal of @adev. + * freed by the ACPI core automatically during the removal of @data. * * Return: %0 if array property (package) with @name has been found (success), * %-EINVAL if the arguments are invalid, @@ -391,14 +436,15 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property); * %-EPROTO if the property is not a package or the type of its elements * doesn't match @type. */ -int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, - acpi_object_type type, - const union acpi_object **obj) +static int acpi_data_get_property_array(struct acpi_device_data *data, + const char *name, + acpi_object_type type, + const union acpi_object **obj) { const union acpi_object *prop; int ret, i; - ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop); + ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop); if (ret) return ret; @@ -413,7 +459,6 @@ int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, return 0; } -EXPORT_SYMBOL_GPL(acpi_dev_get_property_array); /** * acpi_dev_get_property_reference - returns handle to the referenced object @@ -518,15 +563,9 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, } EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); -int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, - void **valptr) -{ - return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, - (const union acpi_object **)valptr); -} - -int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, - enum dev_prop_type proptype, void *val) +static int acpi_data_prop_read_single(struct acpi_device_data *data, + const char *propname, + enum dev_prop_type proptype, void *val) { const union acpi_object *obj; int ret; @@ -535,7 +574,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, return -EINVAL; if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { - ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj); + ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj); if (ret) return ret; @@ -560,7 +599,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, break; } } else if (proptype == DEV_PROP_STRING) { - ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj); + ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj); if (ret) return ret; @@ -571,6 +610,12 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, return ret; } +int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, + enum dev_prop_type proptype, void *val) +{ + return adev ? acpi_data_prop_read_single(&adev->data, propname, proptype, val) : -EINVAL; +} + static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val, size_t nval) { @@ -647,20 +692,22 @@ static int acpi_copy_property_array_string(const union acpi_object *items, return 0; } -int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, - enum dev_prop_type proptype, void *val, size_t nval) +static int acpi_data_prop_read(struct acpi_device_data *data, + const char *propname, + enum dev_prop_type proptype, + void *val, size_t nval) { const union acpi_object *obj; const union acpi_object *items; int ret; if (val && nval == 1) { - ret = acpi_dev_prop_read_single(adev, propname, proptype, val); + ret = acpi_data_prop_read_single(data, propname, proptype, val); if (!ret) return ret; } - ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj); + ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj); if (ret) return ret; @@ -696,3 +743,28 @@ int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, } return ret; } + +int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, + enum dev_prop_type proptype, void *val, size_t nval) +{ + return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL; +} + +/** + * acpi_node_prop_read - retrieve the value of an ACPI property with given name. + * @fwnode: Firmware node to get the property from. + * @propname: Name of the property. + * @proptype: Expected property type. + * @val: Location to store the property value (if not %NULL). + * @nval: Size of the array pointed to by @val. + * + * If @val is %NULL, return the number of array elements comprising the value + * of the property. Otherwise, read at most @nval values to the array at the + * location pointed to by @val. + */ +int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname, + enum dev_prop_type proptype, void *val, size_t nval) +{ + return acpi_data_prop_read(acpi_device_data_of_node(fwnode), + propname, proptype, val, nval); +} diff --git a/drivers/base/property.c b/drivers/base/property.c index 2d75366c61e0..ca118169a6c5 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -134,7 +134,7 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) if (is_of_node(fwnode)) return of_property_read_bool(to_of_node(fwnode), propname); else if (is_acpi_node(fwnode)) - return !acpi_dev_prop_get(to_acpi_node(fwnode), propname, NULL); + return !acpi_node_prop_get(fwnode, propname, NULL); return !!pset_prop_get(to_pset(fwnode), propname); } @@ -298,8 +298,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string); _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \ _type_, _val_, _nval_); \ else if (is_acpi_node(_fwnode_)) \ - _ret_ = acpi_dev_prop_read(to_acpi_node(_fwnode_), _propname_, \ - _proptype_, _val_, _nval_); \ + _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \ + _val_, _nval_); \ else if (is_pset(_fwnode_)) \ _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ _proptype_, _val_, _nval_); \ @@ -440,8 +440,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode, propname, val, nval) : of_property_count_strings(to_of_node(fwnode), propname); else if (is_acpi_node(fwnode)) - return acpi_dev_prop_read(to_acpi_node(fwnode), propname, - DEV_PROP_STRING, val, nval); + return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, + val, nval); else if (is_pset(fwnode)) return pset_prop_read_array(to_pset(fwnode), propname, DEV_PROP_STRING, val, nval); @@ -470,8 +470,8 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode, if (is_of_node(fwnode)) return of_property_read_string(to_of_node(fwnode), propname, val); else if (is_acpi_node(fwnode)) - return acpi_dev_prop_read(to_acpi_node(fwnode), propname, - DEV_PROP_STRING, val, 1); + return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, + val, 1); return pset_prop_read_array(to_pset(fwnode), propname, DEV_PROP_STRING, val, 1); @@ -495,7 +495,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev, } else if (IS_ENABLED(CONFIG_ACPI)) { struct acpi_device *node; - node = acpi_get_next_child(dev, to_acpi_node(child)); + node = acpi_get_next_child(dev, to_acpi_device_node(child)); if (node) return acpi_fwnode_handle(node); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 980c1f87866a..f43e808a49d9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2083,11 +2083,11 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, &flags); if (!IS_ERR(desc)) active_low = flags & OF_GPIO_ACTIVE_LOW; - } else if (is_acpi_node(fwnode)) { + } else if (is_acpi_device_node(fwnode)) { struct acpi_gpio_info info; - desc = acpi_get_gpiod_by_index(to_acpi_node(fwnode), propname, 0, - &info); + desc = acpi_get_gpiod_by_index(to_acpi_device_node(fwnode), + propname, 0, &info); if (!IS_ERR(desc)) active_low = info.active_low; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e0d7c193d6e0..e234725eadc7 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -424,16 +424,33 @@ static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent) } static inline bool is_acpi_node(struct fwnode_handle *fwnode) +{ + return fwnode && (fwnode->type == FWNODE_ACPI + || fwnode->type == FWNODE_ACPI_DATA); +} + +static inline bool is_acpi_device_node(struct fwnode_handle *fwnode) { return fwnode && fwnode->type == FWNODE_ACPI; } -static inline struct acpi_device *to_acpi_node(struct fwnode_handle *fwnode) +static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode) { - return is_acpi_node(fwnode) ? + return is_acpi_device_node(fwnode) ? container_of(fwnode, struct acpi_device, fwnode) : NULL; } +static inline bool is_acpi_data_node(struct fwnode_handle *fwnode) +{ + return fwnode && fwnode->type == FWNODE_ACPI_DATA; +} + +static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode) +{ + return is_acpi_data_node(fwnode) ? + container_of(fwnode, struct acpi_data_node, fwnode) : NULL; +} + static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) { return &adev->fwnode; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 7235c4851460..6be94ba4e980 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -49,7 +49,7 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) return adev ? adev->handle : NULL; } -#define ACPI_COMPANION(dev) to_acpi_node((dev)->fwnode) +#define ACPI_COMPANION(dev) to_acpi_device_node((dev)->fwnode) #define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \ acpi_fwnode_handle(adev) : NULL) #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) @@ -69,7 +69,7 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) static inline bool has_acpi_companion(struct device *dev) { - return is_acpi_node(dev->fwnode); + return is_acpi_device_node(dev->fwnode); } static inline void acpi_preset_companion(struct device *dev, @@ -461,7 +461,22 @@ static inline bool is_acpi_node(struct fwnode_handle *fwnode) return false; } -static inline struct acpi_device *to_acpi_node(struct fwnode_handle *fwnode) +static inline bool is_acpi_device_node(struct fwnode_handle *fwnode) +{ + return false; +} + +static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode) +{ + return NULL; +} + +static inline bool is_acpi_data_node(struct fwnode_handle *fwnode) +{ + return false; +} + +static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode) { return NULL; } @@ -743,17 +758,16 @@ struct acpi_reference_args { #ifdef CONFIG_ACPI int acpi_dev_get_property(struct acpi_device *adev, const char *name, acpi_object_type type, const union acpi_object **obj); -int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, - acpi_object_type type, - const union acpi_object **obj); int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, size_t index, struct acpi_reference_args *args); -int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, - void **valptr); +int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, + void **valptr); int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, enum dev_prop_type proptype, void *val); +int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname, + enum dev_prop_type proptype, void *val, size_t nval); int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, enum dev_prop_type proptype, void *val, size_t nval); @@ -766,13 +780,7 @@ static inline int acpi_dev_get_property(struct acpi_device *adev, { return -ENXIO; } -static inline int acpi_dev_get_property_array(struct acpi_device *adev, - const char *name, - acpi_object_type type, - const union acpi_object **obj) -{ - return -ENXIO; -} + static inline int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, const char *cells_name, size_t index, struct acpi_reference_args *args) @@ -780,6 +788,13 @@ static inline int acpi_dev_get_property_reference(struct acpi_device *adev, return -ENXIO; } +static inline int acpi_node_prop_get(struct fwnode_handle *fwnode, + const char *propname, + void **valptr) +{ + return -ENXIO; +} + static inline int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, void **valptr) @@ -795,6 +810,14 @@ static inline int acpi_dev_prop_read_single(struct acpi_device *adev, return -ENXIO; } +static inline int acpi_node_prop_read(struct fwnode_handle *fwnode, + const char *propname, + enum dev_prop_type proptype, + void *val, size_t nval) +{ + return -ENXIO; +} + static inline int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, enum dev_prop_type proptype, -- cgit v1.3-6-gb490 From 504a33749971c36c54ba5ccb1364872dee1f17a7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 27 Aug 2015 04:42:33 +0200 Subject: ACPI / property: Extend device_get_next_child_node() to data-only nodes Make device_get_next_child_node() work with ACPI data-only subnodes introduced previously. Namely, replace acpi_get_next_child() with acpi_get_next_subnode() that can handle (and return) child device objects as well as child data-only subnodes of the given device and modify the ACPI part of the GPIO subsystem to handle data-only subnodes returned by it. To that end, introduce acpi_node_get_gpiod() taking a struct fwnode_handle pointer as the first argument. That argument may point to an ACPI device object as well as to a data-only subnode and the function should do the right thing (ie. look for the matching GPIO descriptor correctly) in either case. Next, modify fwnode_get_named_gpiod() to use acpi_node_get_gpiod() instead of acpi_get_gpiod_by_index() which automatically causes devm_get_gpiod_from_child() to work with ACPI data-only subnodes that may be returned by device_get_next_child_node() which in turn is required by the users of that function (the gpio_keys_polled and gpio-leds drivers). Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg Acked-by: Linus Walleij --- drivers/acpi/property.c | 88 ++++++++++++++++++++++++++++++++++++++++----- drivers/acpi/scan.c | 20 ----------- drivers/base/property.c | 6 +--- drivers/gpio/gpiolib-acpi.c | 58 +++++++++++++++++++++++++++--- drivers/gpio/gpiolib.c | 5 ++- drivers/gpio/gpiolib.h | 10 +++++- include/linux/acpi.h | 17 +++++---- 7 files changed, 153 insertions(+), 51 deletions(-) (limited to 'include') diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index e78551726acb..14654435c295 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -461,9 +461,9 @@ static int acpi_data_get_property_array(struct acpi_device_data *data, } /** - * acpi_dev_get_property_reference - returns handle to the referenced object - * @adev: ACPI device to get property - * @name: Name of the property + * acpi_data_get_property_reference - returns handle to the referenced object + * @data: ACPI device data object containing the property + * @propname: Name of the property * @index: Index of the reference to return * @args: Location to store the returned reference with optional arguments * @@ -477,16 +477,16 @@ static int acpi_data_get_property_array(struct acpi_device_data *data, * * Return: %0 on success, negative error code on failure. */ -int acpi_dev_get_property_reference(struct acpi_device *adev, - const char *name, size_t index, - struct acpi_reference_args *args) +static int acpi_data_get_property_reference(struct acpi_device_data *data, + const char *propname, size_t index, + struct acpi_reference_args *args) { const union acpi_object *element, *end; const union acpi_object *obj; struct acpi_device *device; int ret, idx = 0; - ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj); + ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj); if (ret) return ret; @@ -561,7 +561,23 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, return -EPROTO; } -EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); + +/** + * acpi_node_get_property_reference - get a handle to the referenced object. + * @fwnode: Firmware node to get the property from. + * @propname: Name of the property. + * @index: Index of the reference to return. + * @args: Location to store the returned reference with optional arguments. + */ +int acpi_node_get_property_reference(struct fwnode_handle *fwnode, + const char *name, size_t index, + struct acpi_reference_args *args) +{ + struct acpi_device_data *data = acpi_device_data_of_node(fwnode); + + return data ? acpi_data_get_property_reference(data, name, index, args) : -EINVAL; +} +EXPORT_SYMBOL_GPL(acpi_node_get_property_reference); static int acpi_data_prop_read_single(struct acpi_device_data *data, const char *propname, @@ -768,3 +784,59 @@ int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname, return acpi_data_prop_read(acpi_device_data_of_node(fwnode), propname, proptype, val, nval); } + +/** + * acpi_get_next_subnode - Return the next child node handle for a device. + * @dev: Device to find the next child node for. + * @child: Handle to one of the device's child nodes or a null handle. + */ +struct fwnode_handle *acpi_get_next_subnode(struct device *dev, + struct fwnode_handle *child) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct list_head *head, *next; + + if (!adev) + return NULL; + + if (!child || child->type == FWNODE_ACPI) { + head = &adev->children; + if (list_empty(head)) + goto nondev; + + if (child) { + adev = to_acpi_device_node(child); + next = adev->node.next; + if (next == head) { + child = NULL; + goto nondev; + } + adev = list_entry(next, struct acpi_device, node); + } else { + adev = list_first_entry(head, struct acpi_device, node); + } + return acpi_fwnode_handle(adev); + } + + nondev: + if (!child || child->type == FWNODE_ACPI_DATA) { + struct acpi_data_node *dn; + + head = &adev->data.subnodes; + if (list_empty(head)) + return NULL; + + if (child) { + dn = to_acpi_data_node(child); + next = dn->sibling.next; + if (next == head) + return NULL; + + dn = list_entry(next, struct acpi_data_node, sibling); + } else { + dn = list_first_entry(head, struct acpi_data_node, sibling); + } + return &dn->fwnode; + } + return NULL; +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 01136b879038..d1ce377db3e9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -695,26 +695,6 @@ int acpi_device_add(struct acpi_device *device, return result; } -struct acpi_device *acpi_get_next_child(struct device *dev, - struct acpi_device *child) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - struct list_head *head, *next; - - if (!adev) - return NULL; - - head = &adev->children; - if (list_empty(head)) - return NULL; - - if (!child) - return list_first_entry(head, struct acpi_device, node); - - next = child->node.next; - return next == head ? NULL : list_entry(next, struct acpi_device, node); -} - /* -------------------------------------------------------------------------- Device Enumeration -------------------------------------------------------------------------- */ diff --git a/drivers/base/property.c b/drivers/base/property.c index ca118169a6c5..660ecec60bdf 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -493,11 +493,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev, if (node) return &node->fwnode; } else if (IS_ENABLED(CONFIG_ACPI)) { - struct acpi_device *node; - - node = acpi_get_next_child(dev, to_acpi_device_node(child)); - if (node) - return acpi_fwnode_handle(node); + return acpi_get_next_subnode(dev, child); } return NULL; } diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index a38cf16a5828..69a83626f1ae 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -453,7 +453,7 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, return 0; } -static int acpi_gpio_property_lookup(struct acpi_device *adev, +static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_lookup *lookup) { @@ -461,10 +461,16 @@ static int acpi_gpio_property_lookup(struct acpi_device *adev, int ret; memset(&args, 0, sizeof(args)); - ret = acpi_dev_get_property_reference(adev, propname, index, &args); - if (ret && !acpi_get_driver_gpio_data(adev, propname, index, &args)) - return ret; + ret = acpi_node_get_property_reference(fwnode, propname, index, &args); + if (ret) { + struct acpi_device *adev = to_acpi_device_node(fwnode); + if (!adev) + return ret; + + if (!acpi_get_driver_gpio_data(adev, propname, index, &args)) + return ret; + } /* * The property was found and resolved, so need to lookup the GPIO based * on returned args. @@ -518,7 +524,8 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, if (propname) { dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); - ret = acpi_gpio_property_lookup(adev, propname, index, &lookup); + ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev), + propname, index, &lookup); if (ret) return ERR_PTR(ret); @@ -534,6 +541,47 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, return ret ? ERR_PTR(ret) : lookup.desc; } +/** + * acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources + * @fwnode: pointer to an ACPI firmware node to get the GPIO information from + * @propname: Property name of the GPIO + * @index: index of GpioIo/GpioInt resource (starting from %0) + * @info: info pointer to fill in (optional) + * + * If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it. + * Otherwise (ie. it is a data-only non-device object), use the property-based + * GPIO lookup to get to the GPIO resource with the relevant information and use + * that to obtain the GPIO descriptor to return. + */ +struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, + const char *propname, int index, + struct acpi_gpio_info *info) +{ + struct acpi_gpio_lookup lookup; + struct acpi_device *adev; + int ret; + + adev = to_acpi_device_node(fwnode); + if (adev) + return acpi_get_gpiod_by_index(adev, propname, index, info); + + if (!is_acpi_data_node(fwnode)) + return ERR_PTR(-ENODEV); + + if (!propname) + return ERR_PTR(-EINVAL); + + memset(&lookup, 0, sizeof(lookup)); + lookup.index = index; + + ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup); + if (ret) + return ERR_PTR(ret); + + ret = acpi_gpio_resource_lookup(&lookup, info); + return ret ? ERR_PTR(ret) : lookup.desc; +} + /** * acpi_dev_gpio_irq_get() - Find GpioInt and translate it to Linux IRQ number * @adev: pointer to a ACPI device to get IRQ from diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f43e808a49d9..7d61b506c42f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2083,11 +2083,10 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, &flags); if (!IS_ERR(desc)) active_low = flags & OF_GPIO_ACTIVE_LOW; - } else if (is_acpi_device_node(fwnode)) { + } else if (is_acpi_node(fwnode)) { struct acpi_gpio_info info; - desc = acpi_get_gpiod_by_index(to_acpi_device_node(fwnode), - propname, 0, &info); + desc = acpi_node_get_gpiod(fwnode, propname, 0, &info); if (!IS_ERR(desc)) active_low = info.active_low; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index bf343004b008..e69c7157cdad 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -42,6 +42,9 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, int index, struct acpi_gpio_info *info); +struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, + const char *propname, int index, + struct acpi_gpio_info *info); int acpi_gpio_count(struct device *dev, const char *con_id); #else @@ -60,7 +63,12 @@ acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, { return ERR_PTR(-ENOSYS); } - +static inline struct gpio_desc * +acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, + int index, struct acpi_gpio_info *info) +{ + return ERR_PTR(-ENXIO); +} static inline int acpi_gpio_count(struct device *dev, const char *con_id) { return -ENODEV; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6be94ba4e980..865d948c60e6 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -758,9 +758,9 @@ struct acpi_reference_args { #ifdef CONFIG_ACPI int acpi_dev_get_property(struct acpi_device *adev, const char *name, acpi_object_type type, const union acpi_object **obj); -int acpi_dev_get_property_reference(struct acpi_device *adev, - const char *name, size_t index, - struct acpi_reference_args *args); +int acpi_node_get_property_reference(struct fwnode_handle *fwnode, + const char *name, size_t index, + struct acpi_reference_args *args); int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, void **valptr); @@ -771,8 +771,8 @@ int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname, int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, enum dev_prop_type proptype, void *val, size_t nval); -struct acpi_device *acpi_get_next_child(struct device *dev, - struct acpi_device *child); +struct fwnode_handle *acpi_get_next_subnode(struct device *dev, + struct fwnode_handle *subnode); #else static inline int acpi_dev_get_property(struct acpi_device *adev, const char *name, acpi_object_type type, @@ -781,7 +781,7 @@ static inline int acpi_dev_get_property(struct acpi_device *adev, return -ENXIO; } -static inline int acpi_dev_get_property_reference(struct acpi_device *adev, +static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode, const char *name, const char *cells_name, size_t index, struct acpi_reference_args *args) { @@ -826,12 +826,11 @@ static inline int acpi_dev_prop_read(struct acpi_device *adev, return -ENXIO; } -static inline struct acpi_device *acpi_get_next_child(struct device *dev, - struct acpi_device *child) +static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev, + struct fwnode_handle *subnode) { return NULL; } - #endif #endif /*_LINUX_ACPI_H*/ -- cgit v1.3-6-gb490 From f0489a5ef4d011e29f78021ad13a543e8769d619 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Sep 2015 13:47:23 +0530 Subject: PM / OPP: Rename opp init/free table routines free-table routines are opposite of init-table ones, and must be named to make that clear. Opposite of 'init' is 'exit', but those doesn't suit really well. Replace 'init' with 'add' and 'free' with 'remove'. Reported-by: Pavel Machek Reviewed-by: Stephen Boyd Signed-off-by: Viresh Kumar Acked-by: Shawn Guo Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-imx/mach-imx6q.c | 2 +- drivers/base/power/opp.c | 41 ++++++++++++++++++------------------ drivers/cpufreq/arm_big_little.h | 2 +- drivers/cpufreq/arm_big_little_dt.c | 4 ++-- drivers/cpufreq/cpufreq-dt.c | 6 +++--- drivers/cpufreq/exynos5440-cpufreq.c | 6 +++--- drivers/cpufreq/imx6q-cpufreq.c | 6 +++--- drivers/cpufreq/mt8173-cpufreq.c | 6 +++--- include/linux/pm_opp.h | 16 +++++++------- 9 files changed, 44 insertions(+), 45 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 9602cc12d2f1..3286eec91d92 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -350,7 +350,7 @@ static void __init imx6q_opp_init(void) return; } - if (of_init_opp_table(cpu_dev)) { + if (of_add_opp_table(cpu_dev)) { pr_warn("failed to init OPP table\n"); goto put_node; } diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index c3a738652d13..9f0a2929821b 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -828,8 +828,8 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, * The opp is made available by default and it can be controlled using * dev_pm_opp_enable/disable functions and may be removed by dev_pm_opp_remove. * - * NOTE: "dynamic" parameter impacts OPPs added by the of_init_opp_table and - * freed by of_free_opp_table. + * NOTE: "dynamic" parameter impacts OPPs added by the of_add_opp_table and + * freed by of_remove_opp_table. * * Locking: The internal device_opp and opp structures are RCU protected. * Hence this function internally uses RCU updater strategy with mutex locks @@ -1213,7 +1213,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier); #ifdef CONFIG_OF /** - * of_free_opp_table() - Free OPP table entries created from static DT entries + * of_remove_opp_table() - Free OPP table entries created from static DT entries * @dev: device pointer used to lookup device OPPs. * * Free OPPs created using static entries present in DT. @@ -1224,7 +1224,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier); * that this function is *NOT* called under RCU protection or in contexts where * mutex cannot be locked. */ -void of_free_opp_table(struct device *dev) +void of_remove_opp_table(struct device *dev) { struct device_opp *dev_opp; struct dev_pm_opp *opp, *tmp; @@ -1259,9 +1259,9 @@ void of_free_opp_table(struct device *dev) unlock: mutex_unlock(&dev_opp_list_lock); } -EXPORT_SYMBOL_GPL(of_free_opp_table); +EXPORT_SYMBOL_GPL(of_remove_opp_table); -void of_cpumask_free_opp_table(cpumask_var_t cpumask) +void of_cpumask_remove_opp_table(cpumask_var_t cpumask) { struct device *cpu_dev; int cpu; @@ -1276,10 +1276,10 @@ void of_cpumask_free_opp_table(cpumask_var_t cpumask) continue; } - of_free_opp_table(cpu_dev); + of_remove_opp_table(cpu_dev); } } -EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table); +EXPORT_SYMBOL_GPL(of_cpumask_remove_opp_table); /* Returns opp descriptor node for a device, caller must do of_node_put() */ static struct device_node *_of_get_opp_desc_node(struct device *dev) @@ -1295,8 +1295,7 @@ static struct device_node *_of_get_opp_desc_node(struct device *dev) } /* Initializes OPP tables based on new bindings */ -static int _of_init_opp_table_v2(struct device *dev, - struct device_node *opp_np) +static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np) { struct device_node *np; struct device_opp *dev_opp; @@ -1338,13 +1337,13 @@ static int _of_init_opp_table_v2(struct device *dev, return 0; free_table: - of_free_opp_table(dev); + of_remove_opp_table(dev); return ret; } /* Initializes OPP tables based on old-deprecated bindings */ -static int _of_init_opp_table_v1(struct device *dev) +static int _of_add_opp_table_v1(struct device *dev) { const struct property *prop; const __be32 *val; @@ -1381,7 +1380,7 @@ static int _of_init_opp_table_v1(struct device *dev) } /** - * of_init_opp_table() - Initialize opp table from device tree + * of_add_opp_table() - Initialize opp table from device tree * @dev: device pointer used to lookup device OPPs. * * Register the initial OPP table with the OPP library for given device. @@ -1403,7 +1402,7 @@ static int _of_init_opp_table_v1(struct device *dev) * -ENODATA when empty 'operating-points' property is found * -EINVAL when invalid entries are found in opp-v2 table */ -int of_init_opp_table(struct device *dev) +int of_add_opp_table(struct device *dev) { struct device_node *opp_np; int ret; @@ -1418,17 +1417,17 @@ int of_init_opp_table(struct device *dev) * Try old-deprecated bindings for backward compatibility with * older dtbs. */ - return _of_init_opp_table_v1(dev); + return _of_add_opp_table_v1(dev); } - ret = _of_init_opp_table_v2(dev, opp_np); + ret = _of_add_opp_table_v2(dev, opp_np); of_node_put(opp_np); return ret; } -EXPORT_SYMBOL_GPL(of_init_opp_table); +EXPORT_SYMBOL_GPL(of_add_opp_table); -int of_cpumask_init_opp_table(cpumask_var_t cpumask) +int of_cpumask_add_opp_table(cpumask_var_t cpumask) { struct device *cpu_dev; int cpu, ret = 0; @@ -1443,20 +1442,20 @@ int of_cpumask_init_opp_table(cpumask_var_t cpumask) continue; } - ret = of_init_opp_table(cpu_dev); + ret = of_add_opp_table(cpu_dev); if (ret) { pr_err("%s: couldn't find opp table for cpu:%d, %d\n", __func__, cpu, ret); /* Free all other OPPs */ - of_cpumask_free_opp_table(cpumask); + of_cpumask_remove_opp_table(cpumask); break; } } return ret; } -EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table); +EXPORT_SYMBOL_GPL(of_cpumask_add_opp_table); /* Required only for V1 bindings, as v2 can manage it from DT itself */ int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask) diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h index a211f7db9d32..d7ac320ead23 100644 --- a/drivers/cpufreq/arm_big_little.h +++ b/drivers/cpufreq/arm_big_little.h @@ -28,7 +28,7 @@ struct cpufreq_arm_bL_ops { /* * This must set opp table for cpu_dev in a similar way as done by - * of_init_opp_table(). + * of_add_opp_table(). */ int (*init_opp_table)(struct device *cpu_dev); diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c index 36d91dba2965..47ac0ff54e3a 100644 --- a/drivers/cpufreq/arm_big_little_dt.c +++ b/drivers/cpufreq/arm_big_little_dt.c @@ -54,7 +54,7 @@ static int dt_init_opp_table(struct device *cpu_dev) return -ENOENT; } - ret = of_init_opp_table(cpu_dev); + ret = of_add_opp_table(cpu_dev); of_node_put(np); return ret; @@ -82,7 +82,7 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = { .name = "dt-bl", .get_transition_latency = dt_get_transition_latency, .init_opp_table = dt_init_opp_table, - .free_opp_table = of_free_opp_table, + .free_opp_table = of_remove_opp_table, }; static int generic_bL_probe(struct platform_device *pdev) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 7c0d70e2a861..df8333bb4f56 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -238,7 +238,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) * * OPPs might be populated at runtime, don't check for error here */ - of_cpumask_init_opp_table(policy->cpus); + of_cpumask_add_opp_table(policy->cpus); /* * But we need OPP table to function so if it is not there let's @@ -368,7 +368,7 @@ out_free_cpufreq_table: out_free_priv: kfree(priv); out_free_opp: - of_cpumask_free_opp_table(policy->cpus); + of_cpumask_remove_opp_table(policy->cpus); out_node_put: of_node_put(np); out_put_reg_clk: @@ -385,7 +385,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy) cpufreq_cooling_unregister(priv->cdev); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); - of_cpumask_free_opp_table(policy->related_cpus); + of_cpumask_remove_opp_table(policy->related_cpus); clk_put(policy->clk); if (!IS_ERR(priv->cpu_reg)) regulator_put(priv->cpu_reg); diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 21a90ed7f3d8..fc46813d3b83 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -360,7 +360,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) goto err_put_node; } - ret = of_init_opp_table(dvfs_info->dev); + ret = of_add_opp_table(dvfs_info->dev); if (ret) { dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret); goto err_put_node; @@ -424,7 +424,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) err_free_table: dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); err_free_opp: - of_free_opp_table(dvfs_info->dev); + of_remove_opp_table(dvfs_info->dev); err_put_node: of_node_put(np); dev_err(&pdev->dev, "%s: failed initialization\n", __func__); @@ -435,7 +435,7 @@ static int exynos_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&exynos_driver); dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); - of_free_opp_table(dvfs_info->dev); + of_remove_opp_table(dvfs_info->dev); return 0; } diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 380a90d3c57e..3802765aeb9f 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -202,7 +202,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) */ num = dev_pm_opp_get_opp_count(cpu_dev); if (num < 0) { - ret = of_init_opp_table(cpu_dev); + ret = of_add_opp_table(cpu_dev); if (ret < 0) { dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); goto put_reg; @@ -312,7 +312,7 @@ free_freq_table: dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); out_free_opp: if (free_opp) - of_free_opp_table(cpu_dev); + of_remove_opp_table(cpu_dev); put_reg: if (!IS_ERR(arm_reg)) regulator_put(arm_reg); @@ -340,7 +340,7 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev) cpufreq_unregister_driver(&imx6q_cpufreq_driver); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); if (free_opp) - of_free_opp_table(cpu_dev); + of_remove_opp_table(cpu_dev); regulator_put(arm_reg); if (!IS_ERR(pu_reg)) regulator_put(pu_reg); diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 49caed293a3b..519e83146e86 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c @@ -344,7 +344,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) /* Both presence and absence of sram regulator are valid cases. */ sram_reg = regulator_get_exclusive(cpu_dev, "sram"); - ret = of_init_opp_table(cpu_dev); + ret = of_add_opp_table(cpu_dev); if (ret) { pr_warn("no OPP table for cpu%d\n", cpu); goto out_free_resources; @@ -378,7 +378,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) return 0; out_free_opp_table: - of_free_opp_table(cpu_dev); + of_remove_opp_table(cpu_dev); out_free_resources: if (!IS_ERR(proc_reg)) @@ -404,7 +404,7 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) if (!IS_ERR(info->inter_clk)) clk_put(info->inter_clk); - of_free_opp_table(info->cpu_dev); + of_remove_opp_table(info->cpu_dev); } static int mtk_cpufreq_init(struct cpufreq_policy *policy) diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index e817722ee3f0..20adcb4ce443 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -132,28 +132,28 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) -int of_init_opp_table(struct device *dev); -void of_free_opp_table(struct device *dev); -int of_cpumask_init_opp_table(cpumask_var_t cpumask); -void of_cpumask_free_opp_table(cpumask_var_t cpumask); +int of_add_opp_table(struct device *dev); +void of_remove_opp_table(struct device *dev); +int of_cpumask_add_opp_table(cpumask_var_t cpumask); +void of_cpumask_remove_opp_table(cpumask_var_t cpumask); int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask); int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask); #else -static inline int of_init_opp_table(struct device *dev) +static inline int of_add_opp_table(struct device *dev) { return -EINVAL; } -static inline void of_free_opp_table(struct device *dev) +static inline void of_remove_opp_table(struct device *dev) { } -static inline int of_cpumask_init_opp_table(cpumask_var_t cpumask) +static inline int of_cpumask_add_opp_table(cpumask_var_t cpumask) { return -ENOSYS; } -static inline void of_cpumask_free_opp_table(cpumask_var_t cpumask) +static inline void of_cpumask_remove_opp_table(cpumask_var_t cpumask) { } -- cgit v1.3-6-gb490 From 8f8d37b2537a28b5b2e3cb60dfc85a2a1303f99b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Sep 2015 13:47:24 +0530 Subject: PM / OPP: Prefix exported opp routines with dev_pm_opp_ That's the naming convention followed in most of opp core, but few routines didn't follow this, fix them. Reviewed-by: Stephen Boyd Signed-off-by: Viresh Kumar Acked-by: Shawn Guo Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-imx/mach-imx6q.c | 2 +- drivers/base/power/opp.c | 41 ++++++++++++++++++------------------ drivers/cpufreq/arm_big_little.h | 2 +- drivers/cpufreq/arm_big_little_dt.c | 4 ++-- drivers/cpufreq/cpufreq-dt.c | 10 ++++----- drivers/cpufreq/exynos5440-cpufreq.c | 6 +++--- drivers/cpufreq/imx6q-cpufreq.c | 6 +++--- drivers/cpufreq/mt8173-cpufreq.c | 6 +++--- include/linux/pm_opp.h | 24 ++++++++++----------- 9 files changed, 51 insertions(+), 50 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 3286eec91d92..3878494bd118 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -350,7 +350,7 @@ static void __init imx6q_opp_init(void) return; } - if (of_add_opp_table(cpu_dev)) { + if (dev_pm_opp_of_add_table(cpu_dev)) { pr_warn("failed to init OPP table\n"); goto put_node; } diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 9f0a2929821b..aeff1cfb46f2 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -828,8 +828,8 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, * The opp is made available by default and it can be controlled using * dev_pm_opp_enable/disable functions and may be removed by dev_pm_opp_remove. * - * NOTE: "dynamic" parameter impacts OPPs added by the of_add_opp_table and - * freed by of_remove_opp_table. + * NOTE: "dynamic" parameter impacts OPPs added by the dev_pm_opp_of_add_table + * and freed by dev_pm_opp_of_remove_table. * * Locking: The internal device_opp and opp structures are RCU protected. * Hence this function internally uses RCU updater strategy with mutex locks @@ -1213,7 +1213,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier); #ifdef CONFIG_OF /** - * of_remove_opp_table() - Free OPP table entries created from static DT entries + * dev_pm_opp_of_remove_table() - Free OPP table entries created from static DT + * entries * @dev: device pointer used to lookup device OPPs. * * Free OPPs created using static entries present in DT. @@ -1224,7 +1225,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier); * that this function is *NOT* called under RCU protection or in contexts where * mutex cannot be locked. */ -void of_remove_opp_table(struct device *dev) +void dev_pm_opp_of_remove_table(struct device *dev) { struct device_opp *dev_opp; struct dev_pm_opp *opp, *tmp; @@ -1259,9 +1260,9 @@ void of_remove_opp_table(struct device *dev) unlock: mutex_unlock(&dev_opp_list_lock); } -EXPORT_SYMBOL_GPL(of_remove_opp_table); +EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table); -void of_cpumask_remove_opp_table(cpumask_var_t cpumask) +void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask) { struct device *cpu_dev; int cpu; @@ -1276,10 +1277,10 @@ void of_cpumask_remove_opp_table(cpumask_var_t cpumask) continue; } - of_remove_opp_table(cpu_dev); + dev_pm_opp_of_remove_table(cpu_dev); } } -EXPORT_SYMBOL_GPL(of_cpumask_remove_opp_table); +EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table); /* Returns opp descriptor node for a device, caller must do of_node_put() */ static struct device_node *_of_get_opp_desc_node(struct device *dev) @@ -1337,7 +1338,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np) return 0; free_table: - of_remove_opp_table(dev); + dev_pm_opp_of_remove_table(dev); return ret; } @@ -1380,7 +1381,7 @@ static int _of_add_opp_table_v1(struct device *dev) } /** - * of_add_opp_table() - Initialize opp table from device tree + * dev_pm_opp_of_add_table() - Initialize opp table from device tree * @dev: device pointer used to lookup device OPPs. * * Register the initial OPP table with the OPP library for given device. @@ -1402,7 +1403,7 @@ static int _of_add_opp_table_v1(struct device *dev) * -ENODATA when empty 'operating-points' property is found * -EINVAL when invalid entries are found in opp-v2 table */ -int of_add_opp_table(struct device *dev) +int dev_pm_opp_of_add_table(struct device *dev) { struct device_node *opp_np; int ret; @@ -1425,9 +1426,9 @@ int of_add_opp_table(struct device *dev) return ret; } -EXPORT_SYMBOL_GPL(of_add_opp_table); +EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table); -int of_cpumask_add_opp_table(cpumask_var_t cpumask) +int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask) { struct device *cpu_dev; int cpu, ret = 0; @@ -1442,23 +1443,23 @@ int of_cpumask_add_opp_table(cpumask_var_t cpumask) continue; } - ret = of_add_opp_table(cpu_dev); + ret = dev_pm_opp_of_add_table(cpu_dev); if (ret) { pr_err("%s: couldn't find opp table for cpu:%d, %d\n", __func__, cpu, ret); /* Free all other OPPs */ - of_cpumask_remove_opp_table(cpumask); + dev_pm_opp_of_cpumask_remove_table(cpumask); break; } } return ret; } -EXPORT_SYMBOL_GPL(of_cpumask_add_opp_table); +EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table); /* Required only for V1 bindings, as v2 can manage it from DT itself */ -int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask) +int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) { struct device_list_opp *list_dev; struct device_opp *dev_opp; @@ -1496,7 +1497,7 @@ out_rcu_read_unlock: return 0; } -EXPORT_SYMBOL_GPL(set_cpus_sharing_opps); +EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); /* * Works only for OPP v2 bindings. @@ -1504,7 +1505,7 @@ EXPORT_SYMBOL_GPL(set_cpus_sharing_opps); * cpumask should be already set to mask of cpu_dev->id. * Returns -ENOENT if operating-points-v2 bindings aren't supported. */ -int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask) +int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) { struct device_node *np, *tmp_np; struct device *tcpu_dev; @@ -1554,5 +1555,5 @@ put_cpu_node: of_node_put(np); return ret; } -EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps); +EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus); #endif diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h index d7ac320ead23..b88889d9387e 100644 --- a/drivers/cpufreq/arm_big_little.h +++ b/drivers/cpufreq/arm_big_little.h @@ -28,7 +28,7 @@ struct cpufreq_arm_bL_ops { /* * This must set opp table for cpu_dev in a similar way as done by - * of_add_opp_table(). + * dev_pm_opp_of_add_table(). */ int (*init_opp_table)(struct device *cpu_dev); diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c index 47ac0ff54e3a..16ddeefe9443 100644 --- a/drivers/cpufreq/arm_big_little_dt.c +++ b/drivers/cpufreq/arm_big_little_dt.c @@ -54,7 +54,7 @@ static int dt_init_opp_table(struct device *cpu_dev) return -ENOENT; } - ret = of_add_opp_table(cpu_dev); + ret = dev_pm_opp_of_add_table(cpu_dev); of_node_put(np); return ret; @@ -82,7 +82,7 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = { .name = "dt-bl", .get_transition_latency = dt_get_transition_latency, .init_opp_table = dt_init_opp_table, - .free_opp_table = of_remove_opp_table, + .free_opp_table = dev_pm_opp_of_remove_table, }; static int generic_bL_probe(struct platform_device *pdev) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index df8333bb4f56..90d64081ddb3 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -216,7 +216,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) } /* Get OPP-sharing information from "operating-points-v2" bindings */ - ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus); + ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus); if (ret) { /* * operating-points-v2 not supported, fallback to old method of @@ -238,7 +238,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) * * OPPs might be populated at runtime, don't check for error here */ - of_cpumask_add_opp_table(policy->cpus); + dev_pm_opp_of_cpumask_add_table(policy->cpus); /* * But we need OPP table to function so if it is not there let's @@ -261,7 +261,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) * OPP tables are initialized only for policy->cpu, do it for * others as well. */ - ret = set_cpus_sharing_opps(cpu_dev, policy->cpus); + ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus); if (ret) dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", __func__, ret); @@ -368,7 +368,7 @@ out_free_cpufreq_table: out_free_priv: kfree(priv); out_free_opp: - of_cpumask_remove_opp_table(policy->cpus); + dev_pm_opp_of_cpumask_remove_table(policy->cpus); out_node_put: of_node_put(np); out_put_reg_clk: @@ -385,7 +385,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy) cpufreq_cooling_unregister(priv->cdev); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); - of_cpumask_remove_opp_table(policy->related_cpus); + dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); clk_put(policy->clk); if (!IS_ERR(priv->cpu_reg)) regulator_put(priv->cpu_reg); diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index fc46813d3b83..c0f3373706f4 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -360,7 +360,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) goto err_put_node; } - ret = of_add_opp_table(dvfs_info->dev); + ret = dev_pm_opp_of_add_table(dvfs_info->dev); if (ret) { dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret); goto err_put_node; @@ -424,7 +424,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) err_free_table: dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); err_free_opp: - of_remove_opp_table(dvfs_info->dev); + dev_pm_opp_of_remove_table(dvfs_info->dev); err_put_node: of_node_put(np); dev_err(&pdev->dev, "%s: failed initialization\n", __func__); @@ -435,7 +435,7 @@ static int exynos_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&exynos_driver); dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); - of_remove_opp_table(dvfs_info->dev); + dev_pm_opp_of_remove_table(dvfs_info->dev); return 0; } diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 3802765aeb9f..84fbc8e8fc56 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -202,7 +202,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) */ num = dev_pm_opp_get_opp_count(cpu_dev); if (num < 0) { - ret = of_add_opp_table(cpu_dev); + ret = dev_pm_opp_of_add_table(cpu_dev); if (ret < 0) { dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); goto put_reg; @@ -312,7 +312,7 @@ free_freq_table: dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); out_free_opp: if (free_opp) - of_remove_opp_table(cpu_dev); + dev_pm_opp_of_remove_table(cpu_dev); put_reg: if (!IS_ERR(arm_reg)) regulator_put(arm_reg); @@ -340,7 +340,7 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev) cpufreq_unregister_driver(&imx6q_cpufreq_driver); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); if (free_opp) - of_remove_opp_table(cpu_dev); + dev_pm_opp_of_remove_table(cpu_dev); regulator_put(arm_reg); if (!IS_ERR(pu_reg)) regulator_put(pu_reg); diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 519e83146e86..83001dc5b646 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c @@ -344,7 +344,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) /* Both presence and absence of sram regulator are valid cases. */ sram_reg = regulator_get_exclusive(cpu_dev, "sram"); - ret = of_add_opp_table(cpu_dev); + ret = dev_pm_opp_of_add_table(cpu_dev); if (ret) { pr_warn("no OPP table for cpu%d\n", cpu); goto out_free_resources; @@ -378,7 +378,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) return 0; out_free_opp_table: - of_remove_opp_table(cpu_dev); + dev_pm_opp_of_remove_table(cpu_dev); out_free_resources: if (!IS_ERR(proc_reg)) @@ -404,7 +404,7 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) if (!IS_ERR(info->inter_clk)) clk_put(info->inter_clk); - of_remove_opp_table(info->cpu_dev); + dev_pm_opp_of_remove_table(info->cpu_dev); } static int mtk_cpufreq_init(struct cpufreq_policy *policy) diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 20adcb4ce443..9a2e50337af9 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -132,37 +132,37 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) -int of_add_opp_table(struct device *dev); -void of_remove_opp_table(struct device *dev); -int of_cpumask_add_opp_table(cpumask_var_t cpumask); -void of_cpumask_remove_opp_table(cpumask_var_t cpumask); -int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask); -int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask); +int dev_pm_opp_of_add_table(struct device *dev); +void dev_pm_opp_of_remove_table(struct device *dev); +int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask); +void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask); +int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask); +int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask); #else -static inline int of_add_opp_table(struct device *dev) +static inline int dev_pm_opp_of_add_table(struct device *dev) { return -EINVAL; } -static inline void of_remove_opp_table(struct device *dev) +static inline void dev_pm_opp_of_remove_table(struct device *dev) { } -static inline int of_cpumask_add_opp_table(cpumask_var_t cpumask) +static inline int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask) { return -ENOSYS; } -static inline void of_cpumask_remove_opp_table(cpumask_var_t cpumask) +static inline void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask) { } -static inline int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask) +static inline int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) { return -ENOSYS; } -static inline int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask) +static inline int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) { return -ENOSYS; } -- cgit v1.3-6-gb490 From 636c19d38920caee61d694ef306d110d33935038 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 9 Sep 2015 23:59:41 +0200 Subject: ACPI / scan: constify first argument of struct acpi_scan_handler::match One wouldn't expect a "match" function modify the string it searches for, and indeed the only instance of the struct acpi_scan_handler::match callback, acpi_pnp_match, can easily be changed. While there, update its helper matching_id(). This is also preparation for constifying struct acpi_hardware_id::id. Signed-off-by: Rasmus Villemoes Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_pnp.c | 4 ++-- include/acpi/acpi_bus.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index c58940b231d6..48fc3ad13a4b 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -316,7 +316,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {""}, }; -static bool matching_id(char *idstr, char *list_id) +static bool matching_id(const char *idstr, const char *list_id) { int i; @@ -333,7 +333,7 @@ static bool matching_id(char *idstr, char *list_id) return true; } -static bool acpi_pnp_match(char *idstr, const struct acpi_device_id **matchid) +static bool acpi_pnp_match(const char *idstr, const struct acpi_device_id **matchid) { const struct acpi_device_id *devid; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5ba8fb64f664..9a1b46c64fc1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -129,7 +129,7 @@ static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( struct acpi_scan_handler { const struct acpi_device_id *ids; struct list_head list_node; - bool (*match)(char *idstr, const struct acpi_device_id **matchid); + bool (*match)(const char *idstr, const struct acpi_device_id **matchid); int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); void (*detach)(struct acpi_device *dev); void (*bind)(struct device *phys_dev); -- cgit v1.3-6-gb490 From 844142c3f80c66fb2c311b118d60abdfe02322cb Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 9 Sep 2015 23:59:42 +0200 Subject: ACPI / scan: constify struct acpi_hardware_id::id This is preparation for using kstrdup_const to initialize that member. Signed-off-by: Rasmus Villemoes Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 4 ++-- drivers/pnp/pnpacpi/core.c | 4 ++-- include/acpi/acpi_bus.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 01136b879038..a3eaf2080707 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1472,7 +1472,7 @@ bool acpi_device_is_present(struct acpi_device *adev) } static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, - char *idstr, + const char *idstr, const struct acpi_device_id **matchid) { const struct acpi_device_id *devid; @@ -1491,7 +1491,7 @@ static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, return false; } -static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr, +static struct acpi_scan_handler *acpi_scan_match_handler(const char *idstr, const struct acpi_device_id **matchid) { struct acpi_scan_handler *handler; diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 5153d1d69aee..9113876487ed 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -207,7 +207,7 @@ struct pnp_protocol pnpacpi_protocol = { }; EXPORT_SYMBOL(pnpacpi_protocol); -static char *__init pnpacpi_get_id(struct acpi_device *device) +static const char *__init pnpacpi_get_id(struct acpi_device *device) { struct acpi_hardware_id *id; @@ -222,7 +222,7 @@ static char *__init pnpacpi_get_id(struct acpi_device *device) static int __init pnpacpi_add_device(struct acpi_device *device) { struct pnp_dev *dev; - char *pnpid; + const char *pnpid; struct acpi_hardware_id *id; int error; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 9a1b46c64fc1..fec002919b65 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -227,7 +227,7 @@ typedef char acpi_device_class[20]; struct acpi_hardware_id { struct list_head list; - char *id; + const char *id; }; struct acpi_pnp_type { -- cgit v1.3-6-gb490 From 2cbb51574557a8affe0732ad23a840cf90c656b1 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 10 Sep 2015 14:14:27 +0530 Subject: clk: samsung: exynos7: Adds missing clocks gates of CMU_TOPC This adds some of the missing GATE clocks of CMU_TOPC block. Signed-off-by: Alim Akhtar Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 27 +++++++++++++++++++++++++++ include/dt-bindings/clock/exynos7-clk.h | 13 ++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index 1bb9ee1cff8b..586c2c12788f 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -32,7 +32,9 @@ #define DIV_TOPC0 0x0600 #define DIV_TOPC1 0x0604 #define DIV_TOPC3 0x060C +#define ENABLE_ACLK_TOPC0 0x0800 #define ENABLE_ACLK_TOPC1 0x0804 +#define ENABLE_SCLK_TOPC1 0x0A04 static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = { FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_topc_bus0_pll", 1, 2, 0), @@ -143,8 +145,33 @@ static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = { }; static struct samsung_gate_clock topc_gate_clks[] __initdata = { + GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133", + ENABLE_ACLK_TOPC0, 4, 0, 0), + GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532", ENABLE_ACLK_TOPC1, 20, 0, 0), + + GATE(ACLK_PERIS_66, "aclk_peris_66", "dout_aclk_peris_66", + ENABLE_ACLK_TOPC1, 24, 0, 0), + + GATE(SCLK_AUD_PLL, "sclk_aud_pll", "dout_sclk_aud_pll", + ENABLE_SCLK_TOPC1, 20, 0, 0), + GATE(SCLK_MFC_PLL_B, "sclk_mfc_pll_b", "dout_sclk_mfc_pll", + ENABLE_SCLK_TOPC1, 17, 0, 0), + GATE(SCLK_MFC_PLL_A, "sclk_mfc_pll_a", "dout_sclk_mfc_pll", + ENABLE_SCLK_TOPC1, 16, 0, 0), + GATE(SCLK_BUS1_PLL_B, "sclk_bus1_pll_b", "dout_sclk_bus1_pll", + ENABLE_SCLK_TOPC1, 13, 0, 0), + GATE(SCLK_BUS1_PLL_A, "sclk_bus1_pll_a", "dout_sclk_bus1_pll", + ENABLE_SCLK_TOPC1, 12, 0, 0), + GATE(SCLK_BUS0_PLL_B, "sclk_bus0_pll_b", "dout_sclk_bus0_pll", + ENABLE_SCLK_TOPC1, 5, 0, 0), + GATE(SCLK_BUS0_PLL_A, "sclk_bus0_pll_a", "dout_sclk_bus0_pll", + ENABLE_SCLK_TOPC1, 4, 0, 0), + GATE(SCLK_CC_PLL_B, "sclk_cc_pll_b", "dout_sclk_cc_pll", + ENABLE_SCLK_TOPC1, 1, 0, 0), + GATE(SCLK_CC_PLL_A, "sclk_cc_pll_a", "dout_sclk_cc_pll", + ENABLE_SCLK_TOPC1, 0, 0, 0), }; static struct samsung_pll_clock topc_pll_clks[] __initdata = { diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index e33c75a3c09d..d26fe0f3d5db 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -21,7 +21,18 @@ #define ACLK_MSCL_532 8 #define DOUT_SCLK_AUD_PLL 9 #define FOUT_AUD_PLL 10 -#define TOPC_NR_CLK 11 +#define SCLK_AUD_PLL 11 +#define SCLK_MFC_PLL_B 12 +#define SCLK_MFC_PLL_A 13 +#define SCLK_BUS1_PLL_B 14 +#define SCLK_BUS1_PLL_A 15 +#define SCLK_BUS0_PLL_B 16 +#define SCLK_BUS0_PLL_A 17 +#define SCLK_CC_PLL_B 18 +#define SCLK_CC_PLL_A 19 +#define ACLK_CCORE_133 20 +#define ACLK_PERIS_66 21 +#define TOPC_NR_CLK 22 /* TOP0 */ #define DOUT_ACLK_PERIC1 1 -- cgit v1.3-6-gb490 From 3f54fb1e09da301173bc44845f93a1be7fe33d8f Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 10 Sep 2015 14:14:31 +0530 Subject: clk: samsung: exynos7: Correct CMU_PERIC0 clocks names This patch renames CMU_PERIC0 clocks names to match with user manual. And also adds missing gate clock for aclk_peric0_66. Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 12 ++++++++---- include/dt-bindings/clock/exynos7-clk.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index 4dedfcf11814..8dfd820ccc8f 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -224,6 +224,7 @@ CLK_OF_DECLARE(exynos7_clk_topc, "samsung,exynos7-clock-topc", #define DIV_TOP0_PERIC1 0x0634 #define DIV_TOP0_PERIC2 0x0638 #define DIV_TOP0_PERIC3 0x063C +#define ENABLE_ACLK_TOP03 0x080C #define ENABLE_SCLK_TOP0_PERIC0 0x0A30 #define ENABLE_SCLK_TOP0_PERIC1 0x0A34 #define ENABLE_SCLK_TOP0_PERIC2 0x0A38 @@ -338,6 +339,9 @@ static struct samsung_div_clock top0_div_clks[] __initdata = { }; static struct samsung_gate_clock top0_gate_clks[] __initdata = { + GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66", + ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPDIF, "sclk_spdif", "dout_sclk_spdif", ENABLE_SCLK_TOP0_PERIC0, 4, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_sclk_pcm1", @@ -590,8 +594,8 @@ CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore", #define ENABLE_SCLK_PERIC0 0x0A00 /* List of parent clocks for Muxes in CMU_PERIC0 */ -PNAME(mout_aclk_peric0_66_p) = { "fin_pll", "dout_aclk_peric0_66" }; -PNAME(mout_sclk_uart0_p) = { "fin_pll", "sclk_uart0" }; +PNAME(mout_aclk_peric0_66_user_p) = { "fin_pll", "aclk_peric0_66" }; +PNAME(mout_sclk_uart0_user_p) = { "fin_pll", "sclk_uart0" }; static unsigned long peric0_clk_regs[] __initdata = { MUX_SEL_PERIC0, @@ -600,9 +604,9 @@ static unsigned long peric0_clk_regs[] __initdata = { }; static struct samsung_mux_clock peric0_mux_clks[] __initdata = { - MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_p, + MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_user_p, MUX_SEL_PERIC0, 0, 1), - MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_p, + MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_user_p, MUX_SEL_PERIC0, 16, 1), }; diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index d26fe0f3d5db..256188aa4692 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -49,7 +49,8 @@ #define CLK_SCLK_SPDIF 12 #define CLK_SCLK_PCM1 13 #define CLK_SCLK_I2S1 14 -#define TOP0_NR_CLK 15 +#define CLK_ACLK_PERIC0_66 15 +#define TOP0_NR_CLK 16 /* TOP1 */ #define DOUT_ACLK_FSYS1_200 1 -- cgit v1.3-6-gb490 From 33b8b739ef5ec43b5119ab011c0a885fc565ad19 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 10 Sep 2015 14:14:32 +0530 Subject: clk: samsung: exynos7: Correct CMU_PERIC1 clocks names This patch renames CMU_PERIC1 clocks names to match with user manual. And also adds missing gate clock for aclk_peric1_66. Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 38 +++++++++++++++++---------------- include/dt-bindings/clock/exynos7-clk.h | 3 ++- 2 files changed, 22 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index 8dfd820ccc8f..0b5acab91935 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -341,6 +341,8 @@ static struct samsung_div_clock top0_div_clks[] __initdata = { static struct samsung_gate_clock top0_gate_clks[] __initdata = { GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66", ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0), + GATE(CLK_ACLK_PERIC1_66, "aclk_peric1_66", "dout_aclk_peric1_66", + ENABLE_ACLK_TOP03, 12, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPDIF, "sclk_spdif", "dout_sclk_spdif", ENABLE_SCLK_TOP0_PERIC0, 4, CLK_SET_RATE_PARENT, 0), @@ -663,15 +665,15 @@ CLK_OF_DECLARE(exynos7_clk_peric0, "samsung,exynos7-clock-peric0", exynos7_clk_peric0_init); /* List of parent clocks for Muxes in CMU_PERIC1 */ -PNAME(mout_aclk_peric1_66_p) = { "fin_pll", "dout_aclk_peric1_66" }; -PNAME(mout_sclk_uart1_p) = { "fin_pll", "sclk_uart1" }; -PNAME(mout_sclk_uart2_p) = { "fin_pll", "sclk_uart2" }; -PNAME(mout_sclk_uart3_p) = { "fin_pll", "sclk_uart3" }; -PNAME(mout_sclk_spi0_p) = { "fin_pll", "sclk_spi0" }; -PNAME(mout_sclk_spi1_p) = { "fin_pll", "sclk_spi1" }; -PNAME(mout_sclk_spi2_p) = { "fin_pll", "sclk_spi2" }; -PNAME(mout_sclk_spi3_p) = { "fin_pll", "sclk_spi3" }; -PNAME(mout_sclk_spi4_p) = { "fin_pll", "sclk_spi4" }; +PNAME(mout_aclk_peric1_66_user_p) = { "fin_pll", "aclk_peric1_66" }; +PNAME(mout_sclk_uart1_user_p) = { "fin_pll", "sclk_uart1" }; +PNAME(mout_sclk_uart2_user_p) = { "fin_pll", "sclk_uart2" }; +PNAME(mout_sclk_uart3_user_p) = { "fin_pll", "sclk_uart3" }; +PNAME(mout_sclk_spi0_user_p) = { "fin_pll", "sclk_spi0" }; +PNAME(mout_sclk_spi1_user_p) = { "fin_pll", "sclk_spi1" }; +PNAME(mout_sclk_spi2_user_p) = { "fin_pll", "sclk_spi2" }; +PNAME(mout_sclk_spi3_user_p) = { "fin_pll", "sclk_spi3" }; +PNAME(mout_sclk_spi4_user_p) = { "fin_pll", "sclk_spi4" }; static unsigned long peric1_clk_regs[] __initdata = { MUX_SEL_PERIC10, @@ -682,24 +684,24 @@ static unsigned long peric1_clk_regs[] __initdata = { }; static struct samsung_mux_clock peric1_mux_clks[] __initdata = { - MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_p, + MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_user_p, MUX_SEL_PERIC10, 0, 1), - MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_p, + MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_user_p, MUX_SEL_PERIC11, 0, 1, CLK_SET_RATE_PARENT, 0), - MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_p, + MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_user_p, MUX_SEL_PERIC11, 4, 1, CLK_SET_RATE_PARENT, 0), - MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_p, + MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_user_p, MUX_SEL_PERIC11, 8, 1, CLK_SET_RATE_PARENT, 0), - MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_p, + MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_user_p, MUX_SEL_PERIC11, 12, 1, CLK_SET_RATE_PARENT, 0), - MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_p, + MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_user_p, MUX_SEL_PERIC11, 16, 1, CLK_SET_RATE_PARENT, 0), - MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_p, + MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_user_p, MUX_SEL_PERIC11, 20, 1), - MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_p, + MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_user_p, MUX_SEL_PERIC11, 24, 1), - MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_p, + MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_user_p, MUX_SEL_PERIC11, 28, 1), }; diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index 256188aa4692..287665451a89 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -50,7 +50,8 @@ #define CLK_SCLK_PCM1 13 #define CLK_SCLK_I2S1 14 #define CLK_ACLK_PERIC0_66 15 -#define TOP0_NR_CLK 16 +#define CLK_ACLK_PERIC1_66 16 +#define TOP0_NR_CLK 17 /* TOP1 */ #define DOUT_ACLK_FSYS1_200 1 -- cgit v1.3-6-gb490 From a259a61be1d0d01aa2dd4778722e4d161780c813 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 10 Sep 2015 14:14:34 +0530 Subject: clk: samsung: exynos7: Correct CMU_FSYS0 clocks names This patch renames CMU_FSYS0 clocks names to match with user manual. And also adds missing gate clock for aclk_fsys0_200. Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 24 ++++++++++++++---------- include/dt-bindings/clock/exynos7-clk.h | 3 ++- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index b5bc7edc8adc..ad5aba47dd19 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -512,6 +512,9 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = { ENABLE_SCLK_TOP1_FSYS11, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0", ENABLE_SCLK_TOP1_FSYS11, 12, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200", + ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0), }; static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { @@ -849,13 +852,13 @@ CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris", /* * List of parent clocks for Muxes in CMU_FSYS0 */ -PNAME(mout_aclk_fsys0_200_p) = { "fin_pll", "dout_aclk_fsys0_200" }; -PNAME(mout_sclk_mmc2_p) = { "fin_pll", "sclk_mmc2" }; +PNAME(mout_aclk_fsys0_200_user_p) = { "fin_pll", "aclk_fsys0_200" }; +PNAME(mout_sclk_mmc2_user_p) = { "fin_pll", "sclk_mmc2" }; -PNAME(mout_sclk_usbdrd300_p) = { "fin_pll", "sclk_usbdrd300" }; -PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_p) = { "fin_pll", +PNAME(mout_sclk_usbdrd300_user_p) = { "fin_pll", "sclk_usbdrd300" }; +PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_user_p) = { "fin_pll", "phyclk_usbdrd300_udrd30_phyclock" }; -PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_p) = { "fin_pll", +PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p) = { "fin_pll", "phyclk_usbdrd300_udrd30_pipe_pclk" }; /* fixed rate clocks used in the FSYS0 block */ @@ -878,18 +881,19 @@ static unsigned long fsys0_clk_regs[] __initdata = { }; static struct samsung_mux_clock fsys0_mux_clks[] __initdata = { - MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_p, + MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_user_p, MUX_SEL_FSYS00, 24, 1), - MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_p, MUX_SEL_FSYS01, 24, 1), - MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_p, + MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_user_p, + MUX_SEL_FSYS01, 24, 1), + MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_user_p, MUX_SEL_FSYS01, 28, 1), MUX(0, "mout_phyclk_usbdrd300_udrd30_pipe_pclk_user", - mout_phyclk_usbdrd300_udrd30_pipe_pclk_p, + mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p, MUX_SEL_FSYS02, 24, 1), MUX(0, "mout_phyclk_usbdrd300_udrd30_phyclk_user", - mout_phyclk_usbdrd300_udrd30_phyclk_p, + mout_phyclk_usbdrd300_udrd30_phyclk_user_p, MUX_SEL_FSYS02, 28, 1), }; diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index 287665451a89..667faed474ce 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -62,7 +62,8 @@ #define CLK_SCLK_MMC2 6 #define CLK_SCLK_MMC1 7 #define CLK_SCLK_MMC0 8 -#define TOP1_NR_CLK 9 +#define CLK_ACLK_FSYS0_200 9 +#define TOP1_NR_CLK 10 /* CCORE */ #define PCLK_RTC 1 -- cgit v1.3-6-gb490 From 753195a749a6c849dbd05cb82a2deb4190a06257 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 10 Sep 2015 14:14:35 +0530 Subject: clk: samsung: exynos7: Correct CMU_FSYS1 clocks names This patch renames CMU_FSYS1 clocks names to match with user manual. And also adds missing gate clock for aclk_fsys1_200. Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 16 ++++++++++------ include/dt-bindings/clock/exynos7-clk.h | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index ad5aba47dd19..5cc68440e793 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -515,6 +515,8 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = { GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200", ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0), + GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200", + ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0), }; static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { @@ -957,9 +959,9 @@ CLK_OF_DECLARE(exynos7_clk_fsys0, "samsung,exynos7-clock-fsys0", /* * List of parent clocks for Muxes in CMU_FSYS1 */ -PNAME(mout_aclk_fsys1_200_p) = { "fin_pll", "dout_aclk_fsys1_200" }; -PNAME(mout_sclk_mmc0_p) = { "fin_pll", "sclk_mmc0" }; -PNAME(mout_sclk_mmc1_p) = { "fin_pll", "sclk_mmc1" }; +PNAME(mout_aclk_fsys1_200_user_p) = { "fin_pll", "aclk_fsys1_200" }; +PNAME(mout_sclk_mmc0_user_p) = { "fin_pll", "sclk_mmc0" }; +PNAME(mout_sclk_mmc1_user_p) = { "fin_pll", "sclk_mmc1" }; static unsigned long fsys1_clk_regs[] __initdata = { MUX_SEL_FSYS10, @@ -968,11 +970,13 @@ static unsigned long fsys1_clk_regs[] __initdata = { }; static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { - MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_p, + MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_user_p, MUX_SEL_FSYS10, 28, 1), - MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_p, MUX_SEL_FSYS11, 24, 1), - MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_p, MUX_SEL_FSYS11, 28, 1), + MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_user_p, + MUX_SEL_FSYS11, 24, 1), + MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_user_p, + MUX_SEL_FSYS11, 28, 1), }; static struct samsung_gate_clock fsys1_gate_clks[] __initdata = { diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index 667faed474ce..acdf2e5e1ac0 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -63,7 +63,8 @@ #define CLK_SCLK_MMC1 7 #define CLK_SCLK_MMC0 8 #define CLK_ACLK_FSYS0_200 9 -#define TOP1_NR_CLK 10 +#define CLK_ACLK_FSYS1_200 10 +#define TOP1_NR_CLK 11 /* CCORE */ #define PCLK_RTC 1 -- cgit v1.3-6-gb490 From 7993b3ebec979b23c2d7425959c9d232c452498b Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 10 Sep 2015 14:14:37 +0530 Subject: clk: samsung: exynos7: Add required clock tree for UFS Adding required mux/div/gate clocks for UFS controller present on Exynos7. Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 107 ++++++++++++++++++++++++++++++++ include/dt-bindings/clock/exynos7-clk.h | 24 ++++++- 2 files changed, 129 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index 04275efb8c02..924215b219da 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -477,12 +477,21 @@ static struct samsung_mux_clock top1_mux_clks[] __initdata = { MUX(0, "mout_aclk_fsys1_200", mout_top1_group1, MUX_SEL_TOP13, 24, 2), MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2), + MUX(0, "mout_sclk_phy_fsys0_26m", mout_top1_group1, + MUX_SEL_TOP1_FSYS0, 0, 2), MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 16, 2), MUX(0, "mout_sclk_usbdrd300", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 28, 2), + MUX(0, "mout_sclk_phy_fsys1", mout_top1_group1, + MUX_SEL_TOP1_FSYS1, 0, 2), + MUX(0, "mout_sclk_ufsunipro20", mout_top1_group1, + MUX_SEL_TOP1_FSYS1, 16, 2), + MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS11, 0, 2), MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS11, 12, 2), + MUX(0, "mout_sclk_phy_fsys1_26m", mout_top1_group1, + MUX_SEL_TOP1_FSYS11, 24, 2), }; static struct samsung_div_clock top1_div_clks[] __initdata = { @@ -491,6 +500,13 @@ static struct samsung_div_clock top1_div_clks[] __initdata = { DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200", DIV_TOP13, 28, 4), + DIV(DOUT_SCLK_PHY_FSYS1, "dout_sclk_phy_fsys1", + "mout_sclk_phy_fsys1", DIV_TOP1_FSYS1, 0, 6), + + DIV(DOUT_SCLK_UFSUNIPRO20, "dout_sclk_ufsunipro20", + "mout_sclk_ufsunipro20", + DIV_TOP1_FSYS1, 16, 6), + DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2", DIV_TOP1_FSYS0, 16, 10), DIV(0, "dout_sclk_usbdrd300", "mout_sclk_usbdrd300", @@ -500,6 +516,9 @@ static struct samsung_div_clock top1_div_clks[] __initdata = { DIV_TOP1_FSYS11, 0, 10), DIV(DOUT_SCLK_MMC0, "dout_sclk_mmc0", "mout_sclk_mmc0", DIV_TOP1_FSYS11, 12, 10), + + DIV(DOUT_SCLK_PHY_FSYS1_26M, "dout_sclk_phy_fsys1_26m", + "mout_sclk_phy_fsys1_26m", DIV_TOP1_FSYS11, 24, 6), }; static struct samsung_gate_clock top1_gate_clks[] __initdata = { @@ -508,6 +527,12 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = { GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300", ENABLE_SCLK_TOP1_FSYS0, 28, 0, 0), + GATE(CLK_SCLK_PHY_FSYS1, "sclk_phy_fsys1", "dout_sclk_phy_fsys1", + ENABLE_SCLK_TOP1_FSYS1, 0, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_SCLK_UFSUNIPRO20, "sclk_ufsunipro20", "dout_sclk_ufsunipro20", + ENABLE_SCLK_TOP1_FSYS1, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1", ENABLE_SCLK_TOP1_FSYS11, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0", @@ -517,6 +542,10 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = { ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0), GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200", ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_SCLK_PHY_FSYS1_26M, "sclk_phy_fsys1_26m", + "dout_sclk_phy_fsys1_26m", ENABLE_SCLK_TOP1_FSYS11, + 24, CLK_SET_RATE_PARENT, 0), }; static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { @@ -956,22 +985,54 @@ CLK_OF_DECLARE(exynos7_clk_fsys0, "samsung,exynos7-clock-fsys0", /* Register Offset definitions for CMU_FSYS1 (0x156E0000) */ #define MUX_SEL_FSYS10 0x0200 #define MUX_SEL_FSYS11 0x0204 +#define MUX_SEL_FSYS12 0x0208 +#define DIV_FSYS1 0x0600 #define ENABLE_ACLK_FSYS1 0x0800 +#define ENABLE_PCLK_FSYS1 0x0900 +#define ENABLE_SCLK_FSYS11 0x0A04 +#define ENABLE_SCLK_FSYS12 0x0A08 +#define ENABLE_SCLK_FSYS13 0x0A0C /* * List of parent clocks for Muxes in CMU_FSYS1 */ PNAME(mout_aclk_fsys1_200_user_p) = { "fin_pll", "aclk_fsys1_200" }; +PNAME(mout_fsys1_group_p) = { "fin_pll", "fin_pll_26m", + "sclk_phy_fsys1_26m" }; PNAME(mout_sclk_mmc0_user_p) = { "fin_pll", "sclk_mmc0" }; PNAME(mout_sclk_mmc1_user_p) = { "fin_pll", "sclk_mmc1" }; +PNAME(mout_sclk_ufsunipro20_user_p) = { "fin_pll", "sclk_ufsunipro20" }; +PNAME(mout_phyclk_ufs20_tx0_user_p) = { "fin_pll", "phyclk_ufs20_tx0_symbol" }; +PNAME(mout_phyclk_ufs20_rx0_user_p) = { "fin_pll", "phyclk_ufs20_rx0_symbol" }; +PNAME(mout_phyclk_ufs20_rx1_user_p) = { "fin_pll", "phyclk_ufs20_rx1_symbol" }; + +/* fixed rate clocks used in the FSYS1 block */ +struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = { + FRATE(PHYCLK_UFS20_TX0_SYMBOL, "phyclk_ufs20_tx0_symbol", NULL, + CLK_IS_ROOT, 300000000), + FRATE(PHYCLK_UFS20_RX0_SYMBOL, "phyclk_ufs20_rx0_symbol", NULL, + CLK_IS_ROOT, 300000000), + FRATE(PHYCLK_UFS20_RX1_SYMBOL, "phyclk_ufs20_rx1_symbol", NULL, + CLK_IS_ROOT, 300000000), +}; static unsigned long fsys1_clk_regs[] __initdata = { MUX_SEL_FSYS10, MUX_SEL_FSYS11, + MUX_SEL_FSYS12, + DIV_FSYS1, ENABLE_ACLK_FSYS1, + ENABLE_PCLK_FSYS1, + ENABLE_SCLK_FSYS11, + ENABLE_SCLK_FSYS12, + ENABLE_SCLK_FSYS13, }; static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { + MUX(MOUT_FSYS1_PHYCLK_SEL1, "mout_fsys1_phyclk_sel1", + mout_fsys1_group_p, MUX_SEL_FSYS10, 16, 2), + MUX(0, "mout_fsys1_phyclk_sel0", mout_fsys1_group_p, + MUX_SEL_FSYS10, 20, 2), MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_user_p, MUX_SEL_FSYS10, 28, 1), @@ -979,18 +1040,64 @@ static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { MUX_SEL_FSYS11, 24, 1), MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_user_p, MUX_SEL_FSYS11, 28, 1), + MUX(0, "mout_sclk_ufsunipro20_user", mout_sclk_ufsunipro20_user_p, + MUX_SEL_FSYS11, 20, 1), + + MUX(0, "mout_phyclk_ufs20_rx1_symbol_user", + mout_phyclk_ufs20_rx1_user_p, MUX_SEL_FSYS12, 16, 1), + MUX(0, "mout_phyclk_ufs20_rx0_symbol_user", + mout_phyclk_ufs20_rx0_user_p, MUX_SEL_FSYS12, 24, 1), + MUX(0, "mout_phyclk_ufs20_tx0_symbol_user", + mout_phyclk_ufs20_tx0_user_p, MUX_SEL_FSYS12, 28, 1), +}; + +static struct samsung_div_clock fsys1_div_clks[] __initdata = { + DIV(DOUT_PCLK_FSYS1, "dout_pclk_fsys1", "mout_aclk_fsys1_200_user", + DIV_FSYS1, 0, 2), }; static struct samsung_gate_clock fsys1_gate_clks[] __initdata = { + GATE(SCLK_UFSUNIPRO20_USER, "sclk_ufsunipro20_user", + "mout_sclk_ufsunipro20_user", + ENABLE_SCLK_FSYS11, 20, 0, 0), + GATE(ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys1_200_user", ENABLE_ACLK_FSYS1, 29, 0, 0), GATE(ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys1_200_user", ENABLE_ACLK_FSYS1, 30, 0, 0), + + GATE(ACLK_UFS20_LINK, "aclk_ufs20_link", "dout_pclk_fsys1", + ENABLE_ACLK_FSYS1, 31, 0, 0), + GATE(PCLK_GPIO_FSYS1, "pclk_gpio_fsys1", "mout_aclk_fsys1_200_user", + ENABLE_PCLK_FSYS1, 30, 0, 0), + + GATE(PHYCLK_UFS20_RX1_SYMBOL_USER, "phyclk_ufs20_rx1_symbol_user", + "mout_phyclk_ufs20_rx1_symbol_user", + ENABLE_SCLK_FSYS12, 16, 0, 0), + GATE(PHYCLK_UFS20_RX0_SYMBOL_USER, "phyclk_ufs20_rx0_symbol_user", + "mout_phyclk_ufs20_rx0_symbol_user", + ENABLE_SCLK_FSYS12, 24, 0, 0), + GATE(PHYCLK_UFS20_TX0_SYMBOL_USER, "phyclk_ufs20_tx0_symbol_user", + "mout_phyclk_ufs20_tx0_symbol_user", + ENABLE_SCLK_FSYS12, 28, 0, 0), + + GATE(OSCCLK_PHY_CLKOUT_EMBEDDED_COMBO_PHY, + "oscclk_phy_clkout_embedded_combo_phy", + "fin_pll", + ENABLE_SCLK_FSYS12, 4, CLK_IGNORE_UNUSED, 0), + + GATE(SCLK_COMBO_PHY_EMBEDDED_26M, "sclk_combo_phy_embedded_26m", + "mout_fsys1_phyclk_sel1", + ENABLE_SCLK_FSYS13, 24, CLK_IGNORE_UNUSED, 0), }; static struct samsung_cmu_info fsys1_cmu_info __initdata = { + .fixed_clks = fixed_rate_clks_fsys1, + .nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys1), .mux_clks = fsys1_mux_clks, .nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks), + .div_clks = fsys1_div_clks, + .nr_div_clks = ARRAY_SIZE(fsys1_div_clks), .gate_clks = fsys1_gate_clks, .nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks), .nr_clk_ids = FSYS1_NR_CLK, diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h index acdf2e5e1ac0..10c558611085 100644 --- a/include/dt-bindings/clock/exynos7-clk.h +++ b/include/dt-bindings/clock/exynos7-clk.h @@ -64,7 +64,14 @@ #define CLK_SCLK_MMC0 8 #define CLK_ACLK_FSYS0_200 9 #define CLK_ACLK_FSYS1_200 10 -#define TOP1_NR_CLK 11 +#define CLK_SCLK_PHY_FSYS1 11 +#define CLK_SCLK_PHY_FSYS1_26M 12 +#define MOUT_SCLK_UFSUNIPRO20 13 +#define DOUT_SCLK_UFSUNIPRO20 14 +#define CLK_SCLK_UFSUNIPRO20 15 +#define DOUT_SCLK_PHY_FSYS1 16 +#define DOUT_SCLK_PHY_FSYS1_26M 17 +#define TOP1_NR_CLK 18 /* CCORE */ #define PCLK_RTC 1 @@ -139,7 +146,20 @@ /* FSYS1 */ #define ACLK_MMC1 1 #define ACLK_MMC0 2 -#define FSYS1_NR_CLK 3 +#define PHYCLK_UFS20_TX0_SYMBOL 3 +#define PHYCLK_UFS20_RX0_SYMBOL 4 +#define PHYCLK_UFS20_RX1_SYMBOL 5 +#define ACLK_UFS20_LINK 6 +#define SCLK_UFSUNIPRO20_USER 7 +#define PHYCLK_UFS20_RX1_SYMBOL_USER 8 +#define PHYCLK_UFS20_RX0_SYMBOL_USER 9 +#define PHYCLK_UFS20_TX0_SYMBOL_USER 10 +#define OSCCLK_PHY_CLKOUT_EMBEDDED_COMBO_PHY 11 +#define SCLK_COMBO_PHY_EMBEDDED_26M 12 +#define DOUT_PCLK_FSYS1 13 +#define PCLK_GPIO_FSYS1 14 +#define MOUT_FSYS1_PHYCLK_SEL1 15 +#define FSYS1_NR_CLK 16 /* MSCL */ #define USERMUX_ACLK_MSCL_532 1 -- cgit v1.3-6-gb490 From b7503e0cdb5dbec5d201aa69d8888c14679b5ae8 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 2 Sep 2015 13:58:35 -0700 Subject: net: Add FIB table id to rtable Add the FIB table id to rtable to make the information available for IPv4 as it is for IPv6. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 2 ++ include/net/route.h | 2 ++ net/ipv4/route.c | 8 ++++++++ net/ipv4/xfrm4_policy.c | 1 + 4 files changed, 13 insertions(+) (limited to 'include') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index e7094fbd7568..8c9ab5ebea23 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -320,6 +320,7 @@ static void vrf_rtable_destroy(struct net_vrf *vrf) static struct rtable *vrf_rtable_create(struct net_device *dev) { + struct net_vrf *vrf = netdev_priv(dev); struct rtable *rth; rth = dst_alloc(&vrf_dst_ops, dev, 2, @@ -335,6 +336,7 @@ static struct rtable *vrf_rtable_create(struct net_device *dev) rth->rt_pmtu = 0; rth->rt_gateway = 0; rth->rt_uses_gateway = 0; + rth->rt_table_id = vrf->tb_id; INIT_LIST_HEAD(&rth->rt_uncached); rth->rt_uncached_list = NULL; } diff --git a/include/net/route.h b/include/net/route.h index cc61cb95f059..10a7d21a211c 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -64,6 +64,8 @@ struct rtable { /* Miscellaneous cached information */ u32 rt_pmtu; + u32 rt_table_id; + struct list_head rt_uncached; struct uncached_list *rt_uncached_list; }; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index eaefeadce07c..92acc95b7578 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1457,6 +1457,7 @@ static struct rtable *rt_dst_alloc(struct net_device *dev, rt->rt_pmtu = 0; rt->rt_gateway = 0; rt->rt_uses_gateway = 0; + rt->rt_table_id = 0; INIT_LIST_HEAD(&rt->rt_uncached); rt->dst.output = ip_output; @@ -1629,6 +1630,8 @@ static int __mkroute_input(struct sk_buff *skb, } rth->rt_is_input = 1; + if (res->table) + rth->rt_table_id = res->table->tb_id; RT_CACHE_STAT_INC(in_slow_tot); rth->dst.input = ip_forward; @@ -1808,6 +1811,8 @@ local_input: rth->dst.tclassid = itag; #endif rth->rt_is_input = 1; + if (res.table) + rth->rt_table_id = res.table->tb_id; RT_CACHE_STAT_INC(in_slow_tot); if (res.type == RTN_UNREACHABLE) { @@ -1988,6 +1993,9 @@ add: return ERR_PTR(-ENOBUFS); rth->rt_iif = orig_oif ? : 0; + if (res->table) + rth->rt_table_id = res->table->tb_id; + RT_CACHE_STAT_INC(out_slow_tot); if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) { diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index bb919b28619f..671011055ad5 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -95,6 +95,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, xdst->u.rt.rt_gateway = rt->rt_gateway; xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; xdst->u.rt.rt_pmtu = rt->rt_pmtu; + xdst->u.rt.rt_table_id = rt->rt_table_id; INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); return 0; -- cgit v1.3-6-gb490 From c36ba6603a1154ac617d023bbcc062a12afb258b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 2 Sep 2015 13:58:36 -0700 Subject: net: Allow user to get table id from route lookup rt_fill_info which is called for 'route get' requests hardcodes the table id as RT_TABLE_MAIN which is not correct when multiple tables are used. Use the newly added table id in the rtable to send back the correct table similar to what is done for IPv6. To maintain current ABI a new request flag, RTM_F_LOOKUP_TABLE, is added to indicate the actual table is wanted versus the hardcoded response. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- include/uapi/linux/rtnetlink.h | 1 + net/ipv4/route.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 702024769c74..06625b401422 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -270,6 +270,7 @@ enum rt_scope_t { #define RTM_F_CLONED 0x200 /* This route is cloned */ #define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ #define RTM_F_PREFIX 0x800 /* Prefix addresses */ +#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */ /* Reserved table identifiers */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 92acc95b7578..da427a4a33fe 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2305,7 +2305,7 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, } EXPORT_SYMBOL_GPL(ip_route_output_flow); -static int rt_fill_info(struct net *net, __be32 dst, __be32 src, +static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, struct flowi4 *fl4, struct sk_buff *skb, u32 portid, u32 seq, int event, int nowait, unsigned int flags) { @@ -2325,8 +2325,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, r->rtm_dst_len = 32; r->rtm_src_len = 0; r->rtm_tos = fl4->flowi4_tos; - r->rtm_table = RT_TABLE_MAIN; - if (nla_put_u32(skb, RTA_TABLE, RT_TABLE_MAIN)) + r->rtm_table = table_id; + if (nla_put_u32(skb, RTA_TABLE, table_id)) goto nla_put_failure; r->rtm_type = rt->rt_type; r->rtm_scope = RT_SCOPE_UNIVERSE; @@ -2431,6 +2431,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) int err; int mark; struct sk_buff *skb; + u32 table_id = RT_TABLE_MAIN; err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy); if (err < 0) @@ -2500,7 +2501,10 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; - err = rt_fill_info(net, dst, src, &fl4, skb, + if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE) + table_id = rt->rt_table_id; + + err = rt_fill_info(net, dst, src, table_id, &fl4, skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0); if (err < 0) -- cgit v1.3-6-gb490 From c40a2c8817e42273a4627c48c884b805475a733f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 7 Sep 2015 16:05:38 +0200 Subject: CDC: common parser for extra headers CDC drivers all implement their own parser for the extra headers. This patch fixes the code duplication introducing a single common parser in usbnet. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/usb/cdc.h | 47 ++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 include/linux/usb/cdc.h (limited to 'include') diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index b4cf10781348..060918f49fea 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1962,6 +1963,143 @@ out: return err; } +int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, + struct usb_interface *intf, + u8 *buffer, + int buflen) +{ + /* duplicates are ignored */ + struct usb_cdc_union_desc *union_header = NULL; + + /* duplicates are not tolerated */ + struct usb_cdc_header_desc *header = NULL; + struct usb_cdc_ether_desc *ether = NULL; + struct usb_cdc_mdlm_detail_desc *detail = NULL; + struct usb_cdc_mdlm_desc *desc = NULL; + + unsigned int elength; + int cnt = 0; + + memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header)); + hdr->phonet_magic_present = false; + while (buflen > 0) { + elength = buffer[0]; + if (!elength) { + dev_err(&intf->dev, "skipping garbage byte\n"); + elength = 1; + goto next_desc; + } + if (buffer[1] != USB_DT_CS_INTERFACE) { + dev_err(&intf->dev, "skipping garbage\n"); + goto next_desc; + } + + switch (buffer[2]) { + case USB_CDC_UNION_TYPE: /* we've found it */ + if (elength < sizeof(struct usb_cdc_union_desc)) + goto next_desc; + if (union_header) { + dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); + goto next_desc; + } + union_header = (struct usb_cdc_union_desc *)buffer; + break; + case USB_CDC_COUNTRY_TYPE: + if (elength < sizeof(struct usb_cdc_country_functional_desc)) + goto next_desc; + hdr->usb_cdc_country_functional_desc = + (struct usb_cdc_country_functional_desc *)buffer; + break; + case USB_CDC_HEADER_TYPE: + if (elength != sizeof(struct usb_cdc_header_desc)) + goto next_desc; + if (header) + return -EINVAL; + header = (struct usb_cdc_header_desc *)buffer; + break; + case USB_CDC_ACM_TYPE: + if (elength < sizeof(struct usb_cdc_acm_descriptor)) + goto next_desc; + hdr->usb_cdc_acm_descriptor = + (struct usb_cdc_acm_descriptor *)buffer; + break; + case USB_CDC_ETHERNET_TYPE: + if (elength != sizeof(struct usb_cdc_ether_desc)) + goto next_desc; + if (ether) + return -EINVAL; + ether = (struct usb_cdc_ether_desc *)buffer; + break; + case USB_CDC_CALL_MANAGEMENT_TYPE: + if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor)) + goto next_desc; + hdr->usb_cdc_call_mgmt_descriptor = + (struct usb_cdc_call_mgmt_descriptor *)buffer; + break; + case USB_CDC_DMM_TYPE: + if (elength < sizeof(struct usb_cdc_dmm_desc)) + goto next_desc; + hdr->usb_cdc_dmm_desc = + (struct usb_cdc_dmm_desc *)buffer; + break; + case USB_CDC_MDLM_TYPE: + if (elength < sizeof(struct usb_cdc_mdlm_desc *)) + goto next_desc; + if (desc) + return -EINVAL; + desc = (struct usb_cdc_mdlm_desc *)buffer; + break; + case USB_CDC_MDLM_DETAIL_TYPE: + if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *)) + goto next_desc; + if (detail) + return -EINVAL; + detail = (struct usb_cdc_mdlm_detail_desc *)buffer; + break; + case USB_CDC_NCM_TYPE: + if (elength < sizeof(struct usb_cdc_ncm_desc)) + goto next_desc; + hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer; + break; + case USB_CDC_MBIM_TYPE: + if (elength < sizeof(struct usb_cdc_mbim_desc)) + goto next_desc; + + hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer; + break; + case USB_CDC_MBIM_EXTENDED_TYPE: + if (elength < sizeof(struct usb_cdc_mbim_extended_desc)) + break; + hdr->usb_cdc_mbim_extended_desc = + (struct usb_cdc_mbim_extended_desc *)buffer; + break; + case CDC_PHONET_MAGIC_NUMBER: + hdr->phonet_magic_present = true; + break; + default: + /* + * there are LOTS more CDC descriptors that + * could legitimately be found here. + */ + dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n", + buffer[2], elength); + goto next_desc; + } + cnt++; +next_desc: + buflen -= elength; + buffer += elength; + } + hdr->usb_cdc_union_desc = union_header; + hdr->usb_cdc_header_desc = header; + hdr->usb_cdc_mdlm_detail_desc = detail; + hdr->usb_cdc_mdlm_desc = desc; + hdr->usb_cdc_ether_desc = ether; + return cnt; +} + +EXPORT_SYMBOL(cdc_parse_cdc_header); + /* * The function can't be called inside suspend/resume callback, * otherwise deadlock will be caused. diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h new file mode 100644 index 000000000000..cd8f2e1c3bdf --- /dev/null +++ b/include/linux/usb/cdc.h @@ -0,0 +1,47 @@ +/* + * USB CDC common helpers + * + * Copyright (c) 2015 Oliver Neukum + * + * 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. + */ + +#include + +/* + * inofficial magic numbers + */ + +#define CDC_PHONET_MAGIC_NUMBER 0xAB + +/* + * parsing CDC headers + */ + +struct usb_cdc_parsed_header { + struct usb_cdc_union_desc *usb_cdc_union_desc; + struct usb_cdc_header_desc *usb_cdc_header_desc; + + struct usb_cdc_call_mgmt_descriptor *usb_cdc_call_mgmt_descriptor; + struct usb_cdc_acm_descriptor *usb_cdc_acm_descriptor; + struct usb_cdc_country_functional_desc *usb_cdc_country_functional_desc; + struct usb_cdc_network_terminal_desc *usb_cdc_network_terminal_desc; + struct usb_cdc_ether_desc *usb_cdc_ether_desc; + struct usb_cdc_dmm_desc *usb_cdc_dmm_desc; + struct usb_cdc_mdlm_desc *usb_cdc_mdlm_desc; + struct usb_cdc_mdlm_detail_desc *usb_cdc_mdlm_detail_desc; + struct usb_cdc_obex_desc *usb_cdc_obex_desc; + struct usb_cdc_ncm_desc *usb_cdc_ncm_desc; + struct usb_cdc_mbim_desc *usb_cdc_mbim_desc; + struct usb_cdc_mbim_extended_desc *usb_cdc_mbim_extended_desc; + + bool phonet_magic_present; +}; + + +int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, + struct usb_interface *intf, + u8 *buffer, + int buflen); -- cgit v1.3-6-gb490 From ad1e7b97b3adb91d46f3adb70a7867a50fc274cf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 15 Sep 2015 13:25:03 -0700 Subject: cdc: Fix build warning. In file included from drivers/usb/gadget/function/u_serial.h:16:0, from drivers/usb/gadget/function/f_acm.c:23: >> include/linux/usb/cdc.h:47:5: warning: 'struct usb_interface' declared inside parameter list int buflen); ^ >> include/linux/usb/cdc.h:47:5: warning: its scope is only this definition or declaration, which is probably not what you want Reported-by: kbuild test robot Signed-off-by: David S. Miller --- include/linux/usb/cdc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index cd8f2e1c3bdf..959d0c838113 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -40,7 +40,7 @@ struct usb_cdc_parsed_header { bool phonet_magic_present; }; - +struct usb_interface; int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, struct usb_interface *intf, u8 *buffer, -- cgit v1.3-6-gb490 From d5566fd72ec1924958fcfd48b65c022c8f7eae64 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Fri, 11 Sep 2015 16:48:48 -0400 Subject: rtnetlink: RTEXT_FILTER_SKIP_STATS support to avoid dumping inet/inet6 stats Many commonly used functions like getifaddrs() invoke RTM_GETLINK to dump the interface information, and do not need the the AF_INET6 statististics that are always returned by default from rtnl_fill_ifinfo(). Computing the statistics can be an expensive operation that impacts scaling, so it is desirable to avoid this if the information is not needed. This patch adds a the RTEXT_FILTER_SKIP_STATS extended info flag that can be passed with netlink_request() to avoid statistics computation for the ifinfo path. Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- include/net/rtnetlink.h | 3 ++- include/uapi/linux/rtnetlink.h | 1 + net/core/rtnetlink.c | 2 +- net/ipv4/devinet.c | 3 ++- net/ipv6/addrconf.c | 13 +++++++++---- 5 files changed, 15 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 18fdb98185ab..aff6ceb891a9 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -122,7 +122,8 @@ struct rtnl_af_ops { int family; int (*fill_link_af)(struct sk_buff *skb, - const struct net_device *dev); + const struct net_device *dev, + u32 ext_filter_mask); size_t (*get_link_af_size)(const struct net_device *dev); int (*validate_link_af)(const struct net_device *dev, diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 06625b401422..4db0b3ccb497 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -667,6 +667,7 @@ struct tcamsg { #define RTEXT_FILTER_VF (1 << 0) #define RTEXT_FILTER_BRVLAN (1 << 1) #define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) +#define RTEXT_FILTER_SKIP_STATS (1 << 3) /* End of information exported to user level */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a466821d1441..e5452296ec2f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1272,7 +1272,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, if (!(af = nla_nest_start(skb, af_ops->family))) goto nla_put_failure; - err = af_ops->fill_link_af(skb, dev); + err = af_ops->fill_link_af(skb, dev, ext_filter_mask); /* * Caller may return ENODATA to indicate that there diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 2d9cb1748f81..735008472844 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1654,7 +1654,8 @@ static size_t inet_get_link_af_size(const struct net_device *dev) return nla_total_size(IPV4_DEVCONF_MAX * 4); /* IFLA_INET_CONF */ } -static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev) +static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev, + u32 ext_filter_mask) { struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); struct nlattr *nla; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 030fefdc9aed..75d3dde32c69 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4729,7 +4729,8 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, } } -static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) +static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev, + u32 ext_filter_mask) { struct nlattr *nla; struct ifla_cacheinfo ci; @@ -4749,6 +4750,9 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) /* XXX - MC not implemented */ + if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS) + return 0; + nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); if (!nla) goto nla_put_failure; @@ -4784,14 +4788,15 @@ static size_t inet6_get_link_af_size(const struct net_device *dev) return inet6_ifla6_size(); } -static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev) +static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev, + u32 ext_filter_mask) { struct inet6_dev *idev = __in6_dev_get(dev); if (!idev) return -ENODATA; - if (inet6_fill_ifla6_attrs(skb, idev) < 0) + if (inet6_fill_ifla6_attrs(skb, idev, ext_filter_mask) < 0) return -EMSGSIZE; return 0; @@ -4946,7 +4951,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, if (!protoinfo) goto nla_put_failure; - if (inet6_fill_ifla6_attrs(skb, idev) < 0) + if (inet6_fill_ifla6_attrs(skb, idev, 0) < 0) goto nla_put_failure; nla_nest_end(skb, protoinfo); -- cgit v1.3-6-gb490 From b84ee0d7f375ed7840c7c110d46eac24cf94b2a2 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 16 Sep 2015 11:10:16 +1000 Subject: cdc: add header guards Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- include/linux/usb/cdc.h | 4 ++++ include/uapi/linux/usb/cdc.h | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index 959d0c838113..b5706f94ee9e 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -7,6 +7,8 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ +#ifndef __LINUX_USB_CDC_H +#define __LINUX_USB_CDC_H #include @@ -45,3 +47,5 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, struct usb_interface *intf, u8 *buffer, int buflen); + +#endif /* __LINUX_USB_CDC_H */ diff --git a/include/uapi/linux/usb/cdc.h b/include/uapi/linux/usb/cdc.h index b6a9cdd6e096..e2bc417b243b 100644 --- a/include/uapi/linux/usb/cdc.h +++ b/include/uapi/linux/usb/cdc.h @@ -6,8 +6,8 @@ * firmware based USB peripherals. */ -#ifndef __LINUX_USB_CDC_H -#define __LINUX_USB_CDC_H +#ifndef __UAPI_LINUX_USB_CDC_H +#define __UAPI_LINUX_USB_CDC_H #include @@ -444,4 +444,4 @@ struct usb_cdc_ncm_ndp_input_size { #define USB_CDC_NCM_CRC_NOT_APPENDED 0x00 #define USB_CDC_NCM_CRC_APPENDED 0x01 -#endif /* __LINUX_USB_CDC_H */ +#endif /* __UAPI_LINUX_USB_CDC_H */ -- cgit v1.3-6-gb490 From a6f5f0dd4e21191ce35030dd4d6421e1cca10ee4 Mon Sep 17 00:00:00 2001 From: Alexandra Yates Date: Tue, 15 Sep 2015 10:32:46 -0700 Subject: PM / sleep: Report interrupt that caused system wakeup Add a sysfs attribute, /sys/power/pm_wakeup_irq, reporting the IRQ number of the first wakeup interrupt (that is, the first interrupt from an IRQ line armed for system wakeup) seen by the kernel during the most recent system suspend/resume cycle. This feature will be useful for system wakeup diagnostics of spurious wakeup interrupts. Signed-off-by: Alexandra Yates [ rjw: Fixed up pm_wakeup_irq definition ] Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-power | 12 ++++++++++++ drivers/base/power/wakeup.c | 12 ++++++++++++ include/linux/suspend.h | 3 +++ kernel/irq/pm.c | 2 +- kernel/power/main.c | 17 +++++++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power index f4551816329e..50b368d490b5 100644 --- a/Documentation/ABI/testing/sysfs-power +++ b/Documentation/ABI/testing/sysfs-power @@ -256,3 +256,15 @@ Description: Writing a "1" enables this printing while writing a "0" disables it. The default value is "0". Reading from this file will display the current value. + +What: /sys/power/pm_wakeup_irq +Date: April 2015 +Contact: Alexandra Yates +Description: + The /sys/power/pm_wakeup_irq file reports to user space the IRQ + number of the first wakeup interrupt (that is, the first + interrupt from an IRQ line armed for system wakeup) seen by the + kernel during the most recent system suspend/resume cycle. + + This output is useful for system wakeup diagnostics of spurious + wakeup interrupts. diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 51f15bc15774..3b361ecfaffc 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -25,6 +25,9 @@ */ bool events_check_enabled __read_mostly; +/* First wakeup IRQ seen by the kernel in the last cycle. */ +unsigned int pm_wakeup_irq __read_mostly; + /* If set and the system is suspending, terminate the suspend. */ static bool pm_abort_suspend __read_mostly; @@ -868,6 +871,15 @@ EXPORT_SYMBOL_GPL(pm_system_wakeup); void pm_wakeup_clear(void) { pm_abort_suspend = false; + pm_wakeup_irq = 0; +} + +void pm_system_irq_wakeup(unsigned int irq_number) +{ + if (pm_wakeup_irq == 0) { + pm_wakeup_irq = irq_number; + pm_system_wakeup(); + } } /** diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5efe743ce1e8..33aaf9a9596c 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -387,10 +387,12 @@ extern int unregister_pm_notifier(struct notifier_block *nb); /* drivers/base/power/wakeup.c */ extern bool events_check_enabled; +extern unsigned int pm_wakeup_irq; extern bool pm_wakeup_pending(void); extern void pm_system_wakeup(void); extern void pm_wakeup_clear(void); +extern void pm_system_irq_wakeup(unsigned int irq_number); extern bool pm_get_wakeup_count(unsigned int *count, bool block); extern bool pm_save_wakeup_count(unsigned int count); extern void pm_wakep_autosleep_enabled(bool set); @@ -440,6 +442,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) static inline bool pm_wakeup_pending(void) { return false; } static inline void pm_system_wakeup(void) {} static inline void pm_wakeup_clear(void) {} +static inline void pm_system_irq_wakeup(unsigned int irq_number) {} static inline void lock_system_sleep(void) {} static inline void unlock_system_sleep(void) {} diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 21c62617a35a..e80c4400118a 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -21,7 +21,7 @@ bool irq_pm_check_wakeup(struct irq_desc *desc) desc->istate |= IRQS_SUSPENDED | IRQS_PENDING; desc->depth++; irq_disable(desc); - pm_system_wakeup(); + pm_system_irq_wakeup(irq_desc_get_irq(desc)); return true; } return false; diff --git a/kernel/power/main.c b/kernel/power/main.c index 63d395b5df93..b2dd4d999900 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -272,6 +272,22 @@ static inline void pm_print_times_init(void) { pm_print_times_enabled = !!initcall_debug; } + +static ssize_t pm_wakeup_irq_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA; +} + +static ssize_t pm_wakeup_irq_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + return -EINVAL; +} +power_attr(pm_wakeup_irq); + #else /* !CONFIG_PM_SLEEP_DEBUG */ static inline void pm_print_times_init(void) {} #endif /* CONFIG_PM_SLEEP_DEBUG */ @@ -604,6 +620,7 @@ static struct attribute * g[] = { #endif #ifdef CONFIG_PM_SLEEP_DEBUG &pm_print_times_attr.attr, + &pm_wakeup_irq_attr.attr, #endif #endif #ifdef CONFIG_FREEZER -- cgit v1.3-6-gb490 From 1ed1328792ff46e4bb86a3d7f7be2971f4549f6c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 16 Sep 2015 12:53:17 -0400 Subject: sched, cgroup: replace signal_struct->group_rwsem with a global percpu_rwsem Note: This commit was originally committed as d59cfc09c32a but got reverted by 0c986253b939 due to the performance regression from the percpu_rwsem write down/up operations added to cgroup task migration path. percpu_rwsem changes which alleviate the performance issue are pending for v4.4-rc1 merge window. Re-apply. The cgroup side of threadgroup locking uses signal_struct->group_rwsem to synchronize against threadgroup changes. This per-process rwsem adds small overhead to thread creation, exit and exec paths, forces cgroup code paths to do lock-verify-unlock-retry dance in a couple places and makes it impossible to atomically perform operations across multiple processes. This patch replaces signal_struct->group_rwsem with a global percpu_rwsem cgroup_threadgroup_rwsem which is cheaper on the reader side and contained in cgroups proper. This patch converts one-to-one. This does make writer side heavier and lower the granularity; however, cgroup process migration is a fairly cold path, we do want to optimize thread operations over it and cgroup migration operations don't take enough time for the lower granularity to matter. Signed-off-by: Tejun Heo Link: http://lkml.kernel.org/g/55F8097A.7000206@de.ibm.com Cc: Ingo Molnar Cc: Peter Zijlstra --- include/linux/cgroup-defs.h | 27 ++++++++++++++-- include/linux/init_task.h | 8 ----- include/linux/sched.h | 12 ------- kernel/cgroup.c | 77 ++++++++++++--------------------------------- kernel/fork.c | 4 --- 5 files changed, 45 insertions(+), 83 deletions(-) (limited to 'include') diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 8492721b39be..4d8fcf2187dc 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -473,8 +473,31 @@ struct cgroup_subsys { unsigned int depends_on; }; -void cgroup_threadgroup_change_begin(struct task_struct *tsk); -void cgroup_threadgroup_change_end(struct task_struct *tsk); +extern struct percpu_rw_semaphore cgroup_threadgroup_rwsem; + +/** + * cgroup_threadgroup_change_begin - threadgroup exclusion for cgroups + * @tsk: target task + * + * Called from threadgroup_change_begin() and allows cgroup operations to + * synchronize against threadgroup changes using a percpu_rw_semaphore. + */ +static inline void cgroup_threadgroup_change_begin(struct task_struct *tsk) +{ + percpu_down_read(&cgroup_threadgroup_rwsem); +} + +/** + * cgroup_threadgroup_change_end - threadgroup exclusion for cgroups + * @tsk: target task + * + * Called from threadgroup_change_end(). Counterpart of + * cgroup_threadcgroup_change_begin(). + */ +static inline void cgroup_threadgroup_change_end(struct task_struct *tsk) +{ + percpu_up_read(&cgroup_threadgroup_rwsem); +} #else /* CONFIG_CGROUPS */ diff --git a/include/linux/init_task.h b/include/linux/init_task.h index e38681f4912d..d0b380ee7d67 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -25,13 +25,6 @@ extern struct files_struct init_files; extern struct fs_struct init_fs; -#ifdef CONFIG_CGROUPS -#define INIT_GROUP_RWSEM(sig) \ - .group_rwsem = __RWSEM_INITIALIZER(sig.group_rwsem), -#else -#define INIT_GROUP_RWSEM(sig) -#endif - #ifdef CONFIG_CPUSETS #define INIT_CPUSET_SEQ(tsk) \ .mems_allowed_seq = SEQCNT_ZERO(tsk.mems_allowed_seq), @@ -64,7 +57,6 @@ extern struct fs_struct init_fs; INIT_PREV_CPUTIME(sig) \ .cred_guard_mutex = \ __MUTEX_INITIALIZER(sig.cred_guard_mutex), \ - INIT_GROUP_RWSEM(sig) \ } extern struct nsproxy init_nsproxy; diff --git a/include/linux/sched.h b/include/linux/sched.h index b7b9501b41af..a4ab9daa387c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -762,18 +762,6 @@ struct signal_struct { unsigned audit_tty_log_passwd; struct tty_audit_buf *tty_audit_buf; #endif -#ifdef CONFIG_CGROUPS - /* - * group_rwsem prevents new tasks from entering the threadgroup and - * member tasks from exiting,a more specifically, setting of - * PF_EXITING. fork and exit paths are protected with this rwsem - * using threadgroup_change_begin/end(). Users which require - * threadgroup to remain stable should use threadgroup_[un]lock() - * which also takes care of exec path. Currently, cgroup is the - * only user. - */ - struct rw_semaphore group_rwsem; -#endif oom_flags_t oom_flags; short oom_score_adj; /* OOM kill score adjustment */ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2c9eae6ad970..115091efa889 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,8 @@ static DEFINE_SPINLOCK(cgroup_idr_lock); */ static DEFINE_SPINLOCK(release_agent_path_lock); +struct percpu_rw_semaphore cgroup_threadgroup_rwsem; + #define cgroup_assert_mutex_or_rcu_locked() \ RCU_LOCKDEP_WARN(!rcu_read_lock_held() && \ !lockdep_is_held(&cgroup_mutex), \ @@ -871,48 +874,6 @@ static struct css_set *find_css_set(struct css_set *old_cset, return cset; } -void cgroup_threadgroup_change_begin(struct task_struct *tsk) -{ - down_read(&tsk->signal->group_rwsem); -} - -void cgroup_threadgroup_change_end(struct task_struct *tsk) -{ - up_read(&tsk->signal->group_rwsem); -} - -/** - * threadgroup_lock - lock threadgroup - * @tsk: member task of the threadgroup to lock - * - * Lock the threadgroup @tsk belongs to. No new task is allowed to enter - * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or - * change ->group_leader/pid. This is useful for cases where the threadgroup - * needs to stay stable across blockable operations. - * - * fork and exit explicitly call threadgroup_change_{begin|end}() for - * synchronization. While held, no new task will be added to threadgroup - * and no existing live task will have its PF_EXITING set. - * - * de_thread() does threadgroup_change_{begin|end}() when a non-leader - * sub-thread becomes a new leader. - */ -static void threadgroup_lock(struct task_struct *tsk) -{ - down_write(&tsk->signal->group_rwsem); -} - -/** - * threadgroup_unlock - unlock threadgroup - * @tsk: member task of the threadgroup to unlock - * - * Reverse threadgroup_lock(). - */ -static inline void threadgroup_unlock(struct task_struct *tsk) -{ - up_write(&tsk->signal->group_rwsem); -} - static struct cgroup_root *cgroup_root_from_kf(struct kernfs_root *kf_root) { struct cgroup *root_cgrp = kf_root->kn->priv; @@ -2113,9 +2074,9 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp, lockdep_assert_held(&css_set_rwsem); /* - * We are synchronized through threadgroup_lock() against PF_EXITING - * setting such that we can't race against cgroup_exit() changing the - * css_set to init_css_set and dropping the old one. + * We are synchronized through cgroup_threadgroup_rwsem against + * PF_EXITING setting such that we can't race against cgroup_exit() + * changing the css_set to init_css_set and dropping the old one. */ WARN_ON_ONCE(tsk->flags & PF_EXITING); old_cset = task_css_set(tsk); @@ -2172,10 +2133,11 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets) * @src_cset and add it to @preloaded_csets, which should later be cleaned * up by cgroup_migrate_finish(). * - * This function may be called without holding threadgroup_lock even if the - * target is a process. Threads may be created and destroyed but as long - * as cgroup_mutex is not dropped, no new css_set can be put into play and - * the preloaded css_sets are guaranteed to cover all migrations. + * This function may be called without holding cgroup_threadgroup_rwsem + * even if the target is a process. Threads may be created and destroyed + * but as long as cgroup_mutex is not dropped, no new css_set can be put + * into play and the preloaded css_sets are guaranteed to cover all + * migrations. */ static void cgroup_migrate_add_src(struct css_set *src_cset, struct cgroup *dst_cgrp, @@ -2278,7 +2240,7 @@ err: * @threadgroup: whether @leader points to the whole process or a single task * * Migrate a process or task denoted by @leader to @cgrp. If migrating a - * process, the caller must be holding threadgroup_lock of @leader. The + * process, the caller must be holding cgroup_threadgroup_rwsem. The * caller is also responsible for invoking cgroup_migrate_add_src() and * cgroup_migrate_prepare_dst() on the targets before invoking this * function and following up with cgroup_migrate_finish(). @@ -2406,7 +2368,7 @@ out_release_tset: * @leader: the task or the leader of the threadgroup to be attached * @threadgroup: attach the whole threadgroup? * - * Call holding cgroup_mutex and threadgroup_lock of @leader. + * Call holding cgroup_mutex and cgroup_threadgroup_rwsem. */ static int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader, bool threadgroup) @@ -2528,7 +2490,7 @@ retry_find_task: get_task_struct(tsk); rcu_read_unlock(); - threadgroup_lock(tsk); + percpu_down_write(&cgroup_threadgroup_rwsem); if (threadgroup) { if (!thread_group_leader(tsk)) { /* @@ -2538,7 +2500,7 @@ retry_find_task: * try again; this is * "double-double-toil-and-trouble-check locking". */ - threadgroup_unlock(tsk); + percpu_up_write(&cgroup_threadgroup_rwsem); put_task_struct(tsk); goto retry_find_task; } @@ -2548,7 +2510,7 @@ retry_find_task: if (!ret) ret = cgroup_attach_task(cgrp, tsk, threadgroup); - threadgroup_unlock(tsk); + percpu_up_write(&cgroup_threadgroup_rwsem); put_task_struct(tsk); out_unlock_cgroup: @@ -2751,17 +2713,17 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp) goto out_finish; last_task = task; - threadgroup_lock(task); + percpu_down_write(&cgroup_threadgroup_rwsem); /* raced against de_thread() from another thread? */ if (!thread_group_leader(task)) { - threadgroup_unlock(task); + percpu_up_write(&cgroup_threadgroup_rwsem); put_task_struct(task); continue; } ret = cgroup_migrate(src_cset->dfl_cgrp, task, true); - threadgroup_unlock(task); + percpu_up_write(&cgroup_threadgroup_rwsem); put_task_struct(task); if (WARN(ret, "cgroup: failed to update controllers for the default hierarchy (%d), further operations may crash or hang\n", ret)) @@ -5083,6 +5045,7 @@ int __init cgroup_init(void) unsigned long key; int ssid, err; + BUG_ON(percpu_init_rwsem(&cgroup_threadgroup_rwsem)); BUG_ON(cgroup_init_cftypes(NULL, cgroup_dfl_base_files)); BUG_ON(cgroup_init_cftypes(NULL, cgroup_legacy_base_files)); diff --git a/kernel/fork.c b/kernel/fork.c index 2845623fb582..7d5f0f118a63 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1149,10 +1149,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) tty_audit_fork(sig); sched_autogroup_fork(sig); -#ifdef CONFIG_CGROUPS - init_rwsem(&sig->group_rwsem); -#endif - sig->oom_score_adj = current->signal->oom_score_adj; sig->oom_score_adj_min = current->signal->oom_score_adj_min; -- cgit v1.3-6-gb490 From 6131084a0bc966107021d8c89489f9cd1663b902 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 9 Sep 2015 21:27:43 +0300 Subject: ASoC: simple-card: Add tdm slot mask support to simple-card Adds DT binding for explicitly choosing a tdm mask for DAI and uses it in simple-card. The API for snd_soc_of_parse_tdm_slot() has also been changed. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tdm-slot.txt | 11 +++++++++- include/sound/simple_card.h | 2 ++ include/sound/soc.h | 2 ++ sound/soc/generic/simple-card.c | 8 +++++-- sound/soc/soc-core.c | 25 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.txt b/Documentation/devicetree/bindings/sound/tdm-slot.txt index 6a2c84247f91..34cf70e2cbc4 100644 --- a/Documentation/devicetree/bindings/sound/tdm-slot.txt +++ b/Documentation/devicetree/bindings/sound/tdm-slot.txt @@ -4,11 +4,15 @@ This specifies audio DAI's TDM slot. TDM slot properties: dai-tdm-slot-num : Number of slots in use. -dai-tdm-slot-width : Width in bits for each slot. +dai-tdm-slot-width : Width in bits for each slot. +dai-tdm-slot-tx-mask : Transmit direction slot mask, optional +dai-tdm-slot-rx-mask : Receive direction slot mask, optional For instance: dai-tdm-slot-num = <2>; dai-tdm-slot-width = <8>; + dai-tdm-slot-tx-mask = <0 1>; + dai-tdm-slot-rx-mask = <1 0>; And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() to specify a explicit mapping of the channels and the slots. If it's absent @@ -18,3 +22,8 @@ tx and rx masks. For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit for an active slot as default, and the default active bits are at the LSB of the masks. + +The explicit masks are given as array of integers, where the first +number presents bit-0 (LSB), second presents bit-1, etc. Any non zero +number is considered 1 and 0 is 0. snd_soc_of_xlate_tdm_slot_mask() +does not do anything, if either mask is set non zero value. diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index b9b4f289fe6b..0399352f3a62 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -19,6 +19,8 @@ struct asoc_simple_dai { unsigned int sysclk; int slots; int slot_width; + unsigned int tx_slot_mask; + unsigned int rx_slot_mask; struct clk *clk; }; diff --git a/include/sound/soc.h b/include/sound/soc.h index 884e728b09d9..a76622d7bb2f 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1601,6 +1601,8 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *tx_mask, + unsigned int *rx_mask, unsigned int *slots, unsigned int *slot_width); void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 3ff76d419436..54c33204541f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -151,7 +151,9 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, } if (set->slots) { - ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, + ret = snd_soc_dai_set_tdm_slot(dai, + set->tx_slot_mask, + set->rx_slot_mask, set->slots, set->slot_width); if (ret && ret != -ENOTSUPP) { @@ -243,7 +245,9 @@ asoc_simple_card_sub_parse_of(struct device_node *np, return ret; /* Parse TDM slot */ - ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); + ret = snd_soc_of_parse_tdm_slot(np, &dai->tx_slot_mask, + &dai->rx_slot_mask, + &dai->slots, &dai->slot_width); if (ret) return ret; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6173d15236c3..c5e21ca0c015 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3291,13 +3291,38 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); +static int snd_soc_of_get_slot_mask(struct device_node *np, + const char *prop_name, + unsigned int *mask) +{ + u32 val; + const u32 *of_slot_mask = of_get_property(np, prop_name, &val); + int i; + + if (!of_slot_mask) + return 0; + val /= sizeof(u32); + for (i = 0; i < val; i++) + if (be32_to_cpup(&of_slot_mask[i])) + *mask |= (1 << i); + + return val; +} + int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *tx_mask, + unsigned int *rx_mask, unsigned int *slots, unsigned int *slot_width) { u32 val; int ret; + if (tx_mask) + snd_soc_of_get_slot_mask(np, "dai-tdm-slot-tx-mask", tx_mask); + if (rx_mask) + snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask", rx_mask); + if (of_property_read_bool(np, "dai-tdm-slot-num")) { ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); if (ret) -- cgit v1.3-6-gb490 From 9685cd9df75c1f5686308601c870f5e4ebc809be Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 25 Aug 2015 15:35:57 -0400 Subject: drm/fb-helper: add headerdoc for drm_fb_helper Signed-off-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drm_fb_helper.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 67de1f10008e..62541363f747 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -104,6 +104,20 @@ struct drm_fb_helper_connector { struct drm_connector *connector; }; +/** + * struct drm_fb_helper - helper to emulate fbdev on top of kms + * @fb: Scanout framebuffer object + * @dev: DRM device + * @crtc_count: number of possible CRTCs + * @crtc_info: per-CRTC helper state (mode, x/y offset, etc) + * @connector_count: number of connected connectors + * @connector_info_alloc_count: size of connector_info + * @funcs: driver callbacks for fb helper + * @fbdev: emulated fbdev device info struct + * @pseudo_palette: fake palette of 16 colors + * @kernel_fb_list: list_head in kernel_fb_helper_list + * @delayed_hotplug: was there a hotplug while kms master active? + */ struct drm_fb_helper { struct drm_framebuffer *fb; struct drm_device *dev; -- cgit v1.3-6-gb490 From bbb1e52402b2a288b09ae37e8182599931c7e9df Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 25 Aug 2015 15:35:58 -0400 Subject: drm/fb-helper: atomic restore_fbdev_mode().. Add support for using atomic code-paths for restore_fbdev_mode(). Signed-off-by: Rob Clark [danvet: Bikeshed comments slightly.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 131 +++++++++++++++++++++--------------- drivers/gpu/drm/drm_fb_helper.c | 73 ++++++++++++++++++++ include/drm/drm_atomic_helper.h | 6 ++ include/drm/drm_fb_helper.h | 11 +++ 4 files changed, 168 insertions(+), 53 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 94d6c8ed3dc4..ee57ecfd3de0 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1553,21 +1553,9 @@ retry: goto fail; } - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); + ret = __drm_atomic_helper_disable_plane(plane, plane_state); if (ret != 0) goto fail; - drm_atomic_set_fb_for_plane(plane_state, NULL); - plane_state->crtc_x = 0; - plane_state->crtc_y = 0; - plane_state->crtc_h = 0; - plane_state->crtc_w = 0; - plane_state->src_x = 0; - plane_state->src_y = 0; - plane_state->src_h = 0; - plane_state->src_w = 0; - - if (plane == plane->crtc->cursor) - state->legacy_cursor_update = true; ret = drm_atomic_commit(state); if (ret != 0) @@ -1597,6 +1585,32 @@ backoff: } EXPORT_SYMBOL(drm_atomic_helper_disable_plane); +/* just used from fb-helper and atomic-helper: */ +int __drm_atomic_helper_disable_plane(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); + if (ret != 0) + return ret; + + drm_atomic_set_fb_for_plane(plane_state, NULL); + plane_state->crtc_x = 0; + plane_state->crtc_y = 0; + plane_state->crtc_h = 0; + plane_state->crtc_w = 0; + plane_state->src_x = 0; + plane_state->src_y = 0; + plane_state->src_h = 0; + plane_state->src_w = 0; + + if (plane->crtc && (plane == plane->crtc->cursor)) + plane_state->state->legacy_cursor_update = true; + + return 0; +} + static int update_output_state(struct drm_atomic_state *state, struct drm_mode_set *set) { @@ -1680,8 +1694,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) { struct drm_atomic_state *state; struct drm_crtc *crtc = set->crtc; - struct drm_crtc_state *crtc_state; - struct drm_plane_state *primary_state; int ret = 0; state = drm_atomic_state_alloc(crtc->dev); @@ -1690,17 +1702,54 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); retry: - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); + ret = __drm_atomic_helper_set_config(set, state); + if (ret != 0) goto fail; - } - primary_state = drm_atomic_get_plane_state(state, crtc->primary); - if (IS_ERR(primary_state)) { - ret = PTR_ERR(primary_state); + ret = drm_atomic_commit(state); + if (ret != 0) goto fail; - } + + /* Driver takes ownership of state on successful commit. */ + return 0; +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + /* + * Someone might have exchanged the framebuffer while we dropped locks + * in the backoff code. We need to fix up the fb refcount tracking the + * core does for us. + */ + crtc->primary->old_fb = crtc->primary->fb; + + goto retry; +} +EXPORT_SYMBOL(drm_atomic_helper_set_config); + +/* just used from fb-helper and atomic-helper: */ +int __drm_atomic_helper_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_plane_state *primary_state; + struct drm_crtc *crtc = set->crtc; + int ret; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + primary_state = drm_atomic_get_plane_state(state, crtc->primary); + if (IS_ERR(primary_state)) + return PTR_ERR(primary_state); if (!set->mode) { WARN_ON(set->fb); @@ -1708,13 +1757,13 @@ retry: ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); if (ret != 0) - goto fail; + return ret; crtc_state->active = false; ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); if (ret != 0) - goto fail; + return ret; drm_atomic_set_fb_for_plane(primary_state, NULL); @@ -1726,13 +1775,14 @@ retry: ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode); if (ret != 0) - goto fail; + return ret; crtc_state->active = true; ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); if (ret != 0) - goto fail; + return ret; + drm_atomic_set_fb_for_plane(primary_state, set->fb); primary_state->crtc_x = 0; primary_state->crtc_y = 0; @@ -1746,35 +1796,10 @@ retry: commit: ret = update_output_state(state, set); if (ret) - goto fail; - - ret = drm_atomic_commit(state); - if (ret != 0) - goto fail; + return ret; - /* Driver takes ownership of state on successful commit. */ return 0; -fail: - if (ret == -EDEADLK) - goto backoff; - - drm_atomic_state_free(state); - - return ret; -backoff: - drm_atomic_state_clear(state); - drm_atomic_legacy_backoff(state); - - /* - * Someone might have exchanged the framebuffer while we dropped locks - * in the backoff code. We need to fix up the fb refcount tracking the - * core does for us. - */ - crtc->primary->old_fb = crtc->primary->fb; - - goto retry; } -EXPORT_SYMBOL(drm_atomic_helper_set_config); /** * drm_atomic_helper_crtc_set_property - helper for crtc properties diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index ba12f51f106f..0180fdd5da20 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include static bool drm_fbdev_emulation = true; module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); @@ -334,6 +336,72 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); +static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper) +{ + struct drm_device *dev = fb_helper->dev; + struct drm_plane *plane; + struct drm_atomic_state *state; + int i, ret; + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = dev->mode_config.acquire_ctx; +retry: + drm_for_each_plane(plane, dev) { + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto fail; + } + + ret = drm_atomic_plane_set_property(plane, plane_state, + dev->mode_config.rotation_property, + BIT(DRM_ROTATE_0)); + if (ret != 0) + goto fail; + + /* disable non-primary: */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + continue; + + ret = __drm_atomic_helper_disable_plane(plane, plane_state); + if (ret != 0) + goto fail; + } + + for(i = 0; i < fb_helper->crtc_count; i++) { + struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + + ret = __drm_atomic_helper_set_config(mode_set, state); + if (ret != 0) + goto fail; + } + + ret = drm_atomic_commit(state); + if (ret != 0) + goto fail; + + return 0; + +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + goto retry; +} + static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; @@ -342,6 +410,9 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) drm_warn_on_modeset_not_all_locked(dev); + if (fb_helper->atomic) + return restore_fbdev_mode_atomic(fb_helper); + drm_for_each_plane(plane, dev) { if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); @@ -644,6 +715,8 @@ int drm_fb_helper_init(struct drm_device *dev, i++; } + fb_helper->atomic = !!drm_core_check_feature(dev, DRIVER_ATOMIC); + return 0; out_free: drm_fb_helper_crtc_free(fb_helper); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 1547eb43c14a..8cba54a2a0a0 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -30,6 +30,8 @@ #include +struct drm_atomic_state; + int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state); int drm_atomic_helper_check_planes(struct drm_device *dev, @@ -73,7 +75,11 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); int drm_atomic_helper_disable_plane(struct drm_plane *plane); +int __drm_atomic_helper_disable_plane(struct drm_plane *plane, + struct drm_plane_state *plane_state); int drm_atomic_helper_set_config(struct drm_mode_set *set); +int __drm_atomic_helper_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state); int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 62541363f747..87b090c4b730 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -134,6 +134,17 @@ struct drm_fb_helper { /* we got a hotplug but fbdev wasn't running the console delay until next set_par */ bool delayed_hotplug; + + /** + * @atomic: + * + * Use atomic updates for restore_fbdev_mode(), etc. This defaults to + * true if driver has DRIVER_ATOMIC feature flag, but drivers can + * override it to true after drm_fb_helper_init() if they support atomic + * modeset but do not yet advertise DRIVER_ATOMIC (note that fb-helper + * does not require ASYNC commits). + */ + bool atomic; }; #ifdef CONFIG_DRM_FBDEV_EMULATION -- cgit v1.3-6-gb490 From a54e22f40480eb63533d3f0520e9c84b102dd09f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 16 Sep 2015 13:59:42 +0100 Subject: ASoC: Add SOC_SINGLE_RANGE_EXT_TLV macro Add a version of the SOC_SINGLE_RANGE_TLV macro that allows a custom get and put to be specified. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- include/sound/soc.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 884e728b09d9..9ffa28514fa7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -226,6 +226,18 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } +#define SOC_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ + xhandler_get, xhandler_put, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw_range, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .rreg = xreg, .shift = xshift, \ + .rshift = xshift, .min = xmin, .max = xmax, \ + .platform_max = xmax, .invert = xinvert} } #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ -- cgit v1.3-6-gb490 From 073ae2b41c44903b9c28e3dc0263814c7fd33d5b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 6 Aug 2015 16:07:46 +0530 Subject: clk: qcom: gdsc: Add GDSCs in msm8916 GCC Add all data for the GDSCs which are part of msm8916 GCC block. Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + drivers/clk/qcom/gcc-msm8916.c | 51 ++++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8916.h | 8 +++++ 3 files changed, 60 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index d3a695b97aa0..abec45a6444c 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -53,6 +53,7 @@ config MSM_GCC_8660 config MSM_GCC_8916 tristate "MSM8916 Global Clock Controller" + select QCOM_GDSC depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8916 devices. diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index 3de282365d8d..83871b663e21 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -31,6 +31,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" +#include "gdsc.h" enum { P_XO, @@ -2550,6 +2551,46 @@ static struct clk_branch gcc_venus0_vcodec0_clk = { }, }; +static struct gdsc venus_gdsc = { + .gdscr = 0x4c018, + .pd = { + .name = "venus", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mdss_gdsc = { + .gdscr = 0x4d078, + .pd = { + .name = "mdss", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc jpeg_gdsc = { + .gdscr = 0x5701c, + .pd = { + .name = "jpeg", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc vfe_gdsc = { + .gdscr = 0x58034, + .pd = { + .name = "vfe", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc oxili_gdsc = { + .gdscr = 0x5901c, + .pd = { + .name = "oxili", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *gcc_msm8916_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL0_VOTE] = &gpll0_vote, @@ -2691,6 +2732,14 @@ static struct clk_regmap *gcc_msm8916_clocks[] = { [GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr, }; +static struct gdsc *gcc_msm8916_gdscs[] = { + [VENUS_GDSC] = &venus_gdsc, + [MDSS_GDSC] = &mdss_gdsc, + [JPEG_GDSC] = &jpeg_gdsc, + [VFE_GDSC] = &vfe_gdsc, + [OXILI_GDSC] = &oxili_gdsc, +}; + static const struct qcom_reset_map gcc_msm8916_resets[] = { [GCC_BLSP1_BCR] = { 0x01000 }, [GCC_BLSP1_QUP1_BCR] = { 0x02000 }, @@ -2798,6 +2847,8 @@ static const struct qcom_cc_desc gcc_msm8916_desc = { .num_clks = ARRAY_SIZE(gcc_msm8916_clocks), .resets = gcc_msm8916_resets, .num_resets = ARRAY_SIZE(gcc_msm8916_resets), + .gdscs = gcc_msm8916_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_msm8916_gdscs), }; static const struct of_device_id gcc_msm8916_match_table[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h index e430f644dd6c..11566c567356 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8916.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h @@ -153,4 +153,12 @@ #define GCC_VENUS0_AXI_CLK 136 #define GCC_VENUS0_VCODEC0_CLK 137 +/* Indexes for GDSCs */ +#define BIMC_GDSC 0 +#define VENUS_GDSC 1 +#define MDSS_GDSC 2 +#define JPEG_GDSC 3 +#define VFE_GDSC 4 +#define OXILI_GDSC 5 + #endif -- cgit v1.3-6-gb490 From 340029efdc83c7ba682dae731feff0d72a0ffd66 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 6 Aug 2015 16:07:47 +0530 Subject: clk: qcom: gdsc: Add GDSCs in msm8974 GCC There's just one GDSC as part of the msm8974 GCC block. Signed-off-by: Stephen Boyd Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + drivers/clk/qcom/gcc-msm8974.c | 15 +++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8974.h | 3 +++ 3 files changed, 19 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index abec45a6444c..a6fcb1ddb567 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -88,6 +88,7 @@ config MSM_MMCC_8960 config MSM_GCC_8974 tristate "MSM8974 Global Clock Controller" + select QCOM_GDSC depends on COMMON_CLK_QCOM help Support for the global clock controller on msm8974 devices. diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 2bcf87538f9d..ebad55c74917 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -31,6 +31,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" +#include "gdsc.h" enum { P_XO, @@ -2432,6 +2433,14 @@ static struct clk_branch gcc_usb_hsic_system_clk = { }, }; +static struct gdsc usb_hs_hsic_gdsc = { + .gdscr = 0x404, + .pd = { + .name = "usb_hs_hsic", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *gcc_msm8974_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL0_VOTE] = &gpll0_vote, @@ -2661,6 +2670,10 @@ static const struct qcom_reset_map gcc_msm8974_resets[] = { [GCC_VENUS_RESTART] = { 0x1740 }, }; +static struct gdsc *gcc_msm8974_gdscs[] = { + [USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc, +}; + static const struct regmap_config gcc_msm8974_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -2675,6 +2688,8 @@ static const struct qcom_cc_desc gcc_msm8974_desc = { .num_clks = ARRAY_SIZE(gcc_msm8974_clocks), .resets = gcc_msm8974_resets, .num_resets = ARRAY_SIZE(gcc_msm8974_resets), + .gdscs = gcc_msm8974_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_msm8974_gdscs), }; static const struct of_device_id gcc_msm8974_match_table[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-msm8974.h b/include/dt-bindings/clock/qcom,gcc-msm8974.h index 51e51c860fe6..81d32f639190 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8974.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8974.h @@ -321,4 +321,7 @@ #define GCC_SDCC1_CDCCAL_SLEEP_CLK 304 #define GCC_SDCC1_CDCCAL_FF_CLK 305 +/* gdscs */ +#define USB_HS_HSIC_GDSC 0 + #endif -- cgit v1.3-6-gb490 From 8108b23ca7270ff2c2b551f447e57436d534d23a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 6 Aug 2015 16:07:48 +0530 Subject: clk: qcom: gdsc: Add GDSCs in msm8974 MMCC Add the GDSC instances that exist as part of msm8974 MMCC block Signed-off-by: Stephen Boyd Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + drivers/clk/qcom/mmcc-msm8974.c | 72 +++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,mmcc-msm8974.h | 8 +++ 3 files changed, 81 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index a6fcb1ddb567..edab1724537b 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -98,6 +98,7 @@ config MSM_GCC_8974 config MSM_MMCC_8974 tristate "MSM8974 Multimedia Clock Controller" select MSM_GCC_8974 + select QCOM_GDSC depends on COMMON_CLK_QCOM help Support for the multimedia clock controller on msm8974 devices. diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c index 197700e3b2c9..fe8320dc41db 100644 --- a/drivers/clk/qcom/mmcc-msm8974.c +++ b/drivers/clk/qcom/mmcc-msm8974.c @@ -31,6 +31,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" +#include "gdsc.h" enum { P_XO, @@ -2342,6 +2343,66 @@ static struct pll_config mmpll3_config = { .aux_output_mask = BIT(1), }; +static struct gdsc venus0_gdsc = { + .gdscr = 0x1024, + .cxcs = (unsigned int []){ 0x1028 }, + .cxc_count = 1, + .resets = (unsigned int []){ VENUS0_RESET }, + .reset_count = 1, + .pd = { + .name = "venus0", + }, + .pwrsts = PWRSTS_ON, +}; + +static struct gdsc mdss_gdsc = { + .gdscr = 0x2304, + .cxcs = (unsigned int []){ 0x231c, 0x2320 }, + .cxc_count = 2, + .pd = { + .name = "mdss", + }, + .pwrsts = PWRSTS_RET_ON, +}; + +static struct gdsc camss_jpeg_gdsc = { + .gdscr = 0x35a4, + .cxcs = (unsigned int []){ 0x35a8, 0x35ac, 0x35b0 }, + .cxc_count = 3, + .pd = { + .name = "camss_jpeg", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_vfe_gdsc = { + .gdscr = 0x36a4, + .cxcs = (unsigned int []){ 0x36a8, 0x36ac, 0x3704, 0x3714, 0x36b0 }, + .cxc_count = 5, + .pd = { + .name = "camss_vfe", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc oxili_gdsc = { + .gdscr = 0x4024, + .cxcs = (unsigned int []){ 0x4028 }, + .cxc_count = 1, + .pd = { + .name = "oxili", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc oxilicx_gdsc = { + .gdscr = 0x4034, + .pd = { + .name = "oxilicx", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *mmcc_msm8974_clocks[] = { [MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr, [MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr, @@ -2518,6 +2579,15 @@ static const struct qcom_reset_map mmcc_msm8974_resets[] = { [OCMEMNOC_RESET] = { 0x50b0 }, }; +static struct gdsc *mmcc_msm8974_gdscs[] = { + [VENUS0_GDSC] = &venus0_gdsc, + [MDSS_GDSC] = &mdss_gdsc, + [CAMSS_JPEG_GDSC] = &camss_jpeg_gdsc, + [CAMSS_VFE_GDSC] = &camss_vfe_gdsc, + [OXILI_GDSC] = &oxili_gdsc, + [OXILICX_GDSC] = &oxilicx_gdsc, +}; + static const struct regmap_config mmcc_msm8974_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -2532,6 +2602,8 @@ static const struct qcom_cc_desc mmcc_msm8974_desc = { .num_clks = ARRAY_SIZE(mmcc_msm8974_clocks), .resets = mmcc_msm8974_resets, .num_resets = ARRAY_SIZE(mmcc_msm8974_resets), + .gdscs = mmcc_msm8974_gdscs, + .num_gdscs = ARRAY_SIZE(mmcc_msm8974_gdscs), }; static const struct of_device_id mmcc_msm8974_match_table[] = { diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8974.h b/include/dt-bindings/clock/qcom,mmcc-msm8974.h index 032ed87ef0f3..28651e54c9ae 100644 --- a/include/dt-bindings/clock/qcom,mmcc-msm8974.h +++ b/include/dt-bindings/clock/qcom,mmcc-msm8974.h @@ -158,4 +158,12 @@ #define SPDM_RM_AXI 141 #define SPDM_RM_OCMEMNOC 142 +/* gdscs */ +#define VENUS0_GDSC 0 +#define MDSS_GDSC 1 +#define CAMSS_JPEG_GDSC 2 +#define CAMSS_VFE_GDSC 3 +#define OXILI_GDSC 4 +#define OXILICX_GDSC 5 + #endif -- cgit v1.3-6-gb490 From 639af9490b545bb41ae1f7623aec73d6951d5630 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 6 Aug 2015 16:07:49 +0530 Subject: clk: qcom: gdsc: Add GDSCs in apq8084 GCC Add the GDSC instances that exist as part of apq8084 GCC block Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + drivers/clk/qcom/gcc-apq8084.c | 42 ++++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-apq8084.h | 6 ++++ 3 files changed, 49 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index edab1724537b..fe00dd66af88 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -7,6 +7,7 @@ config COMMON_CLK_QCOM config APQ_GCC_8084 tristate "APQ8084 Global Clock Controller" + select QCOM_GDSC depends on COMMON_CLK_QCOM help Support for the global clock controller on apq8084 devices. diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c index 3563019b8e3c..b88c40115263 100644 --- a/drivers/clk/qcom/gcc-apq8084.c +++ b/drivers/clk/qcom/gcc-apq8084.c @@ -31,6 +31,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" +#include "gdsc.h" enum { P_XO, @@ -3254,6 +3255,38 @@ static struct clk_branch gcc_usb_hsic_system_clk = { }, }; +static struct gdsc usb_hs_hsic_gdsc = { + .gdscr = 0x404, + .pd = { + .name = "usb_hs_hsic", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie0_gdsc = { + .gdscr = 0x1ac4, + .pd = { + .name = "pcie0", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie1_gdsc = { + .gdscr = 0x1b44, + .pd = { + .name = "pcie1", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_gdsc = { + .gdscr = 0x1e84, + .pd = { + .name = "usb30", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *gcc_apq8084_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL0_VOTE] = &gpll0_vote, @@ -3447,6 +3480,13 @@ static struct clk_regmap *gcc_apq8084_clocks[] = { [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, }; +static struct gdsc *gcc_apq8084_gdscs[] = { + [USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc, + [PCIE0_GDSC] = &pcie0_gdsc, + [PCIE1_GDSC] = &pcie1_gdsc, + [USB30_GDSC] = &usb30_gdsc, +}; + static const struct qcom_reset_map gcc_apq8084_resets[] = { [GCC_SYSTEM_NOC_BCR] = { 0x0100 }, [GCC_CONFIG_NOC_BCR] = { 0x0140 }, @@ -3555,6 +3595,8 @@ static const struct qcom_cc_desc gcc_apq8084_desc = { .num_clks = ARRAY_SIZE(gcc_apq8084_clocks), .resets = gcc_apq8084_resets, .num_resets = ARRAY_SIZE(gcc_apq8084_resets), + .gdscs = gcc_apq8084_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_apq8084_gdscs), }; static const struct of_device_id gcc_apq8084_match_table[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-apq8084.h b/include/dt-bindings/clock/qcom,gcc-apq8084.h index 2c0da566c46a..5aa7ebeae411 100644 --- a/include/dt-bindings/clock/qcom,gcc-apq8084.h +++ b/include/dt-bindings/clock/qcom,gcc-apq8084.h @@ -348,4 +348,10 @@ #define GCC_PCIE_1_PIPE_CLK 331 #define GCC_PCIE_1_SLV_AXI_CLK 332 +/* gdscs */ +#define USB_HS_HSIC_GDSC 0 +#define PCIE0_GDSC 1 +#define PCIE1_GDSC 2 +#define USB30_GDSC 3 + #endif -- cgit v1.3-6-gb490 From cb2eb7de38e946e8e49536af7fa439c0f0210931 Mon Sep 17 00:00:00 2001 From: Stephane Viau Date: Thu, 6 Aug 2015 16:07:50 +0530 Subject: clk: qcom: gdsc: Add GDSCs in apq8084 MMCC Add the GDSC instances that exist as part of apq8084 MMCC block. Signed-off-by: Stephane Viau Signed-off-by: Rajendra Nayak Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + drivers/clk/qcom/mmcc-apq8084.c | 86 ++++++++++++++++++++++++++- include/dt-bindings/clock/qcom,mmcc-apq8084.h | 10 ++++ 3 files changed, 96 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index fe00dd66af88..47b988f567e8 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -17,6 +17,7 @@ config APQ_GCC_8084 config APQ_MMCC_8084 tristate "APQ8084 Multimedia Clock Controller" select APQ_GCC_8084 + select QCOM_GDSC depends on COMMON_CLK_QCOM help Support for the multimedia clock controller on apq8084 devices. diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c index 5d2aab7663f0..aa3809d9cec5 100644 --- a/drivers/clk/qcom/mmcc-apq8084.c +++ b/drivers/clk/qcom/mmcc-apq8084.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -26,6 +26,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" +#include "gdsc.h" enum { P_XO, @@ -3063,6 +3064,76 @@ static const struct pll_config mmpll3_config = { .aux_output_mask = BIT(1), }; +static struct gdsc venus0_gdsc = { + .gdscr = 0x1024, + .pd = { + .name = "venus0", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc venus0_core0_gdsc = { + .gdscr = 0x1040, + .pd = { + .name = "venus0_core0", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc venus0_core1_gdsc = { + .gdscr = 0x1044, + .pd = { + .name = "venus0_core1", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mdss_gdsc = { + .gdscr = 0x2304, + .cxcs = (unsigned int []){ 0x231c, 0x2320 }, + .cxc_count = 2, + .pd = { + .name = "mdss", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_jpeg_gdsc = { + .gdscr = 0x35a4, + .pd = { + .name = "camss_jpeg", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_vfe_gdsc = { + .gdscr = 0x36a4, + .cxcs = (unsigned int []){ 0x36a8, 0x36ac, 0x36b0 }, + .cxc_count = 3, + .pd = { + .name = "camss_vfe", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc oxili_gdsc = { + .gdscr = 0x4024, + .cxcs = (unsigned int []){ 0x4028 }, + .cxc_count = 1, + .pd = { + .name = "oxili", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc oxilicx_gdsc = { + .gdscr = 0x4034, + .pd = { + .name = "oxilicx", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *mmcc_apq8084_clocks[] = { [MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr, [MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr, @@ -3280,6 +3351,17 @@ static const struct qcom_reset_map mmcc_apq8084_resets[] = { [MMSSNOCAXI_RESET] = { 0x5060 }, }; +static struct gdsc *mmcc_apq8084_gdscs[] = { + [VENUS0_GDSC] = &venus0_gdsc, + [VENUS0_CORE0_GDSC] = &venus0_core0_gdsc, + [VENUS0_CORE1_GDSC] = &venus0_core1_gdsc, + [MDSS_GDSC] = &mdss_gdsc, + [CAMSS_JPEG_GDSC] = &camss_jpeg_gdsc, + [CAMSS_VFE_GDSC] = &camss_vfe_gdsc, + [OXILI_GDSC] = &oxili_gdsc, + [OXILICX_GDSC] = &oxilicx_gdsc, +}; + static const struct regmap_config mmcc_apq8084_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -3294,6 +3376,8 @@ static const struct qcom_cc_desc mmcc_apq8084_desc = { .num_clks = ARRAY_SIZE(mmcc_apq8084_clocks), .resets = mmcc_apq8084_resets, .num_resets = ARRAY_SIZE(mmcc_apq8084_resets), + .gdscs = mmcc_apq8084_gdscs, + .num_gdscs = ARRAY_SIZE(mmcc_apq8084_gdscs), }; static const struct of_device_id mmcc_apq8084_match_table[] = { diff --git a/include/dt-bindings/clock/qcom,mmcc-apq8084.h b/include/dt-bindings/clock/qcom,mmcc-apq8084.h index d72b5b35f15e..03861e3f498e 100644 --- a/include/dt-bindings/clock/qcom,mmcc-apq8084.h +++ b/include/dt-bindings/clock/qcom,mmcc-apq8084.h @@ -180,4 +180,14 @@ #define VPU_SLEEP_CLK 163 #define VPU_VDP_CLK 164 +/* GDSCs */ +#define VENUS0_GDSC 0 +#define VENUS0_CORE0_GDSC 1 +#define VENUS0_CORE1_GDSC 2 +#define MDSS_GDSC 3 +#define CAMSS_JPEG_GDSC 4 +#define CAMSS_VFE_GDSC 5 +#define OXILI_GDSC 6 +#define OXILICX_GDSC 7 + #endif -- cgit v1.3-6-gb490 From 4e478098ac0ac1b6ef9a70fcdc2ec8b93f1b59a1 Mon Sep 17 00:00:00 2001 From: Alex Gartrell Date: Mon, 14 Sep 2015 23:23:05 -0700 Subject: ipvs: add sysctl to ignore tunneled packets This is a way to avoid nasty routing loops when multiple ipvs instances can forward to eachother. Signed-off-by: Alex Gartrell Signed-off-by: Simon Horman --- Documentation/networking/ipvs-sysctl.txt | 10 ++++++++++ include/net/ip_vs.h | 11 +++++++++++ net/netfilter/ipvs/ip_vs_core.c | 10 +++++++++- net/netfilter/ipvs/ip_vs_ctl.c | 7 +++++++ 4 files changed, 37 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt index 3ba709531adb..e6b1c025fdd8 100644 --- a/Documentation/networking/ipvs-sysctl.txt +++ b/Documentation/networking/ipvs-sysctl.txt @@ -157,6 +157,16 @@ expire_quiescent_template - BOOLEAN persistence template if it is to be used to schedule a new connection and the destination server is quiescent. +ignore_tunneled - BOOLEAN + 0 - disabled (default) + not 0 - enabled + + If set, ipvs will set the ipvs_property on all packets which are of + unrecognized protocols. This prevents us from routing tunneled + protocols like ipip, which is useful to prevent rescheduling + packets that have been tunneled to the ipvs host (i.e. to prevent + ipvs routing loops when ipvs is also acting as a real server). + nat_icmp_send - BOOLEAN 0 - disabled (default) not 0 - enabled diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 47677f0493c7..1096a71ab6ed 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -998,6 +998,7 @@ struct netns_ipvs { int sysctl_backup_only; int sysctl_conn_reuse_mode; int sysctl_schedule_icmp; + int sysctl_ignore_tunneled; /* ip_vs_lblc */ int sysctl_lblc_expiration; @@ -1121,6 +1122,11 @@ static inline int sysctl_schedule_icmp(struct netns_ipvs *ipvs) return ipvs->sysctl_schedule_icmp; } +static inline int sysctl_ignore_tunneled(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_ignore_tunneled; +} + #else static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) @@ -1198,6 +1204,11 @@ static inline int sysctl_schedule_icmp(struct netns_ipvs *ipvs) return 0; } +static inline int sysctl_ignore_tunneled(struct netns_ipvs *ipvs) +{ + return 0; +} + #endif /* IPVS core functions diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 99be6801c795..453972c6909e 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1760,8 +1760,16 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) /* Protocol supported? */ pd = ip_vs_proto_data_get(net, iph.protocol); - if (unlikely(!pd)) + if (unlikely(!pd)) { + /* The only way we'll see this packet again is if it's + * encapsulated, so mark it with ipvs_property=1 so we + * skip it if we're ignoring tunneled packets + */ + if (sysctl_ignore_tunneled(ipvs)) + skb->ipvs_property = 1; + return NF_ACCEPT; + } pp = pd->pp; /* * Check if the packet belongs to an existing connection entry diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 31d80e203863..7338827ee5e9 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1850,6 +1850,12 @@ static struct ctl_table vs_vars[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "ignore_tunneled", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #ifdef CONFIG_IP_VS_DEBUG { .procname = "debug_level", @@ -3902,6 +3908,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) ipvs->sysctl_conn_reuse_mode = 1; tbl[idx++].data = &ipvs->sysctl_conn_reuse_mode; tbl[idx++].data = &ipvs->sysctl_schedule_icmp; + tbl[idx++].data = &ipvs->sysctl_ignore_tunneled; ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); if (ipvs->sysctl_hdr == NULL) { -- cgit v1.3-6-gb490 From 7b7d1968e4c8d8392e8e63906d45d0bcad079037 Mon Sep 17 00:00:00 2001 From: Guo Zeng Date: Thu, 17 Sep 2015 05:23:20 +0000 Subject: regmap: irq: add support for chips who have separate unmask registers Some chips have separate unmask registers from mask registers for some consideration of concurrency SMP write performance. And this patch adds a flag for it. An user will be CSR SiRFSoC ARM chips. Signed-off-by: Guo Zeng Signed-off-by: Barry Song Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 31 ++++++++++++++++++++++++++++--- include/linux/regmap.h | 3 +++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 38d1f72d869c..e65eec2e7def 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -63,6 +63,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) struct regmap *map = d->map; int i, ret; u32 reg; + u32 unmask_offset; if (d->chip->runtime_pm) { ret = pm_runtime_get_sync(map->dev); @@ -79,12 +80,28 @@ static void regmap_irq_sync_unlock(struct irq_data *data) for (i = 0; i < d->chip->num_regs; i++) { reg = d->chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); - if (d->chip->mask_invert) + if (d->chip->mask_invert) { ret = regmap_update_bits(d->map, reg, d->mask_buf_def[i], ~d->mask_buf[i]); - else + } else if (d->chip->unmask_base) { + /* set mask with mask_base register */ + ret = regmap_update_bits(d->map, reg, + d->mask_buf_def[i], ~d->mask_buf[i]); + if (ret < 0) + dev_err(d->map->dev, + "Failed to sync unmasks in %x\n", + reg); + unmask_offset = d->chip->unmask_base - + d->chip->mask_base; + /* clear mask with unmask_base register */ + ret = regmap_update_bits(d->map, + reg + unmask_offset, + d->mask_buf_def[i], + d->mask_buf[i]); + } else { ret = regmap_update_bits(d->map, reg, d->mask_buf_def[i], d->mask_buf[i]); + } if (ret != 0) dev_err(d->map->dev, "Failed to sync masks in %x\n", reg); @@ -339,6 +356,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, int i; int ret = -ENOMEM; u32 reg; + u32 unmask_offset; if (chip->num_regs <= 0) return -EINVAL; @@ -420,7 +438,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, if (chip->mask_invert) ret = regmap_update_bits(map, reg, d->mask_buf[i], ~d->mask_buf[i]); - else + else if (d->chip->unmask_base) { + unmask_offset = d->chip->unmask_base - + d->chip->mask_base; + ret = regmap_update_bits(d->map, + reg + unmask_offset, + d->mask_buf[i], + d->mask_buf[i]); + } else ret = regmap_update_bits(map, reg, d->mask_buf[i], d->mask_buf[i]); if (ret != 0) { diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 8fc0bfd8edc4..f98fe9f5faa2 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -800,6 +800,8 @@ struct regmap_irq { * * @status_base: Base status register address. * @mask_base: Base mask register address. + * @unmask_base: Base unmask register address. for chips who have + * separate mask and unmask registers * @ack_base: Base ack address. If zero then the chip is clear on read. * Using zero value is possible with @use_ack bit. * @wake_base: Base address for wake enables. If zero unsupported. @@ -820,6 +822,7 @@ struct regmap_irq_chip { unsigned int status_base; unsigned int mask_base; + unsigned int unmask_base; unsigned int ack_base; unsigned int wake_base; unsigned int irq_reg_stride; -- cgit v1.3-6-gb490 From a650fdd9427f1f5236f83d2d8137bea9b452fa53 Mon Sep 17 00:00:00 2001 From: Guo Zeng Date: Thu, 17 Sep 2015 05:23:21 +0000 Subject: regmap: irq: add ack_invert flag for chips using cleared bits as ack An user will be CSR SiRFSoC ARM chips. Signed-off-by: Guo Zeng Signed-off-by: Barry Song Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 12 ++++++++++-- include/linux/regmap.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index e65eec2e7def..8d16db533527 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -133,7 +133,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data) if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) { reg = d->chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); - ret = regmap_write(map, reg, d->mask_buf[i]); + /* some chips ack by write 0 */ + if (d->chip->ack_invert) + ret = regmap_write(map, reg, ~d->mask_buf[i]); + else + ret = regmap_write(map, reg, d->mask_buf[i]); if (ret != 0) dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", reg, ret); @@ -470,7 +474,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); - ret = regmap_write(map, reg, + if (chip->ack_invert) + ret = regmap_write(map, reg, + ~(d->status_buf[i] & d->mask_buf[i])); + else + ret = regmap_write(map, reg, d->status_buf[i] & d->mask_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to ack 0x%x: %d\n", diff --git a/include/linux/regmap.h b/include/linux/regmap.h index f98fe9f5faa2..f36c9f96d32d 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -809,6 +809,7 @@ struct regmap_irq { * @init_ack_masked: Ack all masked interrupts once during initalization. * @mask_invert: Inverted mask register: cleared bits are masked out. * @use_ack: Use @ack register even if it is zero. + * @ack_invert: Inverted ack register: cleared bits for ack. * @wake_invert: Inverted wake register: cleared bits are wake enabled. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * @@ -829,6 +830,7 @@ struct regmap_irq_chip { bool init_ack_masked:1; bool mask_invert:1; bool use_ack:1; + bool ack_invert:1; bool wake_invert:1; bool runtime_pm:1; -- cgit v1.3-6-gb490 From c15f6ed3a18f10cdc33f64906ab353f17a6df114 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 17 Aug 2015 11:52:54 +0800 Subject: spi: bitbang: Replace spinlock by mutex chipselect (in the case of spi-gpio: spi_gpio_chipselect, which calls gpiod_set_raw_value_cansleep) can sleep, so we should not hold a spinlock while calling it from spi_bitbang_setup. This issue was introduced by this commit, which converted spi-gpio to cansleep variants: d9dda5a191 "spi: spi-gpio: Use 'cansleep' variants to access GPIO" Replacing the lock variable by a mutex fixes the issue: This is safe as all instances where the lock is used are called from contexts that can sleep. Finally, update spi-ppc4xx and and spi-s3c24xx to use mutex functions, as they directly hold the lock for similar purpose. Signed-off-by: Nicolas Boichat Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 17 +++++++---------- drivers/spi/spi-ppc4xx.c | 4 ++-- drivers/spi/spi-s3c24xx.c | 4 ++-- include/linux/spi/spi_bitbang.h | 2 +- 4 files changed, 12 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 840a4984d365..ef43ef507c9a 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -180,7 +180,6 @@ int spi_bitbang_setup(struct spi_device *spi) { struct spi_bitbang_cs *cs = spi->controller_state; struct spi_bitbang *bitbang; - unsigned long flags; bitbang = spi_master_get_devdata(spi->master); @@ -210,12 +209,12 @@ int spi_bitbang_setup(struct spi_device *spi) */ /* deselect chip (low or high) */ - spin_lock_irqsave(&bitbang->lock, flags); + mutex_lock(&bitbang->lock); if (!bitbang->busy) { bitbang->chipselect(spi, BITBANG_CS_INACTIVE); ndelay(cs->nsecs); } - spin_unlock_irqrestore(&bitbang->lock, flags); + mutex_unlock(&bitbang->lock); return 0; } @@ -255,13 +254,12 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) static int spi_bitbang_prepare_hardware(struct spi_master *spi) { struct spi_bitbang *bitbang; - unsigned long flags; bitbang = spi_master_get_devdata(spi); - spin_lock_irqsave(&bitbang->lock, flags); + mutex_lock(&bitbang->lock); bitbang->busy = 1; - spin_unlock_irqrestore(&bitbang->lock, flags); + mutex_unlock(&bitbang->lock); return 0; } @@ -378,13 +376,12 @@ static int spi_bitbang_transfer_one(struct spi_master *master, static int spi_bitbang_unprepare_hardware(struct spi_master *spi) { struct spi_bitbang *bitbang; - unsigned long flags; bitbang = spi_master_get_devdata(spi); - spin_lock_irqsave(&bitbang->lock, flags); + mutex_lock(&bitbang->lock); bitbang->busy = 0; - spin_unlock_irqrestore(&bitbang->lock, flags); + mutex_unlock(&bitbang->lock); return 0; } @@ -427,7 +424,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) if (!master || !bitbang->chipselect) return -EINVAL; - spin_lock_init(&bitbang->lock); + mutex_init(&bitbang->lock); if (!master->mode_bits) master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 54fb984a3e17..dd3d0a218d8b 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -210,12 +210,12 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) if (in_8(&hw->regs->cdm) != cdm) out_8(&hw->regs->cdm, cdm); - spin_lock(&hw->bitbang.lock); + mutex_lock(&hw->bitbang.lock); if (!hw->bitbang.busy) { hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); /* Need to ndelay here? */ } - spin_unlock(&hw->bitbang.lock); + mutex_unlock(&hw->bitbang.lock); return 0; } diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index f36bc320a807..4e7d1bfed7e6 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -198,12 +198,12 @@ static int s3c24xx_spi_setup(struct spi_device *spi) if (ret) return ret; - spin_lock(&hw->bitbang.lock); + mutex_lock(&hw->bitbang.lock); if (!hw->bitbang.busy) { hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); /* need to ndelay for 0.5 clocktick ? */ } - spin_unlock(&hw->bitbang.lock); + mutex_unlock(&hw->bitbang.lock); return 0; } diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 85578d4be034..154788ed218c 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -4,7 +4,7 @@ #include struct spi_bitbang { - spinlock_t lock; + struct mutex lock; u8 busy; u8 use_dma; u8 flags; /* extra spi->mode support */ -- cgit v1.3-6-gb490 From 6f558b70fb39fc8272fc513ecf191b3ad87d867b Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Sun, 30 Aug 2015 18:16:55 +0200 Subject: Bluetooth: Add bt_dev logging macros Add specific bluetooth device logging macros since hci device name is repeatedly referred in bluetooth subsystem logs. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- include/net/bluetooth/bluetooth.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 38d8a34d3589..fcf2ae7dbfa0 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -128,6 +128,13 @@ void bt_err(const char *fmt, ...); #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__) #define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__) +#define bt_dev_info(hdev, fmt, ...) \ + BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__) +#define bt_dev_err(hdev, fmt, ...) \ + BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__) +#define bt_dev_dbg(hdev, fmt, ...) \ + BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__) + /* Connection and socket states */ enum { BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ -- cgit v1.3-6-gb490 From 6b3cc1db68ac83647d37f7d16f0261621eda24aa Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 2 Sep 2015 12:10:12 +0200 Subject: Bluetooth: close HCI device when user channel socket gets closed With 9380f9eacfbbee701daa416edd6625efcd3e29e1 the order of unsetting the HCI_USER_CHANNEL flag of the HCI device was reverted to ensure the device is first closed before making it available again. Due to hci_dev_close checking for HCI_USER_CHANNEL being set on the device it was never really closed and was kept opened. We're now calling hci_dev_do_close directly to make sure the device is correctly closed and we keep the correct order to unset the flag on our device object. Signed-off-by: Simon Fels Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_sock.c | 11 ++++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9e1a59e01fa2..256e6734c1fb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -987,6 +987,7 @@ int hci_resume_dev(struct hci_dev *hdev); int hci_reset_dev(struct hci_dev *hdev); int hci_dev_open(__u16 dev); int hci_dev_close(__u16 dev); +int hci_dev_do_close(struct hci_dev *hdev); int hci_dev_reset(__u16 dev); int hci_dev_reset_stat(__u16 dev); int hci_dev_cmd(unsigned int cmd, void __user *arg); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5a3602046a8b..a7cdd99ec3f1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1549,7 +1549,7 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) BT_DBG("All LE pending actions cleared"); } -static int hci_dev_do_close(struct hci_dev *hdev) +int hci_dev_do_close(struct hci_dev *hdev) { BT_DBG("%s %p", hdev->name, hdev); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f2d30d1156c9..150556345263 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -503,7 +503,16 @@ static int hci_sock_release(struct socket *sock) if (hdev) { if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { - hci_dev_close(hdev->id); + /* When releasing an user channel exclusive access, + * call hci_dev_do_close directly instead of calling + * hci_dev_close to ensure the exclusive access will + * be released and the controller brought back down. + * + * The checking of HCI_AUTO_OFF is not needed in this + * case since it will have been cleared already when + * opening the user channel. + */ + hci_dev_do_close(hdev); hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); mgmt_index_added(hdev); } -- cgit v1.3-6-gb490 From 72a5e6bb5120d6464c9e7855c5a22555ede819dc Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 2 Sep 2015 14:21:25 +0200 Subject: ieee820154: 6lowpan: dispatch evaluation rework This patch complete reworks the evaluation of 6lowpan dispatch value by introducing a receive handler mechanism for each dispatch value. A list of changes: - Doing uncompression on-the-fly when FRAG1 is received, this require some special handling for 802.15.4 lltype in generic 6lowpan branch for setting the payload length correct. - Fix dispatch mask for fragmentation. - Add IPv6 dispatch evaluation for FRAG1. - Add skb_unshare for dispatch which might manipulate the skb data buffer. Cc: Jukka Rissanen Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/6lowpan.h | 31 ++++-- net/6lowpan/iphc.c | 13 ++- net/6lowpan/nhc_udp.c | 13 ++- net/ieee802154/6lowpan/6lowpan_i.h | 12 +++ net/ieee802154/6lowpan/reassembly.c | 142 +++++++++++++++++++-------- net/ieee802154/6lowpan/rx.c | 188 ++++++++++++++++++++++++------------ 6 files changed, 288 insertions(+), 111 deletions(-) (limited to 'include') diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index a2f59ec98d24..35098411dbb4 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -126,13 +126,19 @@ (((a)[6]) == 0xFF) && \ (((a)[7]) == 0xFF)) -#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */ -#define LOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */ -#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */ -#define LOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */ -#define LOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */ +#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */ +#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */ +#define LOWPAN_DISPATCH_IPHC_MASK 0xe0 -#define LOWPAN_DISPATCH_MASK 0xf8 /* 11111000 */ +static inline bool lowpan_is_ipv6(u8 dispatch) +{ + return dispatch == LOWPAN_DISPATCH_IPV6; +} + +static inline bool lowpan_is_iphc(u8 dispatch) +{ + return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC; +} #define LOWPAN_FRAG_TIMEOUT (HZ * 60) /* time-out 60 sec */ @@ -218,6 +224,19 @@ struct lowpan_priv *lowpan_priv(const struct net_device *dev) return netdev_priv(dev); } +struct lowpan_802154_cb { + u16 d_tag; + unsigned int d_size; + u8 d_offset; +}; + +static inline +struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb)); + return (struct lowpan_802154_cb *)skb->cb; +} + #ifdef DEBUG /* print data in line */ static inline void raw_dump_inline(const char *caller, char *msg, diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 1e0071fdcf72..78c8a495b571 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -366,7 +366,18 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, return err; } - hdr.payload_len = htons(skb->len); + switch (lowpan_priv(dev)->lltype) { + case LOWPAN_LLTYPE_IEEE802154: + if (lowpan_802154_cb(skb)->d_size) + hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size - + sizeof(struct ipv6hdr)); + else + hdr.payload_len = htons(skb->len); + break; + default: + hdr.payload_len = htons(skb->len); + break; + } pr_debug("skb headroom size = %d, data length = %d\n", skb_headroom(skb), skb->len); diff --git a/net/6lowpan/nhc_udp.c b/net/6lowpan/nhc_udp.c index c6bcaeb428ae..72d0b57eb6e5 100644 --- a/net/6lowpan/nhc_udp.c +++ b/net/6lowpan/nhc_udp.c @@ -71,7 +71,18 @@ static int udp_uncompress(struct sk_buff *skb, size_t needed) * here, we obtain the hint from the remaining size of the * frame */ - uh.len = htons(skb->len + sizeof(struct udphdr)); + switch (lowpan_priv(skb->dev)->lltype) { + case LOWPAN_LLTYPE_IEEE802154: + if (lowpan_802154_cb(skb)->d_size) + uh.len = htons(lowpan_802154_cb(skb)->d_size - + sizeof(struct ipv6hdr)); + else + uh.len = htons(skb->len + sizeof(struct udphdr)); + break; + default: + uh.len = htons(skb->len + sizeof(struct udphdr)); + break; + } pr_debug("uncompressed UDP length: src = %d", ntohs(uh.len)); /* replace the compressed UDP head by the uncompressed UDP diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h index 9aa7b62b87fa..b4e17a7c0df0 100644 --- a/net/ieee802154/6lowpan/6lowpan_i.h +++ b/net/ieee802154/6lowpan/6lowpan_i.h @@ -7,6 +7,15 @@ #include #include +typedef unsigned __bitwise__ lowpan_rx_result; +#define RX_CONTINUE ((__force lowpan_rx_result) 0u) +#define RX_DROP_UNUSABLE ((__force lowpan_rx_result) 1u) +#define RX_DROP ((__force lowpan_rx_result) 2u) +#define RX_QUEUED ((__force lowpan_rx_result) 3u) + +#define LOWPAN_DISPATCH_FRAG1 0xc0 +#define LOWPAN_DISPATCH_FRAGN 0xe0 + struct lowpan_create_arg { u16 tag; u16 d_size; @@ -62,4 +71,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, const void *_saddr, unsigned int len); netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev); +int lowpan_iphc_decompress(struct sk_buff *skb); +lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb); + #endif /* __IEEE802154_6LOWPAN_I_H__ */ diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index 0fc3350ace5a..12e8cf4bda9f 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c @@ -32,17 +32,6 @@ static const char lowpan_frags_cache_name[] = "lowpan-frags"; -struct lowpan_frag_info { - u16 d_tag; - u16 d_size; - u8 d_offset; -}; - -static struct lowpan_frag_info *lowpan_cb(struct sk_buff *skb) -{ - return (struct lowpan_frag_info *)skb->cb; -} - static struct inet_frags lowpan_frags; static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, @@ -111,7 +100,7 @@ out: } static inline struct lowpan_frag_queue * -fq_find(struct net *net, const struct lowpan_frag_info *frag_info, +fq_find(struct net *net, const struct lowpan_802154_cb *cb, const struct ieee802154_addr *src, const struct ieee802154_addr *dst) { @@ -121,12 +110,12 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info, struct netns_ieee802154_lowpan *ieee802154_lowpan = net_ieee802154_lowpan(net); - arg.tag = frag_info->d_tag; - arg.d_size = frag_info->d_size; + arg.tag = cb->d_tag; + arg.d_size = cb->d_size; arg.src = src; arg.dst = dst; - hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst); + hash = lowpan_hash_frag(cb->d_tag, cb->d_size, src, dst); q = inet_frag_find(&ieee802154_lowpan->frags, &lowpan_frags, &arg, hash); @@ -138,7 +127,7 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info, } static int lowpan_frag_queue(struct lowpan_frag_queue *fq, - struct sk_buff *skb, const u8 frag_type) + struct sk_buff *skb, u8 frag_type) { struct sk_buff *prev, *next; struct net_device *ldev; @@ -147,8 +136,8 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq, if (fq->q.flags & INET_FRAG_COMPLETE) goto err; - offset = lowpan_cb(skb)->d_offset << 3; - end = lowpan_cb(skb)->d_size; + offset = lowpan_802154_cb(skb)->d_offset << 3; + end = lowpan_802154_cb(skb)->d_size; /* Is this the final fragment? */ if (offset + skb->len == end) { @@ -174,13 +163,16 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq, * this fragment, right? */ prev = fq->q.fragments_tail; - if (!prev || lowpan_cb(prev)->d_offset < lowpan_cb(skb)->d_offset) { + if (!prev || + lowpan_802154_cb(prev)->d_offset < + lowpan_802154_cb(skb)->d_offset) { next = NULL; goto found; } prev = NULL; for (next = fq->q.fragments; next != NULL; next = next->next) { - if (lowpan_cb(next)->d_offset >= lowpan_cb(skb)->d_offset) + if (lowpan_802154_cb(next)->d_offset >= + lowpan_802154_cb(skb)->d_offset) break; /* bingo! */ prev = next; } @@ -200,13 +192,10 @@ found: skb->dev = NULL; fq->q.stamp = skb->tstamp; - if (frag_type == LOWPAN_DISPATCH_FRAG1) { - /* Calculate uncomp. 6lowpan header to estimate full size */ - fq->q.meat += lowpan_uncompress_size(skb, NULL); + if (frag_type == LOWPAN_DISPATCH_FRAG1) fq->q.flags |= INET_FRAG_FIRST_IN; - } else { - fq->q.meat += skb->len; - } + + fq->q.meat += skb->len; add_frag_mem_limit(fq->q.net, skb->truesize); if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && @@ -325,24 +314,87 @@ out_oom: return -1; } -static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type, - struct lowpan_frag_info *frag_info) +static int lowpan_frag_rx_handlers_result(struct sk_buff *skb, + lowpan_rx_result res) +{ + switch (res) { + case RX_QUEUED: + return NET_RX_SUCCESS; + case RX_CONTINUE: + /* nobody cared about this packet */ + net_warn_ratelimited("%s: received unknown dispatch\n", + __func__); + + /* fall-through */ + default: + /* all others failure */ + return NET_RX_DROP; + } +} + +static lowpan_rx_result lowpan_frag_rx_h_iphc(struct sk_buff *skb) +{ + int ret; + + if (!lowpan_is_iphc(*skb_network_header(skb))) + return RX_CONTINUE; + + ret = lowpan_iphc_decompress(skb); + if (ret < 0) + return RX_DROP; + + return RX_QUEUED; +} + +static int lowpan_invoke_frag_rx_handlers(struct sk_buff *skb) +{ + lowpan_rx_result res; + +#define CALL_RXH(rxh) \ + do { \ + res = rxh(skb); \ + if (res != RX_CONTINUE) \ + goto rxh_next; \ + } while (0) + + /* likely at first */ + CALL_RXH(lowpan_frag_rx_h_iphc); + CALL_RXH(lowpan_rx_h_ipv6); + +rxh_next: + return lowpan_frag_rx_handlers_result(skb, res); +#undef CALL_RXH +} + +#define LOWPAN_FRAG_DGRAM_SIZE_HIGH_MASK 0x07 +#define LOWPAN_FRAG_DGRAM_SIZE_HIGH_SHIFT 8 + +static int lowpan_get_cb(struct sk_buff *skb, u8 frag_type, + struct lowpan_802154_cb *cb) { bool fail; - u8 pattern = 0, low = 0; + u8 high = 0, low = 0; __be16 d_tag = 0; - fail = lowpan_fetch_skb(skb, &pattern, 1); + fail = lowpan_fetch_skb(skb, &high, 1); fail |= lowpan_fetch_skb(skb, &low, 1); - frag_info->d_size = (pattern & 7) << 8 | low; + /* remove the dispatch value and use first three bits as high value + * for the datagram size + */ + cb->d_size = (high & LOWPAN_FRAG_DGRAM_SIZE_HIGH_MASK) << + LOWPAN_FRAG_DGRAM_SIZE_HIGH_SHIFT | low; fail |= lowpan_fetch_skb(skb, &d_tag, 2); - frag_info->d_tag = ntohs(d_tag); + cb->d_tag = ntohs(d_tag); if (frag_type == LOWPAN_DISPATCH_FRAGN) { - fail |= lowpan_fetch_skb(skb, &frag_info->d_offset, 1); + fail |= lowpan_fetch_skb(skb, &cb->d_offset, 1); } else { skb_reset_network_header(skb); - frag_info->d_offset = 0; + cb->d_offset = 0; + /* check if datagram_size has ipv6hdr on FRAG1 */ + fail |= cb->d_size < sizeof(struct ipv6hdr); + /* check if we can dereference the dispatch value */ + fail |= !skb->len; } if (unlikely(fail)) @@ -351,27 +403,33 @@ static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type, return 0; } -int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) +int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type) { struct lowpan_frag_queue *fq; struct net *net = dev_net(skb->dev); - struct lowpan_frag_info *frag_info = lowpan_cb(skb); - struct ieee802154_addr source, dest; + struct lowpan_802154_cb *cb = lowpan_802154_cb(skb); + struct ieee802154_hdr hdr; int err; - source = mac_cb(skb)->source; - dest = mac_cb(skb)->dest; + if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) + goto err; - err = lowpan_get_frag_info(skb, frag_type, frag_info); + err = lowpan_get_cb(skb, frag_type, cb); if (err < 0) goto err; - if (frag_info->d_size > IPV6_MIN_MTU) { + if (frag_type == LOWPAN_DISPATCH_FRAG1) { + err = lowpan_invoke_frag_rx_handlers(skb); + if (err == NET_RX_DROP) + goto err; + } + + if (cb->d_size > IPV6_MIN_MTU) { net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n"); goto err; } - fq = fq_find(net, frag_info, &source, &dest); + fq = fq_find(net, cb, &hdr.source, &hdr.dest); if (fq != NULL) { int ret; diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c index f9cb70b6749f..fded1099fae0 100644 --- a/net/ieee802154/6lowpan/rx.c +++ b/net/ieee802154/6lowpan/rx.c @@ -15,8 +15,9 @@ #include "6lowpan_i.h" -static int lowpan_give_skb_to_device(struct sk_buff *skb, - struct net_device *wdev) +#define LOWPAN_DISPATCH_FRAG_MASK 0xf8 + +static int lowpan_give_skb_to_device(struct sk_buff *skb) { skb->protocol = htons(ETH_P_IPV6); skb->pkt_type = PACKET_HOST; @@ -24,21 +25,77 @@ static int lowpan_give_skb_to_device(struct sk_buff *skb, return netif_rx(skb); } -static int -iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) +static int lowpan_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res) +{ + switch (res) { + case RX_CONTINUE: + /* nobody cared about this packet */ + net_warn_ratelimited("%s: received unknown dispatch\n", + __func__); + + /* fall-through */ + case RX_DROP_UNUSABLE: + kfree_skb(skb); + + /* fall-through */ + case RX_DROP: + return NET_RX_DROP; + case RX_QUEUED: + return lowpan_give_skb_to_device(skb); + default: + break; + } + + return NET_RX_DROP; +} + +static inline bool lowpan_is_frag1(u8 dispatch) +{ + return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAG1; +} + +static inline bool lowpan_is_fragn(u8 dispatch) +{ + return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAGN; +} + +static lowpan_rx_result lowpan_rx_h_frag(struct sk_buff *skb) +{ + int ret; + + if (!(lowpan_is_frag1(*skb_network_header(skb)) || + lowpan_is_fragn(*skb_network_header(skb)))) + return RX_CONTINUE; + + ret = lowpan_frag_rcv(skb, *skb_network_header(skb) & + LOWPAN_DISPATCH_FRAG_MASK); + if (ret == 1) + return RX_QUEUED; + + /* Packet is freed by lowpan_frag_rcv on error or put into the frag + * bucket. + */ + return RX_DROP; +} + +int lowpan_iphc_decompress(struct sk_buff *skb) { - u8 iphc0, iphc1; struct ieee802154_addr_sa sa, da; + struct ieee802154_hdr hdr; + u8 iphc0, iphc1; void *sap, *dap; + if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) + return -EINVAL; + raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); if (lowpan_fetch_skb_u8(skb, &iphc0) || lowpan_fetch_skb_u8(skb, &iphc1)) return -EINVAL; - ieee802154_addr_to_sa(&sa, &hdr->source); - ieee802154_addr_to_sa(&da, &hdr->dest); + ieee802154_addr_to_sa(&sa, &hdr.source); + ieee802154_addr_to_sa(&da, &hdr.dest); if (sa.addr_type == IEEE802154_ADDR_SHORT) sap = &sa.short_addr; @@ -55,78 +112,87 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) IEEE802154_ADDR_LEN, iphc0, iphc1); } +static lowpan_rx_result lowpan_rx_h_iphc(struct sk_buff *skb) +{ + int ret; + + if (!lowpan_is_iphc(*skb_network_header(skb))) + return RX_CONTINUE; + + /* Setting datagram_offset to zero indicates non frag handling + * while doing lowpan_header_decompress. + */ + lowpan_802154_cb(skb)->d_size = 0; + + ret = lowpan_iphc_decompress(skb); + if (ret < 0) + return RX_DROP_UNUSABLE; + + return RX_QUEUED; +} + +lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb) +{ + if (!lowpan_is_ipv6(*skb_network_header(skb))) + return RX_CONTINUE; + + /* Pull off the 1-byte of 6lowpan header. */ + skb_pull(skb, 1); + return RX_QUEUED; +} + +static int lowpan_invoke_rx_handlers(struct sk_buff *skb) +{ + lowpan_rx_result res; + +#define CALL_RXH(rxh) \ + do { \ + res = rxh(skb); \ + if (res != RX_CONTINUE) \ + goto rxh_next; \ + } while (0) + + /* likely at first */ + CALL_RXH(lowpan_rx_h_iphc); + CALL_RXH(lowpan_rx_h_frag); + CALL_RXH(lowpan_rx_h_ipv6); + +rxh_next: + return lowpan_rx_handlers_result(skb, res); +#undef CALL_RXH +} + static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev, struct packet_type *pt, struct net_device *orig_wdev) { - struct ieee802154_hdr hdr; struct net_device *ldev; - int ret; if (wdev->type != ARPHRD_IEEE802154 || skb->pkt_type == PACKET_OTHERHOST) - goto drop; + return NET_RX_DROP; ldev = wdev->ieee802154_ptr->lowpan_dev; if (!ldev || !netif_running(ldev)) - goto drop; + return NET_RX_DROP; /* Replacing skb->dev and followed rx handlers will manipulate skb. */ skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) - goto drop; + return NET_RX_DROP; skb->dev = ldev; - if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) - goto drop_skb; - - /* check that it's our buffer */ - if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { - /* Pull off the 1-byte of 6lowpan header. */ - skb_pull(skb, 1); - return lowpan_give_skb_to_device(skb, wdev); - } else { - switch (skb->data[0] & 0xe0) { - case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ - ret = iphc_decompress(skb, &hdr); - if (ret < 0) - goto drop_skb; - - return lowpan_give_skb_to_device(skb, wdev); - case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ - ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1); - if (ret == 1) { - ret = iphc_decompress(skb, &hdr); - if (ret < 0) - goto drop_skb; - - return lowpan_give_skb_to_device(skb, wdev); - } else if (ret == -1) { - return NET_RX_DROP; - } else { - return NET_RX_SUCCESS; - } - case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ - ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN); - if (ret == 1) { - ret = iphc_decompress(skb, &hdr); - if (ret < 0) - goto drop_skb; - - return lowpan_give_skb_to_device(skb, wdev); - } else if (ret == -1) { - return NET_RX_DROP; - } else { - return NET_RX_SUCCESS; - } - default: - break; - } + /* When receive frag1 it's likely that we manipulate the buffer. + * When recevie iphc we manipulate the data buffer. So we need + * to unshare the buffer. + */ + if (lowpan_is_frag1(*skb_network_header(skb)) || + lowpan_is_iphc(*skb_network_header(skb))) { + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + return RX_DROP; } -drop_skb: - kfree_skb(skb); -drop: - return NET_RX_DROP; + return lowpan_invoke_rx_handlers(skb); } static struct packet_type lowpan_packet_type = { -- cgit v1.3-6-gb490 From 54552d03023cfd485cedf8d7471d1554139d58aa Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 2 Sep 2015 14:21:29 +0200 Subject: ieee802154: 6lowpan: check on valid 802.15.4 frame This patch adds frame control checks to check if the received frame is something which could contain a 6LoWPAN packet. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 25 +++++++++++++++++++++++++ include/net/mac802154.h | 15 +++++++++++++++ net/ieee802154/6lowpan/rx.c | 8 ++++++++ 3 files changed, 48 insertions(+) (limited to 'include') diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 1dc1f4ed4001..db01492814d3 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -205,6 +205,31 @@ enum { IEEE802154_SCAN_IN_PROGRESS = 0xfc, }; +/* frame control handling */ +#define IEEE802154_FCTL_FTYPE 0x0003 +#define IEEE802154_FCTL_INTRA_PAN 0x0040 + +#define IEEE802154_FTYPE_DATA 0x0001 + +/* + * ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA + * @fc: frame control bytes in little-endian byteorder + */ +static inline int ieee802154_is_data(__le16 fc) +{ + return (fc & cpu_to_le16(IEEE802154_FCTL_FTYPE)) == + cpu_to_le16(IEEE802154_FTYPE_DATA); +} + +/** + * ieee802154_is_intra_pan - check if intra pan id communication + * @fc: frame control bytes in little-endian byteorder + */ +static inline bool ieee802154_is_intra_pan(__le16 fc) +{ + return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN); +} + /** * ieee802154_is_valid_psdu_len - check if psdu len is valid * available lengths: diff --git a/include/net/mac802154.h b/include/net/mac802154.h index b7f99615224b..32bd7c0467d4 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -249,6 +249,21 @@ struct ieee802154_ops { const bool on); }; +/** + * ieee802154_get_fc_from_skb - get the frame control field from an skb + * @skb: skb where the frame control field will be get from + */ +static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb) +{ + /* return some invalid fc on failure */ + if (unlikely(skb->mac_len < 2)) { + WARN_ON(1); + return cpu_to_le16(0); + } + + return (__force __le16)__get_unaligned_memmove16(skb_mac_header(skb)); +} + /** * ieee802154_be64_to_le64 - copies and convert be64 to le64 * @le64_dst: le64 destination pointer diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c index 45ce121369c2..f7eb091203a8 100644 --- a/net/ieee802154/6lowpan/rx.c +++ b/net/ieee802154/6lowpan/rx.c @@ -11,6 +11,7 @@ #include #include +#include #include #include "6lowpan_i.h" @@ -280,6 +281,13 @@ static inline bool lowpan_is_reserved(u8 dispatch) */ static inline bool lowpan_rx_h_check(struct sk_buff *skb) { + __le16 fc = ieee802154_get_fc_from_skb(skb); + + /* check on ieee802154 conform 6LoWPAN header */ + if (!ieee802154_is_data(fc) || + !ieee802154_is_intra_pan(fc)) + return false; + /* check if we can dereference the dispatch */ if (unlikely(!skb->len)) return false; -- cgit v1.3-6-gb490 From 187625e18498ff0f3738a059778a8578171f06c8 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 2 Sep 2015 14:21:31 +0200 Subject: ieee802154: 6lowpan: remove tx full-size calc workaround This patch removes a workaround for datagram_size calculation while doing fragmentation on transmit. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/6lowpan.h | 113 -------------------------------------------- net/ieee802154/6lowpan/tx.c | 18 ++++--- 2 files changed, 11 insertions(+), 120 deletions(-) (limited to 'include') diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index 35098411dbb4..eeae5eb58754 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -299,119 +299,6 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data, *hc_ptr += len; } -static inline u8 lowpan_addr_mode_size(const u8 addr_mode) -{ - static const u8 addr_sizes[] = { - [LOWPAN_IPHC_ADDR_00] = 16, - [LOWPAN_IPHC_ADDR_01] = 8, - [LOWPAN_IPHC_ADDR_02] = 2, - [LOWPAN_IPHC_ADDR_03] = 0, - }; - return addr_sizes[addr_mode]; -} - -static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 *uncomp_header) -{ - u8 ret = 1; - - if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { - *uncomp_header += sizeof(struct udphdr); - - switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) { - case LOWPAN_NHC_UDP_CS_P_00: - ret += 4; - break; - case LOWPAN_NHC_UDP_CS_P_01: - case LOWPAN_NHC_UDP_CS_P_10: - ret += 3; - break; - case LOWPAN_NHC_UDP_CS_P_11: - ret++; - break; - default: - break; - } - - if (!(h_enc & LOWPAN_NHC_UDP_CS_C)) - ret += 2; - } - - return ret; -} - -/** - * lowpan_uncompress_size - returns skb->len size with uncompressed header - * @skb: sk_buff with 6lowpan header inside - * @datagram_offset: optional to get the datagram_offset value - * - * Returns the skb->len with uncompressed header - */ -static inline u16 -lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset) -{ - u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr); - u8 iphc0, iphc1, h_enc; - - iphc0 = skb_network_header(skb)[0]; - iphc1 = skb_network_header(skb)[1]; - - switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { - case 0: - ret += 4; - break; - case 1: - ret += 3; - break; - case 2: - ret++; - break; - default: - break; - } - - if (!(iphc0 & LOWPAN_IPHC_NH_C)) - ret++; - - if (!(iphc0 & 0x03)) - ret++; - - ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >> - LOWPAN_IPHC_SAM_BIT); - - if (iphc1 & LOWPAN_IPHC_M) { - switch ((iphc1 & LOWPAN_IPHC_DAM_11) >> - LOWPAN_IPHC_DAM_BIT) { - case LOWPAN_IPHC_DAM_00: - ret += 16; - break; - case LOWPAN_IPHC_DAM_01: - ret += 6; - break; - case LOWPAN_IPHC_DAM_10: - ret += 4; - break; - case LOWPAN_IPHC_DAM_11: - ret++; - break; - default: - break; - } - } else { - ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >> - LOWPAN_IPHC_DAM_BIT); - } - - if (iphc0 & LOWPAN_IPHC_NH_C) { - h_enc = skb_network_header(skb)[ret]; - ret += lowpan_next_hdr_size(h_enc, &uncomp_header); - } - - if (dgram_offset) - *dgram_offset = uncomp_header; - - return skb->len + uncomp_header - ret; -} - void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype); int diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c index 9a2147e7f600..54939d031ea5 100644 --- a/net/ieee802154/6lowpan/tx.c +++ b/net/ieee802154/6lowpan/tx.c @@ -123,16 +123,14 @@ lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr, static int lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev, - const struct ieee802154_hdr *wpan_hdr) + const struct ieee802154_hdr *wpan_hdr, u16 dgram_size, + u16 dgram_offset) { - u16 dgram_size, dgram_offset; __be16 frag_tag; u8 frag_hdr[5]; int frag_cap, frag_len, payload_cap, rc; int skb_unprocessed, skb_offset; - dgram_size = lowpan_uncompress_size(skb, &dgram_offset) - - skb->mac_len; frag_tag = htons(lowpan_dev_info(ldev)->fragment_tag); lowpan_dev_info(ldev)->fragment_tag++; @@ -187,7 +185,8 @@ err: return rc; } -static int lowpan_header(struct sk_buff *skb, struct net_device *ldev) +static int lowpan_header(struct sk_buff *skb, struct net_device *ldev, + u16 *dgram_size, u16 *dgram_offset) { struct wpan_dev *wpan_dev = lowpan_dev_info(ldev)->wdev->ieee802154_ptr; struct ieee802154_addr sa, da; @@ -201,7 +200,10 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *ldev) daddr = &info.daddr.u.extended_addr; saddr = &info.saddr.u.extended_addr; + *dgram_size = skb->len; lowpan_header_compress(skb, ldev, ETH_P_IPV6, daddr, saddr, skb->len); + /* dgram_offset = (saved bytes after compression) + lowpan header len */ + *dgram_offset = (*dgram_size - skb->len) + skb_network_header_len(skb); cb->type = IEEE802154_FC_TYPE_DATA; @@ -234,6 +236,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) { struct ieee802154_hdr wpan_hdr; int max_single, ret; + u16 dgram_size, dgram_offset; pr_debug("package xmit\n"); @@ -244,7 +247,7 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) if (!skb) return NET_XMIT_DROP; - ret = lowpan_header(skb, ldev); + ret = lowpan_header(skb, ldev, &dgram_size, &dgram_offset); if (ret < 0) { kfree_skb(skb); return NET_XMIT_DROP; @@ -264,7 +267,8 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) netdev_tx_t rc; pr_debug("frame is too big, fragmentation is needed\n"); - rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr); + rc = lowpan_xmit_fragmented(skb, ldev, &wpan_hdr, dgram_size, + dgram_offset); return rc < 0 ? NET_XMIT_DROP : rc; } -- cgit v1.3-6-gb490 From bfe08a875a8903c0abb1ef5d57722252d14ede2e Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Thu, 3 Sep 2015 16:31:35 +0200 Subject: ieee802154: af_ieee802154: fix typo in comment. Signed-off-by: Stefan Schmidt Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/af_ieee802154.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/af_ieee802154.h b/include/net/af_ieee802154.h index 7d38e2ffd256..a5563d27a3eb 100644 --- a/include/net/af_ieee802154.h +++ b/include/net/af_ieee802154.h @@ -1,5 +1,5 @@ /* - * IEEE 802.15.4 inteface for userspace + * IEEE 802.15.4 interface for userspace * * Copyright 2007, 2008 Siemens AG * -- cgit v1.3-6-gb490 From b07461a8e45b7a62ef7fb46e4f6ada66f63406a8 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Thu, 17 Sep 2015 10:09:37 -0500 Subject: PCI/AER: Clear error status registers during enumeration and restore AER errors might be recorded when powering-on devices. These errors can be ignored, so firmware usually clears them before the OS enumerates devices. However, firmware is not involved when devices are added via hotplug, so the OS may discover power-up errors that should be ignored. The same may happen when powering up devices when resuming after suspend. Clear the AER error status registers during enumeration and resume. [bhelgaas: changelog, remove repetitive comments] Signed-off-by: Taku Izumi Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 3 +++ drivers/pci/pcie/aer/aerdrv_core.c | 28 ++++++++++++++++++++++++++++ drivers/pci/probe.c | 3 +++ include/linux/aer.h | 5 +++++ 4 files changed, 39 insertions(+) (limited to 'include') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6a9a1116f1eb..62ecf45a4230 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "pci.h" const char *pci_power_names[] = { @@ -1099,6 +1100,8 @@ void pci_restore_state(struct pci_dev *dev) pci_restore_ats_state(dev); pci_restore_vc_state(dev); + pci_cleanup_aer_error_status_regs(dev); + pci_restore_config_space(dev); pci_restore_pcix_state(dev); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 9803e3d039fe..fba785e9df75 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -74,6 +74,34 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); +int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) +{ + int pos; + u32 status; + int port_type; + + if (!pci_is_pcie(dev)) + return -ENODEV; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + if (!pos) + return -EIO; + + port_type = pci_pcie_type(dev); + if (port_type == PCI_EXP_TYPE_ROOT_PORT) { + pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status); + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status); + } + + pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); + pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status); + + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); + + return 0; +} + /** * add_error_device - list device to be handled * @e_info: pointer to error info diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 0b2be174d981..8cd9710498e4 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "pci.h" @@ -1621,6 +1622,8 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Enable ACS P2P upstream forwarding */ pci_enable_acs(dev); + + pci_cleanup_aer_error_status_regs(dev); } static void pci_set_msi_domain(struct pci_dev *dev) diff --git a/include/linux/aer.h b/include/linux/aer.h index 4fef65e57023..744b997d6a94 100644 --- a/include/linux/aer.h +++ b/include/linux/aer.h @@ -42,6 +42,7 @@ struct aer_capability_regs { int pci_enable_pcie_error_reporting(struct pci_dev *dev); int pci_disable_pcie_error_reporting(struct pci_dev *dev); int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); +int pci_cleanup_aer_error_status_regs(struct pci_dev *dev); #else static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) { @@ -55,6 +56,10 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) { return -EINVAL; } +static inline int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) +{ + return -EINVAL; +} #endif void cper_print_aer(struct pci_dev *dev, int cper_severity, -- cgit v1.3-6-gb490 From f81c11af617ca4bad5028e9e431feae8d4166bc7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 4 Sep 2015 17:50:08 +0100 Subject: of/pci: Add of_pci_check_probe_only to parse "linux,pci-probe-only" Both pci-host-generic and Pseries parse the "linux,pci-probe-only" property to engage the PCI_PROBE_ONLY mode, and both have a subtle bug that can be triggered if the property has no parameter. Provide a generic, safe implementation that can be used by both. [bhelgaas: fold in #include ] Signed-off-by: Marc Zyngier Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring --- drivers/of/of_pci.c | 26 ++++++++++++++++++++++++++ include/linux/of_pci.h | 3 +++ 2 files changed, 29 insertions(+) (limited to 'include') diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index 5751dc5b6494..d0c8902dfbf4 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -5,6 +5,7 @@ #include #include #include +#include static inline int __of_pci_pci_compare(struct device_node *node, unsigned int data) @@ -117,6 +118,31 @@ int of_get_pci_domain_nr(struct device_node *node) } EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); +/** + * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only + * is present and valid + */ +void of_pci_check_probe_only(void) +{ + u32 val; + int ret; + + ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val); + if (ret) { + if (ret == -ENODATA || ret == -EOVERFLOW) + pr_warn("linux,pci-probe-only without valid value, ignoring\n"); + return; + } + + if (val) + pci_add_flags(PCI_PROBE_ONLY); + else + pci_clear_flags(PCI_PROBE_ONLY); + + pr_info("PCI: PROBE_ONLY %sabled\n", val ? "en" : "dis"); +} +EXPORT_SYMBOL_GPL(of_pci_check_probe_only); + /** * of_pci_dma_configure - Setup DMA configuration * @dev: ptr to pci_dev struct of the PCI device diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h index 29fd3fe1c035..38c0533a3359 100644 --- a/include/linux/of_pci.h +++ b/include/linux/of_pci.h @@ -17,6 +17,7 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin); int of_pci_parse_bus_range(struct device_node *node, struct resource *res); int of_get_pci_domain_nr(struct device_node *node); void of_pci_dma_configure(struct pci_dev *pci_dev); +void of_pci_check_probe_only(void); #else static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) { @@ -53,6 +54,8 @@ of_get_pci_domain_nr(struct device_node *node) } static inline void of_pci_dma_configure(struct pci_dev *pci_dev) { } + +static inline void of_pci_check_probe_only(void) { } #endif #if defined(CONFIG_OF_ADDRESS) -- cgit v1.3-6-gb490 From 93e71695daa654918fbe5b768cd8c5bca677df0c Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 17 Sep 2015 19:39:26 +0300 Subject: clk: qcom: Add MSM8916 iommu clocks Add support for the msm8916 TCU (Translation Control Unit) clocks that are needed for IOMMU. Signed-off-by: Georgi Djakov Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8916.c | 48 ++++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8916.h | 3 ++ 2 files changed, 51 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index 83871b663e21..ad9316751eb2 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -2347,6 +2347,51 @@ static struct clk_branch gcc_sdcc2_apps_clk = { }, }; +static struct clk_rcg2 bimc_ddr_clk_src = { + .cmd_rcgr = 0x32004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "bimc_ddr_clk_src", + .parent_names = gcc_xo_gpll0_bimc, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_branch gcc_apss_tcu_clk = { + .halt_reg = 0x12018, + .clkr = { + .enable_reg = 0x4500c, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_tcu_clk", + .parent_names = (const char *[]){ + "bimc_ddr_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gfx_tcu_clk = { + .halt_reg = 0x12020, + .clkr = { + .enable_reg = 0x4500c, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gfx_tcu_clk", + .parent_names = (const char *[]){ + "bimc_ddr_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_gtcu_ahb_clk = { .halt_reg = 0x12044, .clkr = { @@ -2730,6 +2775,9 @@ static struct clk_regmap *gcc_msm8916_clocks[] = { [GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr, [GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr, [GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr, + [BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr, + [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr, + [GCC_GFX_TCU_CLK] = &gcc_gfx_tcu_clk.clkr, }; static struct gdsc *gcc_msm8916_gdscs[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h index 11566c567356..9169ae656c77 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8916.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h @@ -152,6 +152,9 @@ #define GCC_VENUS0_AHB_CLK 135 #define GCC_VENUS0_AXI_CLK 136 #define GCC_VENUS0_VCODEC0_CLK 137 +#define BIMC_DDR_CLK_SRC 138 +#define GCC_APSS_TCU_CLK 139 +#define GCC_GFX_TCU_CLK 140 /* Indexes for GDSCs */ #define BIMC_GDSC 0 -- cgit v1.3-6-gb490 From a2e8272f3f898bedfc78e20b373a9d7356e16608 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 17 Sep 2015 19:39:28 +0300 Subject: clk: qcom: Add MSM8916 gpu clocks Add support for the msm8916 BIMC (Bus Integrated Memory Controller) clocks that are needed for GPU. Signed-off-by: Georgi Djakov Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8916.c | 61 ++++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8916.h | 3 ++ 2 files changed, 64 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index ad9316751eb2..bd87a3e2cbeb 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -1083,6 +1083,30 @@ static struct clk_rcg2 apss_tcu_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_bimc_gpu_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + F(200000000, P_GPLL0, 4, 0, 0), + F(266500000, P_BIMC, 4, 0, 0), + F(400000000, P_GPLL0, 2, 0, 0), + F(533000000, P_BIMC, 2, 0, 0), + { } +}; + +static struct clk_rcg2 bimc_gpu_clk_src = { + .cmd_rcgr = 0x31028, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .freq_tbl = ftbl_gcc_bimc_gpu_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "bimc_gpu_clk_src", + .parent_names = gcc_xo_gpll0_bimc, + .num_parents = 3, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_rcg2_shared_ops, + }, +}; + static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = { F(80000000, P_GPLL0, 10, 0, 0), { } @@ -2409,6 +2433,40 @@ static struct clk_branch gcc_gtcu_ahb_clk = { }, }; +static struct clk_branch gcc_bimc_gfx_clk = { + .halt_reg = 0x31024, + .clkr = { + .enable_reg = 0x31024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_bimc_gfx_clk", + .parent_names = (const char *[]){ + "bimc_gpu_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_bimc_gpu_clk = { + .halt_reg = 0x31040, + .clkr = { + .enable_reg = 0x31040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_bimc_gpu_clk", + .parent_names = (const char *[]){ + "bimc_gpu_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_jpeg_tbu_clk = { .halt_reg = 0x12034, .clkr = { @@ -2778,6 +2836,9 @@ static struct clk_regmap *gcc_msm8916_clocks[] = { [BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr, [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr, [GCC_GFX_TCU_CLK] = &gcc_gfx_tcu_clk.clkr, + [BIMC_GPU_CLK_SRC] = &bimc_gpu_clk_src.clkr, + [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr, + [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr, }; static struct gdsc *gcc_msm8916_gdscs[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h index 9169ae656c77..d21501bb3d52 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8916.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h @@ -155,6 +155,9 @@ #define BIMC_DDR_CLK_SRC 138 #define GCC_APSS_TCU_CLK 139 #define GCC_GFX_TCU_CLK 140 +#define BIMC_GPU_CLK_SRC 141 +#define GCC_BIMC_GFX_CLK 142 +#define GCC_BIMC_GPU_CLK 143 /* Indexes for GDSCs */ #define BIMC_GDSC 0 -- cgit v1.3-6-gb490 From 7001b3f960c66a7f3617da632564b35ddba39498 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 17 Sep 2015 19:39:29 +0300 Subject: clk: qcom: Add MSM8916 audio clocks Add support for the msm8916 audio clocks. This includes core bus, low-power audio and codec clocks. They are required for audio playback. Signed-off-by: Georgi Djakov Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8916.c | 388 +++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8916.h | 16 ++ 2 files changed, 404 insertions(+) (limited to 'include') diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index bd87a3e2cbeb..f7aff814368a 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -45,6 +45,9 @@ enum { P_SLEEP_CLK, P_DSI0_PHYPLL_BYTE, P_DSI0_PHYPLL_DSI, + P_EXT_PRI_I2S, + P_EXT_SEC_I2S, + P_EXT_MCLK, }; static const struct parent_map gcc_xo_gpll0_map[] = { @@ -191,6 +194,76 @@ static const char * const gcc_xo_gpll0a_gpll1_gpll2[] = { "gpll2_vote", }; +static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1, 2 }, + { P_SLEEP_CLK, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll1_sleep[] = { + "xo", + "gpll0_vote", + "gpll1_vote", + "sleep_clk", +}; + +static const struct parent_map gcc_xo_gpll1_epi2s_emclk_sleep_map[] = { + { P_XO, 0 }, + { P_GPLL1, 1 }, + { P_EXT_PRI_I2S, 2 }, + { P_EXT_MCLK, 3 }, + { P_SLEEP_CLK, 6 } +}; + +static const char * const gcc_xo_gpll1_epi2s_emclk_sleep[] = { + "xo", + "gpll1_vote", + "ext_pri_i2s", + "ext_mclk", + "sleep_clk", +}; + +static const struct parent_map gcc_xo_gpll1_esi2s_emclk_sleep_map[] = { + { P_XO, 0 }, + { P_GPLL1, 1 }, + { P_EXT_SEC_I2S, 2 }, + { P_EXT_MCLK, 3 }, + { P_SLEEP_CLK, 6 } +}; + +static const char * const gcc_xo_gpll1_esi2s_emclk_sleep[] = { + "xo", + "gpll1_vote", + "ext_sec_i2s", + "ext_mclk", + "sleep_clk", +}; + +static const struct parent_map gcc_xo_sleep_map[] = { + { P_XO, 0 }, + { P_SLEEP_CLK, 6 } +}; + +static const char * const gcc_xo_sleep[] = { + "xo", + "sleep_clk", +}; + +static const struct parent_map gcc_xo_gpll1_emclk_sleep_map[] = { + { P_XO, 0 }, + { P_GPLL1, 1 }, + { P_EXT_MCLK, 2 }, + { P_SLEEP_CLK, 6 } +}; + +static const char * const gcc_xo_gpll1_emclk_sleep[] = { + "xo", + "gpll1_vote", + "ext_mclk", + "sleep_clk", +}; + #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } static struct clk_pll gpll0 = { @@ -1125,6 +1198,305 @@ static struct clk_rcg2 usb_hs_system_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_ultaudio_ahb_clk[] = { + F(3200000, P_XO, 6, 0, 0), + F(6400000, P_XO, 3, 0, 0), + F(9600000, P_XO, 2, 0, 0), + F(19200000, P_XO, 1, 0, 0), + F(40000000, P_GPLL0, 10, 1, 2), + F(66670000, P_GPLL0, 12, 0, 0), + F(80000000, P_GPLL0, 10, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + { } +}; + +static struct clk_rcg2 ultaudio_ahbfabric_clk_src = { + .cmd_rcgr = 0x1c010, + .hid_width = 5, + .mnd_width = 8, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_ultaudio_ahb_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ultaudio_ahbfabric_clk_src", + .parent_names = gcc_xo_gpll0_gpll1_sleep, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_clk = { + .halt_reg = 0x1c028, + .clkr = { + .enable_reg = 0x1c028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_ahbfabric_ixfabric_clk", + .parent_names = (const char *[]){ + "ultaudio_ahbfabric_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_lpm_clk = { + .halt_reg = 0x1c024, + .clkr = { + .enable_reg = 0x1c024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_ahbfabric_ixfabric_lpm_clk", + .parent_names = (const char *[]){ + "ultaudio_ahbfabric_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_ultaudio_lpaif_i2s_clk[] = { + F(256000, P_XO, 5, 1, 15), + F(512000, P_XO, 5, 2, 15), + F(705600, P_GPLL1, 16, 1, 80), + F(768000, P_XO, 5, 1, 5), + F(800000, P_XO, 5, 5, 24), + F(1024000, P_GPLL1, 14, 1, 63), + F(1152000, P_XO, 1, 3, 50), + F(1411200, P_GPLL1, 16, 1, 40), + F(1536000, P_XO, 1, 2, 25), + F(1600000, P_XO, 12, 0, 0), + F(2048000, P_GPLL1, 9, 1, 49), + F(2400000, P_XO, 8, 0, 0), + F(2822400, P_GPLL1, 16, 1, 20), + F(3072000, P_GPLL1, 14, 1, 21), + F(4096000, P_GPLL1, 9, 2, 49), + F(4800000, P_XO, 4, 0, 0), + F(5644800, P_GPLL1, 16, 1, 10), + F(6144000, P_GPLL1, 7, 1, 21), + F(8192000, P_GPLL1, 9, 4, 49), + F(9600000, P_XO, 2, 0, 0), + F(11289600, P_GPLL1, 16, 1, 5), + F(12288000, P_GPLL1, 7, 2, 21), + { } +}; + +static struct clk_rcg2 ultaudio_lpaif_pri_i2s_clk_src = { + .cmd_rcgr = 0x1c054, + .hid_width = 5, + .mnd_width = 8, + .parent_map = gcc_xo_gpll1_epi2s_emclk_sleep_map, + .freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ultaudio_lpaif_pri_i2s_clk_src", + .parent_names = gcc_xo_gpll1_epi2s_emclk_sleep, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ultaudio_lpaif_pri_i2s_clk = { + .halt_reg = 0x1c068, + .clkr = { + .enable_reg = 0x1c068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_lpaif_pri_i2s_clk", + .parent_names = (const char *[]){ + "ultaudio_lpaif_pri_i2s_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_rcg2 ultaudio_lpaif_sec_i2s_clk_src = { + .cmd_rcgr = 0x1c06c, + .hid_width = 5, + .mnd_width = 8, + .parent_map = gcc_xo_gpll1_esi2s_emclk_sleep_map, + .freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ultaudio_lpaif_sec_i2s_clk_src", + .parent_names = gcc_xo_gpll1_esi2s_emclk_sleep, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ultaudio_lpaif_sec_i2s_clk = { + .halt_reg = 0x1c080, + .clkr = { + .enable_reg = 0x1c080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_lpaif_sec_i2s_clk", + .parent_names = (const char *[]){ + "ultaudio_lpaif_sec_i2s_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_rcg2 ultaudio_lpaif_aux_i2s_clk_src = { + .cmd_rcgr = 0x1c084, + .hid_width = 5, + .mnd_width = 8, + .parent_map = gcc_xo_gpll1_emclk_sleep_map, + .freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ultaudio_lpaif_aux_i2s_clk_src", + .parent_names = gcc_xo_gpll1_esi2s_emclk_sleep, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ultaudio_lpaif_aux_i2s_clk = { + .halt_reg = 0x1c098, + .clkr = { + .enable_reg = 0x1c098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_lpaif_aux_i2s_clk", + .parent_names = (const char *[]){ + "ultaudio_lpaif_aux_i2s_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_ultaudio_xo_clk[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 ultaudio_xo_clk_src = { + .cmd_rcgr = 0x1c034, + .hid_width = 5, + .parent_map = gcc_xo_sleep_map, + .freq_tbl = ftbl_gcc_ultaudio_xo_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ultaudio_xo_clk_src", + .parent_names = gcc_xo_sleep, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ultaudio_avsync_xo_clk = { + .halt_reg = 0x1c04c, + .clkr = { + .enable_reg = 0x1c04c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_avsync_xo_clk", + .parent_names = (const char *[]){ + "ultaudio_xo_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ultaudio_stc_xo_clk = { + .halt_reg = 0x1c050, + .clkr = { + .enable_reg = 0x1c050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_stc_xo_clk", + .parent_names = (const char *[]){ + "ultaudio_xo_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_codec_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(11289600, P_EXT_MCLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 codec_digcodec_clk_src = { + .cmd_rcgr = 0x1c09c, + .hid_width = 5, + .parent_map = gcc_xo_gpll1_emclk_sleep_map, + .freq_tbl = ftbl_codec_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "codec_digcodec_clk_src", + .parent_names = gcc_xo_gpll1_emclk_sleep, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_codec_digcodec_clk = { + .halt_reg = 0x1c0b0, + .clkr = { + .enable_reg = 0x1c0b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_codec_digcodec_clk", + .parent_names = (const char *[]){ + "codec_digcodec_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ultaudio_pcnoc_mport_clk = { + .halt_reg = 0x1c000, + .clkr = { + .enable_reg = 0x1c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_pcnoc_mport_clk", + .parent_names = (const char *[]){ + "pcnoc_bfdcd_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ultaudio_pcnoc_sway_clk = { + .halt_reg = 0x1c004, + .clkr = { + .enable_reg = 0x1c004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ultaudio_pcnoc_sway_clk", + .parent_names = (const char *[]){ + "pcnoc_bfdcd_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = { F(100000000, P_GPLL0, 8, 0, 0), F(160000000, P_GPLL0, 5, 0, 0), @@ -2839,6 +3211,22 @@ static struct clk_regmap *gcc_msm8916_clocks[] = { [BIMC_GPU_CLK_SRC] = &bimc_gpu_clk_src.clkr, [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr, [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr, + [ULTAUDIO_AHBFABRIC_CLK_SRC] = &ultaudio_ahbfabric_clk_src.clkr, + [ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC] = &ultaudio_lpaif_pri_i2s_clk_src.clkr, + [ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC] = &ultaudio_lpaif_sec_i2s_clk_src.clkr, + [ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC] = &ultaudio_lpaif_aux_i2s_clk_src.clkr, + [ULTAUDIO_XO_CLK_SRC] = &ultaudio_xo_clk_src.clkr, + [CODEC_DIGCODEC_CLK_SRC] = &codec_digcodec_clk_src.clkr, + [GCC_ULTAUDIO_PCNOC_MPORT_CLK] = &gcc_ultaudio_pcnoc_mport_clk.clkr, + [GCC_ULTAUDIO_PCNOC_SWAY_CLK] = &gcc_ultaudio_pcnoc_sway_clk.clkr, + [GCC_ULTAUDIO_AVSYNC_XO_CLK] = &gcc_ultaudio_avsync_xo_clk.clkr, + [GCC_ULTAUDIO_STC_XO_CLK] = &gcc_ultaudio_stc_xo_clk.clkr, + [GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_clk.clkr, + [GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_lpm_clk.clkr, + [GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK] = &gcc_ultaudio_lpaif_pri_i2s_clk.clkr, + [GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK] = &gcc_ultaudio_lpaif_sec_i2s_clk.clkr, + [GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK] = &gcc_ultaudio_lpaif_aux_i2s_clk.clkr, + [GCC_CODEC_DIGCODEC_CLK] = &gcc_codec_digcodec_clk.clkr, }; static struct gdsc *gcc_msm8916_gdscs[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h index d21501bb3d52..257e2fbedd94 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8916.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h @@ -158,6 +158,22 @@ #define BIMC_GPU_CLK_SRC 141 #define GCC_BIMC_GFX_CLK 142 #define GCC_BIMC_GPU_CLK 143 +#define ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC 144 +#define ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC 145 +#define ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC 146 +#define ULTAUDIO_XO_CLK_SRC 147 +#define ULTAUDIO_AHBFABRIC_CLK_SRC 148 +#define CODEC_DIGCODEC_CLK_SRC 149 +#define GCC_ULTAUDIO_PCNOC_MPORT_CLK 150 +#define GCC_ULTAUDIO_PCNOC_SWAY_CLK 151 +#define GCC_ULTAUDIO_AVSYNC_XO_CLK 152 +#define GCC_ULTAUDIO_STC_XO_CLK 153 +#define GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK 154 +#define GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK 155 +#define GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK 156 +#define GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK 157 +#define GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK 158 +#define GCC_CODEC_DIGCODEC_CLK 159 /* Indexes for GDSCs */ #define BIMC_GDSC 0 -- cgit v1.3-6-gb490 From fb884253a919148677c5bf347ffb62c539370440 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:03:49 -0500 Subject: netfilter: Remove !CONFIG_NETFITLER definition of nf_hook_thresh The !CONFIG_NETFILTER definition of nf_hook_thresh calls okfn when the CONFIG_NETFITLER defintion does not, making it buggy. As the !CONFIG_NETFILTER defintion of nf_hook_thresh is not used remove it rather than fix it. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netfilter.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 36a652531791..1abac85ec907 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -344,15 +344,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, sk, skb, indev, outdev, okfn) (okfn)(sk, skb) #define NF_HOOK_COND(pf, hook, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb) -static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, - struct sock *sk, - struct sk_buff *skb, - struct net_device *indev, - struct net_device *outdev, - int (*okfn)(struct sock *sk, struct sk_buff *), int thresh) -{ - return okfn(sk, skb); -} static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, -- cgit v1.3-6-gb490 From b11b1f652dccde707d568f4012b01a8ec5bd5f57 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:03:50 -0500 Subject: netfilter: Store net in nf_hook_state Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netfilter.h | 5 ++++- include/linux/netfilter_ingress.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 1abac85ec907..889ac0e11f01 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -54,6 +54,7 @@ struct nf_hook_state { struct net_device *in; struct net_device *out; struct sock *sk; + struct net *net; struct list_head *hook_list; int (*okfn)(struct sock *, struct sk_buff *); }; @@ -65,6 +66,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p, struct net_device *indev, struct net_device *outdev, struct sock *sk, + struct net *net, int (*okfn)(struct sock *, struct sk_buff *)) { p->hook = hook; @@ -73,6 +75,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p, p->in = indev; p->out = outdev; p->sk = sk; + p->net = net; p->hook_list = hook_list; p->okfn = okfn; } @@ -181,7 +184,7 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, struct nf_hook_state state; nf_hook_state_init(&state, hook_list, hook, thresh, - pf, indev, outdev, sk, okfn); + pf, indev, outdev, sk, net, okfn); return nf_hook_slow(skb, &state); } return 1; diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_ingress.h index cb0727fe2b3d..187feabe557c 100644 --- a/include/linux/netfilter_ingress.h +++ b/include/linux/netfilter_ingress.h @@ -17,7 +17,7 @@ static inline int nf_hook_ingress(struct sk_buff *skb) nf_hook_state_init(&state, &skb->dev->nf_hooks_ingress, NF_NETDEV_INGRESS, INT_MIN, NFPROTO_NETDEV, NULL, - skb->dev, NULL, NULL); + skb->dev, NULL, dev_net(skb->dev), NULL); return nf_hook_slow(skb, &state); } -- cgit v1.3-6-gb490 From 7a7735044e1eab1415697b3139e758d24a600099 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:03:51 -0500 Subject: netfilter: Pass net to nf_hook_thresh Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netfilter.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 889ac0e11f01..042148dc1e22 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -170,6 +170,7 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state); * value indicates the packet has been consumed by the hook. */ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, + struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *indev, @@ -177,7 +178,6 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, int (*okfn)(struct sock *, struct sk_buff *), int thresh) { - struct net *net = dev_net(indev ? indev : outdev); struct list_head *hook_list = &net->nf.hooks[pf][hook]; if (nf_hook_list_active(hook_list, pf, hook)) { @@ -195,7 +195,8 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk, struct net_device *outdev, int (*okfn)(struct sock *, struct sk_buff *)) { - return nf_hook_thresh(pf, hook, sk, skb, indev, outdev, okfn, INT_MIN); + struct net *net = dev_net(indev ? indev : outdev); + return nf_hook_thresh(pf, hook, net, sk, skb, indev, outdev, okfn, INT_MIN); } /* Activate hook; either okfn or kfree_skb called, unless a hook @@ -221,7 +222,8 @@ NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sock *sk, struct net_device *out, int (*okfn)(struct sock *, struct sk_buff *), int thresh) { - int ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, thresh); + struct net *net = dev_net(in ? in : out); + int ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, thresh); if (ret == 1) ret = okfn(sk, skb); return ret; @@ -232,10 +234,11 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct sock *, struct sk_buff *), bool cond) { + struct net *net = dev_net(in ? in : out); int ret; if (!cond || - ((ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, INT_MIN)) == 1)) + ((ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, INT_MIN)) == 1)) ret = okfn(sk, skb); return ret; } -- cgit v1.3-6-gb490 From a6568b2425daffc7b21ae63b6601b57ae14b5cb8 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:03:52 -0500 Subject: xfrm: Remove unused afinfo method init_dst Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 -- net/xfrm/xfrm_policy.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 312e3fee9ccf..fd176106909a 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -296,8 +296,6 @@ struct xfrm_policy_afinfo { struct flowi *fl, int reverse); int (*get_tos)(const struct flowi *fl); - void (*init_dst)(struct net *net, - struct xfrm_dst *dst); int (*init_path)(struct xfrm_dst *path, struct dst_entry *dst, int nfheader_len); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 94af3d065785..6b5d6e2b9a49 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1583,8 +1583,6 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); xdst->flo.ops = &xfrm_bundle_fc_ops; - if (afinfo->init_dst) - afinfo->init_dst(net, xdst); } else xdst = ERR_PTR(-ENOBUFS); -- cgit v1.3-6-gb490 From 5a70649e0dae02ba5090540fffce667d2300bc5a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:03:53 -0500 Subject: net: Merge dst_output and dst_output_sk Add a sock paramter to dst_output making dst_output_sk superfluous. Add a skb->sk parameter to all of the callers of dst_output Have the callers of dst_output_sk call dst_output. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/net/dst.h | 6 +----- net/decnet/dn_nsp_out.c | 4 ++-- net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_output.c | 6 +++--- net/ipv4/ip_vti.c | 2 +- net/ipv4/ipmr.c | 2 +- net/ipv4/raw.c | 2 +- net/ipv4/xfrm4_output.c | 2 +- net/ipv6/ip6_output.c | 4 ++-- net/ipv6/ip6_vti.c | 2 +- net/ipv6/ip6mr.c | 2 +- net/ipv6/mcast.c | 4 ++-- net/ipv6/ndisc.c | 2 +- net/ipv6/output_core.c | 4 ++-- net/ipv6/raw.c | 2 +- net/ipv6/xfrm6_output.c | 2 +- net/netfilter/ipvs/ip_vs_xmit.c | 4 ++-- net/xfrm/xfrm_output.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- 19 files changed, 26 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/include/net/dst.h b/include/net/dst.h index 9261d928303d..c72e58474e52 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -454,14 +454,10 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout) } /* Output packet to network from transport. */ -static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb) +static inline int dst_output(struct sock *sk, struct sk_buff *skb) { return skb_dst(skb)->output(sk, skb); } -static inline int dst_output(struct sk_buff *skb) -{ - return dst_output_sk(skb->sk, skb); -} /* Input packet from network to transport. */ static inline int dst_input(struct sk_buff *skb) diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index 1aaa51ebbda6..4b02dd300f50 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -85,7 +85,7 @@ static void dn_nsp_send(struct sk_buff *skb) if (dst) { try_again: skb_dst_set(skb, dst); - dst_output(skb); + dst_output(skb->sk, skb); return; } @@ -582,7 +582,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, * associations. */ skb_dst_set(skb, dst_clone(dst)); - dst_output(skb); + dst_output(skb->sk, skb); } diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 2d3aa408fbdc..28fb90108f56 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -72,7 +72,7 @@ static int ip_forward_finish(struct sock *sk, struct sk_buff *skb) ip_forward_options(skb); skb_sender_cpu_clear(skb); - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } int ip_forward(struct sk_buff *skb) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 0138fada0951..f076f11aa94a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -102,7 +102,7 @@ static int __ip_local_out_sk(struct sock *sk, struct sk_buff *skb) iph->tot_len = htons(skb->len); ip_send_check(iph); return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb, NULL, - skb_dst(skb)->dev, dst_output_sk); + skb_dst(skb)->dev, dst_output); } int __ip_local_out(struct sk_buff *skb) @@ -116,7 +116,7 @@ int ip_local_out_sk(struct sock *sk, struct sk_buff *skb) err = __ip_local_out(skb); if (likely(err == 1)) - err = dst_output_sk(sk, skb); + err = dst_output(sk, skb); return err; } @@ -271,7 +271,7 @@ static int ip_finish_output(struct sock *sk, struct sk_buff *skb) /* Policy lookup after SNAT yielded a new policy */ if (skb_dst(skb)->xfrm) { IPCB(skb)->flags |= IPSKB_REROUTED; - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } #endif mtu = ip_skb_dst_mtu(skb); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 0c152087ca15..3b87ec5178f9 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -197,7 +197,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, skb_dst_set(skb, dst); skb->dev = skb_dst(skb)->dev; - err = dst_output(skb); + err = dst_output(skb->sk, skb); if (net_xmit_eval(err) == 0) err = skb->len; iptunnel_xmit_stats(err, &dev->stats, dev->tstats); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 866ee89f5254..a0a5def920fc 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1688,7 +1688,7 @@ static inline int ipmr_forward_finish(struct sock *sk, struct sk_buff *skb) if (unlikely(opt->optlen)) ip_forward_options(skb); - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } /* diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 561cd4b8fc6e..09ab5bb6913a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -412,7 +412,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, skb_transport_header(skb))->type); err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb, - NULL, rt->dst.dev, dst_output_sk); + NULL, rt->dst.dev, dst_output); if (err > 0) err = net_xmit_errno(err); if (err) diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 2878dbfffeb7..737f5e395a6a 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -87,7 +87,7 @@ static int __xfrm4_output(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_NETFILTER if (!x) { IPCB(skb)->flags |= IPSKB_REROUTED; - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } #endif diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 26ea47930740..a80502c64523 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -225,7 +225,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUT, skb->len); return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, dst->dev, dst_output_sk); + NULL, dst->dev, dst_output); } skb->dev = dst->dev; @@ -320,7 +320,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) static inline int ip6_forward_finish(struct sock *sk, struct sk_buff *skb) { skb_sender_cpu_clear(skb); - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 0224c032dca5..f96f1c19b4a8 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -482,7 +482,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) return -EMSGSIZE; } - err = dst_output(skb); + err = dst_output(skb->sk, skb); if (net_xmit_eval(err) == 0) { struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 0e004cc42a22..e95f6b6281de 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1991,7 +1991,7 @@ static inline int ip6mr_forward2_finish(struct sock *sk, struct sk_buff *skb) IPSTATS_MIB_OUTFORWDATAGRAMS); IP6_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTOCTETS, skb->len); - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } /* diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 083b2927fc67..5b3f2841acf6 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1646,7 +1646,7 @@ static void mld_sendpack(struct sk_buff *skb) err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net->ipv6.igmp_sk, skb, NULL, skb->dev, - dst_output_sk); + dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT); @@ -2009,7 +2009,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) skb_dst_set(skb, dst); err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, skb->dev, dst_output_sk); + NULL, skb->dev, dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 64a71354b069..349ac1b022b6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -465,7 +465,7 @@ static void ndisc_send_skb(struct sk_buff *skb, err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, NULL, dst->dev, - dst_output_sk); + dst_output); if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 928a0fb0b744..8178f72fe90d 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -149,7 +149,7 @@ static int __ip6_local_out_sk(struct sock *sk, struct sk_buff *skb) IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, skb_dst(skb)->dev, dst_output_sk); + NULL, skb_dst(skb)->dev, dst_output); } int __ip6_local_out(struct sk_buff *skb) @@ -164,7 +164,7 @@ int ip6_local_out_sk(struct sock *sk, struct sk_buff *skb) err = __ip6_local_out_sk(sk, skb); if (likely(err == 1)) - err = dst_output_sk(sk, skb); + err = dst_output(sk, skb); return err; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index fdbada1569a3..1636537705f5 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -654,7 +654,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, rt->dst.dev, dst_output_sk); + NULL, rt->dst.dev, dst_output); if (err > 0) err = net_xmit_errno(err); if (err) diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 09c76a7b474d..b0fcd6c09837 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -140,7 +140,7 @@ static int __xfrm6_output(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_NETFILTER if (!x) { IP6CB(skb)->flags |= IP6SKB_REROUTED; - return dst_output_sk(sk, skb); + return dst_output(sk, skb); } #endif diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 258a0b0e82a2..b8e5544af87f 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -574,7 +574,7 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, if (!skb->sk) skb_sender_cpu_clear(skb); NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, - NULL, skb_dst(skb)->dev, dst_output_sk); + NULL, skb_dst(skb)->dev, dst_output); } else ret = NF_ACCEPT; @@ -596,7 +596,7 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb, if (!skb->sk) skb_sender_cpu_clear(skb); NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, - NULL, skb_dst(skb)->dev, dst_output_sk); + NULL, skb_dst(skb)->dev, dst_output); } else ret = NF_ACCEPT; return ret; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 68ada2ca4b60..57a50f6ce28c 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -139,7 +139,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err) goto out; if (!skb_dst(skb)->xfrm) - return dst_output(skb); + return dst_output(skb->sk, skb); err = nf_hook(skb_dst(skb)->ops->family, NF_INET_POST_ROUTING, skb->sk, skb, diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 6b5d6e2b9a49..e7f64bcb78a8 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1945,7 +1945,7 @@ static void xfrm_policy_queue_process(unsigned long arg) skb_dst_drop(skb); skb_dst_set(skb, dst); - dst_output(skb); + dst_output(skb->sk, skb); } out: -- cgit v1.3-6-gb490 From 2b4aa3cec4873005a0d5155395b34641584b3a4e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:04:07 -0500 Subject: net: Remove dev_queue_xmit_sk A function with weird arguments that it will never use to accomdate a netfilter callback prototype is absolutely in the core of the networking stack. Frankly it does not make sense and it causes a lot of confusion as to why arguments that are never used are being passed to the function. As I am preparing to make a second change to arguments to the okfn even the names stops making sense. As I have removed the two callers of this function remove this confusion from the networking stack. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 +----- net/core/dev.c | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 88a00694eda5..e664f87c8e4c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2213,11 +2213,7 @@ int dev_close(struct net_device *dev); int dev_close_many(struct list_head *head, bool unlink); void dev_disable_lro(struct net_device *dev); int dev_loopback_xmit(struct sock *sk, struct sk_buff *newskb); -int dev_queue_xmit_sk(struct sock *sk, struct sk_buff *skb); -static inline int dev_queue_xmit(struct sk_buff *skb) -{ - return dev_queue_xmit_sk(skb->sk, skb); -} +int dev_queue_xmit(struct sk_buff *skb); int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv); int register_netdevice(struct net_device *dev); void unregister_netdevice_queue(struct net_device *dev, struct list_head *head); diff --git a/net/core/dev.c b/net/core/dev.c index 877c84834d81..dcf9ff913925 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3143,11 +3143,11 @@ out: return rc; } -int dev_queue_xmit_sk(struct sock *sk, struct sk_buff *skb) +int dev_queue_xmit(struct sk_buff *skb) { return __dev_queue_xmit(skb, NULL); } -EXPORT_SYMBOL(dev_queue_xmit_sk); +EXPORT_SYMBOL(dev_queue_xmit); int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv) { -- cgit v1.3-6-gb490 From 04eb44890e5bb3cc855e5c0f18a05eb7311364b7 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:04:15 -0500 Subject: bridge: Add br_netif_receive_skb remove netif_receive_skb_sk netif_receive_skb_sk is only called once in the bridge code, replace it with a bridge specific function that calls netif_receive_skb. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 +----- net/bridge/br_input.c | 7 ++++++- net/core/dev.c | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e664f87c8e4c..97ab5c9a7069 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2985,11 +2985,7 @@ static inline void dev_consume_skb_any(struct sk_buff *skb) int netif_rx(struct sk_buff *skb); int netif_rx_ni(struct sk_buff *skb); -int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb); -static inline int netif_receive_skb(struct sk_buff *skb) -{ - return netif_receive_skb_sk(skb->sk, skb); -} +int netif_receive_skb(struct sk_buff *skb); gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); void napi_gro_flush(struct napi_struct *napi, bool flush_old); struct sk_buff *napi_get_frags(struct napi_struct *napi); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index f921a5dce22d..2359c041e27c 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -26,6 +26,11 @@ br_should_route_hook_t __rcu *br_should_route_hook __read_mostly; EXPORT_SYMBOL(br_should_route_hook); +static int br_netif_receive_skb(struct sock *sk, struct sk_buff *skb) +{ + return netif_receive_skb(skb); +} + static int br_pass_frame_up(struct sk_buff *skb) { struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; @@ -57,7 +62,7 @@ static int br_pass_frame_up(struct sk_buff *skb) return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, NULL, skb, indev, NULL, - netif_receive_skb_sk); + br_netif_receive_skb); } static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br, diff --git a/net/core/dev.c b/net/core/dev.c index dcf9ff913925..7db9b012dfb7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3982,13 +3982,13 @@ static int netif_receive_skb_internal(struct sk_buff *skb) * NET_RX_SUCCESS: no congestion * NET_RX_DROP: packet was dropped */ -int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb) +int netif_receive_skb(struct sk_buff *skb) { trace_netif_receive_skb_entry(skb); return netif_receive_skb_internal(skb); } -EXPORT_SYMBOL(netif_receive_skb_sk); +EXPORT_SYMBOL(netif_receive_skb); /* Network device is going away, flush any packets still pending * Called with irqs disabled. -- cgit v1.3-6-gb490 From 29a26a56803855a79dbd028cd61abee56237d6e5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:04:16 -0500 Subject: netfilter: Pass struct net into the netfilter hooks Pass a network namespace parameter into the netfilter hooks. At the call site of the netfilter hooks the path a packet is taking through the network stack is well known which allows the network namespace to be easily and reliabily. This allows the replacement of magic code like "dev_net(state->in?:state->out)" that appears at the start of most netfilter hooks with "state->net". In almost all cases the network namespace passed in is derived from the first network device passed in, guaranteeing those paths will not see any changes in practice. The exceptions are: xfrm/xfrm_output.c:xfrm_output_resume() xs_net(skb_dst(skb)->xfrm) ipvs/ip_vs_xmit.c:ip_vs_nat_send_or_cont() ip_vs_conn_net(cp) ipvs/ip_vs_xmit.c:ip_vs_send_or_cont() ip_vs_conn_net(cp) ipv4/raw.c:raw_send_hdrinc() sock_net(sk) ipv6/ip6_output.c:ip6_xmit() sock_net(sk) ipv6/ndisc.c:ndisc_send_skb() dev_net(skb->dev) not dev_net(dst->dev) ipv6/raw.c:raw6_send_hdrinc() sock_net(sk) br_netfilter_hooks.c:br_nf_pre_routing_finish() dev_net(skb->dev) before skb->dev is set to nf_bridge->physindev In all cases these exceptions seem to be a better expression for the network namespace the packet is being processed in then the historic "dev_net(in?in:out)". I am documenting them in case something odd pops up and someone starts trying to track down what happened. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 7 ++++--- include/linux/netfilter.h | 27 ++++++++++++--------------- net/bridge/br_forward.c | 13 +++++++------ net/bridge/br_input.c | 13 +++++++------ net/bridge/br_multicast.c | 4 ++-- net/bridge/br_netfilter_hooks.c | 15 ++++++++------- net/bridge/br_netfilter_ipv6.c | 7 ++++--- net/bridge/br_stp_bpdu.c | 4 ++-- net/decnet/dn_neigh.c | 15 +++++++++------ net/decnet/dn_nsp_in.c | 4 ++-- net/decnet/dn_route.c | 24 ++++++++++++------------ net/ipv4/arp.c | 10 ++++++---- net/ipv4/ip_forward.c | 5 +++-- net/ipv4/ip_input.c | 8 ++++---- net/ipv4/ip_output.c | 22 +++++++++++++--------- net/ipv4/ipmr.c | 4 ++-- net/ipv4/raw.c | 5 +++-- net/ipv4/xfrm4_input.c | 4 ++-- net/ipv4/xfrm4_output.c | 6 ++++-- net/ipv6/ip6_input.c | 8 ++++---- net/ipv6/ip6_output.c | 15 ++++++++------- net/ipv6/ip6mr.c | 4 ++-- net/ipv6/mcast.c | 7 ++++--- net/ipv6/ndisc.c | 4 ++-- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 2 +- net/ipv6/output_core.c | 6 ++++-- net/ipv6/raw.c | 2 +- net/ipv6/xfrm6_input.c | 4 ++-- net/ipv6/xfrm6_output.c | 6 ++++-- net/netfilter/ipvs/ip_vs_xmit.c | 4 ++-- net/xfrm/xfrm_output.c | 3 ++- 31 files changed, 142 insertions(+), 120 deletions(-) (limited to 'include') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 8c9ab5ebea23..979a4db9c6bc 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -298,14 +298,15 @@ err: static int vrf_output(struct sock *sk, struct sk_buff *skb) { struct net_device *dev = skb_dst(skb)->dev; + struct net *net = dev_net(dev); - IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); + IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len); skb->dev = dev; skb->protocol = htons(ETH_P_IP); - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb, - NULL, dev, + return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, skb, NULL, dev, vrf_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 042148dc1e22..295f2650b5dc 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -190,12 +190,11 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, return 1; } -static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk, - struct sk_buff *skb, struct net_device *indev, - struct net_device *outdev, +static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, + struct sock *sk, struct sk_buff *skb, + struct net_device *indev, struct net_device *outdev, int (*okfn)(struct sock *, struct sk_buff *)) { - struct net *net = dev_net(indev ? indev : outdev); return nf_hook_thresh(pf, hook, net, sk, skb, indev, outdev, okfn, INT_MIN); } @@ -217,12 +216,11 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk, */ static inline int -NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sock *sk, +NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct sock *, struct sk_buff *), int thresh) { - struct net *net = dev_net(in ? in : out); int ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, thresh); if (ret == 1) ret = okfn(sk, skb); @@ -230,11 +228,10 @@ NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sock *sk, } static inline int -NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sock *sk, +NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct sock *, struct sk_buff *), bool cond) { - struct net *net = dev_net(in ? in : out); int ret; if (!cond || @@ -244,11 +241,11 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sock *sk, } static inline int -NF_HOOK(uint8_t pf, unsigned int hook, struct sock *sk, struct sk_buff *skb, +NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct sock *, struct sk_buff *)) { - return NF_HOOK_THRESH(pf, hook, sk, skb, in, out, okfn, INT_MIN); + return NF_HOOK_THRESH(pf, hook, net, sk, skb, in, out, okfn, INT_MIN); } /* Call setsockopt() */ @@ -348,11 +345,11 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) } #else /* !CONFIG_NETFILTER */ -#define NF_HOOK(pf, hook, sk, skb, indev, outdev, okfn) (okfn)(sk, skb) -#define NF_HOOK_COND(pf, hook, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb) -static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk, - struct sk_buff *skb, struct net_device *indev, - struct net_device *outdev, +#define NF_HOOK(pf, hook, net, sk, skb, indev, outdev, okfn) (okfn)(sk, skb) +#define NF_HOOK_COND(pf, hook, net, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb) +static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, + struct sock *sk, struct sk_buff *skb, + struct net_device *indev, struct net_device *outdev, int (*okfn)(struct sock *, struct sk_buff *)) { return 1; diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index fa7bfced888e..2dd2a23ce707 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -67,8 +67,9 @@ EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit); int br_forward_finish(struct sock *sk, struct sk_buff *skb) { - return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, sk, skb, - NULL, skb->dev, + struct net *net = dev_net(skb->dev); + return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, + net, sk, skb, NULL, skb->dev, br_dev_queue_push_xmit); } @@ -92,8 +93,8 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) return; } - NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, NULL, skb, - NULL, skb->dev, + NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, + dev_net(skb->dev), NULL, skb,NULL, skb->dev, br_forward_finish); } @@ -114,8 +115,8 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) skb->dev = to->dev; skb_forward_csum(skb); - NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, NULL, skb, - indev, skb->dev, + NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, + dev_net(indev), NULL, skb, indev, skb->dev, br_forward_finish); } diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 2359c041e27c..78fa7acd836e 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -60,8 +60,8 @@ static int br_pass_frame_up(struct sk_buff *skb) if (!skb) return NET_RX_DROP; - return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, NULL, skb, - indev, NULL, + return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, + dev_net(indev), NULL, skb, indev, NULL, br_netif_receive_skb); } @@ -283,8 +283,9 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) } /* Deliver packet to local host only */ - if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, NULL, skb, - skb->dev, NULL, br_handle_local_finish)) { + if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, + br_handle_local_finish)) { return RX_HANDLER_CONSUMED; /* consumed by filter */ } else { *pskb = skb; @@ -308,8 +309,8 @@ forward: if (ether_addr_equal(p->br->dev->dev_addr, dest)) skb->pkt_type = PACKET_HOST; - NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, NULL, skb, - skb->dev, NULL, + NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, br_handle_frame_finish); break; default: diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 66efdc21f548..b4d858a18eb6 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -829,8 +829,8 @@ static void __br_multicast_send_query(struct net_bridge *br, if (port) { skb->dev = port->dev; - NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, NULL, skb, - NULL, skb->dev, + NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, + dev_net(port->dev), NULL, skb, NULL, skb->dev, br_dev_queue_push_xmit); } else { br_multicast_select_own_querier(br, ip, skb); diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index c1127908e23a..7886c9d7e23d 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -394,7 +394,7 @@ bridged_dnat: nf_bridge_push_encap_header(skb); NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, - sk, skb, skb->dev, NULL, + net, sk, skb, skb->dev, NULL, br_nf_pre_routing_finish_bridge, 1); return 0; @@ -414,7 +414,7 @@ bridged_dnat: skb->dev = nf_bridge->physindev; nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, sk, skb, + NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, net, sk, skb, skb->dev, NULL, br_handle_frame_finish, 1); @@ -512,7 +512,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, skb->protocol = htons(ETH_P_IP); - NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, + NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb, skb->dev, NULL, br_nf_pre_routing_finish); @@ -539,6 +539,7 @@ static unsigned int br_nf_local_in(const struct nf_hook_ops *ops, static int br_nf_forward_finish(struct sock *sk, struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); + struct net *net = dev_net(skb->dev); struct net_device *in; if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) { @@ -560,7 +561,7 @@ static int br_nf_forward_finish(struct sock *sk, struct sk_buff *skb) } nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_FORWARD, sk, skb, + NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_FORWARD, net, sk, skb, in, skb->dev, br_forward_finish, 1); return 0; } @@ -627,7 +628,7 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops, else skb->protocol = htons(ETH_P_IPV6); - NF_HOOK(pf, NF_INET_FORWARD, NULL, skb, + NF_HOOK(pf, NF_INET_FORWARD, state->net, NULL, skb, brnf_get_logical_dev(skb, state->in), parent, br_nf_forward_finish); @@ -662,7 +663,7 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops, return NF_ACCEPT; } *d = state->in; - NF_HOOK(NFPROTO_ARP, NF_ARP_FORWARD, state->sk, skb, + NF_HOOK(NFPROTO_ARP, NF_ARP_FORWARD, state->net, state->sk, skb, state->in, state->out, br_nf_forward_finish); return NF_STOLEN; @@ -842,7 +843,7 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops, else skb->protocol = htons(ETH_P_IPV6); - NF_HOOK(pf, NF_INET_POST_ROUTING, state->sk, skb, + NF_HOOK(pf, NF_INET_POST_ROUTING, state->net, state->sk, skb, NULL, realoutdev, br_nf_dev_queue_xmit); diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c index 77383bfe7ea3..5d19361ad5d3 100644 --- a/net/bridge/br_netfilter_ipv6.c +++ b/net/bridge/br_netfilter_ipv6.c @@ -166,6 +166,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); struct rtable *rt; struct net_device *dev = skb->dev; + struct net *net = dev_net(dev); const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops(); nf_bridge->frag_max_size = IP6CB(skb)->frag_max_size; @@ -189,7 +190,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, - sk, skb, skb->dev, NULL, + net, sk, skb, skb->dev, NULL, br_nf_pre_routing_finish_bridge, 1); return 0; @@ -208,7 +209,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) skb->dev = nf_bridge->physindev; nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, sk, skb, + NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, net, sk, skb, skb->dev, NULL, br_handle_frame_finish, 1); @@ -237,7 +238,7 @@ unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; skb->protocol = htons(ETH_P_IPV6); - NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->sk, skb, + NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->net, state->sk, skb, skb->dev, NULL, br_nf_pre_routing_finish_ipv6); diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 3017a396cdef..8e2e8c352198 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -59,8 +59,8 @@ static void br_send_bpdu(struct net_bridge_port *p, skb_reset_mac_header(skb); - NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, NULL, skb, - NULL, skb->dev, + NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, + dev_net(p->dev), NULL, skb, NULL, skb->dev, br_send_bpdu_finish); } diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 4507b188fc51..305ab2fe25cd 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -246,8 +246,9 @@ static int dn_long_output(struct neighbour *neigh, struct sock *sk, skb_reset_network_header(skb); - return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, sk, skb, - NULL, neigh->dev, dn_neigh_output_packet); + return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, + &init_net, sk, skb, NULL, neigh->dev, + dn_neigh_output_packet); } /* @@ -286,8 +287,9 @@ static int dn_short_output(struct neighbour *neigh, struct sock *sk, skb_reset_network_header(skb); - return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, sk, skb, - NULL, neigh->dev, dn_neigh_output_packet); + return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, + &init_net, sk, skb, NULL, neigh->dev, + dn_neigh_output_packet); } /* @@ -327,8 +329,9 @@ static int dn_phase3_output(struct neighbour *neigh, struct sock *sk, skb_reset_network_header(skb); - return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, sk, skb, - NULL, neigh->dev, dn_neigh_output_packet); + return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, + &init_net, sk, skb, NULL, neigh->dev, + dn_neigh_output_packet); } int dn_to_neigh_output(struct sock *sk, struct sk_buff *skb) diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index a321eac9fd0c..e7b0605ca34a 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -814,8 +814,8 @@ free_out: int dn_nsp_rx(struct sk_buff *skb) { - return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN, NULL, skb, - skb->dev, NULL, + return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN, + &init_net, NULL, skb, skb->dev, NULL, dn_nsp_rx_packet); } diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 03227ffd19ce..fefcd2e85ef9 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -573,8 +573,8 @@ static int dn_route_rx_long(struct sk_buff *skb) ptr++; cb->hops = *ptr++; /* Visit Count */ - return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, NULL, skb, - skb->dev, NULL, + return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, + &init_net, NULL, skb, skb->dev, NULL, dn_route_rx_packet); drop_it: @@ -601,8 +601,8 @@ static int dn_route_rx_short(struct sk_buff *skb) ptr += 2; cb->hops = *ptr & 0x3f; - return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, NULL, skb, - skb->dev, NULL, + return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, + &init_net, NULL, skb, skb->dev, NULL, dn_route_rx_packet); drop_it: @@ -706,22 +706,22 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type switch (flags & DN_RT_CNTL_MSK) { case DN_RT_PKT_HELO: return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, - NULL, skb, skb->dev, NULL, + &init_net, NULL, skb, skb->dev, NULL, dn_route_ptp_hello); case DN_RT_PKT_L1RT: case DN_RT_PKT_L2RT: return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE, - NULL, skb, skb->dev, NULL, + &init_net, NULL, skb, skb->dev, NULL, dn_route_discard); case DN_RT_PKT_ERTH: return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, - NULL, skb, skb->dev, NULL, + &init_net, NULL, skb, skb->dev, NULL, dn_neigh_router_hello); case DN_RT_PKT_EEDH: return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, - NULL, skb, skb->dev, NULL, + &init_net, NULL, skb, skb->dev, NULL, dn_neigh_endnode_hello); } } else { @@ -770,8 +770,8 @@ static int dn_output(struct sock *sk, struct sk_buff *skb) cb->rt_flags |= DN_RT_F_IE; cb->hops = 0; - return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, sk, skb, - NULL, dev, + return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, + &init_net, sk, skb, NULL, dev, dn_to_neigh_output); error: @@ -819,8 +819,8 @@ static int dn_forward(struct sk_buff *skb) if (rt->rt_flags & RTCF_DOREDIRECT) cb->rt_flags |= DN_RT_F_IE; - return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, NULL, skb, - dev, skb->dev, + return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, + &init_net, NULL, skb, dev, skb->dev, dn_to_neigh_output); drop: diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 3632e98eb0f9..ae71e9ade5f9 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -632,8 +632,9 @@ static int arp_xmit_finish(struct sock *sk, struct sk_buff *skb) void arp_xmit(struct sk_buff *skb) { /* Send it off, maybe filter it using firewalling first. */ - NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, NULL, skb, - NULL, skb->dev, arp_xmit_finish); + NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, + dev_net(skb->dev), NULL, skb, NULL, skb->dev, + arp_xmit_finish); } EXPORT_SYMBOL(arp_xmit); @@ -897,8 +898,9 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev, memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); - return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, NULL, skb, - dev, NULL, arp_process); + return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, + dev_net(dev), NULL, skb, dev, NULL, + arp_process); consumeskb: consume_skb(skb); diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 95235c813f18..0a3c45a2e757 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -146,8 +146,9 @@ int ip_forward(struct sk_buff *skb) skb->priority = rt_tos2priority(iph->tos); - return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, NULL, skb, - skb->dev, rt->dst.dev, ip_forward_finish); + return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, + net, NULL, skb, skb->dev, rt->dst.dev, + ip_forward_finish); sr_failed: /* diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index cc242b9501d9..991d082c7312 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -254,8 +254,8 @@ int ip_local_deliver(struct sk_buff *skb) return 0; } - return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, NULL, skb, - skb->dev, NULL, + return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, ip_local_deliver_finish); } @@ -453,8 +453,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, /* Must drop socket now because of tproxy. */ skb_orphan(skb); - return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, NULL, skb, - dev, NULL, + return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, + net, NULL, skb, dev, NULL, ip_rcv_finish); csum_error: diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index fc550e97daac..4c9532259a7f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -97,12 +97,14 @@ EXPORT_SYMBOL(ip_send_check); static int __ip_local_out_sk(struct sock *sk, struct sk_buff *skb) { + struct net *net = dev_net(skb_dst(skb)->dev); struct iphdr *iph = ip_hdr(skb); iph->tot_len = htons(skb->len); ip_send_check(iph); - return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb, NULL, - skb_dst(skb)->dev, dst_output); + return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, skb_dst(skb)->dev, + dst_output); } int __ip_local_out(struct sk_buff *skb) @@ -322,7 +324,7 @@ int ip_mc_output(struct sock *sk, struct sk_buff *skb) struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); if (newskb) NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, - sk, newskb, NULL, newskb->dev, + net, sk, newskb, NULL, newskb->dev, dev_loopback_xmit); } @@ -337,12 +339,14 @@ int ip_mc_output(struct sock *sk, struct sk_buff *skb) if (rt->rt_flags&RTCF_BROADCAST) { struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); if (newskb) - NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, newskb, - NULL, newskb->dev, dev_loopback_xmit); + NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, newskb, NULL, newskb->dev, + dev_loopback_xmit); } - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb, NULL, - skb->dev, ip_finish_output, + return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, skb, NULL, skb->dev, + ip_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } @@ -356,8 +360,8 @@ int ip_output(struct sock *sk, struct sk_buff *skb) skb->dev = dev; skb->protocol = htons(ETH_P_IP); - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb, - NULL, dev, + return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, skb, NULL, dev, ip_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index dfe4e8ec6c3a..a88c0c5374ff 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1788,8 +1788,8 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, * not mrouter) cannot join to more than one interface - it will * result in receiving multiple packets. */ - NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, NULL, skb, - skb->dev, dev, + NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, + net, NULL, skb, skb->dev, dev, ipmr_forward_finish); return; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 09ab5bb6913a..2045b1aaa6ef 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -411,8 +411,9 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, icmp_out_count(net, ((struct icmphdr *) skb_transport_header(skb))->type); - err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb, - NULL, rt->dst.dev, dst_output); + err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, rt->dst.dev, + dst_output); if (err > 0) err = net_xmit_errno(err); if (err) diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 60b032f58ccc..5093000d3d5e 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -52,8 +52,8 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) iph->tot_len = htons(skb->len); ip_send_check(iph); - NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, NULL, skb, - skb->dev, NULL, + NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, xfrm4_rcv_encap_finish); return 0; } diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 737f5e395a6a..e4a85199e015 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -96,8 +96,10 @@ static int __xfrm4_output(struct sock *sk, struct sk_buff *skb) int xfrm4_output(struct sock *sk, struct sk_buff *skb) { - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb, - NULL, skb_dst(skb)->dev, __xfrm4_output, + struct net *net = dev_net(skb_dst(skb)->dev); + return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, skb, NULL, skb_dst(skb)->dev, + __xfrm4_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c628dba477d4..583cf959c23d 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -183,8 +183,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt /* Must drop socket now because of tproxy. */ skb_orphan(skb); - return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, NULL, skb, - dev, NULL, + return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, + net, NULL, skb, dev, NULL, ip6_rcv_finish); err: IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); @@ -278,8 +278,8 @@ discard: int ip6_input(struct sk_buff *skb) { - return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, NULL, skb, - skb->dev, NULL, + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, ip6_input_finish); } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 8cab909b181e..96e76ddd4a44 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -83,7 +83,7 @@ static int ip6_finish_output2(struct sock *sk, struct sk_buff *skb) */ if (newskb) NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, - sk, newskb, NULL, newskb->dev, + net, sk, newskb, NULL, newskb->dev, dev_loopback_xmit); if (ipv6_hdr(skb)->hop_limit == 0) { @@ -142,8 +142,8 @@ int ip6_output(struct sock *sk, struct sk_buff *skb) return 0; } - return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, sk, skb, - NULL, dev, + return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, + net, sk, skb, NULL, dev, ip6_finish_output, !(IP6CB(skb)->flags & IP6SKB_REROUTED)); } @@ -223,8 +223,9 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) { IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUT, skb->len); - return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, dst->dev, dst_output); + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, dst->dev, + dst_output); } skb->dev = dst->dev; @@ -511,8 +512,8 @@ int ip6_forward(struct sk_buff *skb) IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); - return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, NULL, skb, - skb->dev, dst->dev, + return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, + net, NULL, skb, skb->dev, dst->dev, ip6_forward_finish); error: diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 3e3085b37a91..e830942b2090 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -2064,8 +2064,8 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, IP6CB(skb)->flags |= IP6SKB_FORWARDED; - return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, NULL, skb, - skb->dev, dev, + return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, + net, NULL, skb, skb->dev, dev, ip6mr_forward2_finish); out_free: diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 5b3f2841acf6..124338a39e29 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1645,7 +1645,7 @@ static void mld_sendpack(struct sk_buff *skb) payload_len = skb->len; err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, - net->ipv6.igmp_sk, skb, NULL, skb->dev, + net, net->ipv6.igmp_sk, skb, NULL, skb->dev, dst_output); out: if (!err) { @@ -2008,8 +2008,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) } skb_dst_set(skb, dst); - err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, skb->dev, dst_output); + err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, skb->dev, + dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 349ac1b022b6..dd2b08d7c8d1 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -463,8 +463,8 @@ static void ndisc_send_skb(struct sk_buff *skb, idev = __in6_dev_get(dst->dev); IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); - err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, dst->dev, + err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 6d9c0b3d5b8c..6b576be3c83e 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c @@ -74,7 +74,7 @@ static unsigned int ipv6_defrag(const struct nf_hook_ops *ops, nf_ct_frag6_consume_orig(reasm); - NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, state->sk, reasm, + NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, state->net, state->sk, reasm, state->in, state->out, state->okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1); diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 8178f72fe90d..9cc9127fb5e7 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -140,6 +140,7 @@ EXPORT_SYMBOL(ip6_dst_hoplimit); static int __ip6_local_out_sk(struct sock *sk, struct sk_buff *skb) { + struct net *net = dev_net(skb_dst(skb)->dev); int len; len = skb->len - sizeof(struct ipv6hdr); @@ -148,8 +149,9 @@ static int __ip6_local_out_sk(struct sock *sk, struct sk_buff *skb) ipv6_hdr(skb)->payload_len = htons(len); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); - return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, - NULL, skb_dst(skb)->dev, dst_output); + return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, skb_dst(skb)->dev, + dst_output); } int __ip6_local_out(struct sk_buff *skb) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5aa461302716..dc65ec198f7c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -654,7 +654,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, goto error_fault; IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); - err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb, + err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, rt->dst.dev, dst_output); if (err > 0) err = net_xmit_errno(err); diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 74bd17882a2f..0eaab1fa6be5 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -42,8 +42,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) ipv6_hdr(skb)->payload_len = htons(skb->len); __skb_push(skb, skb->data - skb_network_header(skb)); - NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, NULL, skb, - skb->dev, NULL, + NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, ip6_rcv_finish); return -1; } diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index b0fcd6c09837..431ae2c22234 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -168,7 +168,9 @@ static int __xfrm6_output(struct sock *sk, struct sk_buff *skb) int xfrm6_output(struct sock *sk, struct sk_buff *skb) { - return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, sk, skb, - NULL, skb_dst(skb)->dev, __xfrm6_output, + struct net *net = dev_net(skb_dst(skb)->dev); + return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, + net, sk, skb, NULL, skb_dst(skb)->dev, + __xfrm6_output, !(IP6CB(skb)->flags & IP6SKB_REROUTED)); } diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index b8e5544af87f..65c996c14bca 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -573,7 +573,7 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, skb_forward_csum(skb); if (!skb->sk) skb_sender_cpu_clear(skb); - NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, + NF_HOOK(pf, NF_INET_LOCAL_OUT, ip_vs_conn_net(cp), NULL, skb, NULL, skb_dst(skb)->dev, dst_output); } else ret = NF_ACCEPT; @@ -595,7 +595,7 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb, skb_forward_csum(skb); if (!skb->sk) skb_sender_cpu_clear(skb); - NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, + NF_HOOK(pf, NF_INET_LOCAL_OUT, ip_vs_conn_net(cp), NULL, skb, NULL, skb_dst(skb)->dev, dst_output); } else ret = NF_ACCEPT; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 57a50f6ce28c..c21f1a02ce13 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -131,6 +131,7 @@ out: int xfrm_output_resume(struct sk_buff *skb, int err) { + struct net *net = xs_net(skb_dst(skb)->xfrm); while (likely((err = xfrm_output_one(skb, err)) == 0)) { nf_reset(skb); @@ -142,7 +143,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err) return dst_output(skb->sk, skb); err = nf_hook(skb_dst(skb)->ops->family, - NF_INET_POST_ROUTING, skb->sk, skb, + NF_INET_POST_ROUTING, net, skb->sk, skb, NULL, skb_dst(skb)->dev, xfrm_output2); if (unlikely(err != 1)) goto out; -- cgit v1.3-6-gb490 From 0c4b51f0054ce85c0ec578ab818f0631834573eb Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:04:18 -0500 Subject: netfilter: Pass net into okfn This is immediately motivated by the bridge code that chains functions that call into netfilter. Without passing net into the okfns the bridge code would need to guess about the best expression for the network namespace to process packets in. As net is frequently one of the first things computed in continuation functions after netfilter has done it's job passing in the desired network namespace is in many cases a code simplification. To support this change the function dst_output_okfn is introduced to simplify passing dst_output as an okfn. For the moment dst_output_okfn just silently drops the struct net. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 2 +- include/linux/netdevice.h | 2 +- include/linux/netfilter.h | 26 ++++++++++++++------------ include/linux/netfilter_bridge.h | 2 +- include/net/dn_neigh.h | 6 +++--- include/net/dst.h | 4 ++++ include/net/ipv6.h | 2 +- include/net/netfilter/br_netfilter.h | 2 +- net/bridge/br_forward.c | 5 ++--- net/bridge/br_input.c | 7 ++++--- net/bridge/br_netfilter_hooks.c | 21 +++++++++------------ net/bridge/br_netfilter_ipv6.c | 3 +-- net/bridge/br_private.h | 6 +++--- net/bridge/br_stp_bpdu.c | 3 ++- net/core/dev.c | 4 +++- net/decnet/dn_neigh.c | 8 ++++---- net/decnet/dn_nsp_in.c | 3 ++- net/decnet/dn_route.c | 6 +++--- net/ipv4/arp.c | 7 +++---- net/ipv4/ip_forward.c | 3 +-- net/ipv4/ip_input.c | 7 ++----- net/ipv4/ip_output.c | 4 ++-- net/ipv4/ipmr.c | 4 ++-- net/ipv4/raw.c | 2 +- net/ipv4/xfrm4_input.c | 3 ++- net/ipv4/xfrm4_output.c | 2 +- net/ipv6/ip6_input.c | 5 ++--- net/ipv6/ip6_output.c | 7 ++++--- net/ipv6/ip6mr.c | 3 +-- net/ipv6/mcast.c | 4 ++-- net/ipv6/ndisc.c | 2 +- net/ipv6/output_core.c | 2 +- net/ipv6/raw.c | 2 +- net/ipv6/xfrm6_output.c | 2 +- net/netfilter/ipvs/ip_vs_xmit.c | 4 ++-- net/netfilter/nf_queue.c | 2 +- net/xfrm/xfrm_output.c | 12 ++++++------ 37 files changed, 95 insertions(+), 94 deletions(-) (limited to 'include') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 979a4db9c6bc..637e9fd1e14c 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -253,7 +253,7 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) } /* modelled after ip_finish_output2 */ -static int vrf_finish_output(struct sock *sk, struct sk_buff *skb) +static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct rtable *rt = (struct rtable *)dst; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 97ab5c9a7069..b791405958b4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2212,7 +2212,7 @@ int dev_open(struct net_device *dev); int dev_close(struct net_device *dev); int dev_close_many(struct list_head *head, bool unlink); void dev_disable_lro(struct net_device *dev); -int dev_loopback_xmit(struct sock *sk, struct sk_buff *newskb); +int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *newskb); int dev_queue_xmit(struct sk_buff *skb); int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv); int register_netdevice(struct net_device *dev); diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 295f2650b5dc..0b4d4560f33d 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -56,7 +56,7 @@ struct nf_hook_state { struct sock *sk; struct net *net; struct list_head *hook_list; - int (*okfn)(struct sock *, struct sk_buff *); + int (*okfn)(struct net *, struct sock *, struct sk_buff *); }; static inline void nf_hook_state_init(struct nf_hook_state *p, @@ -67,7 +67,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p, struct net_device *outdev, struct sock *sk, struct net *net, - int (*okfn)(struct sock *, struct sk_buff *)) + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { p->hook = hook; p->thresh = thresh; @@ -175,7 +175,7 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, - int (*okfn)(struct sock *, struct sk_buff *), + int (*okfn)(struct net *, struct sock *, struct sk_buff *), int thresh) { struct list_head *hook_list = &net->nf.hooks[pf][hook]; @@ -193,7 +193,7 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, - int (*okfn)(struct sock *, struct sk_buff *)) + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { return nf_hook_thresh(pf, hook, net, sk, skb, indev, outdev, okfn, INT_MIN); } @@ -219,31 +219,33 @@ static inline int NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, - int (*okfn)(struct sock *, struct sk_buff *), int thresh) + int (*okfn)(struct net *, struct sock *, struct sk_buff *), + int thresh) { int ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, thresh); if (ret == 1) - ret = okfn(sk, skb); + ret = okfn(net, sk, skb); return ret; } static inline int NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, - int (*okfn)(struct sock *, struct sk_buff *), bool cond) + int (*okfn)(struct net *, struct sock *, struct sk_buff *), + bool cond) { int ret; if (!cond || ((ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, INT_MIN)) == 1)) - ret = okfn(sk, skb); + ret = okfn(net, sk, skb); return ret; } static inline int NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *in, struct net_device *out, - int (*okfn)(struct sock *, struct sk_buff *)) + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { return NF_HOOK_THRESH(pf, hook, net, sk, skb, in, out, okfn, INT_MIN); } @@ -345,12 +347,12 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) } #else /* !CONFIG_NETFILTER */ -#define NF_HOOK(pf, hook, net, sk, skb, indev, outdev, okfn) (okfn)(sk, skb) -#define NF_HOOK_COND(pf, hook, net, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb) +#define NF_HOOK(pf, hook, net, sk, skb, indev, outdev, okfn) (okfn)(net, sk, skb) +#define NF_HOOK_COND(pf, hook, net, sk, skb, indev, outdev, okfn, cond) (okfn)(net, sk, skb) static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, - int (*okfn)(struct sock *, struct sk_buff *)) + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { return 1; } diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index 2437b8a5d7a9..2ed40c402b5e 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -17,7 +17,7 @@ enum nf_br_hook_priorities { #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) -int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb); +int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); static inline void br_drop_fake_rtable(struct sk_buff *skb) { diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h index d0424269313f..5e902fc3f4eb 100644 --- a/include/net/dn_neigh.h +++ b/include/net/dn_neigh.h @@ -18,11 +18,11 @@ struct dn_neigh { void dn_neigh_init(void); void dn_neigh_cleanup(void); -int dn_neigh_router_hello(struct sock *sk, struct sk_buff *skb); -int dn_neigh_endnode_hello(struct sock *sk, struct sk_buff *skb); +int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb); +int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb); void dn_neigh_pointopoint_hello(struct sk_buff *skb); int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n); -int dn_to_neigh_output(struct sock *sk, struct sk_buff *skb); +int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb); extern struct neigh_table dn_neigh_table; diff --git a/include/net/dst.h b/include/net/dst.h index c72e58474e52..df0481a07029 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -458,6 +458,10 @@ static inline int dst_output(struct sock *sk, struct sk_buff *skb) { return skb_dst(skb)->output(sk, skb); } +static inline int dst_output_okfn(struct net *net, struct sock *sk, struct sk_buff *skb) +{ + return dst_output(sk, skb); +} /* Input packet from network to transport. */ static inline int dst_input(struct sk_buff *skb) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 711cca428cc8..384a93cf07d6 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -807,7 +807,7 @@ static inline u8 ip6_tclass(__be32 flowinfo) int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); -int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb); +int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb); /* * upper-layer output functions diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h index d4c6b5f30acd..8fe266504900 100644 --- a/include/net/netfilter/br_netfilter.h +++ b/include/net/netfilter/br_netfilter.h @@ -31,7 +31,7 @@ static inline void nf_bridge_push_encap_header(struct sk_buff *skb) skb->network_header -= len; } -int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb); +int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_buff *skb); static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) { diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 2dd2a23ce707..48afca729ed7 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -35,7 +35,7 @@ static inline int should_deliver(const struct net_bridge_port *p, p->state == BR_STATE_FORWARDING; } -int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb) +int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) { if (!is_skb_forwardable(skb->dev, skb)) goto drop; @@ -65,9 +65,8 @@ drop: } EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit); -int br_forward_finish(struct sock *sk, struct sk_buff *skb) +int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct net *net = dev_net(skb->dev); return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, net, sk, skb, NULL, skb->dev, br_dev_queue_push_xmit); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 78fa7acd836e..223f4040d9df 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -26,7 +26,8 @@ br_should_route_hook_t __rcu *br_should_route_hook __read_mostly; EXPORT_SYMBOL(br_should_route_hook); -static int br_netif_receive_skb(struct sock *sk, struct sk_buff *skb) +static int +br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) { return netif_receive_skb(skb); } @@ -125,7 +126,7 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br, } /* note: already called with rcu_read_lock */ -int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb) +int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { const unsigned char *dest = eth_hdr(skb)->h_dest; struct net_bridge_port *p = br_port_get_rcu(skb->dev); @@ -213,7 +214,7 @@ drop: EXPORT_SYMBOL_GPL(br_handle_frame_finish); /* note: already called with rcu_read_lock */ -static int br_handle_local_finish(struct sock *sk, struct sk_buff *skb) +static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { struct net_bridge_port *p = br_port_get_rcu(skb->dev); u16 vid = 0; diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 7886c9d7e23d..e6e76bbdc82f 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -256,7 +256,7 @@ void nf_bridge_update_protocol(struct sk_buff *skb) * don't, we use the neighbour framework to find out. In both cases, we make * sure that br_handle_frame_finish() is called afterwards. */ -int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb) +int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_buff *skb) { struct neighbour *neigh; struct dst_entry *dst; @@ -273,7 +273,7 @@ int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb) if (neigh->hh.hh_len) { neigh_hh_bridge(&neigh->hh, skb); skb->dev = nf_bridge->physindev; - ret = br_handle_frame_finish(sk, skb); + ret = br_handle_frame_finish(net, sk, skb); } else { /* the neighbour function below overwrites the complete * MAC header, so we save the Ethernet source address and @@ -342,11 +342,10 @@ br_nf_ipv4_daddr_was_changed(const struct sk_buff *skb, * device, we proceed as if ip_route_input() succeeded. If it differs from the * logical bridge port or if ip_route_output_key() fails we drop the packet. */ -static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb) +static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { struct net_device *dev = skb->dev; struct iphdr *iph = ip_hdr(skb); - struct net *net = dev_net(dev); struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); struct rtable *rt; int err; @@ -536,10 +535,9 @@ static unsigned int br_nf_local_in(const struct nf_hook_ops *ops, } /* PF_BRIDGE/FORWARD *************************************************/ -static int br_nf_forward_finish(struct sock *sk, struct sk_buff *skb) +static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); - struct net *net = dev_net(skb->dev); struct net_device *in; if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) { @@ -692,7 +690,7 @@ static int br_nf_push_frag_xmit(struct net *net, struct sock *sk, struct sk_buff __skb_push(skb, data->encap_size); nf_bridge_info_free(skb); - return br_dev_queue_push_xmit(sk, skb); + return br_dev_queue_push_xmit(net, sk, skb); } static int br_nf_push_frag_xmit_sk(struct sock *sk, struct sk_buff *skb) { @@ -728,17 +726,16 @@ static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) return 0; } -static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb) +static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) { struct nf_bridge_info *nf_bridge; unsigned int mtu_reserved; - struct net *net = dev_net(skb_dst(skb)->dev); mtu_reserved = nf_bridge_mtu_reduction(skb); if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) { nf_bridge_info_free(skb); - return br_dev_queue_push_xmit(sk, skb); + return br_dev_queue_push_xmit(net, sk, skb); } nf_bridge = nf_bridge_info_get(skb); @@ -797,7 +794,7 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb) } #endif nf_bridge_info_free(skb); - return br_dev_queue_push_xmit(sk, skb); + return br_dev_queue_push_xmit(net, sk, skb); drop: kfree_skb(skb); return 0; @@ -887,7 +884,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) skb->dev = nf_bridge->physindev; nf_bridge->physoutdev = NULL; - br_handle_frame_finish(NULL, skb); + br_handle_frame_finish(dev_net(skb->dev), NULL, skb); } static int br_nf_dev_xmit(struct sk_buff *skb) diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c index 5d19361ad5d3..e4dbbe44c724 100644 --- a/net/bridge/br_netfilter_ipv6.c +++ b/net/bridge/br_netfilter_ipv6.c @@ -161,12 +161,11 @@ br_nf_ipv6_daddr_was_changed(const struct sk_buff *skb, * for br_nf_pre_routing_finish(), same logic is used here but * equivalent IPv6 function ip6_route_input() called indirectly. */ -static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) +static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); struct rtable *rt; struct net_device *dev = skb->dev; - struct net *net = dev_net(dev); const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops(); nf_bridge->frag_max_size = IP6CB(skb)->frag_max_size; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 213baf7aaa93..74e99c75c8e4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -413,10 +413,10 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, /* br_forward.c */ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb); -int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb); +int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb); void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0); -int br_forward_finish(struct sock *sk, struct sk_buff *skb); +int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb); void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast); void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, struct sk_buff *skb2, bool unicast); @@ -434,7 +434,7 @@ void br_port_flags_change(struct net_bridge_port *port, unsigned long mask); void br_manage_promisc(struct net_bridge *br); /* br_input.c */ -int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb); +int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); rx_handler_result_t br_handle_frame(struct sk_buff **pskb); static inline bool br_rx_handler_check_rcu(const struct net_device *dev) diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 8e2e8c352198..5881fbc114a9 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -30,7 +30,8 @@ #define LLC_RESERVE sizeof(struct llc_pdu_un) -static int br_send_bpdu_finish(struct sock *sk, struct sk_buff *skb) +static int br_send_bpdu_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) { return dev_queue_xmit(skb); } diff --git a/net/core/dev.c b/net/core/dev.c index 7db9b012dfb7..00dccfac8939 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2915,9 +2915,11 @@ EXPORT_SYMBOL(xmit_recursion); /** * dev_loopback_xmit - loop back @skb + * @net: network namespace this loopback is happening in + * @sk: sk needed to be a netfilter okfn * @skb: buffer to transmit */ -int dev_loopback_xmit(struct sock *sk, struct sk_buff *skb) +int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) { skb_reset_mac_header(skb); __skb_pull(skb, skb_network_offset(skb)); diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 305ab2fe25cd..482730cd8a56 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -194,7 +194,7 @@ static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb) return err; } -static int dn_neigh_output_packet(struct sock *sk, struct sk_buff *skb) +static int dn_neigh_output_packet(struct net *net, struct sock *sk, struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct dn_route *rt = (struct dn_route *)dst; @@ -334,7 +334,7 @@ static int dn_phase3_output(struct neighbour *neigh, struct sock *sk, dn_neigh_output_packet); } -int dn_to_neigh_output(struct sock *sk, struct sk_buff *skb) +int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct dn_route *rt = (struct dn_route *) dst; @@ -378,7 +378,7 @@ void dn_neigh_pointopoint_hello(struct sk_buff *skb) /* * Ethernet router hello message received */ -int dn_neigh_router_hello(struct sock *sk, struct sk_buff *skb) +int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb) { struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data; @@ -440,7 +440,7 @@ int dn_neigh_router_hello(struct sock *sk, struct sk_buff *skb) /* * Endnode hello message received */ -int dn_neigh_endnode_hello(struct sock *sk, struct sk_buff *skb) +int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb) { struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data; struct neighbour *neigh; diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index e7b0605ca34a..7ac086d5c0c0 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -714,7 +714,8 @@ out: return ret; } -static int dn_nsp_rx_packet(struct sock *sk2, struct sk_buff *skb) +static int dn_nsp_rx_packet(struct net *net, struct sock *sk2, + struct sk_buff *skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct sock *sk = NULL; diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index fefcd2e85ef9..e930321e2c1d 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -512,7 +512,7 @@ static int dn_return_long(struct sk_buff *skb) * * Returns: result of input function if route is found, error code otherwise */ -static int dn_route_rx_packet(struct sock *sk, struct sk_buff *skb) +static int dn_route_rx_packet(struct net *net, struct sock *sk, struct sk_buff *skb) { struct dn_skb_cb *cb; int err; @@ -610,7 +610,7 @@ drop_it: return NET_RX_DROP; } -static int dn_route_discard(struct sock *sk, struct sk_buff *skb) +static int dn_route_discard(struct net *net, struct sock *sk, struct sk_buff *skb) { /* * I know we drop the packet here, but thats considered success in @@ -620,7 +620,7 @@ static int dn_route_discard(struct sock *sk, struct sk_buff *skb) return NET_RX_SUCCESS; } -static int dn_route_ptp_hello(struct sock *sk, struct sk_buff *skb) +static int dn_route_ptp_hello(struct net *net, struct sock *sk, struct sk_buff *skb) { dn_dev_hello(skb); dn_neigh_pointopoint_hello(skb); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index ae71e9ade5f9..61ff5ea31283 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -621,7 +621,7 @@ out: } EXPORT_SYMBOL(arp_create); -static int arp_xmit_finish(struct sock *sk, struct sk_buff *skb) +static int arp_xmit_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { return dev_queue_xmit(skb); } @@ -642,7 +642,7 @@ EXPORT_SYMBOL(arp_xmit); * Process an arp request. */ -static int arp_process(struct sock *sk, struct sk_buff *skb) +static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) { struct net_device *dev = skb->dev; struct in_device *in_dev = __in_dev_get_rcu(dev); @@ -654,7 +654,6 @@ static int arp_process(struct sock *sk, struct sk_buff *skb) u16 dev_type = dev->type; int addr_type; struct neighbour *n; - struct net *net = dev_net(dev); bool is_garp = false; /* arp_rcv below verifies the ARP header and verifies the device @@ -865,7 +864,7 @@ out: static void parp_redo(struct sk_buff *skb) { - arp_process(NULL, skb); + arp_process(dev_net(skb->dev), NULL, skb); } diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 0a3c45a2e757..d66cfb35ba74 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -61,9 +61,8 @@ static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) } -static int ip_forward_finish(struct sock *sk, struct sk_buff *skb) +static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct net *net = dev_net(skb_dst(skb)->dev); struct ip_options *opt = &(IPCB(skb)->opt); IP_INC_STATS_BH(net, IPSTATS_MIB_OUTFORWDATAGRAMS); diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 991d082c7312..7cc9f7bb7fb7 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -188,10 +188,8 @@ bool ip_call_ra_chain(struct sk_buff *skb) return false; } -static int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb) +static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct net *net = dev_net(skb->dev); - __skb_pull(skb, skb_network_header_len(skb)); rcu_read_lock(); @@ -311,10 +309,9 @@ drop: int sysctl_ip_early_demux __read_mostly = 1; EXPORT_SYMBOL(sysctl_ip_early_demux); -static int ip_rcv_finish(struct sock *sk, struct sk_buff *skb) +static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { const struct iphdr *iph = ip_hdr(skb); - struct net *net = dev_net(skb->dev); struct rtable *rt; if (sysctl_ip_early_demux && !skb_dst(skb) && !skb->sk) { diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4c9532259a7f..09a6b7bb7ea3 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -104,7 +104,7 @@ static int __ip_local_out_sk(struct sock *sk, struct sk_buff *skb) ip_send_check(iph); return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb_dst(skb)->dev, - dst_output); + dst_output_okfn); } int __ip_local_out(struct sk_buff *skb) @@ -266,7 +266,7 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb, return ret; } -static int ip_finish_output(struct sock *sk, struct sk_buff *skb) +static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { unsigned int mtu; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index a88c0c5374ff..cfcb996ec51b 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1678,10 +1678,10 @@ static void ip_encap(struct net *net, struct sk_buff *skb, nf_reset(skb); } -static inline int ipmr_forward_finish(struct sock *sk, struct sk_buff *skb) +static inline int ipmr_forward_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) { struct ip_options *opt = &(IPCB(skb)->opt); - struct net *net = dev_net(skb_dst(skb)->dev); IP_INC_STATS_BH(net, IPSTATS_MIB_OUTFORWDATAGRAMS); IP_ADD_STATS_BH(net, IPSTATS_MIB_OUTOCTETS, skb->len); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2045b1aaa6ef..28ef8a913130 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -413,7 +413,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, skb, NULL, rt->dst.dev, - dst_output); + dst_output_okfn); if (err > 0) err = net_xmit_errno(err); if (err) diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 5093000d3d5e..62e1e72db461 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -22,7 +22,8 @@ int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb) return xfrm4_extract_header(skb); } -static inline int xfrm4_rcv_encap_finish(struct sock *sk, struct sk_buff *skb) +static inline int xfrm4_rcv_encap_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) { if (!skb_dst(skb)) { const struct iphdr *iph = ip_hdr(skb); diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index e4a85199e015..28ae2048b93a 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -80,7 +80,7 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb) return xfrm_output(sk, skb); } -static int __xfrm4_output(struct sock *sk, struct sk_buff *skb) +static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct xfrm_state *x = skb_dst(skb)->xfrm; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 583cf959c23d..9075acf081dd 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -47,7 +47,7 @@ #include #include -int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb) +int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) { const struct inet6_protocol *ipprot; @@ -199,9 +199,8 @@ drop: */ -static int ip6_input_finish(struct sock *sk, struct sk_buff *skb) +static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct net *net = dev_net(skb_dst(skb)->dev); const struct inet6_protocol *ipprot; struct inet6_dev *idev; unsigned int nhoff; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 96e76ddd4a44..d8d68e81d123 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -121,7 +121,7 @@ static int ip6_finish_output2(struct sock *sk, struct sk_buff *skb) return -EINVAL; } -static int ip6_finish_output(struct sock *sk, struct sk_buff *skb) +static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || dst_allfrag(skb_dst(skb)) || @@ -225,7 +225,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, IPSTATS_MIB_OUT, skb->len); return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, dst->dev, - dst_output); + dst_output_okfn); } skb->dev = dst->dev; @@ -317,7 +317,8 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) return 0; } -static inline int ip6_forward_finish(struct sock *sk, struct sk_buff *skb) +static inline int ip6_forward_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) { skb_sender_cpu_clear(skb); return dst_output(sk, skb); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index e830942b2090..5e5d16e7ce85 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1985,9 +1985,8 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) } #endif -static inline int ip6mr_forward2_finish(struct sock *sk, struct sk_buff *skb) +static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { - struct net *net = dev_net(skb_dst(skb)->dev); IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTFORWDATAGRAMS); IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 124338a39e29..a8bf57ca74d3 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1646,7 +1646,7 @@ static void mld_sendpack(struct sk_buff *skb) err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, net->ipv6.igmp_sk, skb, NULL, skb->dev, - dst_output); + dst_output_okfn); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT); @@ -2010,7 +2010,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) skb_dst_set(skb, dst); err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb->dev, - dst_output); + dst_output_okfn); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index dd2b08d7c8d1..dde5a1e5875a 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -465,7 +465,7 @@ static void ndisc_send_skb(struct sk_buff *skb, err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, dst->dev, - dst_output); + dst_output_okfn); if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 9cc9127fb5e7..e77102c4f804 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -151,7 +151,7 @@ static int __ip6_local_out_sk(struct sock *sk, struct sk_buff *skb) return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb_dst(skb)->dev, - dst_output); + dst_output_okfn); } int __ip6_local_out(struct sk_buff *skb) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index dc65ec198f7c..fec0151522a2 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -655,7 +655,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, - NULL, rt->dst.dev, dst_output); + NULL, rt->dst.dev, dst_output_okfn); if (err > 0) err = net_xmit_errno(err); if (err) diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 431ae2c22234..68a996f8a044 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -131,7 +131,7 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb) return xfrm_output(sk, skb); } -static int __xfrm6_output(struct sock *sk, struct sk_buff *skb) +static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct xfrm_state *x = dst->xfrm; diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 65c996c14bca..cc7299033af8 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -574,7 +574,7 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, if (!skb->sk) skb_sender_cpu_clear(skb); NF_HOOK(pf, NF_INET_LOCAL_OUT, ip_vs_conn_net(cp), NULL, skb, - NULL, skb_dst(skb)->dev, dst_output); + NULL, skb_dst(skb)->dev, dst_output_okfn); } else ret = NF_ACCEPT; @@ -596,7 +596,7 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb, if (!skb->sk) skb_sender_cpu_clear(skb); NF_HOOK(pf, NF_INET_LOCAL_OUT, ip_vs_conn_net(cp), NULL, skb, - NULL, skb_dst(skb)->dev, dst_output); + NULL, skb_dst(skb)->dev, dst_output_okfn); } else ret = NF_ACCEPT; return ret; diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 96777f9a9350..9f3c3c25fa73 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -215,7 +215,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) case NF_ACCEPT: case NF_STOP: local_bh_disable(); - entry->state.okfn(entry->state.sk, skb); + entry->state.okfn(entry->state.net, entry->state.sk, skb); local_bh_enable(); break; case NF_QUEUE: diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index c21f1a02ce13..61ba99f61dc8 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -19,7 +19,7 @@ #include #include -static int xfrm_output2(struct sock *sk, struct sk_buff *skb); +static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb); static int xfrm_skb_check_space(struct sk_buff *skb) { @@ -157,12 +157,12 @@ out: } EXPORT_SYMBOL_GPL(xfrm_output_resume); -static int xfrm_output2(struct sock *sk, struct sk_buff *skb) +static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb) { return xfrm_output_resume(skb, 1); } -static int xfrm_output_gso(struct sock *sk, struct sk_buff *skb) +static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb) { struct sk_buff *segs; @@ -178,7 +178,7 @@ static int xfrm_output_gso(struct sock *sk, struct sk_buff *skb) int err; segs->next = NULL; - err = xfrm_output2(sk, segs); + err = xfrm_output2(net, sk, segs); if (unlikely(err)) { kfree_skb_list(nskb); @@ -197,7 +197,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) int err; if (skb_is_gso(skb)) - return xfrm_output_gso(sk, skb); + return xfrm_output_gso(net, sk, skb); if (skb->ip_summed == CHECKSUM_PARTIAL) { err = skb_checksum_help(skb); @@ -208,7 +208,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) } } - return xfrm_output2(sk, skb); + return xfrm_output2(net, sk, skb); } EXPORT_SYMBOL_GPL(xfrm_output); -- cgit v1.3-6-gb490 From 58d607d3e52f2b15902f58a1161da9fb3b0f6d47 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 15 Sep 2015 15:24:20 -0700 Subject: tcp: provide skb->hash to synack packets In commit b73c3d0e4f0e ("net: Save TX flow hash in sock and set in skbuf on xmit"), Tom provided a l4 hash to most outgoing TCP packets. We'd like to provide one as well for SYNACK packets, so that all packets of a given flow share same txhash, to later enable bonding driver to also use skb->hash to perform slave selection. Note that a SYNACK retransmit shuffles the tx hash, as Tom did in commit 265f94ff54d62 ("net: Recompute sk_txhash on negative routing advice") for established sockets. This has nice effect making TCP flows resilient to some kind of black holes, even at connection establish phase. Signed-off-by: Eric Dumazet Cc: Tom Herbert Cc: Mahesh Bandewar Acked-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 + include/net/sock.h | 12 ++++++++---- net/ipv4/tcp_input.c | 1 + net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/tcp_output.c | 2 ++ net/ipv6/tcp_ipv6.c | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 48c3696e8645..937b97893d5f 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -113,6 +113,7 @@ struct tcp_request_sock { struct inet_request_sock req; const struct tcp_request_sock_ops *af_specific; bool tfo_listener; + u32 txhash; u32 rcv_isn; u32 snt_isn; u32 snt_synack; /* synack sent time */ diff --git a/include/net/sock.h b/include/net/sock.h index 7aa78440559a..94dff7f566f5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1654,12 +1654,16 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) kuid_t sock_i_uid(struct sock *sk); unsigned long sock_i_ino(struct sock *sk); -static inline void sk_set_txhash(struct sock *sk) +static inline u32 net_tx_rndhash(void) { - sk->sk_txhash = prandom_u32(); + u32 v = prandom_u32(); + + return v ?: 1; +} - if (unlikely(!sk->sk_txhash)) - sk->sk_txhash = 1; +static inline void sk_set_txhash(struct sock *sk) +{ + sk->sk_txhash = net_tx_rndhash(); } static inline void sk_rethink_txhash(struct sock *sk) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a8f515bb19c4..a62e9c76d485 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6228,6 +6228,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, } tcp_rsk(req)->snt_isn = isn; + tcp_rsk(req)->txhash = net_tx_rndhash(); tcp_openreq_init_rwin(req, sk, dst); fastopen = !want_cookie && tcp_try_fastopen(sk, skb, req, &foc, dst); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 93898e093d4e..d671d742a239 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1276,8 +1276,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newinet->mc_index = inet_iif(skb); newinet->mc_ttl = ip_hdr(skb)->ttl; newinet->rcv_tos = ip_hdr(skb)->tos; + newsk->sk_txhash = tcp_rsk(req)->txhash; inet_csk(newsk)->icsk_ext_hdr_len = 0; - sk_set_txhash(newsk); if (inet_opt) inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; newinet->inet_id = newtp->write_seq ^ jiffies; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f9a8a12b62ee..d0ad3554c333 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2987,6 +2987,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, rcu_read_lock(); md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req)); #endif + skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4); tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5, foc) + sizeof(*th); @@ -3505,6 +3506,7 @@ int tcp_rtx_synack(struct sock *sk, struct request_sock *req) struct flowi fl; int res; + tcp_rsk(req)->txhash = net_tx_rndhash(); res = af_ops->send_synack(sk, NULL, &fl, req, 0, NULL); if (!res) { TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 97d9314ea361..f9c0e2640671 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1090,7 +1090,7 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; newsk->sk_bound_dev_if = ireq->ir_iif; - sk_set_txhash(newsk); + newsk->sk_txhash = tcp_rsk(req)->txhash; /* Now IPv6 options... -- cgit v1.3-6-gb490 From 045efa82ff563cd4e656ca1c2e354fa5bf6bbda4 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 15 Sep 2015 23:05:42 -0700 Subject: cls_bpf: introduce integrated actions Often cls_bpf classifier is used with single action drop attached. Optimize this use case and let cls_bpf return both classid and action. For backwards compatibility reasons enable this feature under TCA_BPF_FLAG_ACT_DIRECT flag. Then more interesting programs like the following are easier to write: int cls_bpf_prog(struct __sk_buff *skb) { /* classify arp, ip, ipv6 into different traffic classes * and drop all other packets */ switch (skb->protocol) { case htons(ETH_P_ARP): skb->tc_classid = 1; break; case htons(ETH_P_IP): skb->tc_classid = 2; break; case htons(ETH_P_IPV6): skb->tc_classid = 3; break; default: return TC_ACT_SHOT; } return TC_ACT_OK; } Joint work with Daniel Borkmann. Signed-off-by: Daniel Borkmann Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/net/sch_generic.h | 2 +- include/uapi/linux/bpf.h | 1 + include/uapi/linux/pkt_cls.h | 3 +++ net/core/filter.c | 14 +++++++++++ net/sched/cls_bpf.c | 60 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 68 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 444faa89a55f..da61febb9091 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -251,7 +251,7 @@ struct tcf_proto { struct qdisc_skb_cb { unsigned int pkt_len; u16 slave_dev_queue_mapping; - u16 _pad; + u16 tc_classid; #define QDISC_CB_PRIV_LEN 20 unsigned char data[QDISC_CB_PRIV_LEN]; }; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 92a48e2d5461..2fbd1c71fa3b 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -293,6 +293,7 @@ struct __sk_buff { __u32 tc_index; __u32 cb[5]; __u32 hash; + __u32 tc_classid; }; struct bpf_tunnel_key { diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index 4f0d1bc3647d..0a262a83f9d4 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h @@ -373,6 +373,8 @@ enum { /* BPF classifier */ +#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0) + enum { TCA_BPF_UNSPEC, TCA_BPF_ACT, @@ -382,6 +384,7 @@ enum { TCA_BPF_OPS, TCA_BPF_FD, TCA_BPF_NAME, + TCA_BPF_FLAGS, __TCA_BPF_MAX, }; diff --git a/net/core/filter.c b/net/core/filter.c index 13079f03902e..971d6ba89758 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1632,6 +1632,9 @@ static bool __is_valid_access(int off, int size, enum bpf_access_type type) static bool sk_filter_is_valid_access(int off, int size, enum bpf_access_type type) { + if (off == offsetof(struct __sk_buff, tc_classid)) + return false; + if (type == BPF_WRITE) { switch (off) { case offsetof(struct __sk_buff, cb[0]) ... @@ -1648,6 +1651,9 @@ static bool sk_filter_is_valid_access(int off, int size, static bool tc_cls_act_is_valid_access(int off, int size, enum bpf_access_type type) { + if (off == offsetof(struct __sk_buff, tc_classid)) + return type == BPF_WRITE ? true : false; + if (type == BPF_WRITE) { switch (off) { case offsetof(struct __sk_buff, mark): @@ -1760,6 +1766,14 @@ static u32 bpf_net_convert_ctx_access(enum bpf_access_type type, int dst_reg, *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg, ctx_off); break; + case offsetof(struct __sk_buff, tc_classid): + ctx_off -= offsetof(struct __sk_buff, tc_classid); + ctx_off += offsetof(struct sk_buff, cb); + ctx_off += offsetof(struct qdisc_skb_cb, tc_classid); + WARN_ON(type != BPF_WRITE); + *insn++ = BPF_STX_MEM(BPF_H, dst_reg, src_reg, ctx_off); + break; + case offsetof(struct __sk_buff, tc_index): #ifdef CONFIG_NET_SCHED BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, tc_index) != 2); diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index e5168f8b9640..77b0ef148256 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -38,6 +38,7 @@ struct cls_bpf_prog { struct bpf_prog *filter; struct list_head link; struct tcf_result res; + bool exts_integrated; struct tcf_exts exts; u32 handle; union { @@ -52,6 +53,7 @@ struct cls_bpf_prog { static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = { [TCA_BPF_CLASSID] = { .type = NLA_U32 }, + [TCA_BPF_FLAGS] = { .type = NLA_U32 }, [TCA_BPF_FD] = { .type = NLA_U32 }, [TCA_BPF_NAME] = { .type = NLA_NUL_STRING, .len = CLS_BPF_NAME_LEN }, [TCA_BPF_OPS_LEN] = { .type = NLA_U16 }, @@ -59,6 +61,22 @@ static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = { .len = sizeof(struct sock_filter) * BPF_MAXINSNS }, }; +static int cls_bpf_exec_opcode(int code) +{ + switch (code) { + case TC_ACT_OK: + case TC_ACT_RECLASSIFY: + case TC_ACT_SHOT: + case TC_ACT_PIPE: + case TC_ACT_STOLEN: + case TC_ACT_QUEUED: + case TC_ACT_UNSPEC: + return code; + default: + return TC_ACT_UNSPEC; + } +} + static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res) { @@ -79,6 +97,8 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, list_for_each_entry_rcu(prog, &head->plist, link) { int filter_res; + qdisc_skb_cb(skb)->tc_classid = prog->res.classid; + if (at_ingress) { /* It is safe to push/pull even if skb_shared() */ __skb_push(skb, skb->mac_len); @@ -88,6 +108,16 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, filter_res = BPF_PROG_RUN(prog->filter, skb); } + if (prog->exts_integrated) { + res->class = prog->res.class; + res->classid = qdisc_skb_cb(skb)->tc_classid; + + ret = cls_bpf_exec_opcode(filter_res); + if (ret == TC_ACT_UNSPEC) + continue; + break; + } + if (filter_res == 0) continue; @@ -195,8 +225,7 @@ static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle) return ret; } -static int cls_bpf_prog_from_ops(struct nlattr **tb, - struct cls_bpf_prog *prog, u32 classid) +static int cls_bpf_prog_from_ops(struct nlattr **tb, struct cls_bpf_prog *prog) { struct sock_filter *bpf_ops; struct sock_fprog_kern fprog_tmp; @@ -230,15 +259,13 @@ static int cls_bpf_prog_from_ops(struct nlattr **tb, prog->bpf_ops = bpf_ops; prog->bpf_num_ops = bpf_num_ops; prog->bpf_name = NULL; - prog->filter = fp; - prog->res.classid = classid; return 0; } -static int cls_bpf_prog_from_efd(struct nlattr **tb, - struct cls_bpf_prog *prog, u32 classid) +static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, + const struct tcf_proto *tp) { struct bpf_prog *fp; char *name = NULL; @@ -268,9 +295,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, prog->bpf_ops = NULL; prog->bpf_fd = bpf_fd; prog->bpf_name = name; - prog->filter = fp; - prog->res.classid = classid; return 0; } @@ -280,8 +305,8 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, unsigned long base, struct nlattr **tb, struct nlattr *est, bool ovr) { + bool is_bpf, is_ebpf, have_exts = false; struct tcf_exts exts; - bool is_bpf, is_ebpf; u32 classid; int ret; @@ -298,9 +323,22 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, return ret; classid = nla_get_u32(tb[TCA_BPF_CLASSID]); + if (tb[TCA_BPF_FLAGS]) { + u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]); + + if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) { + tcf_exts_destroy(&exts); + return -EINVAL; + } + + have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT; + } + + prog->res.classid = classid; + prog->exts_integrated = have_exts; - ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog, classid) : - cls_bpf_prog_from_efd(tb, prog, classid); + ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) : + cls_bpf_prog_from_efd(tb, prog, tp); if (ret < 0) { tcf_exts_destroy(&exts); return ret; -- cgit v1.3-6-gb490 From 27b29f63058d26c6c1742f1993338280d5a41dc6 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Tue, 15 Sep 2015 23:05:43 -0700 Subject: bpf: add bpf_redirect() helper Existing bpf_clone_redirect() helper clones skb before redirecting it to RX or TX of destination netdev. Introduce bpf_redirect() helper that does that without cloning. Benchmarked with two hosts using 10G ixgbe NICs. One host is doing line rate pktgen. Another host is configured as: $ tc qdisc add dev $dev ingress $ tc filter add dev $dev root pref 10 u32 match u32 0 0 flowid 1:2 \ action bpf run object-file tcbpf1_kern.o section clone_redirect_xmit drop so it receives the packet on $dev and immediately xmits it on $dev + 1 The section 'clone_redirect_xmit' in tcbpf1_kern.o file has the program that does bpf_clone_redirect() and performance is 2.0 Mpps $ tc filter add dev $dev root pref 10 u32 match u32 0 0 flowid 1:2 \ action bpf run object-file tcbpf1_kern.o section redirect_xmit drop which is using bpf_redirect() - 2.4 Mpps and using cls_bpf with integrated actions as: $ tc filter add dev $dev root pref 10 \ bpf run object-file tcbpf1_kern.o section redirect_xmit integ_act classid 1 performance is 2.5 Mpps To summarize: u32+act_bpf using clone_redirect - 2.0 Mpps u32+act_bpf using redirect - 2.4 Mpps cls_bpf using redirect - 2.5 Mpps For comparison linux bridge in this setup is doing 2.1 Mpps and ixgbe rx + drop in ip_rcv - 7.8 Mpps Signed-off-by: Alexei Starovoitov Acked-by: Daniel Borkmann Acked-by: John Fastabend Signed-off-by: David S. Miller --- include/net/sch_generic.h | 1 + include/uapi/linux/bpf.h | 8 ++++++++ include/uapi/linux/pkt_cls.h | 1 + net/core/dev.c | 8 ++++++++ net/core/filter.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ net/sched/act_bpf.c | 1 + net/sched/cls_bpf.c | 1 + samples/bpf/bpf_helpers.h | 4 ++++ samples/bpf/tcbpf1_kern.c | 24 +++++++++++++++++++++++- 9 files changed, 91 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index da61febb9091..4c79ce8c1f92 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -402,6 +402,7 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_table *stab); bool tcf_destroy(struct tcf_proto *tp, bool force); void tcf_destroy_chain(struct tcf_proto __rcu **fl); +int skb_do_redirect(struct sk_buff *); /* Reset all TX qdiscs greater then index of a device. */ static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2fbd1c71fa3b..4ec0b5488294 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -272,6 +272,14 @@ enum bpf_func_id { BPF_FUNC_skb_get_tunnel_key, BPF_FUNC_skb_set_tunnel_key, BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */ + /** + * bpf_redirect(ifindex, flags) - redirect to another netdev + * @ifindex: ifindex of the net device + * @flags: bit 0 - if set, redirect to ingress instead of egress + * other bits - reserved + * Return: TC_ACT_REDIRECT + */ + BPF_FUNC_redirect, __BPF_FUNC_MAX_ID, }; diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index 0a262a83f9d4..439873775d49 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h @@ -87,6 +87,7 @@ enum { #define TC_ACT_STOLEN 4 #define TC_ACT_QUEUED 5 #define TC_ACT_REPEAT 6 +#define TC_ACT_REDIRECT 7 #define TC_ACT_JUMP 0x10000000 /* Action type identifiers*/ diff --git a/net/core/dev.c b/net/core/dev.c index 00dccfac8939..ee0d6286f934 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3670,6 +3670,14 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb, case TC_ACT_QUEUED: kfree_skb(skb); return NULL; + case TC_ACT_REDIRECT: + /* skb_mac_header check was done by cls/act_bpf, so + * we can safely push the L2 header back before + * redirecting to another netdev + */ + __skb_push(skb, skb->mac_len); + skb_do_redirect(skb); + return NULL; default: break; } diff --git a/net/core/filter.c b/net/core/filter.c index 971d6ba89758..da3f3d94d6e9 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1427,6 +1427,48 @@ const struct bpf_func_proto bpf_clone_redirect_proto = { .arg3_type = ARG_ANYTHING, }; +struct redirect_info { + u32 ifindex; + u32 flags; +}; + +static DEFINE_PER_CPU(struct redirect_info, redirect_info); +static u64 bpf_redirect(u64 ifindex, u64 flags, u64 r3, u64 r4, u64 r5) +{ + struct redirect_info *ri = this_cpu_ptr(&redirect_info); + + ri->ifindex = ifindex; + ri->flags = flags; + return TC_ACT_REDIRECT; +} + +int skb_do_redirect(struct sk_buff *skb) +{ + struct redirect_info *ri = this_cpu_ptr(&redirect_info); + struct net_device *dev; + + dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->ifindex); + ri->ifindex = 0; + if (unlikely(!dev)) { + kfree_skb(skb); + return -EINVAL; + } + + if (BPF_IS_REDIRECT_INGRESS(ri->flags)) + return dev_forward_skb(dev, skb); + + skb->dev = dev; + return dev_queue_xmit(skb); +} + +const struct bpf_func_proto bpf_redirect_proto = { + .func = bpf_redirect, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_ANYTHING, + .arg2_type = ARG_ANYTHING, +}; + static u64 bpf_get_cgroup_classid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) { return task_get_classid((struct sk_buff *) (unsigned long) r1); @@ -1607,6 +1649,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id) return &bpf_skb_get_tunnel_key_proto; case BPF_FUNC_skb_set_tunnel_key: return bpf_get_skb_set_tunnel_key_proto(); + case BPF_FUNC_redirect: + return &bpf_redirect_proto; default: return sk_filter_func_proto(func_id); } diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index 559bfa011bda..0bc6f912f870 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -72,6 +72,7 @@ static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, case TC_ACT_PIPE: case TC_ACT_RECLASSIFY: case TC_ACT_OK: + case TC_ACT_REDIRECT: action = filter_res; break; case TC_ACT_SHOT: diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 77b0ef148256..0590816ab7b0 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -70,6 +70,7 @@ static int cls_bpf_exec_opcode(int code) case TC_ACT_PIPE: case TC_ACT_STOLEN: case TC_ACT_QUEUED: + case TC_ACT_REDIRECT: case TC_ACT_UNSPEC: return code; default: diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h index 3a44d3a272af..21aa1b44c30c 100644 --- a/samples/bpf/bpf_helpers.h +++ b/samples/bpf/bpf_helpers.h @@ -33,6 +33,10 @@ static int (*bpf_get_current_comm)(void *buf, int buf_size) = (void *) BPF_FUNC_get_current_comm; static int (*bpf_perf_event_read)(void *map, int index) = (void *) BPF_FUNC_perf_event_read; +static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) = + (void *) BPF_FUNC_clone_redirect; +static int (*bpf_redirect)(int ifindex, int flags) = + (void *) BPF_FUNC_redirect; /* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions diff --git a/samples/bpf/tcbpf1_kern.c b/samples/bpf/tcbpf1_kern.c index 9bfb2eb34563..fa051b3d53ee 100644 --- a/samples/bpf/tcbpf1_kern.c +++ b/samples/bpf/tcbpf1_kern.c @@ -5,7 +5,7 @@ #include #include #include - +#include #include "bpf_helpers.h" /* compiler workaround */ @@ -64,4 +64,26 @@ int bpf_prog1(struct __sk_buff *skb) return 0; } +SEC("redirect_xmit") +int _redirect_xmit(struct __sk_buff *skb) +{ + return bpf_redirect(skb->ifindex + 1, 0); +} +SEC("redirect_recv") +int _redirect_recv(struct __sk_buff *skb) +{ + return bpf_redirect(skb->ifindex + 1, 1); +} +SEC("clone_redirect_xmit") +int _clone_redirect_xmit(struct __sk_buff *skb) +{ + bpf_clone_redirect(skb, skb->ifindex + 1, 0); + return TC_ACT_SHOT; +} +SEC("clone_redirect_recv") +int _clone_redirect_recv(struct __sk_buff *skb) +{ + bpf_clone_redirect(skb, skb->ifindex + 1, 1); + return TC_ACT_SHOT; +} char _license[] SEC("license") = "GPL"; -- cgit v1.3-6-gb490 From 6e1e5196975fb7ecc501b3fe1075b77aea2b7839 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Mon, 14 Sep 2015 00:37:22 -0700 Subject: locking/qrwlock: Rename ->lock to ->wait_lock ... trivial, but reads a little nicer when we name our actual primitive 'lock'. Signed-off-by: Davidlohr Bueso Signed-off-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Waiman Long Link: http://lkml.kernel.org/r/1442216244-4409-1-git-send-email-dave@stgolabs.net Signed-off-by: Ingo Molnar --- include/asm-generic/qrwlock_types.h | 4 ++-- kernel/locking/qrwlock.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/asm-generic/qrwlock_types.h b/include/asm-generic/qrwlock_types.h index 4d76f24df518..0abc6b6062fb 100644 --- a/include/asm-generic/qrwlock_types.h +++ b/include/asm-generic/qrwlock_types.h @@ -10,12 +10,12 @@ typedef struct qrwlock { atomic_t cnts; - arch_spinlock_t lock; + arch_spinlock_t wait_lock; } arch_rwlock_t; #define __ARCH_RW_LOCK_UNLOCKED { \ .cnts = ATOMIC_INIT(0), \ - .lock = __ARCH_SPIN_LOCK_UNLOCKED, \ + .wait_lock = __ARCH_SPIN_LOCK_UNLOCKED, \ } #endif /* __ASM_GENERIC_QRWLOCK_TYPES_H */ diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c index f17a3e3b3550..fec082338668 100644 --- a/kernel/locking/qrwlock.c +++ b/kernel/locking/qrwlock.c @@ -86,7 +86,7 @@ void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts) /* * Put the reader into the wait queue */ - arch_spin_lock(&lock->lock); + arch_spin_lock(&lock->wait_lock); /* * The ACQUIRE semantics of the following spinning code ensure @@ -99,7 +99,7 @@ void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts) /* * Signal the next one in queue to become queue head */ - arch_spin_unlock(&lock->lock); + arch_spin_unlock(&lock->wait_lock); } EXPORT_SYMBOL(queued_read_lock_slowpath); @@ -112,7 +112,7 @@ void queued_write_lock_slowpath(struct qrwlock *lock) u32 cnts; /* Put the writer into the wait queue */ - arch_spin_lock(&lock->lock); + arch_spin_lock(&lock->wait_lock); /* Try to acquire the lock directly if no reader is present */ if (!atomic_read(&lock->cnts) && @@ -144,6 +144,6 @@ void queued_write_lock_slowpath(struct qrwlock *lock) cpu_relax_lowlatency(); } unlock: - arch_spin_unlock(&lock->lock); + arch_spin_unlock(&lock->wait_lock); } EXPORT_SYMBOL(queued_write_lock_slowpath); -- cgit v1.3-6-gb490 From e781b7f7fcc141d69f63d4eef70d249549dfaeda Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 16 Sep 2015 20:21:53 +0200 Subject: Bluetooth: Add BT_ERR_RATELIMITED This patch adds ratelimited version of the BT_ERR macro. Signed-off-by: Szymon Janc Signed-off-by: Marcel Holtmann --- include/net/bluetooth/bluetooth.h | 4 ++++ net/bluetooth/lib.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index fcf2ae7dbfa0..f5ade8573393 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -123,11 +123,15 @@ __printf(1, 2) void bt_info(const char *fmt, ...); __printf(1, 2) void bt_err(const char *fmt, ...); +__printf(1, 2) +void bt_err_ratelimited(const char *fmt, ...); #define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__) #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__) #define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__) +#define BT_ERR_RATELIMITED(fmt, ...) bt_err_ratelimited(fmt "\n", ##__VA_ARGS__) + #define bt_dev_info(hdev, fmt, ...) \ BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__) #define bt_dev_err(hdev, fmt, ...) \ diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index b36bc0415854..8b4cdce3f62e 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -166,3 +166,19 @@ void bt_err(const char *format, ...) va_end(args); } EXPORT_SYMBOL(bt_err); + +void bt_err_ratelimited(const char *format, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, format); + + vaf.fmt = format; + vaf.va = &args; + + pr_err_ratelimited("%pV", &vaf); + + va_end(args); +} +EXPORT_SYMBOL(bt_err_ratelimited); -- cgit v1.3-6-gb490 From d6157e4f18173ad24441aa9ca04e7e9121a9b4c7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 10 Aug 2015 16:41:45 +0200 Subject: ARM: at91: remove useless includes in platform_data/atmel.h include/linux/platform_data/atmel.h has a lot of useless includes, remove them. Signed-off-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- include/linux/platform_data/atmel.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'include') diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 527a85c61924..4d67a5e82c83 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -9,15 +9,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include #include -#include /* * at91: 6 USARTs and one DBGU port (SAM9260) -- cgit v1.3-6-gb490 From fa128fd735bd236b6b04d3fedfed7a784137c185 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 11:56:28 -0400 Subject: jump_label: make static_key_enabled() work on static_key_true/false types too static_key_enabled() can be used on struct static_key but not on its wrapper types static_key_true and static_key_false. The function is useful for debugging and management of static keys. Update it so that it can be used for the wrapper types too. Signed-off-by: Tejun Heo Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton --- include/linux/jump_label.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index 7f653e8f6690..c9ca050de846 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -216,11 +216,6 @@ static inline int jump_label_apply_nops(struct module *mod) #define STATIC_KEY_INIT STATIC_KEY_INIT_FALSE #define jump_label_enabled static_key_enabled -static inline bool static_key_enabled(struct static_key *key) -{ - return static_key_count(key) > 0; -} - static inline void static_key_enable(struct static_key *key) { int count = static_key_count(key); @@ -267,6 +262,17 @@ struct static_key_false { #define DEFINE_STATIC_KEY_FALSE(name) \ struct static_key_false name = STATIC_KEY_FALSE_INIT +extern bool ____wrong_branch_error(void); + +#define static_key_enabled(x) \ +({ \ + if (!__builtin_types_compatible_p(typeof(*x), struct static_key) && \ + !__builtin_types_compatible_p(typeof(*x), struct static_key_true) &&\ + !__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \ + ____wrong_branch_error(); \ + static_key_count((struct static_key *)x) > 0; \ +}) + #ifdef HAVE_JUMP_LABEL /* @@ -325,8 +331,6 @@ struct static_key_false { * See jump_label_type() / jump_label_init_type(). */ -extern bool ____wrong_branch_error(void); - #define static_branch_likely(x) \ ({ \ bool branch; \ -- cgit v1.3-6-gb490 From 49d1dc4b81797f88270832b11e9f73809e7e7209 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 11:56:28 -0400 Subject: cgroup: implement static_key based cgroup_subsys_enabled() and cgroup_subsys_on_dfl() Whether a subsys is enabled and attached to the default hierarchy seldom changes and may be tested in the hot paths. This patch implements static_key based cgroup_subsys_enabled() and cgroup_subsys_on_dfl() tests. The following patches will update the users and remove duplicate mechanisms. Signed-off-by: Tejun Heo Acked-by: Zefan Li --- include/linux/cgroup.h | 21 +++++++++++++++++++++ kernel/cgroup.c | 27 ++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index eb7ca55f72ef..c3a9f1eb4097 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -50,6 +51,26 @@ extern struct css_set init_css_set; #include #undef SUBSYS +#define SUBSYS(_x) \ + extern struct static_key_true _x ## _cgrp_subsys_enabled_key; \ + extern struct static_key_true _x ## _cgrp_subsys_on_dfl_key; +#include +#undef SUBSYS + +/** + * cgroup_subsys_enabled - fast test on whether a subsys is enabled + * @ss: subsystem in question + */ +#define cgroup_subsys_enabled(ss) \ + static_branch_likely(&ss ## _enabled_key) + +/** + * cgroup_subsys_on_dfl - fast test on whether a subsys is on default hierarchy + * @ss: subsystem in question + */ +#define cgroup_subsys_on_dfl(ss) \ + static_branch_likely(&ss ## _on_dfl_key) + bool css_has_online_children(struct cgroup_subsys_state *css); struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss); struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup, diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2cf0f79f1fc9..361938911bd1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -139,6 +139,27 @@ static const char *cgroup_subsys_name[] = { }; #undef SUBSYS +/* array of static_keys for cgroup_subsys_enabled() and cgroup_subsys_on_dfl() */ +#define SUBSYS(_x) \ + DEFINE_STATIC_KEY_TRUE(_x ## _cgrp_subsys_enabled_key); \ + DEFINE_STATIC_KEY_TRUE(_x ## _cgrp_subsys_on_dfl_key); \ + EXPORT_SYMBOL_GPL(_x ## _cgrp_subsys_enabled_key); \ + EXPORT_SYMBOL_GPL(_x ## _cgrp_subsys_on_dfl_key); +#include +#undef SUBSYS + +#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys_enabled_key, +static struct static_key_true *cgroup_subsys_enabled_key[] = { +#include +}; +#undef SUBSYS + +#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys_on_dfl_key, +static struct static_key_true *cgroup_subsys_on_dfl_key[] = { +#include +}; +#undef SUBSYS + /* * The default hierarchy, reserved for the subsystems that are otherwise * unattached - it never has more than a single cgroup, and all tasks are @@ -1319,9 +1340,12 @@ static int rebind_subsystems(struct cgroup_root *dst_root, /* default hierarchy doesn't enable controllers by default */ dst_root->subsys_mask |= 1 << ssid; - if (dst_root != &cgrp_dfl_root) { + if (dst_root == &cgrp_dfl_root) { + static_branch_enable(cgroup_subsys_on_dfl_key[ssid]); + } else { dst_root->cgrp.subtree_control |= 1 << ssid; cgroup_refresh_child_subsys_mask(&dst_root->cgrp); + static_branch_disable(cgroup_subsys_on_dfl_key[ssid]); } if (ss->bind) @@ -5483,6 +5507,7 @@ static int __init cgroup_disable(char *str) strcmp(token, ss->legacy_name)) continue; + static_branch_disable(cgroup_subsys_enabled_key[i]); ss->disabled = 1; printk(KERN_INFO "Disabling %s control group subsystem\n", ss->name); -- cgit v1.3-6-gb490 From fc5ed1e95410ad73b2ab8f33cd90eb3bcf6c98a1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 11:56:28 -0400 Subject: cgroup: replace cgroup_subsys->disabled tests with cgroup_subsys_enabled() Replace cgroup_subsys->disabled tests in controllers with cgroup_subsys_enabled(). cgroup_subsys_enabled() requires literal subsys name as its parameter and thus can't be used for cgroup core which iterates through controllers. For cgroup core, introduce and use cgroup_ssid_enabled() which uses slower static_key_enabled() test and can be indexed by subsys ID. This leaves cgroup_subsys->disabled unused. Removed. Signed-off-by: Tejun Heo Acked-by: Zefan Li Cc: Johannes Weiner Cc: Michal Hocko --- include/linux/cgroup-defs.h | 1 - include/linux/hugetlb_cgroup.h | 4 +--- include/linux/memcontrol.h | 4 +--- kernel/cgroup.c | 28 +++++++++++++++++++++------- 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 4d8fcf2187dc..c5d41c3c1f00 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -419,7 +419,6 @@ struct cgroup_subsys { struct task_struct *task); void (*bind)(struct cgroup_subsys_state *root_css); - int disabled; int early_init; /* diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h index bcc853eccc85..7edd30515298 100644 --- a/include/linux/hugetlb_cgroup.h +++ b/include/linux/hugetlb_cgroup.h @@ -48,9 +48,7 @@ int set_hugetlb_cgroup(struct page *page, struct hugetlb_cgroup *h_cg) static inline bool hugetlb_cgroup_disabled(void) { - if (hugetlb_cgrp_subsys.disabled) - return true; - return false; + return !cgroup_subsys_enabled(hugetlb_cgrp_subsys); } extern int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index ad800e62cb7a..9aa7820c2177 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -347,9 +347,7 @@ ino_t page_cgroup_ino(struct page *page); static inline bool mem_cgroup_disabled(void) { - if (memory_cgrp_subsys.disabled) - return true; - return false; + return !cgroup_subsys_enabled(memory_cgrp_subsys); } /* diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 361938911bd1..5703ba791b3d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -224,6 +224,19 @@ static void kill_css(struct cgroup_subsys_state *css); static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[], bool is_add); +/** + * cgroup_ssid_enabled - cgroup subsys enabled test by subsys ID + * @ssid: subsys ID of interest + * + * cgroup_subsys_enabled() can only be used with literal subsys names which + * is fine for individual subsystems but unsuitable for cgroup core. This + * is slower static_key_enabled() based test indexed by @ssid. + */ +static bool cgroup_ssid_enabled(int ssid) +{ + return static_key_enabled(cgroup_subsys_enabled_key[ssid]); +} + /* IDR wrappers which synchronize using cgroup_idr_lock */ static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask) @@ -1482,7 +1495,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) for_each_subsys(ss, i) { if (strcmp(token, ss->legacy_name)) continue; - if (ss->disabled) + if (!cgroup_ssid_enabled(i)) continue; /* Mutually exclusive option 'all' + subsystem name */ @@ -1513,7 +1526,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) */ if (all_ss || (!one_ss && !opts->none && !opts->name)) for_each_subsys(ss, i) - if (!ss->disabled) + if (cgroup_ssid_enabled(i)) opts->subsys_mask |= (1 << i); /* @@ -2762,7 +2775,8 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, if (tok[0] == '\0') continue; for_each_subsys_which(ss, ssid, &tmp_ss_mask) { - if (ss->disabled || strcmp(tok + 1, ss->name)) + if (!cgroup_ssid_enabled(ssid) || + strcmp(tok + 1, ss->name)) continue; if (*tok == '+') { @@ -3320,7 +3334,7 @@ static int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) { int ret; - if (ss->disabled) + if (!cgroup_ssid_enabled(ss->id)) return 0; if (!cfts || cfts[0].name[0] == '\0') @@ -5082,7 +5096,7 @@ int __init cgroup_init(void) * disabled flag and cftype registration needs kmalloc, * both of which aren't available during early_init. */ - if (ss->disabled) + if (!cgroup_ssid_enabled(ssid)) continue; cgrp_dfl_root.subsys_mask |= 1 << ss->id; @@ -5217,7 +5231,8 @@ static int proc_cgroupstats_show(struct seq_file *m, void *v) for_each_subsys(ss, i) seq_printf(m, "%s\t%d\t%d\t%d\n", ss->legacy_name, ss->root->hierarchy_id, - atomic_read(&ss->root->nr_cgrps), !ss->disabled); + atomic_read(&ss->root->nr_cgrps), + cgroup_ssid_enabled(i)); mutex_unlock(&cgroup_mutex); return 0; @@ -5508,7 +5523,6 @@ static int __init cgroup_disable(char *str) continue; static_branch_disable(cgroup_subsys_enabled_key[i]); - ss->disabled = 1; printk(KERN_INFO "Disabling %s control group subsystem\n", ss->name); break; -- cgit v1.3-6-gb490 From 9e10a130d9b62af976d17d120c95f3650769312c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 11:56:28 -0400 Subject: cgroup: replace cgroup_on_dfl() tests in controllers with cgroup_subsys_on_dfl() cgroup_on_dfl() tests whether the cgroup's root is the default hierarchy; however, an individual controller is only interested in whether the controller is attached to the default hierarchy and never tests a cgroup which doesn't belong to the hierarchy that the controller is attached to. This patch replaces cgroup_on_dfl() tests in controllers with faster static_key based cgroup_subsys_on_dfl(). This leaves cgroup core as the only user of cgroup_on_dfl() and the function is moved from the header file to cgroup.c. Signed-off-by: Tejun Heo Acked-by: Zefan Li Cc: Vivek Goyal Cc: Jens Axboe Cc: Johannes Weiner Cc: Michal Hocko --- block/blk-throttle.c | 2 +- block/cfq-iosched.c | 4 ++-- include/linux/cgroup.h | 58 -------------------------------------------------- kernel/cgroup.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/cpuset.c | 23 +++++++++++--------- mm/memcontrol.c | 4 ++-- 6 files changed, 76 insertions(+), 73 deletions(-) (limited to 'include') diff --git a/block/blk-throttle.c b/block/blk-throttle.c index c75a2636dd40..2149a1ddbacf 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -369,7 +369,7 @@ static void throtl_pd_init(struct blkg_policy_data *pd) * regardless of the position of the group in the hierarchy. */ sq->parent_sq = &td->service_queue; - if (cgroup_on_dfl(blkg->blkcg->css.cgroup) && blkg->parent) + if (cgroup_subsys_on_dfl(io_cgrp_subsys) && blkg->parent) sq->parent_sq = &blkg_to_tg(blkg->parent)->service_queue; tg->td = td; } diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 04de88463a98..1f9093e901da 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1581,7 +1581,7 @@ static struct blkcg_policy_data *cfq_cpd_alloc(gfp_t gfp) static void cfq_cpd_init(struct blkcg_policy_data *cpd) { struct cfq_group_data *cgd = cpd_to_cfqgd(cpd); - unsigned int weight = cgroup_on_dfl(blkcg_root.css.cgroup) ? + unsigned int weight = cgroup_subsys_on_dfl(io_cgrp_subsys) ? CGROUP_WEIGHT_DFL : CFQ_WEIGHT_LEGACY_DFL; if (cpd_to_blkcg(cpd) == &blkcg_root) @@ -1599,7 +1599,7 @@ static void cfq_cpd_free(struct blkcg_policy_data *cpd) static void cfq_cpd_bind(struct blkcg_policy_data *cpd) { struct blkcg *blkcg = cpd_to_blkcg(cpd); - bool on_dfl = cgroup_on_dfl(blkcg_root.css.cgroup); + bool on_dfl = cgroup_subsys_on_dfl(io_cgrp_subsys); unsigned int weight = on_dfl ? CGROUP_WEIGHT_DFL : CFQ_WEIGHT_LEGACY_DFL; if (blkcg == &blkcg_root) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index c3a9f1eb4097..355bf2ed8867 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -433,64 +433,6 @@ static inline struct cgroup *task_cgroup(struct task_struct *task, return task_css(task, subsys_id)->cgroup; } -/** - * cgroup_on_dfl - test whether a cgroup is on the default hierarchy - * @cgrp: the cgroup of interest - * - * The default hierarchy is the v2 interface of cgroup and this function - * can be used to test whether a cgroup is on the default hierarchy for - * cases where a subsystem should behave differnetly depending on the - * interface version. - * - * The set of behaviors which change on the default hierarchy are still - * being determined and the mount option is prefixed with __DEVEL__. - * - * List of changed behaviors: - * - * - Mount options "noprefix", "xattr", "clone_children", "release_agent" - * and "name" are disallowed. - * - * - When mounting an existing superblock, mount options should match. - * - * - Remount is disallowed. - * - * - rename(2) is disallowed. - * - * - "tasks" is removed. Everything should be at process granularity. Use - * "cgroup.procs" instead. - * - * - "cgroup.procs" is not sorted. pids will be unique unless they got - * recycled inbetween reads. - * - * - "release_agent" and "notify_on_release" are removed. Replacement - * notification mechanism will be implemented. - * - * - "cgroup.clone_children" is removed. - * - * - "cgroup.subtree_populated" is available. Its value is 0 if the cgroup - * and its descendants contain no task; otherwise, 1. The file also - * generates kernfs notification which can be monitored through poll and - * [di]notify when the value of the file changes. - * - * - cpuset: tasks will be kept in empty cpusets when hotplug happens and - * take masks of ancestors with non-empty cpus/mems, instead of being - * moved to an ancestor. - * - * - cpuset: a task can be moved into an empty cpuset, and again it takes - * masks of ancestors. - * - * - memcg: use_hierarchy is on by default and the cgroup file for the flag - * is not created. - * - * - blkcg: blk-throttle becomes properly hierarchical. - * - * - debug: disallowed on the default hierarchy. - */ -static inline bool cgroup_on_dfl(const struct cgroup *cgrp) -{ - return cgrp->root == &cgrp_dfl_root; -} - /* no synchronization, the result can only be used as a hint */ static inline bool cgroup_has_tasks(struct cgroup *cgrp) { diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 5703ba791b3d..c24f929fdeb7 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -237,6 +237,64 @@ static bool cgroup_ssid_enabled(int ssid) return static_key_enabled(cgroup_subsys_enabled_key[ssid]); } +/** + * cgroup_on_dfl - test whether a cgroup is on the default hierarchy + * @cgrp: the cgroup of interest + * + * The default hierarchy is the v2 interface of cgroup and this function + * can be used to test whether a cgroup is on the default hierarchy for + * cases where a subsystem should behave differnetly depending on the + * interface version. + * + * The set of behaviors which change on the default hierarchy are still + * being determined and the mount option is prefixed with __DEVEL__. + * + * List of changed behaviors: + * + * - Mount options "noprefix", "xattr", "clone_children", "release_agent" + * and "name" are disallowed. + * + * - When mounting an existing superblock, mount options should match. + * + * - Remount is disallowed. + * + * - rename(2) is disallowed. + * + * - "tasks" is removed. Everything should be at process granularity. Use + * "cgroup.procs" instead. + * + * - "cgroup.procs" is not sorted. pids will be unique unless they got + * recycled inbetween reads. + * + * - "release_agent" and "notify_on_release" are removed. Replacement + * notification mechanism will be implemented. + * + * - "cgroup.clone_children" is removed. + * + * - "cgroup.subtree_populated" is available. Its value is 0 if the cgroup + * and its descendants contain no task; otherwise, 1. The file also + * generates kernfs notification which can be monitored through poll and + * [di]notify when the value of the file changes. + * + * - cpuset: tasks will be kept in empty cpusets when hotplug happens and + * take masks of ancestors with non-empty cpus/mems, instead of being + * moved to an ancestor. + * + * - cpuset: a task can be moved into an empty cpuset, and again it takes + * masks of ancestors. + * + * - memcg: use_hierarchy is on by default and the cgroup file for the flag + * is not created. + * + * - blkcg: blk-throttle becomes properly hierarchical. + * + * - debug: disallowed on the default hierarchy. + */ +static bool cgroup_on_dfl(const struct cgroup *cgrp) +{ + return cgrp->root == &cgrp_dfl_root; +} + /* IDR wrappers which synchronize using cgroup_idr_lock */ static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index f0acff0f66c9..20eedd8098c0 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -473,7 +473,8 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial) /* On legacy hiearchy, we must be a subset of our parent cpuset. */ ret = -EACCES; - if (!cgroup_on_dfl(cur->css.cgroup) && !is_cpuset_subset(trial, par)) + if (!cgroup_subsys_on_dfl(cpuset_cgrp_subsys) && + !is_cpuset_subset(trial, par)) goto out; /* @@ -879,7 +880,8 @@ static void update_cpumasks_hier(struct cpuset *cs, struct cpumask *new_cpus) * If it becomes empty, inherit the effective mask of the * parent, which is guaranteed to have some CPUs. */ - if (cgroup_on_dfl(cp->css.cgroup) && cpumask_empty(new_cpus)) + if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys) && + cpumask_empty(new_cpus)) cpumask_copy(new_cpus, parent->effective_cpus); /* Skip the whole subtree if the cpumask remains the same. */ @@ -896,7 +898,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct cpumask *new_cpus) cpumask_copy(cp->effective_cpus, new_cpus); spin_unlock_irq(&callback_lock); - WARN_ON(!cgroup_on_dfl(cp->css.cgroup) && + WARN_ON(!cgroup_subsys_on_dfl(cpuset_cgrp_subsys) && !cpumask_equal(cp->cpus_allowed, cp->effective_cpus)); update_tasks_cpumask(cp); @@ -1135,7 +1137,8 @@ static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems) * If it becomes empty, inherit the effective mask of the * parent, which is guaranteed to have some MEMs. */ - if (cgroup_on_dfl(cp->css.cgroup) && nodes_empty(*new_mems)) + if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys) && + nodes_empty(*new_mems)) *new_mems = parent->effective_mems; /* Skip the whole subtree if the nodemask remains the same. */ @@ -1152,7 +1155,7 @@ static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems) cp->effective_mems = *new_mems; spin_unlock_irq(&callback_lock); - WARN_ON(!cgroup_on_dfl(cp->css.cgroup) && + WARN_ON(!cgroup_subsys_on_dfl(cpuset_cgrp_subsys) && !nodes_equal(cp->mems_allowed, cp->effective_mems)); update_tasks_nodemask(cp); @@ -1440,7 +1443,7 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css, /* allow moving tasks into an empty cpuset if on default hierarchy */ ret = -ENOSPC; - if (!cgroup_on_dfl(css->cgroup) && + if (!cgroup_subsys_on_dfl(cpuset_cgrp_subsys) && (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))) goto out_unlock; @@ -1952,7 +1955,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) cpuset_inc(); spin_lock_irq(&callback_lock); - if (cgroup_on_dfl(cs->css.cgroup)) { + if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys)) { cpumask_copy(cs->effective_cpus, parent->effective_cpus); cs->effective_mems = parent->effective_mems; } @@ -2029,7 +2032,7 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css) mutex_lock(&cpuset_mutex); spin_lock_irq(&callback_lock); - if (cgroup_on_dfl(root_css->cgroup)) { + if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys)) { cpumask_copy(top_cpuset.cpus_allowed, cpu_possible_mask); top_cpuset.mems_allowed = node_possible_map; } else { @@ -2210,7 +2213,7 @@ retry: cpus_updated = !cpumask_equal(&new_cpus, cs->effective_cpus); mems_updated = !nodes_equal(new_mems, cs->effective_mems); - if (cgroup_on_dfl(cs->css.cgroup)) + if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys)) hotplug_update_tasks(cs, &new_cpus, &new_mems, cpus_updated, mems_updated); else @@ -2241,7 +2244,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work) static cpumask_t new_cpus; static nodemask_t new_mems; bool cpus_updated, mems_updated; - bool on_dfl = cgroup_on_dfl(top_cpuset.css.cgroup); + bool on_dfl = cgroup_subsys_on_dfl(cpuset_cgrp_subsys); mutex_lock(&cpuset_mutex); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6ddaeba34e09..b35c4cc47a30 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -434,7 +434,7 @@ struct cgroup_subsys_state *mem_cgroup_css_from_page(struct page *page) memcg = page->mem_cgroup; - if (!memcg || !cgroup_on_dfl(memcg->css.cgroup)) + if (!memcg || !cgroup_subsys_on_dfl(memory_cgrp_subsys)) memcg = root_mem_cgroup; rcu_read_unlock(); @@ -5059,7 +5059,7 @@ static void mem_cgroup_bind(struct cgroup_subsys_state *root_css) * guarantees that @root doesn't have any children, so turning it * on for the root memcg is enough. */ - if (cgroup_on_dfl(root_css->cgroup)) + if (cgroup_subsys_on_dfl(memory_cgrp_subsys)) root_mem_cgroup->use_hierarchy = true; else root_mem_cgroup->use_hierarchy = false; -- cgit v1.3-6-gb490 From 339e5b44eda2150baad183def6b7030fad5ec44e Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 18 Sep 2015 13:58:34 -0500 Subject: PCI: Add msi_controller setup_irqs() method for special multivector setup Add a msi_controller setup_irqs() method so MSI chip providers can implement their own multivector MSI setup. [bhelgaas: changelog] Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Reviewed-by: Pratyush Anand --- drivers/pci/msi.c | 3 +++ include/linux/msi.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d4497141d083..74319f497656 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -105,9 +105,12 @@ void __weak arch_teardown_msi_irq(unsigned int irq) int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { + struct msi_controller *chip = dev->bus->msi; struct msi_desc *entry; int ret; + if (chip && chip->setup_irqs) + return chip->setup_irqs(chip, dev, nvec, type); /* * If an architecture wants to support multiple MSI, it needs to * override arch_setup_msi_irqs() diff --git a/include/linux/msi.h b/include/linux/msi.h index ad939d0ba816..0be5db110bfa 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -163,6 +163,8 @@ struct msi_controller { int (*setup_irq)(struct msi_controller *chip, struct pci_dev *dev, struct msi_desc *desc); + int (*setup_irqs)(struct msi_controller *chip, struct pci_dev *dev, + int nvec, int type); void (*teardown_irq)(struct msi_controller *chip, unsigned int irq); }; -- cgit v1.3-6-gb490 From 97b59c3a91d5ee4777658ff2136d1fdf13bd23d0 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:32:54 -0500 Subject: netfilter: ebtables: Simplify the arguments to ebt_do_table Nearly everything thing of interest to ebt_do_table is already present in nf_hook_state. Simplify ebt_do_table by just passing in the skb, nf_hook_state, and the table. This make the code easier to read and maintenance easier. To support this create an nf_hook_state on the stack in ebt_broute (the only caller without a nf_hook_state already available). This new nf_hook_state adds no new computations to ebt_broute, but does use a few more bytes of stack. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter_bridge/ebtables.h | 6 +++--- net/bridge/netfilter/ebtable_broute.c | 8 ++++++-- net/bridge/netfilter/ebtable_filter.c | 6 ++---- net/bridge/netfilter/ebtable_nat.c | 6 ++---- net/bridge/netfilter/ebtables.c | 13 +++++++------ 5 files changed, 20 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 8ca6d6464ea3..2ea517c7c6b9 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -111,9 +111,9 @@ struct ebt_table { extern struct ebt_table *ebt_register_table(struct net *net, const struct ebt_table *table); extern void ebt_unregister_table(struct net *net, struct ebt_table *table); -extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, - const struct net_device *in, const struct net_device *out, - struct ebt_table *table); +extern unsigned int ebt_do_table(struct sk_buff *skb, + const struct nf_hook_state *state, + struct ebt_table *table); /* Used in the kernel match() functions */ #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index d2cdf5d6e98c..ec94c6f1ae88 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -50,10 +50,14 @@ static const struct ebt_table broute_table = { static int ebt_broute(struct sk_buff *skb) { + struct nf_hook_state state; int ret; - ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, - dev_net(skb->dev)->xt.broute_table); + nf_hook_state_init(&state, NULL, NF_BR_BROUTING, INT_MIN, + NFPROTO_BRIDGE, skb->dev, NULL, NULL, + dev_net(skb->dev), NULL); + + ret = ebt_do_table(skb, &state, state.net->xt.broute_table); if (ret == NF_DROP) return 1; /* route it */ return 0; /* bridge it */ diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index ab20d6ed6e2f..118ce40ac181 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -60,16 +60,14 @@ static unsigned int ebt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ebt_do_table(ops->hooknum, skb, state->in, state->out, - state->net->xt.frame_filter); + return ebt_do_table(skb, state, state->net->xt.frame_filter); } static unsigned int ebt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ebt_do_table(ops->hooknum, skb, state->in, state->out, - state->net->xt.frame_filter); + return ebt_do_table(skb, state, state->net->xt.frame_filter); } static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index ad81a5a65644..56c3329d6c37 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -60,16 +60,14 @@ static unsigned int ebt_nat_in(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ebt_do_table(ops->hooknum, skb, state->in, state->out, - state->net->xt.frame_nat); + return ebt_do_table(skb, state, state->net->xt.frame_nat); } static unsigned int ebt_nat_out(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ebt_do_table(ops->hooknum, skb, state->in, state->out, - state->net->xt.frame_nat); + return ebt_do_table(skb, state, state->net->xt.frame_nat); } static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 48b6b01295de..8d5a3975b963 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -183,10 +183,11 @@ struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry) } /* Do some firewalling */ -unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, - const struct net_device *in, const struct net_device *out, - struct ebt_table *table) +unsigned int ebt_do_table(struct sk_buff *skb, + const struct nf_hook_state *state, + struct ebt_table *table) { + unsigned int hook = state->hook; int i, nentries; struct ebt_entry *point; struct ebt_counter *counter_base, *cb_base; @@ -199,8 +200,8 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, struct xt_action_param acpar; acpar.family = NFPROTO_BRIDGE; - acpar.in = in; - acpar.out = out; + acpar.in = state->in; + acpar.out = state->out; acpar.hotdrop = false; acpar.hooknum = hook; @@ -220,7 +221,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, base = private->entries; i = 0; while (i < nentries) { - if (ebt_basic_match(point, skb, in, out)) + if (ebt_basic_match(point, skb, state->in, state->out)) goto letscontinue; if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0) -- cgit v1.3-6-gb490 From 6cb8ff3f1a535b1d8eb5ea318932513d08eb3da7 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:32:55 -0500 Subject: inet netfilter: Remove hook from ip6t_do_table, arp_do_table, ipt_do_table The values of ops->hooknum and state->hook are guaraneted to be equal making the hook argument to ip6t_do_table, arp_do_table, and ipt_do_table is unnecessary. Remove the unnecessary hook argument. In the callers use state->hook instead of ops->hooknum for clarity and to reduce the number of cachelines the callers touch. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter_arp/arp_tables.h | 1 - include/linux/netfilter_ipv4/ip_tables.h | 1 - include/linux/netfilter_ipv6/ip6_tables.h | 1 - net/ipv4/netfilter/arp_tables.c | 2 +- net/ipv4/netfilter/arptable_filter.c | 3 +-- net/ipv4/netfilter/ip_tables.c | 2 +- net/ipv4/netfilter/iptable_filter.c | 5 ++--- net/ipv4/netfilter/iptable_mangle.c | 12 +++++------- net/ipv4/netfilter/iptable_nat.c | 3 +-- net/ipv4/netfilter/iptable_raw.c | 5 ++--- net/ipv4/netfilter/iptable_security.c | 5 ++--- net/ipv6/netfilter/ip6_tables.c | 2 +- net/ipv6/netfilter/ip6table_filter.c | 3 +-- net/ipv6/netfilter/ip6table_mangle.c | 12 +++++------- net/ipv6/netfilter/ip6table_nat.c | 3 +-- net/ipv6/netfilter/ip6table_raw.c | 3 +-- net/ipv6/netfilter/ip6table_security.c | 3 +-- 17 files changed, 25 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index c22a7fb8d0df..6f074db2f23d 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -53,7 +53,6 @@ extern struct xt_table *arpt_register_table(struct net *net, const struct arpt_replace *repl); extern void arpt_unregister_table(struct xt_table *table); extern unsigned int arpt_do_table(struct sk_buff *skb, - unsigned int hook, const struct nf_hook_state *state, struct xt_table *table); diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 4073510da485..aa598f942c01 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -64,7 +64,6 @@ struct ipt_error { extern void *ipt_alloc_initial_table(const struct xt_table *); extern unsigned int ipt_do_table(struct sk_buff *skb, - unsigned int hook, const struct nf_hook_state *state, struct xt_table *table); diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index b40d2b635778..0f76e5c674f9 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -30,7 +30,6 @@ extern struct xt_table *ip6t_register_table(struct net *net, const struct ip6t_replace *repl); extern void ip6t_unregister_table(struct net *net, struct xt_table *table); extern unsigned int ip6t_do_table(struct sk_buff *skb, - unsigned int hook, const struct nf_hook_state *state, struct xt_table *table); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 8f87fc38ccde..10eb2b297450 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -247,10 +247,10 @@ struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry) } unsigned int arpt_do_table(struct sk_buff *skb, - unsigned int hook, const struct nf_hook_state *state, struct xt_table *table) { + unsigned int hook = state->hook; static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); unsigned int verdict = NF_DROP; const struct arphdr *arp; diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index d217e4c19645..1352e12d4068 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -30,8 +30,7 @@ static unsigned int arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return arpt_do_table(skb, ops->hooknum, state, - state->net->ipv4.arptable_filter); + return arpt_do_table(skb, state, state->net->ipv4.arptable_filter); } static struct nf_hook_ops *arpfilter_ops __read_mostly; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 5d514eac4c31..2b049e135de8 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -285,10 +285,10 @@ struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry) /* Returns one of the generic firewall policies, like NF_ACCEPT. */ unsigned int ipt_do_table(struct sk_buff *skb, - unsigned int hook, const struct nf_hook_state *state, struct xt_table *table) { + unsigned int hook = state->hook; static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); const struct iphdr *ip; /* Initializing verdict to NF_DROP keeps gcc happy. */ diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 32feff32b116..02d4c5395d6e 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -36,14 +36,13 @@ static unsigned int iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - if (ops->hooknum == NF_INET_LOCAL_OUT && + if (state->hook == NF_INET_LOCAL_OUT && (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr))) /* root is playing with raw sockets. */ return NF_ACCEPT; - return ipt_do_table(skb, ops->hooknum, state, - state->net->ipv4.iptable_filter); + return ipt_do_table(skb, state, state->net->ipv4.iptable_filter); } static struct nf_hook_ops *filter_ops __read_mostly; diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 4a5150fc9510..dc2ff6884999 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -58,8 +58,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) daddr = iph->daddr; tos = iph->tos; - ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, state, - state->net->ipv4.iptable_mangle); + ret = ipt_do_table(skb, state, state->net->ipv4.iptable_mangle); /* Reroute for ANY change. */ if (ret != NF_DROP && ret != NF_STOLEN) { iph = ip_hdr(skb); @@ -83,14 +82,13 @@ iptable_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - if (ops->hooknum == NF_INET_LOCAL_OUT) + if (state->hook == NF_INET_LOCAL_OUT) return ipt_mangle_out(skb, state); - if (ops->hooknum == NF_INET_POST_ROUTING) - return ipt_do_table(skb, ops->hooknum, state, + if (state->hook == NF_INET_POST_ROUTING) + return ipt_do_table(skb, state, state->net->ipv4.iptable_mangle); /* PREROUTING/INPUT/FORWARD: */ - return ipt_do_table(skb, ops->hooknum, state, - state->net->ipv4.iptable_mangle); + return ipt_do_table(skb, state, state->net->ipv4.iptable_mangle); } static struct nf_hook_ops *mangle_ops __read_mostly; diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 4f4c64f81169..8ff63ac1f0d6 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -33,8 +33,7 @@ static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops, const struct nf_hook_state *state, struct nf_conn *ct) { - return ipt_do_table(skb, ops->hooknum, state, - state->net->ipv4.nat_table); + return ipt_do_table(skb, state, state->net->ipv4.nat_table); } static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops, diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 20126e469ffb..bbb0523d87de 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -23,14 +23,13 @@ static unsigned int iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - if (ops->hooknum == NF_INET_LOCAL_OUT && + if (state->hook == NF_INET_LOCAL_OUT && (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr))) /* root is playing with raw sockets. */ return NF_ACCEPT; - return ipt_do_table(skb, ops->hooknum, state, - state->net->ipv4.iptable_raw); + return ipt_do_table(skb, state, state->net->ipv4.iptable_raw); } static struct nf_hook_ops *rawtable_ops __read_mostly; diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 82fefd609b85..b92417038705 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -40,14 +40,13 @@ static unsigned int iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - if (ops->hooknum == NF_INET_LOCAL_OUT && + if (state->hook == NF_INET_LOCAL_OUT && (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr))) /* Somebody is playing with raw sockets. */ return NF_ACCEPT; - return ipt_do_table(skb, ops->hooknum, state, - state->net->ipv4.iptable_security); + return ipt_do_table(skb, state, state->net->ipv4.iptable_security); } static struct nf_hook_ops *sectbl_ops __read_mostly; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index cd9b401231d3..da6446b6e3f9 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -314,10 +314,10 @@ ip6t_next_entry(const struct ip6t_entry *entry) /* Returns one of the generic firewall policies, like NF_ACCEPT. */ unsigned int ip6t_do_table(struct sk_buff *skb, - unsigned int hook, const struct nf_hook_state *state, struct xt_table *table) { + unsigned int hook = state->hook; static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); /* Initializing verdict to NF_DROP keeps gcc happy. */ unsigned int verdict = NF_DROP; diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 2449005fb5dc..a7327f61b90c 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -35,8 +35,7 @@ static unsigned int ip6table_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ip6t_do_table(skb, ops->hooknum, state, - state->net->ipv6.ip6table_filter); + return ip6t_do_table(skb, state, state->net->ipv6.ip6table_filter); } static struct nf_hook_ops *filter_ops __read_mostly; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index a46dbf097d29..c2e061dcedf3 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -57,8 +57,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *)ipv6_hdr(skb)); - ret = ip6t_do_table(skb, NF_INET_LOCAL_OUT, state, - state->net->ipv6.ip6table_mangle); + ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); if (ret != NF_DROP && ret != NF_STOLEN && (!ipv6_addr_equal(&ipv6_hdr(skb)->saddr, &saddr) || @@ -79,14 +78,13 @@ static unsigned int ip6table_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - if (ops->hooknum == NF_INET_LOCAL_OUT) + if (state->hook == NF_INET_LOCAL_OUT) return ip6t_mangle_out(skb, state); - if (ops->hooknum == NF_INET_POST_ROUTING) - return ip6t_do_table(skb, ops->hooknum, state, + if (state->hook == NF_INET_POST_ROUTING) + return ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); /* INPUT/FORWARD */ - return ip6t_do_table(skb, ops->hooknum, state, - state->net->ipv6.ip6table_mangle); + return ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); } static struct nf_hook_ops *mangle_ops __read_mostly; diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index a56451de127f..efa6754c4d06 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -35,8 +35,7 @@ static unsigned int ip6table_nat_do_chain(const struct nf_hook_ops *ops, const struct nf_hook_state *state, struct nf_conn *ct) { - return ip6t_do_table(skb, ops->hooknum, state, - state->net->ipv6.ip6table_nat); + return ip6t_do_table(skb, state, state->net->ipv6.ip6table_nat); } static unsigned int ip6table_nat_fn(const struct nf_hook_ops *ops, diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 18e831e35782..fac6ad7c0a7c 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -22,8 +22,7 @@ static unsigned int ip6table_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ip6t_do_table(skb, ops->hooknum, state, - state->net->ipv6.ip6table_raw); + return ip6t_do_table(skb, state, state->net->ipv6.ip6table_raw); } static struct nf_hook_ops *rawtable_ops __read_mostly; diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 83bc96ae5d73..96c94fc240c8 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -39,8 +39,7 @@ static unsigned int ip6table_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - return ip6t_do_table(skb, ops->hooknum, state, - state->net->ipv6.ip6table_security); + return ip6t_do_table(skb, state, state->net->ipv6.ip6table_security); } static struct nf_hook_ops *sectbl_ops __read_mostly; -- cgit v1.3-6-gb490 From 6aa187f21ca2d8ade791f01fd8fab908b1f27673 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:32:57 -0500 Subject: netfilter: nf_tables: kill nft_pktinfo.ops - Add nft_pktinfo.pf to replace ops->pf - Add nft_pktinfo.hook to replace ops->hooknum This simplifies the code, makes it more readable, and likely reduces cache line misses. Maintainability is enhanced as the details of nft_hook_ops are of no concern to the recpients of nft_pktinfo. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 9 ++++----- include/net/netfilter/nf_tables_ipv4.h | 3 +-- include/net/netfilter/nf_tables_ipv6.h | 3 +-- net/bridge/netfilter/nf_tables_bridge.c | 16 +++++++--------- net/bridge/netfilter/nft_reject_bridge.c | 12 ++++++------ net/ipv4/netfilter/nf_tables_arp.c | 2 +- net/ipv4/netfilter/nf_tables_ipv4.c | 2 +- net/ipv4/netfilter/nft_chain_nat_ipv4.c | 2 +- net/ipv4/netfilter/nft_chain_route_ipv4.c | 2 +- net/ipv4/netfilter/nft_dup_ipv4.c | 2 +- net/ipv4/netfilter/nft_masq_ipv4.c | 2 +- net/ipv4/netfilter/nft_redir_ipv4.c | 2 +- net/ipv4/netfilter/nft_reject_ipv4.c | 5 ++--- net/ipv6/netfilter/nf_tables_ipv6.c | 2 +- net/ipv6/netfilter/nft_chain_nat_ipv6.c | 2 +- net/ipv6/netfilter/nft_chain_route_ipv6.c | 2 +- net/ipv6/netfilter/nft_dup_ipv6.c | 2 +- net/ipv6/netfilter/nft_redir_ipv6.c | 3 +-- net/ipv6/netfilter/nft_reject_ipv6.c | 5 ++--- net/netfilter/nf_tables_core.c | 2 +- net/netfilter/nf_tables_netdev.c | 16 +++++++--------- net/netfilter/nft_log.c | 2 +- net/netfilter/nft_meta.c | 4 ++-- net/netfilter/nft_queue.c | 2 +- net/netfilter/nft_reject_inet.c | 14 +++++++------- 25 files changed, 54 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index aa8bee72c9d3..c0899f97ff8d 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -16,7 +16,8 @@ struct nft_pktinfo { struct sk_buff *skb; const struct net_device *in; const struct net_device *out; - const struct nf_hook_ops *ops; + u8 pf; + u8 hook; u8 nhoff; u8 thoff; u8 tprot; @@ -25,16 +26,14 @@ struct nft_pktinfo { }; static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { pkt->skb = skb; pkt->in = pkt->xt.in = state->in; pkt->out = pkt->xt.out = state->out; - pkt->ops = ops; - pkt->xt.hooknum = ops->hooknum; - pkt->xt.family = ops->pf; + pkt->hook = pkt->xt.hooknum = state->hook; + pkt->pf = pkt->xt.family = state->pf; } /** diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h index 2df7f96902ee..ca6ef6bf775e 100644 --- a/include/net/netfilter/nf_tables_ipv4.h +++ b/include/net/netfilter/nf_tables_ipv4.h @@ -6,13 +6,12 @@ static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *ip; - nft_set_pktinfo(pkt, ops, skb, state); + nft_set_pktinfo(pkt, skb, state); ip = ip_hdr(pkt->skb); pkt->tprot = ip->protocol; diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h index 97db2e3a5e65..8ad39a6a5fe1 100644 --- a/include/net/netfilter/nf_tables_ipv6.h +++ b/include/net/netfilter/nf_tables_ipv6.h @@ -6,14 +6,13 @@ static inline int nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { int protohdr, thoff = 0; unsigned short frag_off; - nft_set_pktinfo(pkt, ops, skb, state); + nft_set_pktinfo(pkt, skb, state); protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL); /* If malformed, drop it */ diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index a343e62442b1..318d825e4207 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c @@ -65,27 +65,25 @@ int nft_bridge_ip6hdr_validate(struct sk_buff *skb) EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate); static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { if (nft_bridge_iphdr_validate(skb)) - nft_set_pktinfo_ipv4(pkt, ops, skb, state); + nft_set_pktinfo_ipv4(pkt, skb, state); else - nft_set_pktinfo(pkt, ops, skb, state); + nft_set_pktinfo(pkt, skb, state); } static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { #if IS_ENABLED(CONFIG_IPV6) if (nft_bridge_ip6hdr_validate(skb) && - nft_set_pktinfo_ipv6(pkt, ops, skb, state) == 0) + nft_set_pktinfo_ipv6(pkt, skb, state) == 0) return; #endif - nft_set_pktinfo(pkt, ops, skb, state); + nft_set_pktinfo(pkt, skb, state); } static unsigned int @@ -97,13 +95,13 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops, switch (eth_hdr(skb)->h_proto) { case htons(ETH_P_IP): - nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, state); + nft_bridge_set_pktinfo_ipv4(&pkt, skb, state); break; case htons(ETH_P_IPV6): - nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, state); + nft_bridge_set_pktinfo_ipv6(&pkt, skb, state); break; default: - nft_set_pktinfo(&pkt, ops, skb, state); + nft_set_pktinfo(&pkt, skb, state); break; } diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index 858d848564ee..cee92612b2cc 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c @@ -273,16 +273,16 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: nft_reject_br_send_v4_unreach(pkt->skb, pkt->in, - pkt->ops->hooknum, + pkt->hook, priv->icmp_code); break; case NFT_REJECT_TCP_RST: nft_reject_br_send_v4_tcp_reset(pkt->skb, pkt->in, - pkt->ops->hooknum); + pkt->hook); break; case NFT_REJECT_ICMPX_UNREACH: nft_reject_br_send_v4_unreach(pkt->skb, pkt->in, - pkt->ops->hooknum, + pkt->hook, nft_reject_icmp_code(priv->icmp_code)); break; } @@ -291,16 +291,16 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: nft_reject_br_send_v6_unreach(net, pkt->skb, pkt->in, - pkt->ops->hooknum, + pkt->hook, priv->icmp_code); break; case NFT_REJECT_TCP_RST: nft_reject_br_send_v6_tcp_reset(net, pkt->skb, pkt->in, - pkt->ops->hooknum); + pkt->hook); break; case NFT_REJECT_ICMPX_UNREACH: nft_reject_br_send_v6_unreach(net, pkt->skb, pkt->in, - pkt->ops->hooknum, + pkt->hook, nft_reject_icmpv6_code(priv->icmp_code)); break; } diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c index 8412268bbad1..883bbf83fe09 100644 --- a/net/ipv4/netfilter/nf_tables_arp.c +++ b/net/ipv4/netfilter/nf_tables_arp.c @@ -21,7 +21,7 @@ nft_do_chain_arp(const struct nf_hook_ops *ops, { struct nft_pktinfo pkt; - nft_set_pktinfo(&pkt, ops, skb, state); + nft_set_pktinfo(&pkt, skb, state); return nft_do_chain(&pkt, ops); } diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c index aa180d3a69a5..805be5c9fcc3 100644 --- a/net/ipv4/netfilter/nf_tables_ipv4.c +++ b/net/ipv4/netfilter/nf_tables_ipv4.c @@ -24,7 +24,7 @@ static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops, { struct nft_pktinfo pkt; - nft_set_pktinfo_ipv4(&pkt, ops, skb, state); + nft_set_pktinfo_ipv4(&pkt, skb, state); return nft_do_chain(&pkt, ops); } diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c index bf5c30ae14e4..c3ffecf28d38 100644 --- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c @@ -33,7 +33,7 @@ static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops, { struct nft_pktinfo pkt; - nft_set_pktinfo_ipv4(&pkt, ops, skb, state); + nft_set_pktinfo_ipv4(&pkt, skb, state); return nft_do_chain(&pkt, ops); } diff --git a/net/ipv4/netfilter/nft_chain_route_ipv4.c b/net/ipv4/netfilter/nft_chain_route_ipv4.c index e335b0afdaf3..2a1e3d8a3e43 100644 --- a/net/ipv4/netfilter/nft_chain_route_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c @@ -37,7 +37,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; - nft_set_pktinfo_ipv4(&pkt, ops, skb, state); + nft_set_pktinfo_ipv4(&pkt, skb, state); mark = skb->mark; iph = ip_hdr(skb); diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c index b45932d43b69..30bcf820e8bd 100644 --- a/net/ipv4/netfilter/nft_dup_ipv4.c +++ b/net/ipv4/netfilter/nft_dup_ipv4.c @@ -30,7 +30,7 @@ static void nft_dup_ipv4_eval(const struct nft_expr *expr, }; int oif = regs->data[priv->sreg_dev]; - nf_dup_ipv4(pkt->skb, pkt->ops->hooknum, &gw, oif); + nf_dup_ipv4(pkt->skb, pkt->hook, &gw, oif); } static int nft_dup_ipv4_init(const struct nft_ctx *ctx, diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c index 40e414c4ca56..b72ffc58e255 100644 --- a/net/ipv4/netfilter/nft_masq_ipv4.c +++ b/net/ipv4/netfilter/nft_masq_ipv4.c @@ -26,7 +26,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, memset(&range, 0, sizeof(range)); range.flags = priv->flags; - regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, + regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook, &range, pkt->out); } diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c index d8d795df9c13..c09d4381427e 100644 --- a/net/ipv4/netfilter/nft_redir_ipv4.c +++ b/net/ipv4/netfilter/nft_redir_ipv4.c @@ -36,7 +36,7 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr, mr.range[0].flags |= priv->flags; regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, - pkt->ops->hooknum); + pkt->hook); } static struct nft_expr_type nft_redir_ipv4_type; diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index b07e58b51158..c1582e03b628 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c @@ -27,11 +27,10 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr, switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: - nf_send_unreach(pkt->skb, priv->icmp_code, - pkt->ops->hooknum); + nf_send_unreach(pkt->skb, priv->icmp_code, pkt->hook); break; case NFT_REJECT_TCP_RST: - nf_send_reset(pkt->skb, pkt->ops->hooknum); + nf_send_reset(pkt->skb, pkt->hook); break; default: break; diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c index c8148ba76d1a..41340b794f9b 100644 --- a/net/ipv6/netfilter/nf_tables_ipv6.c +++ b/net/ipv6/netfilter/nf_tables_ipv6.c @@ -23,7 +23,7 @@ static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops, struct nft_pktinfo pkt; /* malformed packet, drop it */ - if (nft_set_pktinfo_ipv6(&pkt, ops, skb, state) < 0) + if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0) return NF_DROP; return nft_do_chain(&pkt, ops); diff --git a/net/ipv6/netfilter/nft_chain_nat_ipv6.c b/net/ipv6/netfilter/nft_chain_nat_ipv6.c index 951bb458b7bd..e96feaefeb14 100644 --- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c @@ -31,7 +31,7 @@ static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops, { struct nft_pktinfo pkt; - nft_set_pktinfo_ipv6(&pkt, ops, skb, state); + nft_set_pktinfo_ipv6(&pkt, skb, state); return nft_do_chain(&pkt, ops); } diff --git a/net/ipv6/netfilter/nft_chain_route_ipv6.c b/net/ipv6/netfilter/nft_chain_route_ipv6.c index 0dafdaac5e17..d1bcd2ed7bcc 100644 --- a/net/ipv6/netfilter/nft_chain_route_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c @@ -33,7 +33,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, u32 mark, flowlabel; /* malformed packet, drop it */ - if (nft_set_pktinfo_ipv6(&pkt, ops, skb, state) < 0) + if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0) return NF_DROP; /* save source/dest address, mark, hoplimit, flowlabel, priority */ diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c index 0eaa4f65fdea..c81204faf15d 100644 --- a/net/ipv6/netfilter/nft_dup_ipv6.c +++ b/net/ipv6/netfilter/nft_dup_ipv6.c @@ -28,7 +28,7 @@ static void nft_dup_ipv6_eval(const struct nft_expr *expr, struct in6_addr *gw = (struct in6_addr *)®s->data[priv->sreg_addr]; int oif = regs->data[priv->sreg_dev]; - nf_dup_ipv6(pkt->skb, pkt->ops->hooknum, gw, oif); + nf_dup_ipv6(pkt->skb, pkt->hook, gw, oif); } static int nft_dup_ipv6_init(const struct nft_ctx *ctx, diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c index effd393bd517..aca44e89a881 100644 --- a/net/ipv6/netfilter/nft_redir_ipv6.c +++ b/net/ipv6/netfilter/nft_redir_ipv6.c @@ -35,8 +35,7 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr, range.flags |= priv->flags; - regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, - pkt->ops->hooknum); + regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->hook); } static struct nft_expr_type nft_redir_ipv6_type; diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c index d0d1540ecf87..ffcac7d5da43 100644 --- a/net/ipv6/netfilter/nft_reject_ipv6.c +++ b/net/ipv6/netfilter/nft_reject_ipv6.c @@ -28,11 +28,10 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr, switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: - nf_send_unreach6(net, pkt->skb, priv->icmp_code, - pkt->ops->hooknum); + nf_send_unreach6(net, pkt->skb, priv->icmp_code, pkt->hook); break; case NFT_REJECT_TCP_RST: - nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); + nf_send_reset6(net, pkt->skb, pkt->hook); break; default: break; diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 05d0b03530f6..539083099c0d 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -50,7 +50,7 @@ static void __nft_trace_packet(const struct nft_pktinfo *pkt, { struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); - nf_log_trace(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, + nf_log_trace(net, pkt->pf, pkt->hook, pkt->skb, pkt->in, pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", chain->table->name, chain->name, comments[type], rulenum); diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c index 2cae4d4a03b7..db416a3396e9 100644 --- a/net/netfilter/nf_tables_netdev.c +++ b/net/netfilter/nf_tables_netdev.c @@ -17,13 +17,13 @@ static inline void nft_netdev_set_pktinfo_ipv4(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, + struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *iph, _iph; u32 len, thoff; - nft_set_pktinfo(pkt, ops, skb, state); + nft_set_pktinfo(pkt, skb, state); iph = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*iph), &_iph); @@ -48,7 +48,6 @@ nft_netdev_set_pktinfo_ipv4(struct nft_pktinfo *pkt, static inline void __nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -82,12 +81,11 @@ __nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt, } static inline void nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { - nft_set_pktinfo(pkt, ops, skb, state); - __nft_netdev_set_pktinfo_ipv6(pkt, ops, skb, state); + nft_set_pktinfo(pkt, skb, state); + __nft_netdev_set_pktinfo_ipv6(pkt, skb, state); } static unsigned int @@ -98,13 +96,13 @@ nft_do_chain_netdev(const struct nf_hook_ops *ops, struct sk_buff *skb, switch (eth_hdr(skb)->h_proto) { case htons(ETH_P_IP): - nft_netdev_set_pktinfo_ipv4(&pkt, ops, skb, state); + nft_netdev_set_pktinfo_ipv4(&pkt, skb, state); break; case htons(ETH_P_IPV6): - nft_netdev_set_pktinfo_ipv6(&pkt, ops, skb, state); + nft_netdev_set_pktinfo_ipv6(&pkt, skb, state); break; default: - nft_set_pktinfo(&pkt, ops, skb, state); + nft_set_pktinfo(&pkt, skb, state); break; } diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index a13d6a386d63..c7c7df85f0b7 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c @@ -33,7 +33,7 @@ static void nft_log_eval(const struct nft_expr *expr, const struct nft_log *priv = nft_expr_priv(expr); struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); - nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in, + nf_log_packet(net, pkt->pf, pkt->hook, pkt->skb, pkt->in, pkt->out, &priv->loginfo, "%s", priv->prefix); } diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index cb2f13ebb5a6..e4ad2c24bc41 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -42,7 +42,7 @@ void nft_meta_get_eval(const struct nft_expr *expr, *(__be16 *)dest = skb->protocol; break; case NFT_META_NFPROTO: - *dest = pkt->ops->pf; + *dest = pkt->pf; break; case NFT_META_L4PROTO: *dest = pkt->tprot; @@ -135,7 +135,7 @@ void nft_meta_get_eval(const struct nft_expr *expr, break; } - switch (pkt->ops->pf) { + switch (pkt->pf) { case NFPROTO_IPV4: if (ipv4_is_multicast(ip_hdr(skb)->daddr)) *dest = PACKET_MULTICAST; diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index 96805d21d618..61d216eb7917 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c @@ -42,7 +42,7 @@ static void nft_queue_eval(const struct nft_expr *expr, queue = priv->queuenum + cpu % priv->queues_total; } else { queue = nfqueue_hash(pkt->skb, queue, - priv->queues_total, pkt->ops->pf, + priv->queues_total, pkt->pf, jhash_initval); } } diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 635dbba93d01..dea6750af6ff 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c @@ -24,20 +24,20 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, struct nft_reject *priv = nft_expr_priv(expr); struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); - switch (pkt->ops->pf) { + switch (pkt->pf) { case NFPROTO_IPV4: switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: nf_send_unreach(pkt->skb, priv->icmp_code, - pkt->ops->hooknum); + pkt->hook); break; case NFT_REJECT_TCP_RST: - nf_send_reset(pkt->skb, pkt->ops->hooknum); + nf_send_reset(pkt->skb, pkt->hook); break; case NFT_REJECT_ICMPX_UNREACH: nf_send_unreach(pkt->skb, nft_reject_icmp_code(priv->icmp_code), - pkt->ops->hooknum); + pkt->hook); break; } break; @@ -45,15 +45,15 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: nf_send_unreach6(net, pkt->skb, priv->icmp_code, - pkt->ops->hooknum); + pkt->hook); break; case NFT_REJECT_TCP_RST: - nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); + nf_send_reset6(net, pkt->skb, pkt->hook); break; case NFT_REJECT_ICMPX_UNREACH: nf_send_unreach6(net, pkt->skb, nft_reject_icmpv6_code(priv->icmp_code), - pkt->ops->hooknum); + pkt->hook); break; } break; -- cgit v1.3-6-gb490 From 156c196f6038610770588a708b9e0f7df2ead74a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:32:58 -0500 Subject: netfilter: x_tables: Pass struct net in xt_action_param As xt_action_param lives on the stack this does not bloat any persistent data structures. This is a first step in making netfilter code that needs to know which network namespace it is executing in simpler. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/x_tables.h | 3 ++- include/net/netfilter/nf_tables.h | 1 + net/bridge/netfilter/ebtables.c | 1 + net/ipv4/netfilter/arp_tables.c | 1 + net/ipv4/netfilter/ip_tables.c | 1 + net/ipv6/netfilter/ip6_tables.c | 1 + net/sched/act_ipt.c | 1 + net/sched/em_ipset.c | 1 + 8 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index b006b719183f..c5577410c25d 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -13,6 +13,7 @@ * @target: the target extension * @matchinfo: per-match data * @targetinfo: per-target data + * @net network namespace through which the action was invoked * @in: input netdevice * @out: output netdevice * @fragoff: packet is a fragment, this is the data offset @@ -24,7 +25,6 @@ * Fields written to by extensions: * * @hotdrop: drop packet if we had inspection problems - * Network namespace obtainable using dev_net(in/out) */ struct xt_action_param { union { @@ -34,6 +34,7 @@ struct xt_action_param { union { const void *matchinfo, *targinfo; }; + struct net *net; const struct net_device *in, *out; int fragoff; unsigned int thoff; diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index c0899f97ff8d..c0516529e8a0 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -30,6 +30,7 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, const struct nf_hook_state *state) { pkt->skb = skb; + pkt->xt.net = state->net; pkt->in = pkt->xt.in = state->in; pkt->out = pkt->xt.out = state->out; pkt->hook = pkt->xt.hooknum = state->hook; diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 8d5a3975b963..f46ca417bf2d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -200,6 +200,7 @@ unsigned int ebt_do_table(struct sk_buff *skb, struct xt_action_param acpar; acpar.family = NFPROTO_BRIDGE; + acpar.net = state->net; acpar.in = state->in; acpar.out = state->out; acpar.hotdrop = false; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 10eb2b297450..2dad3e1c5f11 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -285,6 +285,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, */ e = get_entry(table_base, private->hook_entry[hook]); + acpar.net = state->net; acpar.in = state->in; acpar.out = state->out; acpar.hooknum = hook; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2b049e135de8..42d0946956db 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -315,6 +315,7 @@ ipt_do_table(struct sk_buff *skb, acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; acpar.thoff = ip_hdrlen(skb); acpar.hotdrop = false; + acpar.net = state->net; acpar.in = state->in; acpar.out = state->out; acpar.family = NFPROTO_IPV4; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index da6446b6e3f9..80e3bd72b715 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -340,6 +340,7 @@ ip6t_do_table(struct sk_buff *skb, * rule is also a fragment-specific rule, non-fragments won't * match it. */ acpar.hotdrop = false; + acpar.net = state->net; acpar.in = state->in; acpar.out = state->out; acpar.family = NFPROTO_IPV6; diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 99c9cc1c7af9..d05869646515 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -189,6 +189,7 @@ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, * worry later - danger - this API seems to have changed * from earlier kernels */ + par.net = dev_net(skb->dev); par.in = skb->dev; par.out = NULL; par.hooknum = ipt->tcfi_hook; diff --git a/net/sched/em_ipset.c b/net/sched/em_ipset.c index df0328ba6a48..c66ca9400ab4 100644 --- a/net/sched/em_ipset.c +++ b/net/sched/em_ipset.c @@ -95,6 +95,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em, if (skb->skb_iif) indev = dev_get_by_index_rcu(em->net, skb->skb_iif); + acpar.net = em->net; acpar.in = indev ? indev : dev; acpar.out = dev; -- cgit v1.3-6-gb490 From 46448d0093ba18a212e314fd9ea029e740baa476 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:33:00 -0500 Subject: netfilter: nf_tables: Pass struct net in nft_pktinfo nft_pktinfo is passed on the stack so this does not bloat any in core data structures. By centrally computing this information this makes maintence of the code simpler, and understading of the code easier. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index c0516529e8a0..42e239e55aa3 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -14,6 +14,7 @@ struct nft_pktinfo { struct sk_buff *skb; + struct net *net; const struct net_device *in; const struct net_device *out; u8 pf; @@ -30,7 +31,7 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, const struct nf_hook_state *state) { pkt->skb = skb; - pkt->xt.net = state->net; + pkt->net = pkt->xt.net = state->net; pkt->in = pkt->xt.in = state->in; pkt->out = pkt->xt.out = state->out; pkt->hook = pkt->xt.hooknum = state->hook; -- cgit v1.3-6-gb490 From 206e8c00752fbe9cc463184236ac64b2a532cda5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:33:02 -0500 Subject: netfilter: Pass net to nf_dup_ipv4 and nf_dup_ipv6 This allows them to stop guessing the network namespace with pick_net. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/ipv4/nf_dup_ipv4.h | 2 +- include/net/netfilter/ipv6/nf_dup_ipv6.h | 2 +- net/ipv4/netfilter/nf_dup_ipv4.c | 23 ++++------------------- net/ipv4/netfilter/nft_dup_ipv4.c | 2 +- net/ipv6/netfilter/nf_dup_ipv6.c | 23 ++++------------------- net/ipv6/netfilter/nft_dup_ipv6.c | 2 +- net/netfilter/xt_TEE.c | 4 ++-- 7 files changed, 14 insertions(+), 44 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/ipv4/nf_dup_ipv4.h b/include/net/netfilter/ipv4/nf_dup_ipv4.h index 42008f10dfc4..0a14733e8b82 100644 --- a/include/net/netfilter/ipv4/nf_dup_ipv4.h +++ b/include/net/netfilter/ipv4/nf_dup_ipv4.h @@ -1,7 +1,7 @@ #ifndef _NF_DUP_IPV4_H_ #define _NF_DUP_IPV4_H_ -void nf_dup_ipv4(struct sk_buff *skb, unsigned int hooknum, +void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in_addr *gw, int oif); #endif /* _NF_DUP_IPV4_H_ */ diff --git a/include/net/netfilter/ipv6/nf_dup_ipv6.h b/include/net/netfilter/ipv6/nf_dup_ipv6.h index ed6bd66fa5a0..fa6237b382a3 100644 --- a/include/net/netfilter/ipv6/nf_dup_ipv6.h +++ b/include/net/netfilter/ipv6/nf_dup_ipv6.h @@ -1,7 +1,7 @@ #ifndef _NF_DUP_IPV6_H_ #define _NF_DUP_IPV6_H_ -void nf_dup_ipv6(struct sk_buff *skb, unsigned int hooknum, +void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in6_addr *gw, int oif); #endif /* _NF_DUP_IPV6_H_ */ diff --git a/net/ipv4/netfilter/nf_dup_ipv4.c b/net/ipv4/netfilter/nf_dup_ipv4.c index 2d79e6e8d934..ce2a59e5c665 100644 --- a/net/ipv4/netfilter/nf_dup_ipv4.c +++ b/net/ipv4/netfilter/nf_dup_ipv4.c @@ -23,25 +23,10 @@ #include #endif -static struct net *pick_net(struct sk_buff *skb) -{ -#ifdef CONFIG_NET_NS - const struct dst_entry *dst; - - if (skb->dev != NULL) - return dev_net(skb->dev); - dst = skb_dst(skb); - if (dst != NULL && dst->dev != NULL) - return dev_net(dst->dev); -#endif - return &init_net; -} - -static bool nf_dup_ipv4_route(struct sk_buff *skb, const struct in_addr *gw, - int oif) +static bool nf_dup_ipv4_route(struct net *net, struct sk_buff *skb, + const struct in_addr *gw, int oif) { const struct iphdr *iph = ip_hdr(skb); - struct net *net = pick_net(skb); struct rtable *rt; struct flowi4 fl4; @@ -65,7 +50,7 @@ static bool nf_dup_ipv4_route(struct sk_buff *skb, const struct in_addr *gw, return true; } -void nf_dup_ipv4(struct sk_buff *skb, unsigned int hooknum, +void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in_addr *gw, int oif) { struct iphdr *iph; @@ -105,7 +90,7 @@ void nf_dup_ipv4(struct sk_buff *skb, unsigned int hooknum, --iph->ttl; ip_send_check(iph); - if (nf_dup_ipv4_route(skb, gw, oif)) { + if (nf_dup_ipv4_route(net, skb, gw, oif)) { __this_cpu_write(nf_skb_duplicated, true); ip_local_out(skb); __this_cpu_write(nf_skb_duplicated, false); diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c index 30bcf820e8bd..bf855e64fc45 100644 --- a/net/ipv4/netfilter/nft_dup_ipv4.c +++ b/net/ipv4/netfilter/nft_dup_ipv4.c @@ -30,7 +30,7 @@ static void nft_dup_ipv4_eval(const struct nft_expr *expr, }; int oif = regs->data[priv->sreg_dev]; - nf_dup_ipv4(pkt->skb, pkt->hook, &gw, oif); + nf_dup_ipv4(pkt->net, pkt->skb, pkt->hook, &gw, oif); } static int nft_dup_ipv4_init(const struct nft_ctx *ctx, diff --git a/net/ipv6/netfilter/nf_dup_ipv6.c b/net/ipv6/netfilter/nf_dup_ipv6.c index c8ab626556a0..ee0d9a5b16c3 100644 --- a/net/ipv6/netfilter/nf_dup_ipv6.c +++ b/net/ipv6/netfilter/nf_dup_ipv6.c @@ -19,25 +19,10 @@ #include #endif -static struct net *pick_net(struct sk_buff *skb) -{ -#ifdef CONFIG_NET_NS - const struct dst_entry *dst; - - if (skb->dev != NULL) - return dev_net(skb->dev); - dst = skb_dst(skb); - if (dst != NULL && dst->dev != NULL) - return dev_net(dst->dev); -#endif - return &init_net; -} - -static bool nf_dup_ipv6_route(struct sk_buff *skb, const struct in6_addr *gw, - int oif) +static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb, + const struct in6_addr *gw, int oif) { const struct ipv6hdr *iph = ipv6_hdr(skb); - struct net *net = pick_net(skb); struct dst_entry *dst; struct flowi6 fl6; @@ -61,7 +46,7 @@ static bool nf_dup_ipv6_route(struct sk_buff *skb, const struct in6_addr *gw, return true; } -void nf_dup_ipv6(struct sk_buff *skb, unsigned int hooknum, +void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in6_addr *gw, int oif) { if (this_cpu_read(nf_skb_duplicated)) @@ -81,7 +66,7 @@ void nf_dup_ipv6(struct sk_buff *skb, unsigned int hooknum, struct ipv6hdr *iph = ipv6_hdr(skb); --iph->hop_limit; } - if (nf_dup_ipv6_route(skb, gw, oif)) { + if (nf_dup_ipv6_route(net, skb, gw, oif)) { __this_cpu_write(nf_skb_duplicated, true); ip6_local_out(skb); __this_cpu_write(nf_skb_duplicated, false); diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c index c81204faf15d..8bfd470cbe72 100644 --- a/net/ipv6/netfilter/nft_dup_ipv6.c +++ b/net/ipv6/netfilter/nft_dup_ipv6.c @@ -28,7 +28,7 @@ static void nft_dup_ipv6_eval(const struct nft_expr *expr, struct in6_addr *gw = (struct in6_addr *)®s->data[priv->sreg_addr]; int oif = regs->data[priv->sreg_dev]; - nf_dup_ipv6(pkt->skb, pkt->hook, gw, oif); + nf_dup_ipv6(pkt->net, pkt->skb, pkt->hook, gw, oif); } static int nft_dup_ipv6_init(const struct nft_ctx *ctx, diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index fd980aa7715d..899b06115fc5 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -32,7 +32,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_tee_tginfo *info = par->targinfo; - nf_dup_ipv4(skb, par->hooknum, &info->gw.in, info->priv->oif); + nf_dup_ipv4(par->net, skb, par->hooknum, &info->gw.in, info->priv->oif); return XT_CONTINUE; } @@ -43,7 +43,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_tee_tginfo *info = par->targinfo; - nf_dup_ipv6(skb, par->hooknum, &info->gw.in6, info->priv->oif); + nf_dup_ipv6(par->net, skb, par->hooknum, &info->gw.in6, info->priv->oif); return XT_CONTINUE; } -- cgit v1.3-6-gb490 From a4ffe319ae72034e3f3332698a2fd83b6f063b18 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:33:03 -0500 Subject: act_connmark: Remember the struct net instead of guessing it. Stop guessing the struct net instead of remember it. Guessing is just silly and will be problematic in the future when I implement routes between network namespaces. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/net/tc_act/tc_connmark.h | 1 + net/sched/act_connmark.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h index 5c1104c2e24f..02caa406611b 100644 --- a/include/net/tc_act/tc_connmark.h +++ b/include/net/tc_act/tc_connmark.h @@ -5,6 +5,7 @@ struct tcf_connmark_info { struct tcf_common common; + struct net *net; u16 zone; }; diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 5019a47b9270..413ac39147d8 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -74,7 +74,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, zone.id = ca->zone; zone.dir = NF_CT_DEFAULT_ZONE_DIR; - thash = nf_conntrack_find_get(dev_net(skb->dev), &zone, &tuple); + thash = nf_conntrack_find_get(ca->net, &zone, &tuple); if (!thash) goto out; @@ -119,6 +119,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ci = to_connmark(a); ci->tcf_action = parm->action; + ci->net = net; ci->zone = parm->zone; tcf_hash_insert(a); -- cgit v1.3-6-gb490 From a31f1adc0948930fba9ab5a111ccd735a5d864c6 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:33:04 -0500 Subject: netfilter: nf_conntrack: Add a struct net parameter to l4_pkt_to_tuple As gre does not have the srckey in the packet gre_pkt_to_tuple needs to perform a lookup in it's per network namespace tables. Pass in the proper network namespace to all pkt_to_tuple implementations to ensure gre (and any similar protocols) can get this right. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack.h | 3 ++- include/net/netfilter/nf_conntrack_core.h | 1 + include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 4 ++-- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 3 ++- net/netfilter/nf_conntrack_core.c | 10 ++++++---- net/netfilter/nf_conntrack_proto_dccp.c | 2 +- net/netfilter/nf_conntrack_proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_gre.c | 3 +-- net/netfilter/nf_conntrack_proto_sctp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_proto_udp.c | 1 + net/netfilter/nf_conntrack_proto_udplite.c | 1 + net/netfilter/xt_connlimit.c | 2 +- net/openvswitch/conntrack.c | 2 +- net/sched/act_connmark.c | 2 +- 16 files changed, 24 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index e8ad46834df8..d642f68a7c73 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -191,7 +191,8 @@ int nf_conntrack_hash_check_insert(struct nf_conn *ct); bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report); bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, - u_int16_t l3num, struct nf_conntrack_tuple *tuple); + u_int16_t l3num, struct net *net, + struct nf_conntrack_tuple *tuple); bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index c03f9c42b3cd..788ef58a66b9 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -41,6 +41,7 @@ void nf_conntrack_cleanup_end(void); bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, unsigned int dataoff, u_int16_t l3num, u_int8_t protonum, + struct net *net, struct nf_conntrack_tuple *tuple, const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto); diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 1f7061313d54..956d8a6ac069 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -26,7 +26,7 @@ struct nf_conntrack_l4proto { /* Try to fill in the third arg: dataoff is offset past network protocol hdr. Return true if possible. */ bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple); + struct net *net, struct nf_conntrack_tuple *tuple); /* Invert the per-proto part of the tuple: ie. turn xmit into reply. * Some packets can't be inverted: return 0 in that case. diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index cdde3ec496e9..c567e1b5d799 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -30,7 +30,7 @@ static inline struct nf_icmp_net *icmp_pernet(struct net *net) } static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple) + struct net *net, struct nf_conntrack_tuple *tuple) { const struct icmphdr *hp; struct icmphdr _hdr; @@ -144,7 +144,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb) + ip_hdrlen(skb) + sizeof(struct icmphdr), - PF_INET, &origtuple)) { + PF_INET, net, &origtuple)) { pr_debug("icmp_error_message: failed to get tuple\n"); return -NF_ACCEPT; } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 0e6fae103d33..d3b797446cea 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -36,6 +36,7 @@ static inline struct nf_icmp_net *icmpv6_pernet(struct net *net) static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, + struct net *net, struct nf_conntrack_tuple *tuple) { const struct icmp6hdr *hp; @@ -159,7 +160,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, skb_network_offset(skb) + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr), - PF_INET6, &origtuple)) { + PF_INET6, net, &origtuple)) { pr_debug("icmpv6_error: Can't get tuple\n"); return -NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index c09d6c7198f6..09d1d19b2ab9 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -168,6 +168,7 @@ nf_ct_get_tuple(const struct sk_buff *skb, unsigned int dataoff, u_int16_t l3num, u_int8_t protonum, + struct net *net, struct nf_conntrack_tuple *tuple, const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto) @@ -181,12 +182,13 @@ nf_ct_get_tuple(const struct sk_buff *skb, tuple->dst.protonum = protonum; tuple->dst.dir = IP_CT_DIR_ORIGINAL; - return l4proto->pkt_to_tuple(skb, dataoff, tuple); + return l4proto->pkt_to_tuple(skb, dataoff, net, tuple); } EXPORT_SYMBOL_GPL(nf_ct_get_tuple); bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, - u_int16_t l3num, struct nf_conntrack_tuple *tuple) + u_int16_t l3num, + struct net *net, struct nf_conntrack_tuple *tuple) { struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; @@ -205,7 +207,7 @@ bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, l4proto = __nf_ct_l4proto_find(l3num, protonum); - ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple, + ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, net, tuple, l3proto, l4proto); rcu_read_unlock(); @@ -1029,7 +1031,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, u32 hash; if (!nf_ct_get_tuple(skb, skb_network_offset(skb), - dataoff, l3num, protonum, &tuple, l3proto, + dataoff, l3num, protonum, net, &tuple, l3proto, l4proto)) { pr_debug("resolve_normal_ct: Can't get tuple\n"); return NULL; diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 6dd995c7c72b..fce1b1cca32d 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -398,7 +398,7 @@ static inline struct dccp_net *dccp_pernet(struct net *net) } static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple) + struct net *net, struct nf_conntrack_tuple *tuple) { struct dccp_hdr _hdr, *dh; diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 2281be419a74..86dc752e5349 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -45,7 +45,7 @@ static inline struct nf_generic_net *generic_pernet(struct net *net) static bool generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple) + struct net *net, struct nf_conntrack_tuple *tuple) { tuple->src.u.all = 0; tuple->dst.u.all = 0; diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 7648674f29c3..a96451a7af20 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -190,9 +190,8 @@ static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple, /* gre hdr info to tuple */ static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple) + struct net *net, struct nf_conntrack_tuple *tuple) { - struct net *net = dev_net(skb->dev ? skb->dev : skb_dst(skb)->dev); const struct gre_hdr_pptp *pgrehdr; struct gre_hdr_pptp _pgrehdr; __be16 srckey; diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 67197731eb68..9578a7c371ef 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -156,7 +156,7 @@ static inline struct sctp_net *sctp_pernet(struct net *net) } static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple) + struct net *net, struct nf_conntrack_tuple *tuple) { const struct sctphdr *hp; struct sctphdr _hdr; diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 70383de72054..278f3b9356ef 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -277,7 +277,7 @@ static inline struct nf_tcp_net *tcp_pernet(struct net *net) } static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conntrack_tuple *tuple) + struct net *net, struct nf_conntrack_tuple *tuple) { const struct tcphdr *hp; struct tcphdr _hdr; diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 6957281ffee5..478f92f834b6 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -38,6 +38,7 @@ static inline struct nf_udp_net *udp_pernet(struct net *net) static bool udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, + struct net *net, struct nf_conntrack_tuple *tuple) { const struct udphdr *hp; diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index c5903d1649f9..1ac8ee13a873 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -48,6 +48,7 @@ static inline struct udplite_net *udplite_pernet(struct net *net) static bool udplite_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, + struct net *net, struct nf_conntrack_tuple *tuple) { const struct udphdr *hp; diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 213db252e5be..99bbc829868d 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -332,7 +332,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; zone = nf_ct_zone(ct); } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), - par->family, &tuple)) { + par->family, net, &tuple)) { goto hotdrop; } diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index e8e524ad8a01..aaf5cbd6d9ae 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -345,7 +345,7 @@ ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone, { struct nf_conntrack_tuple tuple; - if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, &tuple)) + if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple)) return NULL; return __nf_ct_expect_find(net, zone, &tuple); } diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 413ac39147d8..bb41699c6c49 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -68,7 +68,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, } if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), - proto, &tuple)) + proto, ca->net, &tuple)) goto out; zone.id = ca->zone; -- cgit v1.3-6-gb490 From 06198b34a3e09e06d9aecaa3727e0d37206cea77 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:33:06 -0500 Subject: netfilter: Pass priv instead of nf_hook_ops to netfilter hooks Only pass the void *priv parameter out of the nf_hook_ops. That is all any of the functions are interested now, and by limiting what is passed it becomes simpler to change implementation details. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter.h | 2 +- include/net/netfilter/br_netfilter.h | 2 +- include/net/netfilter/nf_nat_l3proto.h | 32 +++++++++++++------------- include/net/netfilter/nf_tables.h | 3 +-- net/bridge/br_netfilter_hooks.c | 14 +++++------ net/bridge/br_netfilter_ipv6.c | 2 +- net/bridge/netfilter/ebtable_filter.c | 4 ++-- net/bridge/netfilter/ebtable_nat.c | 4 ++-- net/bridge/netfilter/nf_tables_bridge.c | 4 ++-- net/decnet/netfilter/dn_rtmsg.c | 2 +- net/ipv4/netfilter/arptable_filter.c | 2 +- net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 +- net/ipv4/netfilter/ipt_SYNPROXY.c | 2 +- net/ipv4/netfilter/iptable_filter.c | 2 +- net/ipv4/netfilter/iptable_mangle.c | 2 +- net/ipv4/netfilter/iptable_nat.c | 18 +++++++-------- net/ipv4/netfilter/iptable_raw.c | 2 +- net/ipv4/netfilter/iptable_security.c | 2 +- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 8 +++---- net/ipv4/netfilter/nf_defrag_ipv4.c | 2 +- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 24 +++++++++---------- net/ipv4/netfilter/nf_tables_arp.c | 4 ++-- net/ipv4/netfilter/nf_tables_ipv4.c | 8 +++---- net/ipv4/netfilter/nft_chain_nat_ipv4.c | 20 ++++++++-------- net/ipv4/netfilter/nft_chain_route_ipv4.c | 4 ++-- net/ipv6/netfilter/ip6t_SYNPROXY.c | 2 +- net/ipv6/netfilter/ip6table_filter.c | 2 +- net/ipv6/netfilter/ip6table_mangle.c | 2 +- net/ipv6/netfilter/ip6table_nat.c | 18 +++++++-------- net/ipv6/netfilter/ip6table_raw.c | 2 +- net/ipv6/netfilter/ip6table_security.c | 2 +- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 8 +++---- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 2 +- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 24 +++++++++---------- net/ipv6/netfilter/nf_tables_ipv6.c | 8 +++---- net/ipv6/netfilter/nft_chain_nat_ipv6.c | 20 ++++++++-------- net/ipv6/netfilter/nft_chain_route_ipv6.c | 4 ++-- net/netfilter/core.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 24 +++++++++---------- net/netfilter/nf_tables_core.c | 4 ++-- net/netfilter/nf_tables_netdev.c | 4 ++-- security/selinux/hooks.c | 10 ++++---- security/smack/smack_netfilter.c | 4 ++-- 43 files changed, 156 insertions(+), 157 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 0b4d4560f33d..987c74cd523c 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -80,7 +80,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p, p->okfn = okfn; } -typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops, +typedef unsigned int nf_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h index 8fe266504900..c93c75fa41ad 100644 --- a/include/net/netfilter/br_netfilter.h +++ b/include/net/netfilter/br_netfilter.h @@ -46,7 +46,7 @@ void br_netfilter_enable(void); #if IS_ENABLED(CONFIG_IPV6) int br_validate_ipv6(struct sk_buff *skb); -unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, +unsigned int br_nf_pre_routing_ipv6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); #else diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index a3127325f624..aef3e5fc9fd9 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -43,31 +43,31 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum); -unsigned int nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb, +unsigned int nf_nat_ipv4_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); -unsigned int nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb, +unsigned int nf_nat_ipv4_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); -unsigned int nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, +unsigned int nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); -unsigned int nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, +unsigned int nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); @@ -76,31 +76,31 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum, unsigned int hdrlen); -unsigned int nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb, +unsigned int nf_nat_ipv6_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); -unsigned int nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb, +unsigned int nf_nat_ipv6_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); -unsigned int nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, +unsigned int nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); -unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, +unsigned int nf_nat_ipv6_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)); diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 42e239e55aa3..c9149cc0a02d 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -816,8 +816,7 @@ int nft_register_basechain(struct nft_base_chain *basechain, void nft_unregister_basechain(struct nft_base_chain *basechain, unsigned int hook_nops); -unsigned int nft_do_chain(struct nft_pktinfo *pkt, - const struct nf_hook_ops *ops); +unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv); /** * struct nft_table - nf_tables table diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index e6e76bbdc82f..e21e44c13e07 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -464,7 +464,7 @@ struct net_device *setup_pre_routing(struct sk_buff *skb) * receiving device) to make netfilter happy, the REDIRECT * target in particular. Save the original destination IP * address to be able to detect DNAT afterwards. */ -static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, +static unsigned int br_nf_pre_routing(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -486,7 +486,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, return NF_ACCEPT; nf_bridge_pull_encap_header_rcsum(skb); - return br_nf_pre_routing_ipv6(ops, skb, state); + return br_nf_pre_routing_ipv6(priv, skb, state); } if (!brnf_call_iptables && !br->nf_call_iptables) @@ -526,7 +526,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, * took place when the packet entered the bridge), but we * register an IPv4 PRE_ROUTING 'sabotage' hook that will * prevent this from happening. */ -static unsigned int br_nf_local_in(const struct nf_hook_ops *ops, +static unsigned int br_nf_local_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -570,7 +570,7 @@ static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff * but we are still able to filter on the 'real' indev/outdev * because of the physdev module. For ARP, indev and outdev are the * bridge ports. */ -static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops, +static unsigned int br_nf_forward_ip(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -633,7 +633,7 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops, return NF_STOLEN; } -static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops, +static unsigned int br_nf_forward_arp(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -801,7 +801,7 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff } /* PF_BRIDGE/POST_ROUTING ********************************************/ -static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops, +static unsigned int br_nf_post_routing(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -850,7 +850,7 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops, /* IP/SABOTAGE *****************************************************/ /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING * for the second time. */ -static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops, +static unsigned int ip_sabotage_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c index e4dbbe44c724..c51cc3fd50d9 100644 --- a/net/bridge/br_netfilter_ipv6.c +++ b/net/bridge/br_netfilter_ipv6.c @@ -218,7 +218,7 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc /* Replicate the checks that IPv6 does on packet reception and pass the packet * to ip6tables. */ -unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, +unsigned int br_nf_pre_routing_ipv6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 118ce40ac181..f9242dffa65e 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -57,14 +57,14 @@ static const struct ebt_table frame_filter = { }; static unsigned int -ebt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +ebt_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ebt_do_table(skb, state, state->net->xt.frame_filter); } static unsigned int -ebt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +ebt_out_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ebt_do_table(skb, state, state->net->xt.frame_filter); diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 56c3329d6c37..4bbefe03ab58 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -57,14 +57,14 @@ static struct ebt_table frame_nat = { }; static unsigned int -ebt_nat_in(const struct nf_hook_ops *ops, struct sk_buff *skb, +ebt_nat_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ebt_do_table(skb, state, state->net->xt.frame_nat); } static unsigned int -ebt_nat_out(const struct nf_hook_ops *ops, struct sk_buff *skb, +ebt_nat_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ebt_do_table(skb, state, state->net->xt.frame_nat); diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index 318d825e4207..62f6b1b19589 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c @@ -87,7 +87,7 @@ static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt, } static unsigned int -nft_do_chain_bridge(const struct nf_hook_ops *ops, +nft_do_chain_bridge(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -105,7 +105,7 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops, break; } - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } static struct nft_af_info nft_af_bridge __read_mostly = { diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index af34fc9bdf69..85f2fdc360c2 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -87,7 +87,7 @@ static void dnrmg_send_peer(struct sk_buff *skb) } -static unsigned int dnrmg_hook(const struct nf_hook_ops *ops, +static unsigned int dnrmg_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 1352e12d4068..1897ee160920 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -27,7 +27,7 @@ static const struct xt_table packet_filter = { /* The work comes in here from netfilter.c */ static unsigned int -arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +arptable_filter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return arpt_do_table(skb, state, state->net->ipv4.arptable_filter); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 69157d8eba95..3f32c03e8b2e 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -507,7 +507,7 @@ static void arp_print(struct arp_payload *payload) #endif static unsigned int -arp_mangle(const struct nf_hook_ops *ops, +arp_mangle(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c index dfab314981e9..d7021f28c3f0 100644 --- a/net/ipv4/netfilter/ipt_SYNPROXY.c +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c @@ -299,7 +299,7 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par) return XT_CONTINUE; } -static unsigned int ipv4_synproxy_hook(const struct nf_hook_ops *ops, +static unsigned int ipv4_synproxy_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *nhs) { diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 02d4c5395d6e..397ef2dd133e 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -33,7 +33,7 @@ static const struct xt_table packet_filter = { }; static unsigned int -iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +iptable_filter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { if (state->hook == NF_INET_LOCAL_OUT && diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index dc2ff6884999..2d6fc911866f 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -78,7 +78,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) /* The work comes in here from netfilter.c. */ static unsigned int -iptable_mangle_hook(const struct nf_hook_ops *ops, +iptable_mangle_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 8ff63ac1f0d6..3a2e4d830a0b 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -28,7 +28,7 @@ static const struct xt_table nf_nat_ipv4_table = { .af = NFPROTO_IPV4, }; -static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops, +static unsigned int iptable_nat_do_chain(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct) @@ -36,32 +36,32 @@ static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops, return ipt_do_table(skb, state, state->net->ipv4.nat_table); } -static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops, +static unsigned int iptable_nat_ipv4_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_fn(ops, skb, state, iptable_nat_do_chain); + return nf_nat_ipv4_fn(priv, skb, state, iptable_nat_do_chain); } -static unsigned int iptable_nat_ipv4_in(const struct nf_hook_ops *ops, +static unsigned int iptable_nat_ipv4_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_in(ops, skb, state, iptable_nat_do_chain); + return nf_nat_ipv4_in(priv, skb, state, iptable_nat_do_chain); } -static unsigned int iptable_nat_ipv4_out(const struct nf_hook_ops *ops, +static unsigned int iptable_nat_ipv4_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_out(ops, skb, state, iptable_nat_do_chain); + return nf_nat_ipv4_out(priv, skb, state, iptable_nat_do_chain); } -static unsigned int iptable_nat_ipv4_local_fn(const struct nf_hook_ops *ops, +static unsigned int iptable_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_local_fn(ops, skb, state, iptable_nat_do_chain); + return nf_nat_ipv4_local_fn(priv, skb, state, iptable_nat_do_chain); } static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = { diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index bbb0523d87de..1ba02811acb0 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -20,7 +20,7 @@ static const struct xt_table packet_raw = { /* The work comes in here from netfilter.c. */ static unsigned int -iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +iptable_raw_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { if (state->hook == NF_INET_LOCAL_OUT && diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index b92417038705..f534e2f05bad 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -37,7 +37,7 @@ static const struct xt_table security_table = { }; static unsigned int -iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +iptable_security_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { if (state->hook == NF_INET_LOCAL_OUT && diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 15749cc5cf2b..752fb40adcf8 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -92,7 +92,7 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, return NF_ACCEPT; } -static unsigned int ipv4_helper(const struct nf_hook_ops *ops, +static unsigned int ipv4_helper(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -119,7 +119,7 @@ static unsigned int ipv4_helper(const struct nf_hook_ops *ops, ct, ctinfo); } -static unsigned int ipv4_confirm(const struct nf_hook_ops *ops, +static unsigned int ipv4_confirm(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -143,14 +143,14 @@ out: return nf_conntrack_confirm(skb); } -static unsigned int ipv4_conntrack_in(const struct nf_hook_ops *ops, +static unsigned int ipv4_conntrack_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return nf_conntrack_in(state->net, PF_INET, state->hook, skb); } -static unsigned int ipv4_conntrack_local(const struct nf_hook_ops *ops, +static unsigned int ipv4_conntrack_local(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 8aea536d2e83..b246346ee849 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -61,7 +61,7 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, return IP_DEFRAG_CONNTRACK_OUT + zone_id; } -static unsigned int ipv4_conntrack_defrag(const struct nf_hook_ops *ops, +static unsigned int ipv4_conntrack_defrag(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index 16da45a76dac..8593a9d88619 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -255,9 +255,9 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); unsigned int -nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -308,7 +308,7 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, if (!nf_nat_initialized(ct, maniptype)) { unsigned int ret; - ret = do_chain(ops, skb, state, ct); + ret = do_chain(priv, skb, state, ct); if (ret != NF_ACCEPT) return ret; @@ -345,9 +345,9 @@ oif_changed: EXPORT_SYMBOL_GPL(nf_nat_ipv4_fn); unsigned int -nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv4_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -355,7 +355,7 @@ nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb, unsigned int ret; __be32 daddr = ip_hdr(skb)->daddr; - ret = nf_nat_ipv4_fn(ops, skb, state, do_chain); + ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); if (ret != NF_DROP && ret != NF_STOLEN && daddr != ip_hdr(skb)->daddr) skb_dst_drop(skb); @@ -365,9 +365,9 @@ nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_ipv4_in); unsigned int -nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv4_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -384,7 +384,7 @@ nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb, ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; - ret = nf_nat_ipv4_fn(ops, skb, state, do_chain); + ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); #ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN && !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && @@ -407,9 +407,9 @@ nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_ipv4_out); unsigned int -nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -424,7 +424,7 @@ nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; - ret = nf_nat_ipv4_fn(ops, skb, state, do_chain); + ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); if (ret != NF_DROP && ret != NF_STOLEN && (ct = nf_ct_get(skb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c index 883bbf83fe09..9d09d4f59545 100644 --- a/net/ipv4/netfilter/nf_tables_arp.c +++ b/net/ipv4/netfilter/nf_tables_arp.c @@ -15,7 +15,7 @@ #include static unsigned int -nft_do_chain_arp(const struct nf_hook_ops *ops, +nft_do_chain_arp(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -23,7 +23,7 @@ nft_do_chain_arp(const struct nf_hook_ops *ops, nft_set_pktinfo(&pkt, skb, state); - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } static struct nft_af_info nft_af_arp __read_mostly = { diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c index 805be5c9fcc3..ca9dc3c46c4f 100644 --- a/net/ipv4/netfilter/nf_tables_ipv4.c +++ b/net/ipv4/netfilter/nf_tables_ipv4.c @@ -18,7 +18,7 @@ #include #include -static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops, +static unsigned int nft_do_chain_ipv4(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -26,10 +26,10 @@ static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops, nft_set_pktinfo_ipv4(&pkt, skb, state); - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } -static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, +static unsigned int nft_ipv4_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -41,7 +41,7 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, return NF_ACCEPT; } - return nft_do_chain_ipv4(ops, skb, state); + return nft_do_chain_ipv4(priv, skb, state); } struct nft_af_info nft_af_ipv4 __read_mostly = { diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c index c3ffecf28d38..f5c66a7a4bf2 100644 --- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c @@ -26,7 +26,7 @@ #include #include -static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops, +static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct) @@ -35,35 +35,35 @@ static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops, nft_set_pktinfo_ipv4(&pkt, skb, state); - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } -static unsigned int nft_nat_ipv4_fn(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv4_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_fn(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv4_fn(priv, skb, state, nft_nat_do_chain); } -static unsigned int nft_nat_ipv4_in(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv4_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_in(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv4_in(priv, skb, state, nft_nat_do_chain); } -static unsigned int nft_nat_ipv4_out(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv4_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_out(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv4_out(priv, skb, state, nft_nat_do_chain); } -static unsigned int nft_nat_ipv4_local_fn(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv4_local_fn(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv4_local_fn(priv, skb, state, nft_nat_do_chain); } static const struct nf_chain_type nft_chain_nat_ipv4 = { diff --git a/net/ipv4/netfilter/nft_chain_route_ipv4.c b/net/ipv4/netfilter/nft_chain_route_ipv4.c index 2a1e3d8a3e43..9f486b302108 100644 --- a/net/ipv4/netfilter/nft_chain_route_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c @@ -21,7 +21,7 @@ #include #include -static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, +static unsigned int nf_route_table_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -45,7 +45,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, daddr = iph->daddr; tos = iph->tos; - ret = nft_do_chain(&pkt, ops); + ret = nft_do_chain(&pkt, priv); if (ret != NF_DROP && ret != NF_QUEUE) { iph = ip_hdr(skb); diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index 41451809b37c..c2356602158a 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c @@ -316,7 +316,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par) return XT_CONTINUE; } -static unsigned int ipv6_synproxy_hook(const struct nf_hook_ops *ops, +static unsigned int ipv6_synproxy_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *nhs) { diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index a7327f61b90c..8b277b983ca5 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -32,7 +32,7 @@ static const struct xt_table packet_filter = { /* The work comes in here from netfilter.c. */ static unsigned int -ip6table_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip6table_filter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip6t_do_table(skb, state, state->net->ipv6.ip6table_filter); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index c2e061dcedf3..8745b592b2f6 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -75,7 +75,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) /* The work comes in here from netfilter.c. */ static unsigned int -ip6table_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip6table_mangle_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { if (state->hook == NF_INET_LOCAL_OUT) diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index efa6754c4d06..abea175d5853 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -30,7 +30,7 @@ static const struct xt_table nf_nat_ipv6_table = { .af = NFPROTO_IPV6, }; -static unsigned int ip6table_nat_do_chain(const struct nf_hook_ops *ops, +static unsigned int ip6table_nat_do_chain(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct) @@ -38,32 +38,32 @@ static unsigned int ip6table_nat_do_chain(const struct nf_hook_ops *ops, return ip6t_do_table(skb, state, state->net->ipv6.ip6table_nat); } -static unsigned int ip6table_nat_fn(const struct nf_hook_ops *ops, +static unsigned int ip6table_nat_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_fn(ops, skb, state, ip6table_nat_do_chain); + return nf_nat_ipv6_fn(priv, skb, state, ip6table_nat_do_chain); } -static unsigned int ip6table_nat_in(const struct nf_hook_ops *ops, +static unsigned int ip6table_nat_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_in(ops, skb, state, ip6table_nat_do_chain); + return nf_nat_ipv6_in(priv, skb, state, ip6table_nat_do_chain); } -static unsigned int ip6table_nat_out(const struct nf_hook_ops *ops, +static unsigned int ip6table_nat_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_out(ops, skb, state, ip6table_nat_do_chain); + return nf_nat_ipv6_out(priv, skb, state, ip6table_nat_do_chain); } -static unsigned int ip6table_nat_local_fn(const struct nf_hook_ops *ops, +static unsigned int ip6table_nat_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_local_fn(ops, skb, state, ip6table_nat_do_chain); + return nf_nat_ipv6_local_fn(priv, skb, state, ip6table_nat_do_chain); } static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = { diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index fac6ad7c0a7c..9021963565c3 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -19,7 +19,7 @@ static const struct xt_table packet_raw = { /* The work comes in here from netfilter.c. */ static unsigned int -ip6table_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip6table_raw_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip6t_do_table(skb, state, state->net->ipv6.ip6table_raw); diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 96c94fc240c8..0d856fedfeb0 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -36,7 +36,7 @@ static const struct xt_table security_table = { }; static unsigned int -ip6table_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip6table_security_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip6t_do_table(skb, state, state->net->ipv6.ip6table_security); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 339be1d59afc..dd83ad42f8f6 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -95,7 +95,7 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, return NF_ACCEPT; } -static unsigned int ipv6_helper(const struct nf_hook_ops *ops, +static unsigned int ipv6_helper(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -131,7 +131,7 @@ static unsigned int ipv6_helper(const struct nf_hook_ops *ops, return helper->help(skb, protoff, ct, ctinfo); } -static unsigned int ipv6_confirm(const struct nf_hook_ops *ops, +static unsigned int ipv6_confirm(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -165,14 +165,14 @@ out: return nf_conntrack_confirm(skb); } -static unsigned int ipv6_conntrack_in(const struct nf_hook_ops *ops, +static unsigned int ipv6_conntrack_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); } -static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops, +static unsigned int ipv6_conntrack_local(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index a9c08520596b..a99baf63eccf 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c @@ -51,7 +51,7 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, return IP6_DEFRAG_CONNTRACK_OUT + zone_id; } -static unsigned int ipv6_defrag(const struct nf_hook_ops *ops, +static unsigned int ipv6_defrag(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index 8bc94907dbd9..357f57ba47e4 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -262,9 +262,9 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation); unsigned int -nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv6_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -317,7 +317,7 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, if (!nf_nat_initialized(ct, maniptype)) { unsigned int ret; - ret = do_chain(ops, skb, state, ct); + ret = do_chain(priv, skb, state, ct); if (ret != NF_ACCEPT) return ret; @@ -353,9 +353,9 @@ oif_changed: EXPORT_SYMBOL_GPL(nf_nat_ipv6_fn); unsigned int -nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv6_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -363,7 +363,7 @@ nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb, unsigned int ret; struct in6_addr daddr = ipv6_hdr(skb)->daddr; - ret = nf_nat_ipv6_fn(ops, skb, state, do_chain); + ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); if (ret != NF_DROP && ret != NF_STOLEN && ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr)) skb_dst_drop(skb); @@ -373,9 +373,9 @@ nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_ipv6_in); unsigned int -nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv6_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -391,7 +391,7 @@ nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb, if (skb->len < sizeof(struct ipv6hdr)) return NF_ACCEPT; - ret = nf_nat_ipv6_fn(ops, skb, state, do_chain); + ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); #ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN && !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && @@ -414,9 +414,9 @@ nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_ipv6_out); unsigned int -nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, +nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, - unsigned int (*do_chain)(const struct nf_hook_ops *ops, + unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) @@ -430,7 +430,7 @@ nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, if (skb->len < sizeof(struct ipv6hdr)) return NF_ACCEPT; - ret = nf_nat_ipv6_fn(ops, skb, state, do_chain); + ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); if (ret != NF_DROP && ret != NF_STOLEN && (ct = nf_ct_get(skb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c index 41340b794f9b..120ea9131be0 100644 --- a/net/ipv6/netfilter/nf_tables_ipv6.c +++ b/net/ipv6/netfilter/nf_tables_ipv6.c @@ -16,7 +16,7 @@ #include #include -static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops, +static unsigned int nft_do_chain_ipv6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -26,10 +26,10 @@ static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops, if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0) return NF_DROP; - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } -static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops, +static unsigned int nft_ipv6_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -40,7 +40,7 @@ static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops, return NF_ACCEPT; } - return nft_do_chain_ipv6(ops, skb, state); + return nft_do_chain_ipv6(priv, skb, state); } struct nft_af_info nft_af_ipv6 __read_mostly = { diff --git a/net/ipv6/netfilter/nft_chain_nat_ipv6.c b/net/ipv6/netfilter/nft_chain_nat_ipv6.c index e96feaefeb14..443cd306c0b0 100644 --- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c @@ -24,7 +24,7 @@ #include #include -static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops, +static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct) @@ -33,35 +33,35 @@ static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops, nft_set_pktinfo_ipv6(&pkt, skb, state); - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } -static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv6_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_fn(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv6_fn(priv, skb, state, nft_nat_do_chain); } -static unsigned int nft_nat_ipv6_in(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv6_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_in(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv6_in(priv, skb, state, nft_nat_do_chain); } -static unsigned int nft_nat_ipv6_out(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv6_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_out(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv6_out(priv, skb, state, nft_nat_do_chain); } -static unsigned int nft_nat_ipv6_local_fn(const struct nf_hook_ops *ops, +static unsigned int nft_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_nat_ipv6_local_fn(ops, skb, state, nft_nat_do_chain); + return nf_nat_ipv6_local_fn(priv, skb, state, nft_nat_do_chain); } static const struct nf_chain_type nft_chain_nat_ipv6 = { diff --git a/net/ipv6/netfilter/nft_chain_route_ipv6.c b/net/ipv6/netfilter/nft_chain_route_ipv6.c index d1bcd2ed7bcc..d42bbc1d7555 100644 --- a/net/ipv6/netfilter/nft_chain_route_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c @@ -22,7 +22,7 @@ #include #include -static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, +static unsigned int nf_route_table_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -45,7 +45,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u32 *)ipv6_hdr(skb)); - ret = nft_do_chain(&pkt, ops); + ret = nft_do_chain(&pkt, priv); if (ret != NF_DROP && ret != NF_QUEUE && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 8e47f8113495..2e907335ee81 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -269,7 +269,7 @@ unsigned int nf_iterate(struct list_head *head, /* Optimization: we don't need to hold module reference here, since function can't sleep. --RR */ repeat: - verdict = (*elemp)->hook(*elemp, skb, state); + verdict = (*elemp)->hook((*elemp)->priv, skb, state); if (verdict != NF_ACCEPT) { #ifdef CONFIG_NETFILTER_DEBUG if (unlikely((verdict & NF_VERDICT_MASK) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 40e3c85f83b5..1fa12edccbcc 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1311,7 +1311,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) * Check if packet is reply for established ip_vs_conn. */ static unsigned int -ip_vs_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_reply4(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_out(state->hook, skb, AF_INET); @@ -1322,7 +1322,7 @@ ip_vs_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb, * Check if packet is reply for established ip_vs_conn. */ static unsigned int -ip_vs_local_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_local_reply4(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_out(state->hook, skb, AF_INET); @@ -1336,7 +1336,7 @@ ip_vs_local_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb, * Check if packet is reply for established ip_vs_conn. */ static unsigned int -ip_vs_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_reply6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_out(state->hook, skb, AF_INET6); @@ -1347,7 +1347,7 @@ ip_vs_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb, * Check if packet is reply for established ip_vs_conn. */ static unsigned int -ip_vs_local_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_local_reply6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_out(state->hook, skb, AF_INET6); @@ -1847,7 +1847,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) * Schedule and forward packets from remote clients */ static unsigned int -ip_vs_remote_request4(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_remote_request4(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_in(state->hook, skb, AF_INET); @@ -1858,7 +1858,7 @@ ip_vs_remote_request4(const struct nf_hook_ops *ops, struct sk_buff *skb, * Schedule and forward packets from local clients */ static unsigned int -ip_vs_local_request4(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_local_request4(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_in(state->hook, skb, AF_INET); @@ -1871,7 +1871,7 @@ ip_vs_local_request4(const struct nf_hook_ops *ops, struct sk_buff *skb, * Schedule and forward packets from remote clients */ static unsigned int -ip_vs_remote_request6(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_remote_request6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_in(state->hook, skb, AF_INET6); @@ -1882,7 +1882,7 @@ ip_vs_remote_request6(const struct nf_hook_ops *ops, struct sk_buff *skb, * Schedule and forward packets from local clients */ static unsigned int -ip_vs_local_request6(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_local_request6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { return ip_vs_in(state->hook, skb, AF_INET6); @@ -1901,7 +1901,7 @@ ip_vs_local_request6(const struct nf_hook_ops *ops, struct sk_buff *skb, * and send them to ip_vs_in_icmp. */ static unsigned int -ip_vs_forward_icmp(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_forward_icmp(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { int r; @@ -1917,12 +1917,12 @@ ip_vs_forward_icmp(const struct nf_hook_ops *ops, struct sk_buff *skb, if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable)) return NF_ACCEPT; - return ip_vs_in_icmp(skb, &r, ops->hooknum); + return ip_vs_in_icmp(skb, &r, state->hook); } #ifdef CONFIG_IP_VS_IPV6 static unsigned int -ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb, +ip_vs_forward_icmp_v6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { int r; @@ -1940,7 +1940,7 @@ ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb, if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable)) return NF_ACCEPT; - return ip_vs_in_icmp_v6(skb, &r, ops->hooknum, &iphdr); + return ip_vs_in_icmp_v6(skb, &r, state->hook, &iphdr); } #endif diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index e5c1f332e45e..f3695a497408 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -109,9 +109,9 @@ struct nft_jumpstack { }; unsigned int -nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) +nft_do_chain(struct nft_pktinfo *pkt, void *priv) { - const struct nft_chain *chain = ops->priv, *basechain = chain; + const struct nft_chain *chain = priv, *basechain = chain; const struct net *net = pkt->net; const struct nft_rule *rule; const struct nft_expr *expr, *last; diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c index db416a3396e9..7b9c053ba750 100644 --- a/net/netfilter/nf_tables_netdev.c +++ b/net/netfilter/nf_tables_netdev.c @@ -89,7 +89,7 @@ static inline void nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt, } static unsigned int -nft_do_chain_netdev(const struct nf_hook_ops *ops, struct sk_buff *skb, +nft_do_chain_netdev(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct nft_pktinfo pkt; @@ -106,7 +106,7 @@ nft_do_chain_netdev(const struct nf_hook_ops *ops, struct sk_buff *skb, break; } - return nft_do_chain(&pkt, ops); + return nft_do_chain(&pkt, priv); } static struct nft_af_info nft_af_netdev __read_mostly = { diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e4369d86e588..64340160f4ac 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4866,7 +4866,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, return NF_ACCEPT; } -static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops, +static unsigned int selinux_ipv4_forward(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -4874,7 +4874,7 @@ static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops, } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops, +static unsigned int selinux_ipv6_forward(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -4924,7 +4924,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, return NF_ACCEPT; } -static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops, +static unsigned int selinux_ipv4_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -5099,7 +5099,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, return NF_ACCEPT; } -static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops, +static unsigned int selinux_ipv4_postroute(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -5107,7 +5107,7 @@ static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops, } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops, +static unsigned int selinux_ipv6_postroute(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c index a455cfc9ec1f..a9e41da05d28 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -21,7 +21,7 @@ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops, +static unsigned int smack_ipv6_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -38,7 +38,7 @@ static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops, } #endif /* IPV6 */ -static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops, +static unsigned int smack_ipv4_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -- cgit v1.3-6-gb490 From c7af6483b9f7f3eaba01b2e62d3d8a70cd89bdaf Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 18 Sep 2015 14:33:07 -0500 Subject: netfilter: Pass net into nf_xfrm_me_harder Instead of calling dev_net on a likley looking network device pass state->net into nf_xfrm_me_harder. Signed-off-by: "Eric W. Biederman" Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_nat_core.h | 2 +- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 4 ++-- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 4 ++-- net/netfilter/nf_nat_core.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index fbfd1ba4254e..186c54138f35 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -10,7 +10,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum, struct sk_buff *skb); -int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family); +int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family); static inline int nf_nat_initialized(struct nf_conn *ct, enum nf_nat_manip_type manip) diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index 8593a9d88619..bc3b9dcbf080 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -396,7 +396,7 @@ nf_nat_ipv4_out(void *priv, struct sk_buff *skb, (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all)) { - err = nf_xfrm_me_harder(skb, AF_INET); + err = nf_xfrm_me_harder(state->net, skb, AF_INET); if (err < 0) ret = NF_DROP_ERR(err); } @@ -440,7 +440,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) { - err = nf_xfrm_me_harder(skb, AF_INET); + err = nf_xfrm_me_harder(state->net, skb, AF_INET); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index 357f57ba47e4..18e835ffbef3 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -403,7 +403,7 @@ nf_nat_ipv6_out(void *priv, struct sk_buff *skb, (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all)) { - err = nf_xfrm_me_harder(skb, AF_INET6); + err = nf_xfrm_me_harder(state->net, skb, AF_INET6); if (err < 0) ret = NF_DROP_ERR(err); } @@ -446,7 +446,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) { - err = nf_xfrm_me_harder(skb, AF_INET6); + err = nf_xfrm_me_harder(state->net, skb, AF_INET6); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 5113dfd39df9..06a9f45771ab 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -83,7 +83,7 @@ out: rcu_read_unlock(); } -int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family) +int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family) { struct flowi fl; unsigned int hh_len; @@ -99,7 +99,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family) dst = ((struct xfrm_dst *)dst)->route; dst_hold(dst); - dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0); + dst = xfrm_lookup(net, dst, &fl, skb->sk, 0); if (IS_ERR(dst)) return PTR_ERR(dst); -- cgit v1.3-6-gb490 From 4a07c222d3afb00e1113834fee38d23a8e5d71dc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 17:54:22 -0400 Subject: cgroup: replace "cgroup.populated" with "cgroup.events" memcg already uses "memory.events" for event reporting and other controllers may need event reporting too. Let's standardize on "$SUBSYS.events" interface file for reporting events which don't happen too frequently and thus can share event notification. "cgroup.populated" is replaced with "populated" field in "cgroup.events" and documentation is updated accordingly. Signed-off-by: Tejun Heo Cc: Li Zefan Cc: Johannes Weiner --- Documentation/cgroups/unified-hierarchy.txt | 15 ++++++++++----- include/linux/cgroup-defs.h | 2 +- kernel/cgroup.c | 17 +++++++++-------- 3 files changed, 20 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/Documentation/cgroups/unified-hierarchy.txt b/Documentation/cgroups/unified-hierarchy.txt index e0975c2cf03d..176b940f8327 100644 --- a/Documentation/cgroups/unified-hierarchy.txt +++ b/Documentation/cgroups/unified-hierarchy.txt @@ -341,11 +341,11 @@ is riddled with issues. unnecessarily complicated and probably done this way because event delivery itself was expensive. -Unified hierarchy implements an interface file "cgroup.populated" -which can be used to monitor whether the cgroup's subhierarchy has -tasks in it or not. Its value is 0 if there is no task in the cgroup -and its descendants; otherwise, 1. poll and [id]notify events are -triggered when the value changes. +Unified hierarchy implements "populated" field in "cgroup.events" +interface file which can be used to monitor whether the cgroup's +subhierarchy has tasks in it or not. Its value is 0 if there is no +task in the cgroup and its descendants; otherwise, 1. poll and +[id]notify events are triggered when the value changes. This is significantly lighter and simpler and trivially allows delegating management of subhierarchy - subhierarchy monitoring can @@ -435,6 +435,11 @@ may be specified in any order and not all pairs have to be specified. the first entry in the file. Specific entries can use "default" as its value to indicate inheritance of the default value. +- For events which are not very high frequency, an interface file + "events" should be created which lists event key value pairs. + Whenever a notifiable event happens, file modified event should be + generated on the file. + 5-4. Per-Controller Changes diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index c5d41c3c1f00..d95cc88e9dc2 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -226,7 +226,7 @@ struct cgroup { struct kernfs_node *kn; /* cgroup kernfs entry */ struct kernfs_node *procs_kn; /* kn for "cgroup.procs" */ - struct kernfs_node *populated_kn; /* kn for "cgroup.subtree_populated" */ + struct kernfs_node *events_kn; /* kn for "cgroup.events" */ /* * The bitmask of subsystems enabled on the child cgroups. diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c24f929fdeb7..75eba25d8dfd 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -611,8 +611,8 @@ static void cgroup_update_populated(struct cgroup *cgrp, bool populated) if (!trigger) break; - if (cgrp->populated_kn) - kernfs_notify(cgrp->populated_kn); + if (cgrp->events_kn) + kernfs_notify(cgrp->events_kn); cgrp = cgroup_parent(cgrp); } while (cgrp); } @@ -3045,9 +3045,10 @@ err_undo_css: goto out_unlock; } -static int cgroup_populated_show(struct seq_file *seq, void *v) +static int cgroup_events_show(struct seq_file *seq, void *v) { - seq_printf(seq, "%d\n", (bool)seq_css(seq)->cgroup->populated_cnt); + seq_printf(seq, "populated %d\n", + (bool)seq_css(seq)->cgroup->populated_cnt); return 0; } @@ -3214,8 +3215,8 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft) if (cft->write == cgroup_procs_write) cgrp->procs_kn = kn; - else if (cft->seq_show == cgroup_populated_show) - cgrp->populated_kn = kn; + else if (cft->seq_show == cgroup_events_show) + cgrp->events_kn = kn; return 0; } @@ -4388,9 +4389,9 @@ static struct cftype cgroup_dfl_base_files[] = { .write = cgroup_subtree_control_write, }, { - .name = "cgroup.populated", + .name = "cgroup.events", .flags = CFTYPE_NOT_ON_ROOT, - .seq_show = cgroup_populated_show, + .seq_show = cgroup_events_show, }, { } /* terminate */ }; -- cgit v1.3-6-gb490 From 7dbdb199d3bf88f043ea17e97113eb28d5b100bc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 17:54:23 -0400 Subject: cgroup: replace cftype->mode with CFTYPE_WORLD_WRITABLE cftype->mode allows controllers to give arbitrary permissions to interface knobs. Except for "cgroup.event_control", the existing uses are spurious. * Some explicitly specify S_IRUGO | S_IWUSR even though that's the default. * "cpuset.memory_pressure" specifies S_IRUGO while also setting a write callback which returns -EACCES. All it needs to do is simply not setting a write callback. "cgroup.event_control" uses cftype->mode to make the file world-writable. It's a misdesigned interface and we don't want controllers to be tweaking interface file permissions in general. This patch removes cftype->mode and all its spurious uses and implements CFTYPE_WORLD_WRITABLE for "cgroup.event_control" which is marked as compatibility-only. Signed-off-by: Tejun Heo Cc: Li Zefan Cc: Johannes Weiner --- include/linux/cgroup-defs.h | 6 +----- kernel/cgroup.c | 19 +++++++------------ kernel/cpuset.c | 6 ------ mm/memcontrol.c | 3 +-- 4 files changed, 9 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index d95cc88e9dc2..10d814bcd487 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -76,6 +76,7 @@ enum { CFTYPE_ONLY_ON_ROOT = (1 << 0), /* only create on root cgrp */ CFTYPE_NOT_ON_ROOT = (1 << 1), /* don't create on root cgrp */ CFTYPE_NO_PREFIX = (1 << 3), /* (DON'T USE FOR NEW FILES) no subsys prefix */ + CFTYPE_WORLD_WRITABLE = (1 << 4), /* (DON'T USE FOR NEW FILES) S_IWUGO */ /* internal flags, do not use outside cgroup core proper */ __CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */ @@ -324,11 +325,6 @@ struct cftype { */ char name[MAX_CFTYPE_NAME]; unsigned long private; - /* - * If not 0, file mode is set to this value, otherwise it will - * be figured out automatically - */ - umode_t mode; /* * The maximum length of string, excluding trailing nul, that can diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 75eba25d8dfd..5031edc6f077 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1139,23 +1139,21 @@ static char *cgroup_file_name(struct cgroup *cgrp, const struct cftype *cft, * cgroup_file_mode - deduce file mode of a control file * @cft: the control file in question * - * returns cft->mode if ->mode is not 0 - * returns S_IRUGO|S_IWUSR if it has both a read and a write handler - * returns S_IRUGO if it has only a read handler - * returns S_IWUSR if it has only a write hander + * S_IRUGO for read, S_IWUSR for write. */ static umode_t cgroup_file_mode(const struct cftype *cft) { umode_t mode = 0; - if (cft->mode) - return cft->mode; - if (cft->read_u64 || cft->read_s64 || cft->seq_show) mode |= S_IRUGO; - if (cft->write_u64 || cft->write_s64 || cft->write) - mode |= S_IWUSR; + if (cft->write_u64 || cft->write_s64 || cft->write) { + if (cft->flags & CFTYPE_WORLD_WRITABLE) + mode |= S_IWUGO; + else + mode |= S_IWUSR; + } return mode; } @@ -4371,7 +4369,6 @@ static struct cftype cgroup_dfl_base_files[] = { .seq_show = cgroup_pidlist_show, .private = CGROUP_FILE_PROCS, .write = cgroup_procs_write, - .mode = S_IRUGO | S_IWUSR, }, { .name = "cgroup.controllers", @@ -4406,7 +4403,6 @@ static struct cftype cgroup_legacy_base_files[] = { .seq_show = cgroup_pidlist_show, .private = CGROUP_FILE_PROCS, .write = cgroup_procs_write, - .mode = S_IRUGO | S_IWUSR, }, { .name = "cgroup.clone_children", @@ -4426,7 +4422,6 @@ static struct cftype cgroup_legacy_base_files[] = { .seq_show = cgroup_pidlist_show, .private = CGROUP_FILE_TASKS, .write = cgroup_tasks_write, - .mode = S_IRUGO | S_IWUSR, }, { .name = "notify_on_release", diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 20eedd8098c0..312961ef3ccc 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1597,9 +1597,6 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft, case FILE_MEMORY_PRESSURE_ENABLED: cpuset_memory_pressure_enabled = !!val; break; - case FILE_MEMORY_PRESSURE: - retval = -EACCES; - break; case FILE_SPREAD_PAGE: retval = update_flag(CS_SPREAD_PAGE, cs, val); break; @@ -1866,9 +1863,6 @@ static struct cftype files[] = { { .name = "memory_pressure", .read_u64 = cpuset_read_u64, - .write_u64 = cpuset_write_u64, - .private = FILE_MEMORY_PRESSURE, - .mode = S_IRUGO, }, { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b35c4cc47a30..e672f2689326 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4060,8 +4060,7 @@ static struct cftype mem_cgroup_legacy_files[] = { { .name = "cgroup.event_control", /* XXX: for compat */ .write = memcg_write_event_control, - .flags = CFTYPE_NO_PREFIX, - .mode = S_IWUGO, + .flags = CFTYPE_NO_PREFIX | CFTYPE_WORLD_WRITABLE, }, { .name = "swappiness", -- cgit v1.3-6-gb490 From 6f60eade2433cb3a38687d5f8a4f44b92c6c51bf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 17:54:23 -0400 Subject: cgroup: generalize obtaining the handles of and notifying cgroup files cgroup core handles creations and removals of cgroup interface files as described by cftypes. There are cases where the handle for a given file instance is necessary, for example, to generate a file modified event. Currently, this is handled by explicitly matching the callback method pointer and storing the file handle manually in cgroup_add_file(). While this simple approach works for cgroup core files, it can't for controller interface files. This patch generalizes cgroup interface file handle handling. struct cgroup_file is defined and each cftype can optionally tell cgroup core to store the file handle by setting ->file_offset. A file handle remains accessible as long as the containing css is accessible. Both "cgroup.procs" and "cgroup.events" are converted to use the new generic mechanism instead of hooking directly into cgroup_add_file(). Also, cgroup_file_notify() which takes a struct cgroup_file and generates a file modified event on it is added and replaces explicit kernfs_notify() invocations. This generalizes cgroup file handle handling and allows controllers to generate file modified notifications. Signed-off-by: Tejun Heo Cc: Li Zefan Cc: Johannes Weiner --- include/linux/cgroup-defs.h | 26 ++++++++++++++++++++++++-- include/linux/cgroup.h | 13 +++++++++++++ kernel/cgroup.c | 26 +++++++++++++++++++------- 3 files changed, 56 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 10d814bcd487..df589a097539 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -83,6 +83,17 @@ enum { __CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */ }; +/* + * cgroup_file is the handle for a file instance created in a cgroup which + * is used, for example, to generate file changed notifications. This can + * be obtained by setting cftype->file_offset. + */ +struct cgroup_file { + /* do not access any fields from outside cgroup core */ + struct list_head node; /* anchored at css->files */ + struct kernfs_node *kn; +}; + /* * Per-subsystem/per-cgroup state maintained by the system. This is the * fundamental structural building block that controllers deal with. @@ -123,6 +134,9 @@ struct cgroup_subsys_state { */ u64 serial_nr; + /* all cgroup_files associated with this css */ + struct list_head files; + /* percpu_ref killing and RCU release */ struct rcu_head rcu_head; struct work_struct destroy_work; @@ -226,8 +240,8 @@ struct cgroup { int populated_cnt; struct kernfs_node *kn; /* cgroup kernfs entry */ - struct kernfs_node *procs_kn; /* kn for "cgroup.procs" */ - struct kernfs_node *events_kn; /* kn for "cgroup.events" */ + struct cgroup_file procs_file; /* handle for "cgroup.procs" */ + struct cgroup_file events_file; /* handle for "cgroup.events" */ /* * The bitmask of subsystems enabled on the child cgroups. @@ -335,6 +349,14 @@ struct cftype { /* CFTYPE_* flags */ unsigned int flags; + /* + * If non-zero, should contain the offset from the start of css to + * a struct cgroup_file field. cgroup will record the handle of + * the created file into it. The recorded handle can be used as + * long as the containing css remains accessible. + */ + unsigned int file_offset; + /* * Fields used for internal bookkeeping. Initialized automatically * during registration. diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 355bf2ed8867..fb717f2cba5b 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -490,6 +490,19 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp) pr_cont_kernfs_path(cgrp->kn); } +/** + * cgroup_file_notify - generate a file modified event for a cgroup_file + * @cfile: target cgroup_file + * + * @cfile must have been obtained by setting cftype->file_offset. + */ +static inline void cgroup_file_notify(struct cgroup_file *cfile) +{ + /* might not have been created due to one of the CFTYPE selector flags */ + if (cfile->kn) + kernfs_notify(cfile->kn); +} + #else /* !CONFIG_CGROUPS */ struct cgroup_subsys_state; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 06c9d1aeea9d..0be276ffe08a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -612,8 +612,8 @@ static void cgroup_update_populated(struct cgroup *cgrp, bool populated) if (!trigger) break; - if (cgrp->events_kn) - kernfs_notify(cgrp->events_kn); + cgroup_file_notify(&cgrp->events_file); + cgrp = cgroup_parent(cgrp); } while (cgrp); } @@ -1771,6 +1771,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) INIT_LIST_HEAD(&cgrp->self.sibling); INIT_LIST_HEAD(&cgrp->self.children); + INIT_LIST_HEAD(&cgrp->self.files); INIT_LIST_HEAD(&cgrp->cset_links); INIT_LIST_HEAD(&cgrp->pidlists); mutex_init(&cgrp->pidlist_mutex); @@ -2562,7 +2563,7 @@ static int cgroup_procs_write_permission(struct task_struct *task, cgrp = cgroup_parent(cgrp); ret = -ENOMEM; - inode = kernfs_get_inode(sb, cgrp->procs_kn); + inode = kernfs_get_inode(sb, cgrp->procs_file.kn); if (inode) { ret = inode_permission(inode, MAY_WRITE); iput(inode); @@ -3253,10 +3254,14 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp, return ret; } - if (cft->write == cgroup_procs_write) - cgrp->procs_kn = kn; - else if (cft->seq_show == cgroup_events_show) - cgrp->events_kn = kn; + if (cft->file_offset) { + struct cgroup_file *cfile = (void *)css + cft->file_offset; + + kernfs_get(kn); + cfile->kn = kn; + list_add(&cfile->node, &css->files); + } + return 0; } @@ -4408,6 +4413,7 @@ static int cgroup_clone_children_write(struct cgroup_subsys_state *css, static struct cftype cgroup_dfl_base_files[] = { { .name = "cgroup.procs", + .file_offset = offsetof(struct cgroup, procs_file), .seq_start = cgroup_pidlist_start, .seq_next = cgroup_pidlist_next, .seq_stop = cgroup_pidlist_stop, @@ -4433,6 +4439,7 @@ static struct cftype cgroup_dfl_base_files[] = { { .name = "cgroup.events", .flags = CFTYPE_NOT_ON_ROOT, + .file_offset = offsetof(struct cgroup, events_file), .seq_show = cgroup_events_show, }, { } /* terminate */ @@ -4511,9 +4518,13 @@ static void css_free_work_fn(struct work_struct *work) container_of(work, struct cgroup_subsys_state, destroy_work); struct cgroup_subsys *ss = css->ss; struct cgroup *cgrp = css->cgroup; + struct cgroup_file *cfile; percpu_ref_exit(&css->refcnt); + list_for_each_entry(cfile, &css->files, node) + kernfs_put(cfile->kn); + if (ss) { /* css free path */ int id = css->id; @@ -4618,6 +4629,7 @@ static void init_and_link_css(struct cgroup_subsys_state *css, css->ss = ss; INIT_LIST_HEAD(&css->sibling); INIT_LIST_HEAD(&css->children); + INIT_LIST_HEAD(&css->files); css->serial_nr = css_serial_nr_next++; if (cgroup_parent(cgrp)) { -- cgit v1.3-6-gb490 From 6b7bc0618ff1a333d2265131b124e966335d5dee Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 22 Jun 2015 13:02:04 +0000 Subject: spi: add transfer histogram statistics via sysfs report transfer sizes as a histogram via the following files: /sys/class/spi_master/spi*/statistics/transfer_bytes_histo_* /sys/class/spi_master/spi*/spi*.*/statistics/transfer_bytes_histo_* Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 4 ++++ 2 files changed, 65 insertions(+) (limited to 'include') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 3abb3903f2ad..73face0f6b9c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -123,6 +123,28 @@ SPI_STATISTICS_SHOW(bytes, "%llu"); SPI_STATISTICS_SHOW(bytes_rx, "%llu"); SPI_STATISTICS_SHOW(bytes_tx, "%llu"); +#define SPI_STATISTICS_TRANSFER_BYTES_HISTO(index, number) \ + SPI_STATISTICS_SHOW_NAME(transfer_bytes_histo##index, \ + "transfer_bytes_histo_" number, \ + transfer_bytes_histo[index], "%lu") +SPI_STATISTICS_TRANSFER_BYTES_HISTO(0, "0-1"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(1, "2-3"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(2, "4-7"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(3, "8-15"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(4, "16-31"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(5, "32-63"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(6, "64-127"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(7, "128-255"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(8, "256-511"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(9, "512-1023"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(10, "1024-2047"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(11, "2048-4095"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(12, "4096-8191"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(13, "8192-16383"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+"); + static struct attribute *spi_dev_attrs[] = { &dev_attr_modalias.attr, NULL, @@ -143,6 +165,23 @@ static struct attribute *spi_device_statistics_attrs[] = { &dev_attr_spi_device_bytes.attr, &dev_attr_spi_device_bytes_rx.attr, &dev_attr_spi_device_bytes_tx.attr, + &dev_attr_spi_device_transfer_bytes_histo0.attr, + &dev_attr_spi_device_transfer_bytes_histo1.attr, + &dev_attr_spi_device_transfer_bytes_histo2.attr, + &dev_attr_spi_device_transfer_bytes_histo3.attr, + &dev_attr_spi_device_transfer_bytes_histo4.attr, + &dev_attr_spi_device_transfer_bytes_histo5.attr, + &dev_attr_spi_device_transfer_bytes_histo6.attr, + &dev_attr_spi_device_transfer_bytes_histo7.attr, + &dev_attr_spi_device_transfer_bytes_histo8.attr, + &dev_attr_spi_device_transfer_bytes_histo9.attr, + &dev_attr_spi_device_transfer_bytes_histo10.attr, + &dev_attr_spi_device_transfer_bytes_histo11.attr, + &dev_attr_spi_device_transfer_bytes_histo12.attr, + &dev_attr_spi_device_transfer_bytes_histo13.attr, + &dev_attr_spi_device_transfer_bytes_histo14.attr, + &dev_attr_spi_device_transfer_bytes_histo15.attr, + &dev_attr_spi_device_transfer_bytes_histo16.attr, NULL, }; @@ -168,6 +207,23 @@ static struct attribute *spi_master_statistics_attrs[] = { &dev_attr_spi_master_bytes.attr, &dev_attr_spi_master_bytes_rx.attr, &dev_attr_spi_master_bytes_tx.attr, + &dev_attr_spi_master_transfer_bytes_histo0.attr, + &dev_attr_spi_master_transfer_bytes_histo1.attr, + &dev_attr_spi_master_transfer_bytes_histo2.attr, + &dev_attr_spi_master_transfer_bytes_histo3.attr, + &dev_attr_spi_master_transfer_bytes_histo4.attr, + &dev_attr_spi_master_transfer_bytes_histo5.attr, + &dev_attr_spi_master_transfer_bytes_histo6.attr, + &dev_attr_spi_master_transfer_bytes_histo7.attr, + &dev_attr_spi_master_transfer_bytes_histo8.attr, + &dev_attr_spi_master_transfer_bytes_histo9.attr, + &dev_attr_spi_master_transfer_bytes_histo10.attr, + &dev_attr_spi_master_transfer_bytes_histo11.attr, + &dev_attr_spi_master_transfer_bytes_histo12.attr, + &dev_attr_spi_master_transfer_bytes_histo13.attr, + &dev_attr_spi_master_transfer_bytes_histo14.attr, + &dev_attr_spi_master_transfer_bytes_histo15.attr, + &dev_attr_spi_master_transfer_bytes_histo16.attr, NULL, }; @@ -186,10 +242,15 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, struct spi_master *master) { unsigned long flags; + int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1; + + if (l2len < 0) + l2len = 0; spin_lock_irqsave(&stats->lock, flags); stats->transfers++; + stats->transfer_bytes_histo[l2len]++; stats->bytes += xfer->len; if ((xfer->tx_buf) && diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 269e8afd3e2a..5b6fdc48eba7 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -51,6 +51,8 @@ extern struct bus_type spi_bus_type; * @bytes_tx: number of bytes sent to device * @bytes_rx: number of bytes received from device * + * @transfer_bytes_histo: + * transfer bytes histogramm */ struct spi_statistics { spinlock_t lock; /* lock for the whole structure */ @@ -68,6 +70,8 @@ struct spi_statistics { unsigned long long bytes_rx; unsigned long long bytes_tx; +#define SPI_STATISTICS_HISTO_SIZE 17 + unsigned long transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE]; }; void spi_statistics_add_transfer_stats(struct spi_statistics *stats, -- cgit v1.3-6-gb490 From 5cfc5220a63b1008e7198fb4f91c3ef763e46657 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 18 Sep 2015 10:14:41 +0300 Subject: ARM: pxa: Remove unused clock_enable field from struct pxa2xx_spi_master Use for struct pxa2xx_spi_master clock_enable field was removed years ago from the pxa2xx-spi driver by the commit 2f1a74e5a2de ("[ARM] pxa: make pxa2xx_spi driver use ssp_request()/ssp_free()"). Therefore remove it from structure definition, documentation and from couple affected board files. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- Documentation/spi/pxa2xx | 6 ------ arch/arm/mach-pxa/hx4700.c | 1 - arch/arm/mach-pxa/icontrol.c | 2 -- arch/arm/mach-pxa/z2.c | 2 -- include/linux/spi/pxa2xx_spi.h | 1 - 5 files changed, 12 deletions(-) (limited to 'include') diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx index 3352f97430e4..13a0b7fb192f 100644 --- a/Documentation/spi/pxa2xx +++ b/Documentation/spi/pxa2xx @@ -22,15 +22,10 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a found in include/linux/spi/pxa2xx_spi.h: struct pxa2xx_spi_master { - u32 clock_enable; u16 num_chipselect; u8 enable_dma; }; -The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the -corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See -the "PXA2xx Developer Manual" section "Clocks and Power Management". - The "pxa2xx_spi_master.num_chipselect" field is used to determine the number of slave device (chips) attached to this SPI master. @@ -57,7 +52,6 @@ static struct resource pxa_spi_nssp_resources[] = { }; static struct pxa2xx_spi_master pxa_nssp_master_info = { - .clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */ .num_chipselect = 1, /* Matches the number of chips attached to NSSP */ .enable_dma = 1, /* Enables NSSP DMA */ }; diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 5fb41ad6e3bc..1e0301a0dbbb 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -630,7 +630,6 @@ static struct spi_board_info tsc2046_board_info[] __initdata = { static struct pxa2xx_spi_master pxa_ssp2_master_info = { .num_chipselect = 1, - .clock_enable = CKEN_SSP2, .enable_dma = 1, }; diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index 9b0eb0252af6..a1869f9b6219 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -116,13 +116,11 @@ static struct spi_board_info mcp251x_board_info[] = { }; static struct pxa2xx_spi_master pxa_ssp3_spi_master_info = { - .clock_enable = CKEN_SSP3, .num_chipselect = 2, .enable_dma = 1 }; static struct pxa2xx_spi_master pxa_ssp4_spi_master_info = { - .clock_enable = CKEN_SSP4, .num_chipselect = 2, .enable_dma = 1 }; diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index e1a121b36cfa..3deeca7bbe41 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -595,13 +595,11 @@ static struct spi_board_info spi_board_info[] __initdata = { }; static struct pxa2xx_spi_master pxa_ssp1_master_info = { - .clock_enable = CKEN_SSP, .num_chipselect = 1, .enable_dma = 1, }; static struct pxa2xx_spi_master pxa_ssp2_master_info = { - .clock_enable = CKEN_SSP2, .num_chipselect = 1, }; diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index 6d36dacec4ba..9ec4c147abbc 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h @@ -23,7 +23,6 @@ struct dma_chan; /* device.platform_data for SSP controller devices */ struct pxa2xx_spi_master { - u32 clock_enable; u16 num_chipselect; u8 enable_dma; -- cgit v1.3-6-gb490 From 59796edcf21c7c19d58a223001f9ed13746c51c2 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 10 Sep 2015 10:17:59 +0300 Subject: mei: make modules.alias UUID information easier to read scripts/mod/file2alias.c:add_uuid() convert UUID into a single string which does not conform to the standard little endian UUID formatting. This patch changes add_uuid() to output same format as %pUL and modifies the mei driver to match the change. Signed-off-by: Prarit Bhargava Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 7 ++----- include/linux/mod_devicetable.h | 4 ---- scripts/mod/file2alias.c | 8 +++++--- 3 files changed, 7 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index eef1c6b46ad8..e294f70741a0 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -597,9 +597,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); size_t len; - len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":", - cldev->name, MEI_CL_UUID_ARGS(uuid->b)); - + len = snprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid); return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; } static DEVICE_ATTR_RO(modalias); @@ -631,8 +629,7 @@ static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name)) return -ENOMEM; - if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":", - cldev->name, MEI_CL_UUID_ARGS(uuid->b))) + if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:", cldev->name, uuid)) return -ENOMEM; return 0; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 688997a24aad..5e8a0ad22cbc 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -601,10 +601,6 @@ struct ipack_device_id { #define MEI_CL_MODULE_PREFIX "mei:" #define MEI_CL_NAME_SIZE 32 -#define MEI_CL_UUID_FMT "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" -#define MEI_CL_UUID_ARGS(_u) \ - _u[0], _u[1], _u[2], _u[3], _u[4], _u[5], _u[6], _u[7], \ - _u[8], _u[9], _u[10], _u[11], _u[12], _u[13], _u[14], _u[15] /** * struct mei_cl_device_id - MEI client device identifier diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5f2088209132..fa79d113f34c 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -137,10 +137,12 @@ static inline void add_wildcard(char *str) static inline void add_uuid(char *str, uuid_le uuid) { int len = strlen(str); - int i; - for (i = 0; i < 16; i++) - sprintf(str + len + (i << 1), "%02x", uuid.b[i]); + sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0], + uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6], + uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11], + uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]); } /** -- cgit v1.3-6-gb490 From b26864cad1c9f66f4966726ba7bc81d2b9b8f990 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 10 Sep 2015 10:18:01 +0300 Subject: mei: bus: add client protocol version to the device alias The device alias now looks like mei:S:uuid:N:* In that way we can bind different drivers to clients with different protocol versions if required. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 28 +++++++++++++++++++++------- drivers/nfc/microread/mei.c | 2 +- drivers/nfc/pn544/mei.c | 2 +- include/linux/mod_devicetable.h | 3 +++ scripts/mod/devicetable-offsets.c | 1 + scripts/mod/file2alias.c | 4 +++- 6 files changed, 30 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index d92017fa1630..38bc4380ad08 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -453,17 +453,26 @@ struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev, { const struct mei_cl_device_id *id; const uuid_le *uuid; + u8 version; + bool match; uuid = mei_me_cl_uuid(cldev->me_cl); + version = mei_me_cl_ver(cldev->me_cl); id = cldrv->id_table; while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) { if (!uuid_le_cmp(*uuid, id->uuid)) { + match = true; - if (!cldev->name[0]) - return id; + if (cldev->name[0]) + if (strncmp(cldev->name, id->name, + sizeof(id->name))) + match = false; - if (!strncmp(cldev->name, id->name, sizeof(id->name))) + if (id->version != MEI_CL_VERSION_ANY) + if (id->version != version) + match = false; + if (match) return id; } @@ -647,7 +656,8 @@ static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name)) return -ENOMEM; - if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:", cldev->name, uuid)) + if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:", + cldev->name, uuid, version)) return -ENOMEM; return 0; @@ -737,8 +747,10 @@ static bool mei_cl_dev_setup(struct mei_device *bus, mei_cl_dev_fixup(cldev); if (cldev->do_match) - dev_set_name(&cldev->dev, "mei:%s:%pUl", - cldev->name, mei_me_cl_uuid(cldev->me_cl)); + dev_set_name(&cldev->dev, "mei:%s:%pUl:%02X", + cldev->name, + mei_me_cl_uuid(cldev->me_cl), + mei_me_cl_ver(cldev->me_cl)); return cldev->do_match == 1; } @@ -754,7 +766,9 @@ static int mei_cl_bus_dev_add(struct mei_cl_device *cldev) { int ret; - dev_dbg(cldev->bus->dev, "adding %pUL\n", mei_me_cl_uuid(cldev->me_cl)); + dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n", + mei_me_cl_uuid(cldev->me_cl), + mei_me_cl_ver(cldev->me_cl)); ret = device_add(&cldev->dev); if (!ret) cldev->is_added = 1; diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index f9f5fc97cdd7..93328bd45110 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -67,7 +67,7 @@ static int microread_mei_remove(struct mei_cl_device *device) } static struct mei_cl_device_id microread_mei_tbl[] = { - { MICROREAD_DRIVER_NAME, MEI_NFC_UUID}, + { MICROREAD_DRIVER_NAME, MEI_NFC_UUID, MEI_CL_VERSION_ANY}, /* required last entry */ { } diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c index 101a37e12efa..80f897b4a401 100644 --- a/drivers/nfc/pn544/mei.c +++ b/drivers/nfc/pn544/mei.c @@ -67,7 +67,7 @@ static int pn544_mei_remove(struct mei_cl_device *device) } static struct mei_cl_device_id pn544_mei_tbl[] = { - { PN544_DRIVER_NAME, MEI_NFC_UUID}, + { PN544_DRIVER_NAME, MEI_NFC_UUID, MEI_CL_VERSION_ANY}, /* required last entry */ { } diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 5e8a0ad22cbc..6975cbf1435b 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -601,11 +601,13 @@ struct ipack_device_id { #define MEI_CL_MODULE_PREFIX "mei:" #define MEI_CL_NAME_SIZE 32 +#define MEI_CL_VERSION_ANY 0xff /** * struct mei_cl_device_id - MEI client device identifier * @name: helper name * @uuid: client uuid + * @version: client protocol version * @driver_info: information used by the driver. * * identifies mei client device by uuid and name @@ -613,6 +615,7 @@ struct ipack_device_id { struct mei_cl_device_id { char name[MEI_CL_NAME_SIZE]; uuid_le uuid; + __u8 version; kernel_ulong_t driver_info; }; diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index e70fcd12eeeb..5a6edacc85d9 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -185,6 +185,7 @@ int main(void) DEVID(mei_cl_device_id); DEVID_FIELD(mei_cl_device_id, name); DEVID_FIELD(mei_cl_device_id, uuid); + DEVID_FIELD(mei_cl_device_id, version); DEVID(rio_device_id); DEVID_FIELD(rio_device_id, did); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index fa79d113f34c..9bc2cfe0ee37 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1202,16 +1202,18 @@ static int do_cpu_entry(const char *filename, void *symval, char *alias) } ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry); -/* Looks like: mei:S:uuid */ +/* Looks like: mei:S:uuid:N:* */ static int do_mei_entry(const char *filename, void *symval, char *alias) { DEF_FIELD_ADDR(symval, mei_cl_device_id, name); DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid); + DEF_FIELD(symval, mei_cl_device_id, version); sprintf(alias, MEI_CL_MODULE_PREFIX); sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*"); add_uuid(alias, *uuid); + ADD(alias, ":", version != MEI_CL_VERSION_ANY, version); strcat(alias, ":*"); -- cgit v1.3-6-gb490 From baeacd0376975bee0fdf6378e1c24587ab0b6ad4 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 10 Sep 2015 10:18:02 +0300 Subject: mei: bus: export uuid and protocol version to mei_cl bus drivers Export the uuid and the protocol version of the underlying me client for me client bus drivers usage. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 26 ++++++++++++++++++++++++++ include/linux/mei_cl_bus.h | 3 +++ 2 files changed, 29 insertions(+) (limited to 'include') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 38bc4380ad08..53525ca50337 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -341,6 +341,32 @@ void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data) } EXPORT_SYMBOL_GPL(mei_cl_set_drvdata); +/** + * mei_cldev_uuid - return uuid of the underlying me client + * + * @cldev: mei client device + * + * Return: me client uuid + */ +const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev) +{ + return mei_me_cl_uuid(cldev->me_cl); +} +EXPORT_SYMBOL_GPL(mei_cldev_uuid); + +/** + * mei_cldev_ver - return protocol version of the underlying me client + * + * @cldev: mei client device + * + * Return: me client protocol version + */ +u8 mei_cldev_ver(const struct mei_cl_device *cldev) +{ + return mei_me_cl_ver(cldev->me_cl); +} +EXPORT_SYMBOL_GPL(mei_cldev_ver); + /** * mei_cl_enable_device - enable me client device * create connection with me client diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h index 0962b2ca628a..9834f832b098 100644 --- a/include/linux/mei_cl_bus.h +++ b/include/linux/mei_cl_bus.h @@ -85,6 +85,9 @@ int mei_cl_register_event_cb(struct mei_cl_device *device, #define MEI_CL_EVENT_TX 1 #define MEI_CL_EVENT_NOTIF 2 +const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev); +u8 mei_cldev_ver(const struct mei_cl_device *cldev); + void *mei_cl_get_drvdata(const struct mei_cl_device *device); void mei_cl_set_drvdata(struct mei_cl_device *device, void *data); -- cgit v1.3-6-gb490 From 01a14edeaf0456c28e2b9af3afdc0807ec6c20bd Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 10 Sep 2015 10:18:03 +0300 Subject: mei: bus: export mei_cldev_enabled function Let me client device driver query of the device is connected and hence enabled. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 13 +++++++++++++ include/linux/mei_cl_bus.h | 1 + 2 files changed, 14 insertions(+) (limited to 'include') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 53525ca50337..4edf71acfed6 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -367,6 +367,19 @@ u8 mei_cldev_ver(const struct mei_cl_device *cldev) } EXPORT_SYMBOL_GPL(mei_cldev_ver); +/** + * mei_cldev_enabled - check whether the device is enabled + * + * @cldev: mei client device + * + * Return: true if me client is initialized and connected + */ +bool mei_cldev_enabled(struct mei_cl_device *cldev) +{ + return cldev->cl && mei_cl_is_connected(cldev->cl); +} +EXPORT_SYMBOL_GPL(mei_cldev_enabled); + /** * mei_cl_enable_device - enable me client device * create connection with me client diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h index 9834f832b098..30d1c8b94a27 100644 --- a/include/linux/mei_cl_bus.h +++ b/include/linux/mei_cl_bus.h @@ -93,5 +93,6 @@ void mei_cl_set_drvdata(struct mei_cl_device *device, void *data); int mei_cl_enable_device(struct mei_cl_device *device); int mei_cl_disable_device(struct mei_cl_device *device); +bool mei_cldev_enabled(struct mei_cl_device *cldev); #endif /* _LINUX_MEI_CL_BUS_H */ -- cgit v1.3-6-gb490 From 893913822e829f7a37824f6041ff964076374191 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 10 Sep 2015 10:18:04 +0300 Subject: mei: bus: complete variable rename of type struct mei_cl_device In the commit 5c079ae11921 ("mei: bus: fix drivers and devices names confusion") we set the variables of type struct mei_cl_device to 'cldev' but few places were left out, namely mei_cl_bus.h header and the mei nfc drivers. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/mei_phy.c | 30 +++++++++++++++--------------- drivers/nfc/mei_phy.h | 4 ++-- drivers/nfc/microread/mei.c | 8 ++++---- drivers/nfc/pn544/mei.c | 8 ++++---- include/linux/mei_cl_bus.h | 29 ++++++++++++++--------------- 5 files changed, 39 insertions(+), 40 deletions(-) (limited to 'include') diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 754a9bb0f58d..ecd2a0dce797 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -118,7 +118,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy) cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION; MEI_DUMP_NFC_HDR("version", &cmd.hdr); - r = mei_cl_send(phy->device, (u8 *)&cmd, sizeof(struct mei_nfc_cmd)); + r = mei_cl_send(phy->cldev, (u8 *)&cmd, sizeof(struct mei_nfc_cmd)); if (r < 0) { pr_err("Could not send IF version cmd\n"); return r; @@ -132,7 +132,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy) if (!reply) return -ENOMEM; - bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, if_version_length); + bytes_recv = mei_cl_recv(phy->cldev, (u8 *)reply, if_version_length); if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) { pr_err("Could not read IF version\n"); r = -EIO; @@ -186,13 +186,13 @@ static int mei_nfc_connect(struct nfc_mei_phy *phy) connect->vendor_id = phy->vendor_id; MEI_DUMP_NFC_HDR("connect request", &cmd->hdr); - r = mei_cl_send(phy->device, (u8 *)cmd, connect_length); + r = mei_cl_send(phy->cldev, (u8 *)cmd, connect_length); if (r < 0) { pr_err("Could not send connect cmd %d\n", r); goto err; } - bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, connect_resp_length); + bytes_recv = mei_cl_recv(phy->cldev, (u8 *)reply, connect_resp_length); if (bytes_recv < 0) { r = bytes_recv; pr_err("Could not read connect response %d\n", r); @@ -238,7 +238,7 @@ static int mei_nfc_send(struct nfc_mei_phy *phy, u8 *buf, size_t length) MEI_DUMP_NFC_HDR("send", hdr); memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length); - err = mei_cl_send(phy->device, mei_buf, length + MEI_NFC_HEADER_SIZE); + err = mei_cl_send(phy->cldev, mei_buf, length + MEI_NFC_HEADER_SIZE); if (err < 0) goto out; @@ -278,7 +278,7 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length) struct mei_nfc_hdr *hdr; int received_length; - received_length = mei_cl_recv(phy->device, buf, length); + received_length = mei_cl_recv(phy->cldev, buf, length); if (received_length < 0) return received_length; @@ -296,7 +296,7 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length) } -static void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, +static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events, void *context) { struct nfc_mei_phy *phy = context; @@ -337,7 +337,7 @@ static int nfc_mei_phy_enable(void *phy_id) if (phy->powered == 1) return 0; - r = mei_cl_enable_device(phy->device); + r = mei_cl_enable_device(phy->cldev); if (r < 0) { pr_err("Could not enable device %d\n", r); return r; @@ -355,7 +355,7 @@ static int nfc_mei_phy_enable(void *phy_id) goto err; } - r = mei_cl_register_event_cb(phy->device, BIT(MEI_CL_EVENT_RX), + r = mei_cl_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX), nfc_mei_event_cb, phy); if (r) { pr_err("Event cb registration failed %d\n", r); @@ -368,7 +368,7 @@ static int nfc_mei_phy_enable(void *phy_id) err: phy->powered = 0; - mei_cl_disable_device(phy->device); + mei_cl_disable_device(phy->cldev); return r; } @@ -378,7 +378,7 @@ static void nfc_mei_phy_disable(void *phy_id) pr_info("%s\n", __func__); - mei_cl_disable_device(phy->device); + mei_cl_disable_device(phy->cldev); phy->powered = 0; } @@ -390,7 +390,7 @@ struct nfc_phy_ops mei_phy_ops = { }; EXPORT_SYMBOL_GPL(mei_phy_ops); -struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device) +struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *cldev) { struct nfc_mei_phy *phy; @@ -398,9 +398,9 @@ struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device) if (!phy) return NULL; - phy->device = device; + phy->cldev = cldev; init_waitqueue_head(&phy->send_wq); - mei_cl_set_drvdata(device, phy); + mei_cl_set_drvdata(cldev, phy); return phy; } @@ -408,7 +408,7 @@ EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc); void nfc_mei_phy_free(struct nfc_mei_phy *phy) { - mei_cl_disable_device(phy->device); + mei_cl_disable_device(phy->cldev); kfree(phy); } EXPORT_SYMBOL_GPL(nfc_mei_phy_free); diff --git a/drivers/nfc/mei_phy.h b/drivers/nfc/mei_phy.h index fbfa3e61738f..acd3a1fc69e6 100644 --- a/drivers/nfc/mei_phy.h +++ b/drivers/nfc/mei_phy.h @@ -13,7 +13,7 @@ /** * struct nfc_mei_phy * - * @device: mei device + * @cldev: mei client device * @hdev: nfc hci device * @send_wq: send completion wait queue @@ -28,7 +28,7 @@ * and prevents normal operation. */ struct nfc_mei_phy { - struct mei_cl_device *device; + struct mei_cl_device *cldev; struct nfc_hci_dev *hdev; wait_queue_head_t send_wq; diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index 93328bd45110..994871c02b7b 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -29,7 +29,7 @@ #define MICROREAD_DRIVER_NAME "microread" -static int microread_mei_probe(struct mei_cl_device *device, +static int microread_mei_probe(struct mei_cl_device *cldev, const struct mei_cl_device_id *id) { struct nfc_mei_phy *phy; @@ -37,7 +37,7 @@ static int microread_mei_probe(struct mei_cl_device *device, pr_info("Probing NFC microread\n"); - phy = nfc_mei_phy_alloc(device); + phy = nfc_mei_phy_alloc(cldev); if (!phy) { pr_err("Cannot allocate memory for microread mei phy.\n"); return -ENOMEM; @@ -55,9 +55,9 @@ static int microread_mei_probe(struct mei_cl_device *device, return 0; } -static int microread_mei_remove(struct mei_cl_device *device) +static int microread_mei_remove(struct mei_cl_device *cldev) { - struct nfc_mei_phy *phy = mei_cl_get_drvdata(device); + struct nfc_mei_phy *phy = mei_cl_get_drvdata(cldev); microread_remove(phy->hdev); diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c index 80f897b4a401..2a2c9304e64c 100644 --- a/drivers/nfc/pn544/mei.c +++ b/drivers/nfc/pn544/mei.c @@ -27,7 +27,7 @@ #define PN544_DRIVER_NAME "pn544" -static int pn544_mei_probe(struct mei_cl_device *device, +static int pn544_mei_probe(struct mei_cl_device *cldev, const struct mei_cl_device_id *id) { struct nfc_mei_phy *phy; @@ -35,7 +35,7 @@ static int pn544_mei_probe(struct mei_cl_device *device, pr_info("Probing NFC pn544\n"); - phy = nfc_mei_phy_alloc(device); + phy = nfc_mei_phy_alloc(cldev); if (!phy) { pr_err("Cannot allocate memory for pn544 mei phy.\n"); return -ENOMEM; @@ -53,9 +53,9 @@ static int pn544_mei_probe(struct mei_cl_device *device, return 0; } -static int pn544_mei_remove(struct mei_cl_device *device) +static int pn544_mei_remove(struct mei_cl_device *cldev) { - struct nfc_mei_phy *phy = mei_cl_get_drvdata(device); + struct nfc_mei_phy *phy = mei_cl_get_drvdata(cldev); pr_info("Removing pn544\n"); diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h index 30d1c8b94a27..c364df750405 100644 --- a/include/linux/mei_cl_bus.h +++ b/include/linux/mei_cl_bus.h @@ -8,7 +8,7 @@ struct mei_cl_device; struct mei_device; -typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device, +typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *cldev, u32 events, void *context); /** @@ -62,22 +62,21 @@ struct mei_cl_driver { const struct mei_cl_device_id *id_table; - int (*probe)(struct mei_cl_device *dev, + int (*probe)(struct mei_cl_device *cldev, const struct mei_cl_device_id *id); - int (*remove)(struct mei_cl_device *dev); + int (*remove)(struct mei_cl_device *cldev); }; -int __mei_cl_driver_register(struct mei_cl_driver *driver, - struct module *owner); -#define mei_cl_driver_register(driver) \ - __mei_cl_driver_register(driver, THIS_MODULE) +int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner); +#define mei_cl_driver_register(cldrv) \ + __mei_cl_driver_register(cldrv, THIS_MODULE) -void mei_cl_driver_unregister(struct mei_cl_driver *driver); +void mei_cl_driver_unregister(struct mei_cl_driver *cldrv); -ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length); -ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length); +ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length); +ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); -int mei_cl_register_event_cb(struct mei_cl_device *device, +int mei_cl_register_event_cb(struct mei_cl_device *cldev, unsigned long event_mask, mei_cl_event_cb_t read_cb, void *context); @@ -88,11 +87,11 @@ int mei_cl_register_event_cb(struct mei_cl_device *device, const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev); u8 mei_cldev_ver(const struct mei_cl_device *cldev); -void *mei_cl_get_drvdata(const struct mei_cl_device *device); -void mei_cl_set_drvdata(struct mei_cl_device *device, void *data); +void *mei_cl_get_drvdata(const struct mei_cl_device *cldev); +void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data); -int mei_cl_enable_device(struct mei_cl_device *device); -int mei_cl_disable_device(struct mei_cl_device *device); +int mei_cl_enable_device(struct mei_cl_device *cldev); +int mei_cl_disable_device(struct mei_cl_device *cldev); bool mei_cldev_enabled(struct mei_cl_device *cldev); #endif /* _LINUX_MEI_CL_BUS_H */ -- cgit v1.3-6-gb490 From d49dc5e76fc917e5dfef76cb56fe3b3868deed5d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 10 Sep 2015 10:18:05 +0300 Subject: mei: bus: use mei_cldev_ prefix for the API functions Use mei_cldev_ prefix for all mei client bus api functions in order to resolve prefix conflict with functions that handle client function and are defined in client.c Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 67 +++++++++++++++++++++++---------------------- drivers/nfc/mei_phy.c | 25 +++++++++-------- drivers/nfc/microread/mei.c | 6 ++-- drivers/nfc/pn544/mei.c | 6 ++-- include/linux/mei_cl_bus.h | 33 +++++++++++----------- 5 files changed, 70 insertions(+), 67 deletions(-) (limited to 'include') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 4edf71acfed6..0406e7201fe4 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -165,7 +165,7 @@ out: } /** - * mei_cl_send - me device send (write) + * mei_cldev_send - me device send (write) * * @cldev: me client device * @buf: buffer to send @@ -173,7 +173,7 @@ out: * * Return: written size in bytes or < 0 on error */ -ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length) +ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length) { struct mei_cl *cl = cldev->cl; @@ -182,10 +182,10 @@ ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length) return __mei_cl_send(cl, buf, length, 1); } -EXPORT_SYMBOL_GPL(mei_cl_send); +EXPORT_SYMBOL_GPL(mei_cldev_send); /** - * mei_cl_recv - client receive (read) + * mei_cldev_recv - client receive (read) * * @cldev: me client device * @buf: buffer to send @@ -193,7 +193,7 @@ EXPORT_SYMBOL_GPL(mei_cl_send); * * Return: read size in bytes of < 0 on error */ -ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length) +ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length) { struct mei_cl *cl = cldev->cl; @@ -202,15 +202,15 @@ ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length) return __mei_cl_recv(cl, buf, length); } -EXPORT_SYMBOL_GPL(mei_cl_recv); +EXPORT_SYMBOL_GPL(mei_cldev_recv); /** - * mei_bus_event_work - dispatch rx event for a bus device + * mei_cl_bus_event_work - dispatch rx event for a bus device * and schedule new work * * @work: work */ -static void mei_bus_event_work(struct work_struct *work) +static void mei_cl_bus_event_work(struct work_struct *work) { struct mei_cl_device *cldev; @@ -272,7 +272,7 @@ void mei_cl_bus_rx_event(struct mei_cl *cl) } /** - * mei_cl_register_event_cb - register event callback + * mei_cldev_register_event_cb - register event callback * * @cldev: me client devices * @event_cb: callback function @@ -283,9 +283,9 @@ void mei_cl_bus_rx_event(struct mei_cl *cl) * -EALREADY if an callback is already registered * <0 on other errors */ -int mei_cl_register_event_cb(struct mei_cl_device *cldev, - unsigned long events_mask, - mei_cl_event_cb_t event_cb, void *context) +int mei_cldev_register_event_cb(struct mei_cl_device *cldev, + unsigned long events_mask, + mei_cldev_event_cb_t event_cb, void *context) { int ret; @@ -296,7 +296,7 @@ int mei_cl_register_event_cb(struct mei_cl_device *cldev, cldev->events_mask = events_mask; cldev->event_cb = event_cb; cldev->event_context = context; - INIT_WORK(&cldev->event_work, mei_bus_event_work); + INIT_WORK(&cldev->event_work, mei_cl_bus_event_work); if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) { ret = mei_cl_read_start(cldev->cl, 0, NULL); @@ -314,32 +314,32 @@ int mei_cl_register_event_cb(struct mei_cl_device *cldev, return 0; } -EXPORT_SYMBOL_GPL(mei_cl_register_event_cb); +EXPORT_SYMBOL_GPL(mei_cldev_register_event_cb); /** - * mei_cl_get_drvdata - driver data getter + * mei_cldev_get_drvdata - driver data getter * * @cldev: mei client device * * Return: driver private data */ -void *mei_cl_get_drvdata(const struct mei_cl_device *cldev) +void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev) { return dev_get_drvdata(&cldev->dev); } -EXPORT_SYMBOL_GPL(mei_cl_get_drvdata); +EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata); /** - * mei_cl_set_drvdata - driver data setter + * mei_cldev_set_drvdata - driver data setter * * @cldev: mei client device * @data: data to store */ -void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data) +void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data) { dev_set_drvdata(&cldev->dev, data); } -EXPORT_SYMBOL_GPL(mei_cl_set_drvdata); +EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata); /** * mei_cldev_uuid - return uuid of the underlying me client @@ -381,14 +381,14 @@ bool mei_cldev_enabled(struct mei_cl_device *cldev) EXPORT_SYMBOL_GPL(mei_cldev_enabled); /** - * mei_cl_enable_device - enable me client device + * mei_cldev_enable_device - enable me client device * create connection with me client * * @cldev: me client device * * Return: 0 on success and < 0 on error */ -int mei_cl_enable_device(struct mei_cl_device *cldev) +int mei_cldev_enable(struct mei_cl_device *cldev) { struct mei_device *bus = cldev->bus; struct mei_cl *cl; @@ -428,17 +428,17 @@ out: return ret; } -EXPORT_SYMBOL_GPL(mei_cl_enable_device); +EXPORT_SYMBOL_GPL(mei_cldev_enable); /** - * mei_cl_disable_device - disable me client device + * mei_cldev_disable - disable me client device * disconnect form the me client * * @cldev: me client device * * Return: 0 on success and < 0 on error */ -int mei_cl_disable_device(struct mei_cl_device *cldev) +int mei_cldev_disable(struct mei_cl_device *cldev) { struct mei_device *bus; struct mei_cl *cl; @@ -476,7 +476,7 @@ out: mutex_unlock(&bus->device_lock); return err; } -EXPORT_SYMBOL_GPL(mei_cl_disable_device); +EXPORT_SYMBOL_GPL(mei_cldev_disable); /** * mei_cl_device_find - find matching entry in the driver id table @@ -663,14 +663,14 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, } static DEVICE_ATTR_RO(modalias); -static struct attribute *mei_cl_dev_attrs[] = { +static struct attribute *mei_cldev_attrs[] = { &dev_attr_name.attr, &dev_attr_uuid.attr, &dev_attr_version.attr, &dev_attr_modalias.attr, NULL, }; -ATTRIBUTE_GROUPS(mei_cl_dev); +ATTRIBUTE_GROUPS(mei_cldev); /** * mei_cl_device_uevent - me client bus uevent handler @@ -704,7 +704,7 @@ static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env) static struct bus_type mei_cl_bus_type = { .name = "mei", - .dev_groups = mei_cl_dev_groups, + .dev_groups = mei_cldev_groups, .match = mei_cl_device_match, .probe = mei_cl_device_probe, .remove = mei_cl_device_remove, @@ -937,7 +937,8 @@ void mei_cl_bus_rescan(struct mei_device *bus) dev_dbg(bus->dev, "rescan end"); } -int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner) +int __mei_cldev_driver_register(struct mei_cl_driver *cldrv, + struct module *owner) { int err; @@ -953,15 +954,15 @@ int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner) return 0; } -EXPORT_SYMBOL_GPL(__mei_cl_driver_register); +EXPORT_SYMBOL_GPL(__mei_cldev_driver_register); -void mei_cl_driver_unregister(struct mei_cl_driver *cldrv) +void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv) { driver_unregister(&cldrv->driver); pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name); } -EXPORT_SYMBOL_GPL(mei_cl_driver_unregister); +EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister); int __init mei_cl_bus_init(void) diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index ecd2a0dce797..83deda4bb4d6 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -118,7 +118,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy) cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION; MEI_DUMP_NFC_HDR("version", &cmd.hdr); - r = mei_cl_send(phy->cldev, (u8 *)&cmd, sizeof(struct mei_nfc_cmd)); + r = mei_cldev_send(phy->cldev, (u8 *)&cmd, sizeof(struct mei_nfc_cmd)); if (r < 0) { pr_err("Could not send IF version cmd\n"); return r; @@ -132,7 +132,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy) if (!reply) return -ENOMEM; - bytes_recv = mei_cl_recv(phy->cldev, (u8 *)reply, if_version_length); + bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, if_version_length); if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) { pr_err("Could not read IF version\n"); r = -EIO; @@ -186,13 +186,14 @@ static int mei_nfc_connect(struct nfc_mei_phy *phy) connect->vendor_id = phy->vendor_id; MEI_DUMP_NFC_HDR("connect request", &cmd->hdr); - r = mei_cl_send(phy->cldev, (u8 *)cmd, connect_length); + r = mei_cldev_send(phy->cldev, (u8 *)cmd, connect_length); if (r < 0) { pr_err("Could not send connect cmd %d\n", r); goto err; } - bytes_recv = mei_cl_recv(phy->cldev, (u8 *)reply, connect_resp_length); + bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, + connect_resp_length); if (bytes_recv < 0) { r = bytes_recv; pr_err("Could not read connect response %d\n", r); @@ -238,7 +239,7 @@ static int mei_nfc_send(struct nfc_mei_phy *phy, u8 *buf, size_t length) MEI_DUMP_NFC_HDR("send", hdr); memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length); - err = mei_cl_send(phy->cldev, mei_buf, length + MEI_NFC_HEADER_SIZE); + err = mei_cldev_send(phy->cldev, mei_buf, length + MEI_NFC_HEADER_SIZE); if (err < 0) goto out; @@ -278,7 +279,7 @@ static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length) struct mei_nfc_hdr *hdr; int received_length; - received_length = mei_cl_recv(phy->cldev, buf, length); + received_length = mei_cldev_recv(phy->cldev, buf, length); if (received_length < 0) return received_length; @@ -337,7 +338,7 @@ static int nfc_mei_phy_enable(void *phy_id) if (phy->powered == 1) return 0; - r = mei_cl_enable_device(phy->cldev); + r = mei_cldev_enable(phy->cldev); if (r < 0) { pr_err("Could not enable device %d\n", r); return r; @@ -355,7 +356,7 @@ static int nfc_mei_phy_enable(void *phy_id) goto err; } - r = mei_cl_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX), + r = mei_cldev_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX), nfc_mei_event_cb, phy); if (r) { pr_err("Event cb registration failed %d\n", r); @@ -368,7 +369,7 @@ static int nfc_mei_phy_enable(void *phy_id) err: phy->powered = 0; - mei_cl_disable_device(phy->cldev); + mei_cldev_disable(phy->cldev); return r; } @@ -378,7 +379,7 @@ static void nfc_mei_phy_disable(void *phy_id) pr_info("%s\n", __func__); - mei_cl_disable_device(phy->cldev); + mei_cldev_disable(phy->cldev); phy->powered = 0; } @@ -400,7 +401,7 @@ struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *cldev) phy->cldev = cldev; init_waitqueue_head(&phy->send_wq); - mei_cl_set_drvdata(cldev, phy); + mei_cldev_set_drvdata(cldev, phy); return phy; } @@ -408,7 +409,7 @@ EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc); void nfc_mei_phy_free(struct nfc_mei_phy *phy) { - mei_cl_disable_device(phy->cldev); + mei_cldev_disable(phy->cldev); kfree(phy); } EXPORT_SYMBOL_GPL(nfc_mei_phy_free); diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index 994871c02b7b..3092501f26c4 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -57,7 +57,7 @@ static int microread_mei_probe(struct mei_cl_device *cldev, static int microread_mei_remove(struct mei_cl_device *cldev) { - struct nfc_mei_phy *phy = mei_cl_get_drvdata(cldev); + struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev); microread_remove(phy->hdev); @@ -88,7 +88,7 @@ static int microread_mei_init(void) pr_debug(DRIVER_DESC ": %s\n", __func__); - r = mei_cl_driver_register(µread_driver); + r = mei_cldev_driver_register(µread_driver); if (r) { pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n"); return r; @@ -99,7 +99,7 @@ static int microread_mei_init(void) static void microread_mei_exit(void) { - mei_cl_driver_unregister(µread_driver); + mei_cldev_driver_unregister(µread_driver); } module_init(microread_mei_init); diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c index 2a2c9304e64c..46d0eb24eef9 100644 --- a/drivers/nfc/pn544/mei.c +++ b/drivers/nfc/pn544/mei.c @@ -55,7 +55,7 @@ static int pn544_mei_probe(struct mei_cl_device *cldev, static int pn544_mei_remove(struct mei_cl_device *cldev) { - struct nfc_mei_phy *phy = mei_cl_get_drvdata(cldev); + struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev); pr_info("Removing pn544\n"); @@ -88,7 +88,7 @@ static int pn544_mei_init(void) pr_debug(DRIVER_DESC ": %s\n", __func__); - r = mei_cl_driver_register(&pn544_driver); + r = mei_cldev_driver_register(&pn544_driver); if (r) { pr_err(PN544_DRIVER_NAME ": driver registration failed\n"); return r; @@ -99,7 +99,7 @@ static int pn544_mei_init(void) static void pn544_mei_exit(void) { - mei_cl_driver_unregister(&pn544_driver); + mei_cldev_driver_unregister(&pn544_driver); } module_init(pn544_mei_init); diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h index c364df750405..e746919530f5 100644 --- a/include/linux/mei_cl_bus.h +++ b/include/linux/mei_cl_bus.h @@ -8,8 +8,8 @@ struct mei_cl_device; struct mei_device; -typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *cldev, - u32 events, void *context); +typedef void (*mei_cldev_event_cb_t)(struct mei_cl_device *cldev, + u32 events, void *context); /** * struct mei_cl_device - MEI device handle @@ -45,7 +45,7 @@ struct mei_cl_device { char name[MEI_CL_NAME_SIZE]; struct work_struct event_work; - mei_cl_event_cb_t event_cb; + mei_cldev_event_cb_t event_cb; void *event_context; unsigned long events_mask; unsigned long events; @@ -67,18 +67,19 @@ struct mei_cl_driver { int (*remove)(struct mei_cl_device *cldev); }; -int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner); -#define mei_cl_driver_register(cldrv) \ - __mei_cl_driver_register(cldrv, THIS_MODULE) +int __mei_cldev_driver_register(struct mei_cl_driver *cldrv, + struct module *owner); +#define mei_cldev_driver_register(cldrv) \ + __mei_cldev_driver_register(cldrv, THIS_MODULE) -void mei_cl_driver_unregister(struct mei_cl_driver *cldrv); +void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv); -ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length); -ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); +ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length); +ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); -int mei_cl_register_event_cb(struct mei_cl_device *cldev, - unsigned long event_mask, - mei_cl_event_cb_t read_cb, void *context); +int mei_cldev_register_event_cb(struct mei_cl_device *cldev, + unsigned long event_mask, + mei_cldev_event_cb_t read_cb, void *context); #define MEI_CL_EVENT_RX 0 #define MEI_CL_EVENT_TX 1 @@ -87,11 +88,11 @@ int mei_cl_register_event_cb(struct mei_cl_device *cldev, const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev); u8 mei_cldev_ver(const struct mei_cl_device *cldev); -void *mei_cl_get_drvdata(const struct mei_cl_device *cldev); -void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data); +void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev); +void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data); -int mei_cl_enable_device(struct mei_cl_device *cldev); -int mei_cl_disable_device(struct mei_cl_device *cldev); +int mei_cldev_enable(struct mei_cl_device *cldev); +int mei_cldev_disable(struct mei_cl_device *cldev); bool mei_cldev_enabled(struct mei_cl_device *cldev); #endif /* _LINUX_MEI_CL_BUS_H */ -- cgit v1.3-6-gb490 From ff6f46483f0e14b829cd5a71bafcbb1c136a84b6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 10 Sep 2015 15:06:20 -0700 Subject: spmi: Auto-populate driver.owner in spmi_driver_register() Populate the owner field of the spmi driver when spmi_driver_register() is called in a similar fashion to how other *_driver_register() functions do it. This saves driver writers from having to do this themselves. Cc: Andy Gross Cc: Gilad Avidov Signed-off-by: Stephen Boyd Signed-off-by: Greg Kroah-Hartman --- drivers/spmi/spmi.c | 5 +++-- include/linux/spmi.h | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c index 11467e17bdd8..6b3da1bb0d63 100644 --- a/drivers/spmi/spmi.c +++ b/drivers/spmi/spmi.c @@ -560,12 +560,13 @@ EXPORT_SYMBOL_GPL(spmi_controller_remove); * This API will register the client driver with the SPMI framework. * It is typically called from the driver's module-init function. */ -int spmi_driver_register(struct spmi_driver *sdrv) +int __spmi_driver_register(struct spmi_driver *sdrv, struct module *owner) { sdrv->driver.bus = &spmi_bus_type; + sdrv->driver.owner = owner; return driver_register(&sdrv->driver); } -EXPORT_SYMBOL_GPL(spmi_driver_register); +EXPORT_SYMBOL_GPL(__spmi_driver_register); static void __exit spmi_exit(void) { diff --git a/include/linux/spmi.h b/include/linux/spmi.h index f84212cd3b7d..1396a255d2a2 100644 --- a/include/linux/spmi.h +++ b/include/linux/spmi.h @@ -153,7 +153,9 @@ static inline struct spmi_driver *to_spmi_driver(struct device_driver *d) return container_of(d, struct spmi_driver, driver); } -int spmi_driver_register(struct spmi_driver *sdrv); +#define spmi_driver_register(sdrv) \ + __spmi_driver_register(sdrv, THIS_MODULE) +int __spmi_driver_register(struct spmi_driver *sdrv, struct module *owner); /** * spmi_driver_unregister() - unregister an SPMI client driver -- cgit v1.3-6-gb490 From 8203d6d0ee784cfb2ebf89053f7fe399abc867d7 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 2 Aug 2015 13:53:17 -0700 Subject: rcu: Use single-stage IPI algorithm for RCU expedited grace period The current preemptible-RCU expedited grace-period algorithm invokes synchronize_sched_expedited() to enqueue all tasks currently running in a preemptible-RCU read-side critical section, then waits for all the ->blkd_tasks lists to drain. This works, but results in both an IPI and a double context switch even on CPUs that do not happen to be running in a preemptible RCU read-side critical section. This commit implements a new algorithm that causes less OS jitter. This new algorithm IPIs all online CPUs that are not idle (from an RCU perspective), but refrains from self-IPIs. If a CPU receiving this IPI is not in a preemptible RCU read-side critical section (or is just now exiting one), it pushes quiescence up the rcu_node tree, otherwise, it sets a flag that will be handled by the upcoming outermost rcu_read_unlock(), which will then push quiescence up the tree. The expedited grace period must of course wait on any pre-existing blocked readers, and newly blocked readers must be queued carefully based on the state of both the normal and the expedited grace periods. This new queueing approach also avoids the need to update boost state, courtesy of the fact that blocked tasks are no longer ever migrated to the root rcu_node structure. Signed-off-by: Paul E. McKenney --- include/linux/sched.h | 10 +- kernel/rcu/tree.c | 75 ++++++++---- kernel/rcu/tree_plugin.h | 296 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 311 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index a4ab9daa387c..7fa8c4d372e7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1330,10 +1330,12 @@ struct sched_dl_entity { union rcu_special { struct { - bool blocked; - bool need_qs; - } b; - short s; + u8 blocked; + u8 need_qs; + u8 exp_need_qs; + u8 pad; /* Otherwise the compiler can store garbage here. */ + } b; /* Bits. */ + u32 s; /* Set of bits. */ }; struct rcu_node; diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 8526896afea7..6e92bf4337bd 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3461,18 +3461,7 @@ static void __maybe_unused sync_exp_reset_tree(struct rcu_state *rsp) } /* - * Return non-zero if there are any tasks in RCU read-side critical - * sections blocking the current preemptible-RCU expedited grace period. - * If there is no preemptible-RCU expedited grace period currently in - * progress, returns zero unconditionally. - */ -static int rcu_preempted_readers_exp(struct rcu_node *rnp) -{ - return rnp->exp_tasks != NULL; -} - -/* - * return non-zero if there is no RCU expedited grace period in progress + * Return non-zero if there is no RCU expedited grace period in progress * for the specified rcu_node structure, in other words, if all CPUs and * tasks covered by the specified rcu_node structure have done their bit * for the current expedited grace period. Works only for preemptible @@ -3482,7 +3471,7 @@ static int rcu_preempted_readers_exp(struct rcu_node *rnp) */ static int sync_rcu_preempt_exp_done(struct rcu_node *rnp) { - return !rcu_preempted_readers_exp(rnp) && + return rnp->exp_tasks == NULL && READ_ONCE(rnp->expmask) == 0; } @@ -3494,19 +3483,21 @@ static int sync_rcu_preempt_exp_done(struct rcu_node *rnp) * recursively up the tree. (Calm down, calm down, we do the recursion * iteratively!) * - * Caller must hold the root rcu_node's exp_funnel_mutex. + * Caller must hold the root rcu_node's exp_funnel_mutex and the + * specified rcu_node structure's ->lock. */ -static void __maybe_unused rcu_report_exp_rnp(struct rcu_state *rsp, - struct rcu_node *rnp, bool wake) +static void __rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, + bool wake, unsigned long flags) + __releases(rnp->lock) { - unsigned long flags; unsigned long mask; - raw_spin_lock_irqsave(&rnp->lock, flags); - smp_mb__after_unlock_lock(); for (;;) { if (!sync_rcu_preempt_exp_done(rnp)) { - raw_spin_unlock_irqrestore(&rnp->lock, flags); + if (!rnp->expmask) + rcu_initiate_boost(rnp, flags); + else + raw_spin_unlock_irqrestore(&rnp->lock, flags); break; } if (rnp->parent == NULL) { @@ -3522,10 +3513,54 @@ static void __maybe_unused rcu_report_exp_rnp(struct rcu_state *rsp, rnp = rnp->parent; raw_spin_lock(&rnp->lock); /* irqs already disabled */ smp_mb__after_unlock_lock(); + WARN_ON_ONCE(!(rnp->expmask & mask)); rnp->expmask &= ~mask; } } +/* + * Report expedited quiescent state for specified node. This is a + * lock-acquisition wrapper function for __rcu_report_exp_rnp(). + * + * Caller must hold the root rcu_node's exp_funnel_mutex. + */ +static void __maybe_unused rcu_report_exp_rnp(struct rcu_state *rsp, + struct rcu_node *rnp, bool wake) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&rnp->lock, flags); + smp_mb__after_unlock_lock(); + __rcu_report_exp_rnp(rsp, rnp, wake, flags); +} + +/* + * Report expedited quiescent state for multiple CPUs, all covered by the + * specified leaf rcu_node structure. Caller must hold the root + * rcu_node's exp_funnel_mutex. + */ +static void rcu_report_exp_cpu_mult(struct rcu_state *rsp, struct rcu_node *rnp, + unsigned long mask, bool wake) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&rnp->lock, flags); + smp_mb__after_unlock_lock(); + WARN_ON_ONCE((rnp->expmask & mask) != mask); + rnp->expmask &= ~mask; + __rcu_report_exp_rnp(rsp, rnp, wake, flags); /* Releases rnp->lock. */ +} + +/* + * Report expedited quiescent state for specified rcu_data (CPU). + * Caller must hold the root rcu_node's exp_funnel_mutex. + */ +static void __maybe_unused rcu_report_exp_rdp(struct rcu_state *rsp, + struct rcu_data *rdp, bool wake) +{ + rcu_report_exp_cpu_mult(rsp, rdp->mynode, rdp->grpmask, wake); +} + /* Common code for synchronize_{rcu,sched}_expedited() work-done checking. */ static bool sync_exp_work_done(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp, diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 62d05413b7ba..6f7500f9387c 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -101,7 +101,6 @@ RCU_STATE_INITIALIZER(rcu_preempt, 'p', call_rcu); static struct rcu_state *const rcu_state_p = &rcu_preempt_state; static struct rcu_data __percpu *const rcu_data_p = &rcu_preempt_data; -static int rcu_preempted_readers_exp(struct rcu_node *rnp); static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, bool wake); @@ -114,6 +113,147 @@ static void __init rcu_bootup_announce(void) rcu_bootup_announce_oddness(); } +/* Flags for rcu_preempt_ctxt_queue() decision table. */ +#define RCU_GP_TASKS 0x8 +#define RCU_EXP_TASKS 0x4 +#define RCU_GP_BLKD 0x2 +#define RCU_EXP_BLKD 0x1 + +/* + * Queues a task preempted within an RCU-preempt read-side critical + * section into the appropriate location within the ->blkd_tasks list, + * depending on the states of any ongoing normal and expedited grace + * periods. The ->gp_tasks pointer indicates which element the normal + * grace period is waiting on (NULL if none), and the ->exp_tasks pointer + * indicates which element the expedited grace period is waiting on (again, + * NULL if none). If a grace period is waiting on a given element in the + * ->blkd_tasks list, it also waits on all subsequent elements. Thus, + * adding a task to the tail of the list blocks any grace period that is + * already waiting on one of the elements. In contrast, adding a task + * to the head of the list won't block any grace period that is already + * waiting on one of the elements. + * + * This queuing is imprecise, and can sometimes make an ongoing grace + * period wait for a task that is not strictly speaking blocking it. + * Given the choice, we needlessly block a normal grace period rather than + * blocking an expedited grace period. + * + * Note that an endless sequence of expedited grace periods still cannot + * indefinitely postpone a normal grace period. Eventually, all of the + * fixed number of preempted tasks blocking the normal grace period that are + * not also blocking the expedited grace period will resume and complete + * their RCU read-side critical sections. At that point, the ->gp_tasks + * pointer will equal the ->exp_tasks pointer, at which point the end of + * the corresponding expedited grace period will also be the end of the + * normal grace period. + */ +static void rcu_preempt_ctxt_queue(struct rcu_node *rnp, struct rcu_data *rdp, + unsigned long flags) __releases(rnp->lock) +{ + int blkd_state = (rnp->gp_tasks ? RCU_GP_TASKS : 0) + + (rnp->exp_tasks ? RCU_EXP_TASKS : 0) + + (rnp->qsmask & rdp->grpmask ? RCU_GP_BLKD : 0) + + (rnp->expmask & rdp->grpmask ? RCU_EXP_BLKD : 0); + struct task_struct *t = current; + + /* + * Decide where to queue the newly blocked task. In theory, + * this could be an if-statement. In practice, when I tried + * that, it was quite messy. + */ + switch (blkd_state) { + case 0: + case RCU_EXP_TASKS: + case RCU_EXP_TASKS + RCU_GP_BLKD: + case RCU_GP_TASKS: + case RCU_GP_TASKS + RCU_EXP_TASKS: + + /* + * Blocking neither GP, or first task blocking the normal + * GP but not blocking the already-waiting expedited GP. + * Queue at the head of the list to avoid unnecessarily + * blocking the already-waiting GPs. + */ + list_add(&t->rcu_node_entry, &rnp->blkd_tasks); + break; + + case RCU_EXP_BLKD: + case RCU_GP_BLKD: + case RCU_GP_BLKD + RCU_EXP_BLKD: + case RCU_GP_TASKS + RCU_EXP_BLKD: + case RCU_GP_TASKS + RCU_GP_BLKD + RCU_EXP_BLKD: + case RCU_GP_TASKS + RCU_EXP_TASKS + RCU_GP_BLKD + RCU_EXP_BLKD: + + /* + * First task arriving that blocks either GP, or first task + * arriving that blocks the expedited GP (with the normal + * GP already waiting), or a task arriving that blocks + * both GPs with both GPs already waiting. Queue at the + * tail of the list to avoid any GP waiting on any of the + * already queued tasks that are not blocking it. + */ + list_add_tail(&t->rcu_node_entry, &rnp->blkd_tasks); + break; + + case RCU_EXP_TASKS + RCU_EXP_BLKD: + case RCU_EXP_TASKS + RCU_GP_BLKD + RCU_EXP_BLKD: + case RCU_GP_TASKS + RCU_EXP_TASKS + RCU_EXP_BLKD: + + /* + * Second or subsequent task blocking the expedited GP. + * The task either does not block the normal GP, or is the + * first task blocking the normal GP. Queue just after + * the first task blocking the expedited GP. + */ + list_add(&t->rcu_node_entry, rnp->exp_tasks); + break; + + case RCU_GP_TASKS + RCU_GP_BLKD: + case RCU_GP_TASKS + RCU_EXP_TASKS + RCU_GP_BLKD: + + /* + * Second or subsequent task blocking the normal GP. + * The task does not block the expedited GP. Queue just + * after the first task blocking the normal GP. + */ + list_add(&t->rcu_node_entry, rnp->gp_tasks); + break; + + default: + + /* Yet another exercise in excessive paranoia. */ + WARN_ON_ONCE(1); + break; + } + + /* + * We have now queued the task. If it was the first one to + * block either grace period, update the ->gp_tasks and/or + * ->exp_tasks pointers, respectively, to reference the newly + * blocked tasks. + */ + if (!rnp->gp_tasks && (blkd_state & RCU_GP_BLKD)) + rnp->gp_tasks = &t->rcu_node_entry; + if (!rnp->exp_tasks && (blkd_state & RCU_EXP_BLKD)) + rnp->exp_tasks = &t->rcu_node_entry; + raw_spin_unlock(&rnp->lock); + + /* + * Report the quiescent state for the expedited GP. This expedited + * GP should not be able to end until we report, so there should be + * no need to check for a subsequent expedited GP. (Though we are + * still in a quiescent state in any case.) + */ + if (blkd_state & RCU_EXP_BLKD && + t->rcu_read_unlock_special.b.exp_need_qs) { + t->rcu_read_unlock_special.b.exp_need_qs = false; + rcu_report_exp_rdp(rdp->rsp, rdp, true); + } else { + WARN_ON_ONCE(t->rcu_read_unlock_special.b.exp_need_qs); + } + local_irq_restore(flags); +} + /* * Record a preemptible-RCU quiescent state for the specified CPU. Note * that this just means that the task currently running on the CPU is @@ -167,42 +307,18 @@ static void rcu_preempt_note_context_switch(void) t->rcu_blocked_node = rnp; /* - * If this CPU has already checked in, then this task - * will hold up the next grace period rather than the - * current grace period. Queue the task accordingly. - * If the task is queued for the current grace period - * (i.e., this CPU has not yet passed through a quiescent - * state for the current grace period), then as long - * as that task remains queued, the current grace period - * cannot end. Note that there is some uncertainty as - * to exactly when the current grace period started. - * We take a conservative approach, which can result - * in unnecessarily waiting on tasks that started very - * slightly after the current grace period began. C'est - * la vie!!! - * - * But first, note that the current CPU must still be - * on line! + * Verify the CPU's sanity, trace the preemption, and + * then queue the task as required based on the states + * of any ongoing and expedited grace periods. */ WARN_ON_ONCE((rdp->grpmask & rcu_rnp_online_cpus(rnp)) == 0); WARN_ON_ONCE(!list_empty(&t->rcu_node_entry)); - if ((rnp->qsmask & rdp->grpmask) && rnp->gp_tasks != NULL) { - list_add(&t->rcu_node_entry, rnp->gp_tasks->prev); - rnp->gp_tasks = &t->rcu_node_entry; - if (IS_ENABLED(CONFIG_RCU_BOOST) && - rnp->boost_tasks != NULL) - rnp->boost_tasks = rnp->gp_tasks; - } else { - list_add(&t->rcu_node_entry, &rnp->blkd_tasks); - if (rnp->qsmask & rdp->grpmask) - rnp->gp_tasks = &t->rcu_node_entry; - } trace_rcu_preempt_task(rdp->rsp->name, t->pid, (rnp->qsmask & rdp->grpmask) ? rnp->gpnum : rnp->gpnum + 1); - raw_spin_unlock_irqrestore(&rnp->lock, flags); + rcu_preempt_ctxt_queue(rnp, rdp, flags); } else if (t->rcu_read_lock_nesting < 0 && t->rcu_read_unlock_special.s) { @@ -272,6 +388,7 @@ void rcu_read_unlock_special(struct task_struct *t) unsigned long flags; struct list_head *np; bool drop_boost_mutex = false; + struct rcu_data *rdp; struct rcu_node *rnp; union rcu_special special; @@ -282,8 +399,8 @@ void rcu_read_unlock_special(struct task_struct *t) local_irq_save(flags); /* - * If RCU core is waiting for this CPU to exit critical section, - * let it know that we have done so. Because irqs are disabled, + * If RCU core is waiting for this CPU to exit its critical section, + * report the fact that it has exited. Because irqs are disabled, * t->rcu_read_unlock_special cannot change. */ special = t->rcu_read_unlock_special; @@ -296,13 +413,32 @@ void rcu_read_unlock_special(struct task_struct *t) } } + /* + * Respond to a request for an expedited grace period, but only if + * we were not preempted, meaning that we were running on the same + * CPU throughout. If we were preempted, the exp_need_qs flag + * would have been cleared at the time of the first preemption, + * and the quiescent state would be reported when we were dequeued. + */ + if (special.b.exp_need_qs) { + WARN_ON_ONCE(special.b.blocked); + t->rcu_read_unlock_special.b.exp_need_qs = false; + rdp = this_cpu_ptr(rcu_state_p->rda); + rcu_report_exp_rdp(rcu_state_p, rdp, true); + if (!t->rcu_read_unlock_special.s) { + local_irq_restore(flags); + return; + } + } + /* Hardware IRQ handlers cannot block, complain if they get here. */ if (in_irq() || in_serving_softirq()) { lockdep_rcu_suspicious(__FILE__, __LINE__, "rcu_read_unlock() from irq or softirq with blocking in critical section!!!\n"); - pr_alert("->rcu_read_unlock_special: %#x (b: %d, nq: %d)\n", + pr_alert("->rcu_read_unlock_special: %#x (b: %d, enq: %d nq: %d)\n", t->rcu_read_unlock_special.s, t->rcu_read_unlock_special.b.blocked, + t->rcu_read_unlock_special.b.exp_need_qs, t->rcu_read_unlock_special.b.need_qs); local_irq_restore(flags); return; @@ -329,7 +465,7 @@ void rcu_read_unlock_special(struct task_struct *t) raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ } empty_norm = !rcu_preempt_blocked_readers_cgp(rnp); - empty_exp = !rcu_preempted_readers_exp(rnp); + empty_exp = sync_rcu_preempt_exp_done(rnp); smp_mb(); /* ensure expedited fastpath sees end of RCU c-s. */ np = rcu_next_node_entry(t, rnp); list_del_init(&t->rcu_node_entry); @@ -353,7 +489,7 @@ void rcu_read_unlock_special(struct task_struct *t) * Note that rcu_report_unblock_qs_rnp() releases rnp->lock, * so we must take a snapshot of the expedited state. */ - empty_exp_now = !rcu_preempted_readers_exp(rnp); + empty_exp_now = sync_rcu_preempt_exp_done(rnp); if (!empty_norm && !rcu_preempt_blocked_readers_cgp(rnp)) { trace_rcu_quiescent_state_report(TPS("preempt_rcu"), rnp->gpnum, @@ -535,28 +671,99 @@ void synchronize_rcu(void) } EXPORT_SYMBOL_GPL(synchronize_rcu); +/* + * Remote handler for smp_call_function_single(). If there is an + * RCU read-side critical section in effect, request that the + * next rcu_read_unlock() record the quiescent state up the + * ->expmask fields in the rcu_node tree. Otherwise, immediately + * report the quiescent state. + */ +static void sync_rcu_exp_handler(void *info) +{ + struct rcu_data *rdp; + struct rcu_state *rsp = info; + struct task_struct *t = current; + + /* + * Within an RCU read-side critical section, request that the next + * rcu_read_unlock() report. Unless this RCU read-side critical + * section has already blocked, in which case it is already set + * up for the expedited grace period to wait on it. + */ + if (t->rcu_read_lock_nesting > 0 && + !t->rcu_read_unlock_special.b.blocked) { + t->rcu_read_unlock_special.b.exp_need_qs = true; + return; + } + + /* + * We are either exiting an RCU read-side critical section (negative + * values of t->rcu_read_lock_nesting) or are not in one at all + * (zero value of t->rcu_read_lock_nesting). Or we are in an RCU + * read-side critical section that blocked before this expedited + * grace period started. Either way, we can immediately report + * the quiescent state. + */ + rdp = this_cpu_ptr(rsp->rda); + rcu_report_exp_rdp(rsp, rdp, true); +} + /* * Select the nodes that the upcoming expedited grace period needs * to wait for. */ -static void sync_rcu_exp_select_nodes(struct rcu_state *rsp) +static void sync_rcu_exp_select_cpus(struct rcu_state *rsp) { + int cpu; unsigned long flags; + unsigned long mask; + unsigned long mask_ofl_test; + unsigned long mask_ofl_ipi; + int ret; struct rcu_node *rnp; sync_exp_reset_tree(rsp); rcu_for_each_leaf_node(rsp, rnp) { raw_spin_lock_irqsave(&rnp->lock, flags); smp_mb__after_unlock_lock(); - rnp->expmask = 0; /* No per-CPU component yet. */ - if (!rcu_preempt_has_tasks(rnp)) { - /* FIXME: Want __rcu_report_exp_rnp() here. */ - raw_spin_unlock_irqrestore(&rnp->lock, flags); - } else { + + /* Each pass checks a CPU for identity, offline, and idle. */ + mask_ofl_test = 0; + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++) { + struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu); + struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); + + if (raw_smp_processor_id() == cpu || + cpu_is_offline(cpu) || + !(atomic_add_return(0, &rdtp->dynticks) & 0x1)) + mask_ofl_test |= rdp->grpmask; + } + mask_ofl_ipi = rnp->expmask & ~mask_ofl_test; + + /* + * Need to wait for any blocked tasks as well. Note that + * additional blocking tasks will also block the expedited + * GP until such time as the ->expmask bits are cleared. + */ + if (rcu_preempt_has_tasks(rnp)) rnp->exp_tasks = rnp->blkd_tasks.next; - rcu_initiate_boost(rnp, flags); + raw_spin_unlock_irqrestore(&rnp->lock, flags); + + /* IPI the remaining CPUs for expedited quiescent state. */ + mask = 1; + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask <<= 1) { + if (!(mask_ofl_ipi & mask)) + continue; + ret = smp_call_function_single(cpu, + sync_rcu_exp_handler, + rsp, 0); + if (!ret) + mask_ofl_ipi &= ~mask; } - rcu_report_exp_rnp(rsp, rnp, false); + /* Report quiescent states for those that went offline. */ + mask_ofl_test |= mask_ofl_ipi; + if (mask_ofl_test) + rcu_report_exp_cpu_mult(rsp, rnp, mask_ofl_test, false); } } @@ -587,11 +794,8 @@ void synchronize_rcu_expedited(void) rcu_exp_gp_seq_start(rsp); - /* force all RCU readers onto ->blkd_tasks lists. */ - synchronize_sched_expedited(); - /* Initialize the rcu_node tree in preparation for the wait. */ - sync_rcu_exp_select_nodes(rsp); + sync_rcu_exp_select_cpus(rsp); /* Wait for snapshotted ->blkd_tasks lists to drain. */ rnp = rcu_get_root(rsp); -- cgit v1.3-6-gb490 From b05b7c7cc0324524dcda7fa7c2be1255290ee416 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Farooq Date: Fri, 11 Sep 2015 16:42:38 +0200 Subject: ti-st: use worker instead of calling st_int_write in wake up The wake up method is called with the port lock held. The st_int_write method calls port->ops->write with tries to acquire the lock again, causing CPU to wait infinitely. Right way to do is to write data to port in worker thread. Signed-off-by: Muhammad Hamza Farooq Signed-off-by: Jacob Siverskog Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_core.c | 18 ++++++++++++++++-- include/linux/ti_wilink_st.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index c8c6a363069c..6e3af8b42cdd 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -460,6 +460,13 @@ static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) * - TTY layer when write's finished * - st_write (in context of the protocol stack) */ +static void work_fn_write_wakeup(struct work_struct *work) +{ + struct st_data_s *st_gdata = container_of(work, struct st_data_s, + work_write_wakeup); + + st_tx_wakeup((void *)st_gdata); +} void st_tx_wakeup(struct st_data_s *st_data) { struct sk_buff *skb; @@ -812,8 +819,12 @@ static void st_tty_wakeup(struct tty_struct *tty) /* don't do an wakeup for now */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - /* call our internal wakeup */ - st_tx_wakeup((void *)st_gdata); + /* + * schedule the internal wakeup instead of calling directly to + * avoid lockup (port->lock needed in tty->ops->write is + * already taken here + */ + schedule_work(&st_gdata->work_write_wakeup); } static void st_tty_flush_buffer(struct tty_struct *tty) @@ -881,6 +892,9 @@ int st_core_init(struct st_data_s **core_data) pr_err("unable to un-register ldisc"); return err; } + + INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup); + *core_data = st_gdata; return 0; } diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h index d4217eff489f..0a0d56834c8e 100644 --- a/include/linux/ti_wilink_st.h +++ b/include/linux/ti_wilink_st.h @@ -158,6 +158,7 @@ struct st_data_s { unsigned long ll_state; void *kim_data; struct tty_struct *tty; + struct work_struct work_write_wakeup; }; /* -- cgit v1.3-6-gb490 From 2785968cd122b22b289db565b7438f2200984044 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 9 May 2015 17:47:52 +0200 Subject: can: headers: make header files self contained This patch adds the missing #include-s to the dev.h and led.h, so that they can be used without including further header files. Signed-off-by: Marc Kleine-Budde --- include/linux/can/dev.h | 3 ++- include/linux/can/led.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index c3a9c8fc60fa..56dcadd83716 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -14,9 +14,10 @@ #define _CAN_DEV_H #include -#include #include #include +#include +#include /* * CAN mode diff --git a/include/linux/can/led.h b/include/linux/can/led.h index 146de4506d21..2746f7c2f87d 100644 --- a/include/linux/can/led.h +++ b/include/linux/can/led.h @@ -11,6 +11,7 @@ #include #include +#include enum can_led_event { CAN_LED_EVENT_OPEN, -- cgit v1.3-6-gb490 From d11797a0a7acc1fe6a51b1605e166adad04da29b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 21 Sep 2015 07:26:45 -0400 Subject: locks: change tracepoint for generic_add_lease Add some more helpful info to make it easier to determine why a lease wasn't granted. Signed-off-by: Jeff Layton --- include/trace/events/filelock.h | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/trace/events/filelock.h b/include/trace/events/filelock.h index a0d008070962..c72f2dc01d0b 100644 --- a/include/trace/events/filelock.h +++ b/include/trace/events/filelock.h @@ -81,15 +81,47 @@ DEFINE_EVENT(filelock_lease, break_lease_block, TP_PROTO(struct inode *inode, st DEFINE_EVENT(filelock_lease, break_lease_unblock, TP_PROTO(struct inode *inode, struct file_lock *fl), TP_ARGS(inode, fl)); -DEFINE_EVENT(filelock_lease, generic_add_lease, TP_PROTO(struct inode *inode, struct file_lock *fl), - TP_ARGS(inode, fl)); - DEFINE_EVENT(filelock_lease, generic_delete_lease, TP_PROTO(struct inode *inode, struct file_lock *fl), TP_ARGS(inode, fl)); DEFINE_EVENT(filelock_lease, time_out_leases, TP_PROTO(struct inode *inode, struct file_lock *fl), TP_ARGS(inode, fl)); +TRACE_EVENT(generic_add_lease, + TP_PROTO(struct inode *inode, struct file_lock *fl), + + TP_ARGS(inode, fl), + + TP_STRUCT__entry( + __field(unsigned long, i_ino) + __field(int, wcount) + __field(int, dcount) + __field(int, icount) + __field(dev_t, s_dev) + __field(fl_owner_t, fl_owner) + __field(unsigned int, fl_flags) + __field(unsigned char, fl_type) + ), + + TP_fast_assign( + __entry->s_dev = inode->i_sb->s_dev; + __entry->i_ino = inode->i_ino; + __entry->wcount = atomic_read(&inode->i_writecount); + __entry->dcount = d_count(fl->fl_file->f_path.dentry); + __entry->icount = atomic_read(&inode->i_count); + __entry->fl_owner = fl ? fl->fl_owner : NULL; + __entry->fl_flags = fl ? fl->fl_flags : 0; + __entry->fl_type = fl ? fl->fl_type : 0; + ), + + TP_printk("dev=0x%x:0x%x ino=0x%lx wcount=%d dcount=%d icount=%d fl_owner=0x%p fl_flags=%s fl_type=%s", + MAJOR(__entry->s_dev), MINOR(__entry->s_dev), + __entry->i_ino, __entry->wcount, __entry->dcount, + __entry->icount, __entry->fl_owner, + show_fl_flags(__entry->fl_flags), + show_fl_type(__entry->fl_type)) +); + #endif /* _TRACE_FILELOCK_H */ /* This part must be outside protection */ -- cgit v1.3-6-gb490 From 472912a2b5e2027efd58aa47f78acb2373675187 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Sep 2015 18:01:59 -0400 Subject: memcg: generate file modified notifications on "memory.events" cgroup core only recently grew generic notification support. Wire up "memory.events" so that it triggers a file modified event whenever its content changes. v2: Refreshed on top of mem_cgroup relocation. Signed-off-by: Tejun Heo Acked-by: Michal Hocko Acked-by: Johannes Weiner Cc: Li Zefan --- include/linux/memcontrol.h | 4 ++++ mm/memcontrol.c | 1 + 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 9aa7820c2177..c83c699a6605 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -213,6 +213,9 @@ struct mem_cgroup { /* OOM-Killer disable */ int oom_kill_disable; + /* handle for "memory.events" */ + struct cgroup_file events_file; + /* protect arrays of thresholds */ struct mutex thresholds_lock; @@ -286,6 +289,7 @@ static inline void mem_cgroup_events(struct mem_cgroup *memcg, unsigned int nr) { this_cpu_add(memcg->stat->events[idx], nr); + cgroup_file_notify(&memcg->events_file); } bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e672f2689326..9f331402e502 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5202,6 +5202,7 @@ static struct cftype memory_files[] = { { .name = "events", .flags = CFTYPE_NOT_ON_ROOT, + .file_offset = offsetof(struct mem_cgroup, events_file), .seq_show = memory_events_show, }, { } /* terminate */ -- cgit v1.3-6-gb490 From 730a43fbc135e593cc3de3b1b895e49c05c8e2dc Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 3 Sep 2015 18:03:38 +0200 Subject: mtd: nand: add nand_check_erased helper functions Add two helper functions to help NAND controller drivers test whether a specific NAND region is erased or not. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 128 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/nand.h | 5 ++ 2 files changed, 133 insertions(+) (limited to 'include') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 51f7816d67c9..37c0d9d62478 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1100,6 +1100,134 @@ out: } EXPORT_SYMBOL(nand_lock); +/** + * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data + * @buf: buffer to test + * @len: buffer length + * @bitflips_threshold: maximum number of bitflips + * + * Check if a buffer contains only 0xff, which means the underlying region + * has been erased and is ready to be programmed. + * The bitflips_threshold specify the maximum number of bitflips before + * considering the region is not erased. + * Note: The logic of this function has been extracted from the memweight + * implementation, except that nand_check_erased_buf function exit before + * testing the whole buffer if the number of bitflips exceed the + * bitflips_threshold value. + * + * Returns a positive number of bitflips less than or equal to + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the + * threshold. + */ +static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) +{ + const unsigned char *bitmap = buf; + int bitflips = 0; + int weight; + + for (; len && ((uintptr_t)bitmap) % sizeof(long); + len--, bitmap++) { + weight = hweight8(*bitmap); + bitflips += BITS_PER_BYTE - weight; + if (unlikely(bitflips > bitflips_threshold)) + return -EBADMSG; + } + + for (; len >= sizeof(long); + len -= sizeof(long), bitmap += sizeof(long)) { + weight = hweight_long(*((unsigned long *)bitmap)); + bitflips += BITS_PER_LONG - weight; + if (unlikely(bitflips > bitflips_threshold)) + return -EBADMSG; + } + + for (; len > 0; len--, bitmap++) { + weight = hweight8(*bitmap); + bitflips += BITS_PER_BYTE - weight; + if (unlikely(bitflips > bitflips_threshold)) + return -EBADMSG; + } + + return bitflips; +} + +/** + * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only + * 0xff data + * @data: data buffer to test + * @datalen: data length + * @ecc: ECC buffer + * @ecclen: ECC length + * @extraoob: extra OOB buffer + * @extraooblen: extra OOB length + * @bitflips_threshold: maximum number of bitflips + * + * Check if a data buffer and its associated ECC and OOB data contains only + * 0xff pattern, which means the underlying region has been erased and is + * ready to be programmed. + * The bitflips_threshold specify the maximum number of bitflips before + * considering the region as not erased. + * + * Note: + * 1/ ECC algorithms are working on pre-defined block sizes which are usually + * different from the NAND page size. When fixing bitflips, ECC engines will + * report the number of errors per chunk, and the NAND core infrastructure + * expect you to return the maximum number of bitflips for the whole page. + * This is why you should always use this function on a single chunk and + * not on the whole page. After checking each chunk you should update your + * max_bitflips value accordingly. + * 2/ When checking for bitflips in erased pages you should not only check + * the payload data but also their associated ECC data, because a user might + * have programmed almost all bits to 1 but a few. In this case, we + * shouldn't consider the chunk as erased, and checking ECC bytes prevent + * this case. + * 3/ The extraoob argument is optional, and should be used if some of your OOB + * data are protected by the ECC engine. + * It could also be used if you support subpages and want to attach some + * extra OOB data to an ECC chunk. + * + * Returns a positive number of bitflips less than or equal to + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the + * threshold. In case of success, the passed buffers are filled with 0xff. + */ +int nand_check_erased_ecc_chunk(void *data, int datalen, + void *ecc, int ecclen, + void *extraoob, int extraooblen, + int bitflips_threshold) +{ + int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; + + data_bitflips = nand_check_erased_buf(data, datalen, + bitflips_threshold); + if (data_bitflips < 0) + return data_bitflips; + + bitflips_threshold -= data_bitflips; + + ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); + if (ecc_bitflips < 0) + return ecc_bitflips; + + bitflips_threshold -= ecc_bitflips; + + extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, + bitflips_threshold); + if (extraoob_bitflips < 0) + return extraoob_bitflips; + + if (data_bitflips) + memset(data, 0xff, datalen); + + if (ecc_bitflips) + memset(ecc, 0xff, ecclen); + + if (extraoob_bitflips) + memset(extraoob, 0xff, extraooblen); + + return data_bitflips + ecc_bitflips + extraoob_bitflips; +} +EXPORT_SYMBOL(nand_check_erased_ecc_chunk); + /** * nand_read_page_raw - [INTERN] read raw page data without ecc * @mtd: mtd info structure diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 3140b3d94838..c4d8e308f453 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -1030,4 +1030,9 @@ struct nand_sdr_timings { /* get timing characteristics from ONFI timing mode. */ const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode); + +int nand_check_erased_ecc_chunk(void *data, int datalen, + void *ecc, int ecclen, + void *extraoob, int extraooblen, + int threshold); #endif /* __LINUX_MTD_NAND_H */ -- cgit v1.3-6-gb490 From 91e60eb60bdf078fc58b8d2fd1ac12f3c09bb893 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 18 Sep 2015 16:06:52 +0200 Subject: s390/iucv: do not use arrays as argument The iucv code uses arrays as arguments. Even though this does not really cause a problem, it could be misleading, since the compiler turns array arguments into just a pointer argument. To be more precise this patch changes the array arguments into pointers. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/char/monreader.c | 4 ++-- drivers/s390/char/vmlogrdr.c | 8 ++++---- drivers/s390/net/netiucv.c | 21 ++++++++++----------- drivers/s390/net/smsgiucv.c | 5 ++--- drivers/tty/hvc/hvc_iucv.c | 10 +++++----- include/net/iucv/iucv.h | 20 ++++++++++---------- net/iucv/af_iucv.c | 9 ++++----- net/iucv/iucv.c | 12 ++++++------ 8 files changed, 43 insertions(+), 46 deletions(-) (limited to 'include') diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index b7d60306b0bc..fc94bfdceb95 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -229,7 +229,7 @@ static struct mon_msg *mon_next_message(struct mon_private *monpriv) /****************************************************************************** * IUCV handler * *****************************************************************************/ -static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16]) +static void mon_iucv_path_complete(struct iucv_path *path, u8 *ipuser) { struct mon_private *monpriv = path->private; @@ -237,7 +237,7 @@ static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16]) wake_up(&mon_conn_wait_queue); } -static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) +static void mon_iucv_path_severed(struct iucv_path *path, u8 *ipuser) { struct mon_private *monpriv = path->private; diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 9bb48d70957c..799c1524c779 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -99,8 +99,8 @@ static const struct file_operations vmlogrdr_fops = { }; -static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]); -static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]); +static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 *ipuser); +static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 *ipuser); static void vmlogrdr_iucv_message_pending(struct iucv_path *, struct iucv_message *); @@ -160,7 +160,7 @@ static struct cdev *vmlogrdr_cdev = NULL; static int recording_class_AB; -static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16]) +static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 *ipuser) { struct vmlogrdr_priv_t * logptr = path->private; @@ -171,7 +171,7 @@ static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16]) } -static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) +static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 *ipuser) { struct vmlogrdr_priv_t * logptr = path->private; u8 reason = (u8) ipuser[8]; diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 33f7040d711d..0ba3a2f81750 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -149,12 +149,11 @@ static struct device_driver netiucv_driver = { .pm = &netiucv_pm_ops, }; -static int netiucv_callback_connreq(struct iucv_path *, - u8 ipvmid[8], u8 ipuser[16]); -static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]); -static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]); -static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]); -static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]); +static int netiucv_callback_connreq(struct iucv_path *, u8 *, u8 *); +static void netiucv_callback_connack(struct iucv_path *, u8 *); +static void netiucv_callback_connrej(struct iucv_path *, u8 *); +static void netiucv_callback_connsusp(struct iucv_path *, u8 *); +static void netiucv_callback_connres(struct iucv_path *, u8 *); static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *); static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *); @@ -556,8 +555,8 @@ static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16]) fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn); } -static int netiucv_callback_connreq(struct iucv_path *path, - u8 ipvmid[8], u8 ipuser[16]) +static int netiucv_callback_connreq(struct iucv_path *path, u8 *ipvmid, + u8 *ipuser) { struct iucv_connection *conn = path->private; struct iucv_event ev; @@ -587,21 +586,21 @@ static int netiucv_callback_connreq(struct iucv_path *path, return rc; } -static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16]) +static void netiucv_callback_connrej(struct iucv_path *path, u8 *ipuser) { struct iucv_connection *conn = path->private; fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn); } -static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16]) +static void netiucv_callback_connsusp(struct iucv_path *path, u8 *ipuser) { struct iucv_connection *conn = path->private; fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn); } -static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16]) +static void netiucv_callback_connres(struct iucv_path *path, u8 *ipuser) { struct iucv_connection *conn = path->private; diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index d8f990b6b332..a851d34c642b 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -49,7 +49,7 @@ static DEFINE_SPINLOCK(smsg_list_lock); static LIST_HEAD(smsg_list); static int iucv_path_connected; -static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]); +static int smsg_path_pending(struct iucv_path *, u8 *, u8 *); static void smsg_message_pending(struct iucv_path *, struct iucv_message *); static struct iucv_handler smsg_handler = { @@ -57,8 +57,7 @@ static struct iucv_handler smsg_handler = { .message_pending = smsg_message_pending, }; -static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8], - u8 ipuser[16]) +static int smsg_path_pending(struct iucv_path *path, u8 *ipvmid, u8 *ipuser) { if (strncmp(ipvmid, "*MSG ", 8) != 0) return -EINVAL; diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index bb809cf36617..8b70a1627356 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -88,8 +88,8 @@ struct iucv_tty_buffer { }; /* IUCV callback handler */ -static int hvc_iucv_path_pending(struct iucv_path *, u8[8], u8[16]); -static void hvc_iucv_path_severed(struct iucv_path *, u8[16]); +static int hvc_iucv_path_pending(struct iucv_path *, u8 *, u8 *); +static void hvc_iucv_path_severed(struct iucv_path *, u8 *); static void hvc_iucv_msg_pending(struct iucv_path *, struct iucv_message *); static void hvc_iucv_msg_complete(struct iucv_path *, struct iucv_message *); @@ -782,8 +782,8 @@ static int hvc_iucv_filter_connreq(u8 ipvmid[8]) * * Locking: struct hvc_iucv_private->lock */ -static int hvc_iucv_path_pending(struct iucv_path *path, - u8 ipvmid[8], u8 ipuser[16]) +static int hvc_iucv_path_pending(struct iucv_path *path, u8 *ipvmid, + u8 *ipuser) { struct hvc_iucv_private *priv, *tmp; u8 wildcard[9] = "lnxhvc "; @@ -881,7 +881,7 @@ out_path_handled: * * Locking: struct hvc_iucv_private->lock */ -static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) +static void hvc_iucv_path_severed(struct iucv_path *path, u8 *ipuser) { struct hvc_iucv_private *priv = path->private; diff --git a/include/net/iucv/iucv.h b/include/net/iucv/iucv.h index 0894ced31957..b867b0cf79e8 100644 --- a/include/net/iucv/iucv.h +++ b/include/net/iucv/iucv.h @@ -141,14 +141,14 @@ struct iucv_handler { * called is the order of the registration of the iucv handlers * to the base code. */ - int (*path_pending)(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]); + int (*path_pending)(struct iucv_path *, u8 *ipvmid, u8 *ipuser); /* * The path_complete function is called after an iucv interrupt * type 0x02 has been received for a path that has been established * for this handler with iucv_path_connect and got accepted by the * peer with iucv_path_accept. */ - void (*path_complete)(struct iucv_path *, u8 ipuser[16]); + void (*path_complete)(struct iucv_path *, u8 *ipuser); /* * The path_severed function is called after an iucv interrupt * type 0x03 has been received. The communication peer shutdown @@ -156,20 +156,20 @@ struct iucv_handler { * remaining messages can be received until a iucv_path_sever * shuts down the other end of the path as well. */ - void (*path_severed)(struct iucv_path *, u8 ipuser[16]); + void (*path_severed)(struct iucv_path *, u8 *ipuser); /* * The path_quiesced function is called after an icuv interrupt * type 0x04 has been received. The communication peer has quiesced * the path. Delivery of messages is stopped until iucv_path_resume * has been called. */ - void (*path_quiesced)(struct iucv_path *, u8 ipuser[16]); + void (*path_quiesced)(struct iucv_path *, u8 *ipuser); /* * The path_resumed function is called after an icuv interrupt * type 0x05 has been received. The communication peer has resumed * the path. */ - void (*path_resumed)(struct iucv_path *, u8 ipuser[16]); + void (*path_resumed)(struct iucv_path *, u8 *ipuser); /* * The message_pending function is called after an icuv interrupt * type 0x06 or type 0x07 has been received. A new message is @@ -256,7 +256,7 @@ static inline void iucv_path_free(struct iucv_path *path) * Returns the result of the CP IUCV call. */ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, - u8 userdata[16], void *private); + u8 *userdata, void *private); /** * iucv_path_connect @@ -274,7 +274,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, * Returns the result of the CP IUCV call. */ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, - u8 userid[8], u8 system[8], u8 userdata[16], + u8 *userid, u8 *system, u8 *userdata, void *private); /** @@ -287,7 +287,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, * * Returns the result from the CP IUCV call. */ -int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]); +int iucv_path_quiesce(struct iucv_path *path, u8 *userdata); /** * iucv_path_resume: @@ -299,7 +299,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]); * * Returns the result from the CP IUCV call. */ -int iucv_path_resume(struct iucv_path *path, u8 userdata[16]); +int iucv_path_resume(struct iucv_path *path, u8 *userdata); /** * iucv_path_sever @@ -310,7 +310,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16]); * * Returns the result from the CP IUCV call. */ -int iucv_path_sever(struct iucv_path *path, u8 userdata[16]); +int iucv_path_sever(struct iucv_path *path, u8 *userdata); /** * iucv_message_purge diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 918151c11348..fcb2752419c6 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -95,11 +95,10 @@ static void afiucv_hs_callback_txnotify(struct sk_buff *, enum iucv_tx_notify); /* Call Back functions */ static void iucv_callback_rx(struct iucv_path *, struct iucv_message *); static void iucv_callback_txdone(struct iucv_path *, struct iucv_message *); -static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]); -static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], - u8 ipuser[16]); -static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]); -static void iucv_callback_shutdown(struct iucv_path *, u8 ipuser[16]); +static void iucv_callback_connack(struct iucv_path *, u8 *); +static int iucv_callback_connreq(struct iucv_path *, u8 *, u8 *); +static void iucv_callback_connrej(struct iucv_path *, u8 *); +static void iucv_callback_shutdown(struct iucv_path *, u8 *); static struct iucv_sock_list iucv_sk_list = { .lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock), diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 2a6a1fdd62c0..7eaa000c9258 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -713,7 +713,7 @@ static struct notifier_block __refdata iucv_cpu_notifier = { * * Sever an iucv path to free up the pathid. Used internally. */ -static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) +static int iucv_sever_pathid(u16 pathid, u8 *userdata) { union iucv_param *parm; @@ -876,7 +876,7 @@ static struct notifier_block iucv_reboot_notifier = { * Returns the result of the CP IUCV call. */ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, - u8 userdata[16], void *private) + u8 *userdata, void *private) { union iucv_param *parm; int rc; @@ -923,7 +923,7 @@ EXPORT_SYMBOL(iucv_path_accept); * Returns the result of the CP IUCV call. */ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, - u8 userid[8], u8 system[8], u8 userdata[16], + u8 *userid, u8 *system, u8 *userdata, void *private) { union iucv_param *parm; @@ -985,7 +985,7 @@ EXPORT_SYMBOL(iucv_path_connect); * * Returns the result from the CP IUCV call. */ -int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]) +int iucv_path_quiesce(struct iucv_path *path, u8 *userdata) { union iucv_param *parm; int rc; @@ -1017,7 +1017,7 @@ EXPORT_SYMBOL(iucv_path_quiesce); * * Returns the result from the CP IUCV call. */ -int iucv_path_resume(struct iucv_path *path, u8 userdata[16]) +int iucv_path_resume(struct iucv_path *path, u8 *userdata) { union iucv_param *parm; int rc; @@ -1047,7 +1047,7 @@ out: * * Returns the result from the CP IUCV call. */ -int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) +int iucv_path_sever(struct iucv_path *path, u8 *userdata) { int rc; -- cgit v1.3-6-gb490 From 0f1c28ae74bb1a34d36fca2db5161611d58b3148 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Fri, 18 Sep 2015 11:36:14 -0700 Subject: tcp: usec resolution SYN/ACK RTT Currently SYN/ACK RTT is measured in jiffies. For LAN the SYN/ACK RTT is often measured as 0ms or sometimes 1ms, which would affect RTT estimation and min RTT samping used by some congestion control. This patch improves SYN/ACK RTT to be usec resolution if platform supports it. While the timestamping of SYN/ACK is done in request sock, the RTT measurement is carefully arranged to avoid storing another u64 timestamp in tcp_sock. For regular handshake w/o SYNACK retransmission, the RTT is sampled right after the child socket is created and right before the request sock is released (tcp_check_req() in tcp_minisocks.c) For Fast Open the child socket is already created when SYN/ACK was sent, the RTT is sampled in tcp_rcv_state_process() after processing the final ACK an right before the request socket is released. If the SYN/ACK was retransmistted or SYN-cookie was used, we rely on TCP timestamps to measure the RTT. The sample is taken at the same place in tcp_rcv_state_process() after the timestamp values are validated in tcp_validate_incoming(). Note that we do not store TS echo value in request_sock for SYN-cookies, because the value is already stored in tp->rx_opt used by tcp_ack_update_rtt(). One side benefit is that the RTT measurement now happens before initializing congestion control (of the passive side). Therefore the congestion control can use the SYN/ACK RTT. Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/tcp.h | 2 +- include/net/tcp.h | 1 + net/ipv4/syncookies.c | 2 +- net/ipv4/tcp_input.c | 29 ++++++++++++++--------------- net/ipv4/tcp_minisocks.c | 3 ++- net/ipv6/syncookies.c | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 937b97893d5f..fcb573be75d9 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -112,11 +112,11 @@ struct tcp_request_sock_ops; struct tcp_request_sock { struct inet_request_sock req; const struct tcp_request_sock_ops *af_specific; + struct skb_mstamp snt_synack; /* first SYNACK sent time */ bool tfo_listener; u32 txhash; u32 rcv_isn; u32 snt_isn; - u32 snt_synack; /* synack sent time */ u32 last_oow_ack_time; /* last SYNACK */ u32 rcv_nxt; /* the ack # by SYNACK. For * FastOpen it's the seq# diff --git a/include/net/tcp.h b/include/net/tcp.h index 0cab28cd43a9..5cf9672c13e2 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -565,6 +565,7 @@ bool tcp_schedule_loss_probe(struct sock *sk); /* tcp_input.c */ void tcp_resume_early_retransmit(struct sock *sk); void tcp_rearm_rto(struct sock *sk); +void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req); void tcp_reset(struct sock *sk); /* tcp_timer.c */ diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index d70b1f603692..6595affded20 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -345,7 +345,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) ireq->wscale_ok = tcp_opt.wscale_ok; ireq->tstamp_ok = tcp_opt.saw_tstamp; req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; - treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; + treq->snt_synack.v64 = 0; treq->tfo_listener = false; ireq->ir_iif = sk->sk_bound_dev_if; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a62e9c76d485..497adf58a6b8 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2953,21 +2953,21 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, } /* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ -static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp) +void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req) { - struct tcp_sock *tp = tcp_sk(sk); - long seq_rtt_us = -1L; + long rtt_us = -1L; - if (synack_stamp && !tp->total_retrans) - seq_rtt_us = jiffies_to_usecs(tcp_time_stamp - synack_stamp); + if (req && !req->num_retrans && tcp_rsk(req)->snt_synack.v64) { + struct skb_mstamp now; - /* If the ACK acks both the SYNACK and the (Fast Open'd) data packets - * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack() - */ - if (!tp->srtt_us) - tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt_us, -1L); + skb_mstamp_get(&now); + rtt_us = skb_mstamp_us_delta(&now, &tcp_rsk(req)->snt_synack); + } + + tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, rtt_us, -1L); } + static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) { const struct inet_connection_sock *icsk = inet_csk(sk); @@ -5706,7 +5706,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct request_sock *req; int queued = 0; bool acceptable; - u32 synack_stamp; tp->rx_opt.saw_tstamp = 0; @@ -5785,15 +5784,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (!acceptable) return 1; + if (!tp->srtt_us) + tcp_synack_rtt_meas(sk, req); + /* Once we leave TCP_SYN_RECV, we no longer need req * so release it. */ if (req) { - synack_stamp = tcp_rsk(req)->snt_synack; tp->total_retrans = req->num_retrans; reqsk_fastopen_remove(sk, req, false); } else { - synack_stamp = tp->lsndtime; /* Make sure socket is routed, for correct metrics. */ icsk->icsk_af_ops->rebuild_header(sk); tcp_init_congestion_control(sk); @@ -5816,7 +5816,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, tp->snd_una = TCP_SKB_CB(skb)->ack_seq; tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); - tcp_synack_rtt_meas(sk, synack_stamp); if (tp->rx_opt.tstamp_ok) tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; @@ -6027,7 +6026,7 @@ static void tcp_openreq_init(struct request_sock *req, req->cookie_ts = 0; tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq; tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; - tcp_rsk(req)->snt_synack = tcp_time_stamp; + skb_mstamp_get(&tcp_rsk(req)->snt_synack); tcp_rsk(req)->last_oow_ack_time = 0; req->mss = rx_opt->mss_clamp; req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 6d8795b066ac..10933d01b982 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -470,7 +470,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tcp_enable_early_retrans(newtp); newtp->tlp_high_seq = 0; - newtp->lsndtime = treq->snt_synack; + newtp->lsndtime = treq->snt_synack.stamp_jiffies; newtp->last_oow_ack_time = 0; newtp->total_retrans = req->num_retrans; @@ -760,6 +760,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, if (!child) goto listen_overflow; + tcp_synack_rtt_meas(child, req); inet_csk_reqsk_queue_drop(sk, req); inet_csk_reqsk_queue_add(sk, req, child); /* Warning: caller must not call reqsk_put(req); diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 0909f4e0d53c..2461b3ff9551 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -210,7 +210,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) ireq->wscale_ok = tcp_opt.wscale_ok; ireq->tstamp_ok = tcp_opt.saw_tstamp; req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; - treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; + treq->snt_synack.v64 = 0; treq->rcv_isn = ntohl(th->seq) - 1; treq->snt_isn = cookie; -- cgit v1.3-6-gb490 From 79c452adb159dc9abc507ea13faec8d115a78758 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 18 Sep 2015 17:49:25 +0200 Subject: mtd: spi-nor: remove unused read_xfer/write_xfer hooks struct spi_nor_xfer_cfg and read_xfer/write_xfer hooks were never used by any driver. Do some cleanup by removing them. Signed-off-by: Cyrille Pitchen Reviewed-by: Marek Vasut Signed-off-by: Brian Norris --- include/linux/mtd/spi-nor.h | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'include') diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index e9c912d73141..672595a381c5 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -87,33 +87,6 @@ enum read_mode { SPI_NOR_QUAD, }; -/** - * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer - * @wren: command for "Write Enable", or 0x00 for not required - * @cmd: command for operation - * @cmd_pins: number of pins to send @cmd (1, 2, 4) - * @addr: address for operation - * @addr_pins: number of pins to send @addr (1, 2, 4) - * @addr_width: number of address bytes - * (3,4, or 0 for address not required) - * @mode: mode data - * @mode_pins: number of pins to send @mode (1, 2, 4) - * @mode_cycles: number of mode cycles (0 for mode not required) - * @dummy_cycles: number of dummy cycles (0 for dummy not required) - */ -struct spi_nor_xfer_cfg { - u8 wren; - u8 cmd; - u8 cmd_pins; - u32 addr; - u8 addr_pins; - u8 addr_width; - u8 mode; - u8 mode_pins; - u8 mode_cycles; - u8 dummy_cycles; -}; - #define SPI_NOR_MAX_CMD_SIZE 8 enum spi_nor_ops { SPI_NOR_OPS_READ = 0, @@ -144,14 +117,11 @@ struct mtd_info; * @flash_read: the mode of the read * @sst_write_second: used by the SST write operation * @flags: flag options for the current SPI-NOR (SNOR_F_*) - * @cfg: used by the read_xfer/write_xfer * @cmd_buf: used by the write_reg * @prepare: [OPTIONAL] do some preparations for the * read/write/erase/lock/unlock operations * @unprepare: [OPTIONAL] do some post work after the * read/write/erase/lock/unlock operations - * @read_xfer: [OPTIONAL] the read fundamental primitive - * @write_xfer: [OPTIONAL] the writefundamental primitive * @read_reg: [DRIVER-SPECIFIC] read out the register * @write_reg: [DRIVER-SPECIFIC] write data to the register * @read: [DRIVER-SPECIFIC] read data from the SPI NOR @@ -176,15 +146,10 @@ struct spi_nor { enum read_mode flash_read; bool sst_write_second; u32 flags; - struct spi_nor_xfer_cfg cfg; u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); - int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, - u8 *buf, size_t len); - int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, - u8 *buf, size_t len); int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); -- cgit v1.3-6-gb490 From e76e397a7f99bffbd91fb21f96370cbb165b5bcd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 16 Sep 2015 10:42:13 +0100 Subject: mfd: arizona: Add registers for ADC microphone detection The newer devices support using a software comparison to determine whether a 3/4 pole jack is present. Add the registers necessary for this. Signed-off-by: Charles Keepax Acked-by: Lee Jones Signed-off-by: Chanwoo Choi --- drivers/mfd/wm5110-tables.c | 2 ++ include/dt-bindings/mfd/arizona.h | 2 ++ include/linux/mfd/arizona/pdata.h | 3 +++ include/linux/mfd/arizona/registers.h | 6 +++--- 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index c4b9374efd76..5f604e00aaf1 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1811,6 +1811,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_MIC_DETECT_1: case ARIZONA_MIC_DETECT_2: case ARIZONA_MIC_DETECT_3: + case ARIZONA_MIC_DETECT_4: case ARIZONA_MIC_DETECT_LEVEL_1: case ARIZONA_MIC_DETECT_LEVEL_2: case ARIZONA_MIC_DETECT_LEVEL_3: @@ -2847,6 +2848,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS: case ARIZONA_MIC_DETECT_3: + case ARIZONA_MIC_DETECT_4: case ARIZONA_HP_CTRL_1L: case ARIZONA_HP_CTRL_1R: case ARIZONA_HEADPHONE_DETECT_2: diff --git a/include/dt-bindings/mfd/arizona.h b/include/dt-bindings/mfd/arizona.h index 7b2000cead43..c40f665e2712 100644 --- a/include/dt-bindings/mfd/arizona.h +++ b/include/dt-bindings/mfd/arizona.h @@ -107,5 +107,7 @@ #define ARIZONA_ACCDET_MODE_MIC 0 #define ARIZONA_ACCDET_MODE_HPL 1 #define ARIZONA_ACCDET_MODE_HPR 2 +#define ARIZONA_ACCDET_MODE_HPM 4 +#define ARIZONA_ACCDET_MODE_ADC 7 #endif diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h index 1dc385850ba2..92f31ffaf866 100644 --- a/include/linux/mfd/arizona/pdata.h +++ b/include/linux/mfd/arizona/pdata.h @@ -124,6 +124,9 @@ struct arizona_pdata { /** Channel to use for headphone detection */ unsigned int hpdet_channel; + /** Use software comparison to determine mic presence */ + bool micd_software_compare; + /** Extra debounce timeout used during initial mic detection (ms) */ unsigned int micd_detect_debounce; diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index fdd70b3c7418..ab219c9b0b08 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -2359,9 +2359,9 @@ #define ARIZONA_ACCDET_SRC_MASK 0x2000 /* ACCDET_SRC */ #define ARIZONA_ACCDET_SRC_SHIFT 13 /* ACCDET_SRC */ #define ARIZONA_ACCDET_SRC_WIDTH 1 /* ACCDET_SRC */ -#define ARIZONA_ACCDET_MODE_MASK 0x0003 /* ACCDET_MODE - [1:0] */ -#define ARIZONA_ACCDET_MODE_SHIFT 0 /* ACCDET_MODE - [1:0] */ -#define ARIZONA_ACCDET_MODE_WIDTH 2 /* ACCDET_MODE - [1:0] */ +#define ARIZONA_ACCDET_MODE_MASK 0x0007 /* ACCDET_MODE - [2:0] */ +#define ARIZONA_ACCDET_MODE_SHIFT 0 /* ACCDET_MODE - [2:0] */ +#define ARIZONA_ACCDET_MODE_WIDTH 3 /* ACCDET_MODE - [2:0] */ /* * R667 (0x29B) - Headphone Detect 1 -- cgit v1.3-6-gb490 From 1ce376897e02e623ba357594604ca655df61053b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 16 Sep 2015 10:42:14 +0100 Subject: mfd: arizona: Add register bits for general purpose switch The switch is typically used in conjunction with the MICDET clamp in order to suppress pops and clicks associated with jack insertion. Signed-off-by: Charles Keepax Acked-by: Lee Jones Signed-off-by: Chanwoo Choi --- drivers/mfd/wm5110-tables.c | 2 ++ include/linux/mfd/arizona/pdata.h | 3 +++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 5f604e00aaf1..aae17d6997b1 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1481,6 +1481,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000C04, 0xA101 }, /* R3076 - GPIO5 CTRL */ { 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */ { 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */ + { 0x00000C18, 0x0000 }, /* R3096 - GP Switch 1 */ { 0x00000C20, 0x8002 }, /* R3104 - Misc Pad Ctrl 1 */ { 0x00000C21, 0x8001 }, /* R3105 - Misc Pad Ctrl 2 */ { 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */ @@ -2528,6 +2529,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_GPIO5_CTRL: case ARIZONA_IRQ_CTRL_1: case ARIZONA_GPIO_DEBOUNCE_CONFIG: + case ARIZONA_GP_SWITCH_1: case ARIZONA_MISC_PAD_CTRL_1: case ARIZONA_MISC_PAD_CTRL_2: case ARIZONA_MISC_PAD_CTRL_3: diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h index 92f31ffaf866..57b45caaea80 100644 --- a/include/linux/mfd/arizona/pdata.h +++ b/include/linux/mfd/arizona/pdata.h @@ -184,6 +184,9 @@ struct arizona_pdata { /** GPIO for primary IRQ (used for edge triggered emulation) */ int irq_gpio; + + /** General purpose switch control */ + unsigned int gpsw; }; #endif -- cgit v1.3-6-gb490 From b8ba9edb911102b452c815879f520bfe2713fab6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 16 Sep 2015 10:42:15 +0100 Subject: mfd: arizona: Add TST_CAP bits for headphone detection On wm5110/8280 some additional settings are required to get accurate measurements at the top end of the headphone detection range. This patch adds the bits required for this. Signed-off-by: Charles Keepax Acked-by: Lee Jones Signed-off-by: Chanwoo Choi --- drivers/mfd/wm5110-tables.c | 2 ++ include/linux/mfd/arizona/registers.h | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'include') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index aae17d6997b1..28f2ae30507a 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1912,6 +1912,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_HP1_SHORT_CIRCUIT_CTRL: case ARIZONA_HP2_SHORT_CIRCUIT_CTRL: case ARIZONA_HP3_SHORT_CIRCUIT_CTRL: + case ARIZONA_HP_TEST_CTRL_1: case ARIZONA_AIF1_BCLK_CTRL: case ARIZONA_AIF1_TX_PIN_CTRL: case ARIZONA_AIF1_RX_PIN_CTRL: @@ -2857,6 +2858,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_INPUT_ENABLES_STATUS: case ARIZONA_OUTPUT_STATUS_1: case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_HP_TEST_CTRL_1: case ARIZONA_SLIMBUS_RX_PORT_STATUS: case ARIZONA_SLIMBUS_TX_PORT_STATUS: case ARIZONA_INTERRUPT_STATUS_1: diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index ab219c9b0b08..c7c11c900196 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -242,6 +242,7 @@ #define ARIZONA_HP1_SHORT_CIRCUIT_CTRL 0x4A0 #define ARIZONA_HP2_SHORT_CIRCUIT_CTRL 0x4A1 #define ARIZONA_HP3_SHORT_CIRCUIT_CTRL 0x4A2 +#define ARIZONA_HP_TEST_CTRL_1 0x4A4 #define ARIZONA_SPK_CTRL_2 0x4B5 #define ARIZONA_SPK_CTRL_3 0x4B6 #define ARIZONA_DAC_COMP_1 0x4DC @@ -3701,6 +3702,13 @@ #define ARIZONA_HP3_SC_ENA_SHIFT 12 /* HP3_SC_ENA */ #define ARIZONA_HP3_SC_ENA_WIDTH 1 /* HP3_SC_ENA */ +/* + * R1188 (0x4A4) HP Test Ctrl 1 + */ +#define ARIZONA_HP1_TST_CAP_SEL_MASK 0x0003 /* HP1_TST_CAP_SEL - [1:0] */ +#define ARIZONA_HP1_TST_CAP_SEL_SHIFT 0 /* HP1_TST_CAP_SEL - [1:0] */ +#define ARIZONA_HP1_TST_CAP_SEL_WIDTH 2 /* HP1_TST_CAP_SEL - [1:0] */ + /* * R1244 (0x4DC) - DAC comp 1 */ -- cgit v1.3-6-gb490 From a645654b817feba05e5156345325d19fc85ebc9f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 23 Aug 2015 15:18:55 +0200 Subject: vga_switcheroo: Document _ALL_ the things! This adds an "Overview" DOC section plus two DOC sections for the modes of use ("Manual switching and manual power control" and "Driver power control"). Also included is kernel-doc for all public functions, structs and enums. Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter --- drivers/gpu/vga/vga_switcheroo.c | 285 +++++++++++++++++++++++++++++++++++++-- include/linux/vga_switcheroo.h | 85 +++++++++++- 2 files changed, 353 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 21060668fd25..b19a72f7ac7c 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -1,20 +1,31 @@ /* + * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs + * * Copyright (c) 2010 Red Hat Inc. * Author : Dave Airlie * + * Copyright (c) 2015 Lukas Wunner * - * Licensed under GPLv2 + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. * - * Switcher interface - methods require for ATPX and DCM - * - switchto - this throws the output MUX switch - * - discrete_set_power - sets the power state for the discrete card + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS + * IN THE SOFTWARE. * - * GPU driver interface - * - set_gpu_state - this should do the equiv of s/r for the card - * - this should *not* set the discrete power state - * - switch_check - check if the device is in a position to switch now */ #define pr_fmt(fmt) "vga_switcheroo: " fmt @@ -33,6 +44,61 @@ #include +/** + * DOC: Overview + * + * vga_switcheroo is the Linux subsystem for laptop hybrid graphics. + * These come in two flavors: + * + * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs. + * * muxless: Dual GPUs but only one of them is connected to outputs. + * The other one is merely used to offload rendering, its results + * are copied over PCIe into the framebuffer. On Linux this is + * supported with DRI PRIME. + * + * Hybrid graphics started to appear in the late Naughties and were initially + * all muxed. Newer laptops moved to a muxless architecture for cost reasons. + * A notable exception is the MacBook Pro which continues to use a mux. + * Muxes come with varying capabilities: Some switch only the panel, others + * can also switch external displays. Some switch all display pins at once + * while others can switch just the DDC lines. (To allow EDID probing + * for the inactive GPU.) Also, muxes are often used to cut power to the + * discrete GPU while it is not used. + * + * DRM drivers register GPUs with vga_switcheroo, these are heretoforth called + * clients. The mux is called the handler. Muxless machines also register a + * handler to control the power state of the discrete GPU, its ->switchto + * callback is a no-op for obvious reasons. The discrete GPU is often equipped + * with an HDA controller for the HDMI/DP audio signal, this will also + * register as a client so that vga_switcheroo can take care of the correct + * suspend/resume order when changing the discrete GPU's power state. In total + * there can thus be up to three clients: Two vga clients (GPUs) and one audio + * client (on the discrete GPU). The code is mostly prepared to support + * machines with more than two GPUs should they become available. + * The GPU to which the outputs are currently switched is called the + * active client in vga_switcheroo parlance. The GPU not in use is the + * inactive client. + */ + +/** + * struct vga_switcheroo_client - registered client + * @pdev: client pci device + * @fb_info: framebuffer to which console is remapped on switching + * @pwr_state: current power state + * @ops: client callbacks + * @id: client identifier, see enum vga_switcheroo_client_id. + * Determining the id requires the handler, so GPUs are initially + * assigned -1 and later given their true id in vga_switcheroo_enable() + * @active: whether the outputs are currently switched to this client + * @driver_power_control: whether power state is controlled by the driver's + * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs + * interface is a no-op so as not to interfere with runtime pm + * @list: client list + * + * Registered client. A client can be either a GPU or an audio device on a GPU. + * For audio clients, the @fb_info, @active and @driver_power_control members + * are bogus. + */ struct vga_switcheroo_client { struct pci_dev *pdev; struct fb_info *fb_info; @@ -44,10 +110,28 @@ struct vga_switcheroo_client { struct list_head list; }; +/* + * protects access to struct vgasr_priv + */ static DEFINE_MUTEX(vgasr_mutex); +/** + * struct vgasr_priv - vga_switcheroo private data + * @active: whether vga_switcheroo is enabled. + * Prerequisite is the registration of two GPUs and a handler + * @delayed_switch_active: whether a delayed switch is pending + * @delayed_client_id: client to which a delayed switch is pending + * @debugfs_root: directory for vga_switcheroo debugfs interface + * @switch_file: file for vga_switcheroo debugfs interface + * @registered_clients: number of registered GPUs + * (counting only vga clients, not audio clients) + * @clients: list of registered clients + * @handler: registered handler + * + * vga_switcheroo private data. Currently only one vga_switcheroo instance + * per system is supported. + */ struct vgasr_priv { - bool active; bool delayed_switch_active; enum vga_switcheroo_client_id delayed_client_id; @@ -103,6 +187,15 @@ static void vga_switcheroo_enable(void) vgasr_priv.active = true; } +/** + * vga_switcheroo_register_handler() - register handler + * @handler: handler callbacks + * + * Register handler. Enable vga_switcheroo if two vga clients have already + * registered. + * + * Return: 0 on success, -EINVAL if a handler was already registered. + */ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { mutex_lock(&vgasr_mutex); @@ -121,6 +214,11 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) } EXPORT_SYMBOL(vga_switcheroo_register_handler); +/** + * vga_switcheroo_unregister_handler() - unregister handler + * + * Unregister handler. Disable vga_switcheroo. + */ void vga_switcheroo_unregister_handler(void) { mutex_lock(&vgasr_mutex); @@ -164,6 +262,19 @@ static int register_client(struct pci_dev *pdev, return 0; } +/** + * vga_switcheroo_register_client - register vga client + * @pdev: client pci device + * @ops: client callbacks + * @driver_power_control: whether power state is controlled by the driver's + * runtime pm + * + * Register vga client (GPU). Enable vga_switcheroo if another GPU and a + * handler have already registered. The power state of the client is assumed + * to be ON. + * + * Return: 0 on success, -ENOMEM on memory allocation error. + */ int vga_switcheroo_register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) @@ -174,6 +285,18 @@ int vga_switcheroo_register_client(struct pci_dev *pdev, } EXPORT_SYMBOL(vga_switcheroo_register_client); +/** + * vga_switcheroo_register_audio_client - register audio client + * @pdev: client pci device + * @ops: client callbacks + * @id: client identifier, see enum vga_switcheroo_client_id + * @active: whether the audio device is fully initialized + * + * Register audio client (audio device on a GPU). The power state of the + * client is assumed to be ON. + * + * Return: 0 on success, -ENOMEM on memory allocation error. + */ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, int id, bool active) @@ -215,6 +338,15 @@ find_active_client(struct list_head *head) return NULL; } +/** + * vga_switcheroo_get_client_state() - obtain power state of a given client + * @pdev: client pci device + * + * Obtain power state of a given client as seen from vga_switcheroo. + * The function is only called from hda_intel.c. + * + * Return: Power state. + */ int vga_switcheroo_get_client_state(struct pci_dev *pdev) { struct vga_switcheroo_client *client; @@ -228,6 +360,12 @@ int vga_switcheroo_get_client_state(struct pci_dev *pdev) } EXPORT_SYMBOL(vga_switcheroo_get_client_state); +/** + * vga_switcheroo_unregister_client() - unregister client + * @pdev: client pci device + * + * Unregister client. Disable vga_switcheroo if this is a vga client (GPU). + */ void vga_switcheroo_unregister_client(struct pci_dev *pdev) { struct vga_switcheroo_client *client; @@ -249,6 +387,14 @@ void vga_switcheroo_unregister_client(struct pci_dev *pdev) } EXPORT_SYMBOL(vga_switcheroo_unregister_client); +/** + * vga_switcheroo_client_fb_set() - set framebuffer of a given client + * @pdev: client pci device + * @info: framebuffer + * + * Set framebuffer of a given client. The console will be remapped to this + * on switching. + */ void vga_switcheroo_client_fb_set(struct pci_dev *pdev, struct fb_info *info) { @@ -262,6 +408,42 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev, } EXPORT_SYMBOL(vga_switcheroo_client_fb_set); +/** + * DOC: Manual switching and manual power control + * + * In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch + * can be read to retrieve the current vga_switcheroo state and commands + * can be written to it to change the state. The file appears as soon as + * two GPU drivers and one handler have registered with vga_switcheroo. + * The following commands are understood: + * + * * OFF: Power off the device not in use. + * * ON: Power on the device not in use. + * * IGD: Switch to the integrated graphics device. + * Power on the integrated GPU if necessary, power off the discrete GPU. + * Prerequisite is that no user space processes (e.g. Xorg, alsactl) + * have opened device files of the GPUs or the audio client. If the + * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ + * and /dev/snd/controlC1 to identify processes blocking the switch. + * * DIS: Switch to the discrete graphics device. + * * DIGD: Delayed switch to the integrated graphics device. + * This will perform the switch once the last user space process has + * closed the device files of the GPUs and the audio client. + * * DDIS: Delayed switch to the discrete graphics device. + * * MIGD: Mux-only switch to the integrated graphics device. + * Does not remap console or change the power state of either gpu. + * If the integrated GPU is currently off, the screen will turn black. + * If it is on, the screen will show whatever happens to be in VRAM. + * Either way, the user has to blindly enter the command to switch back. + * * MDIS: Mux-only switch to the discrete graphics device. + * + * For GPUs whose power state is controlled by the driver's runtime pm, + * the ON and OFF commands are a no-op (see next section). + * + * For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands + * should not be used. + */ + static int vga_switcheroo_show(struct seq_file *m, void *v) { struct vga_switcheroo_client *client; @@ -559,6 +741,16 @@ fail: return -1; } +/** + * vga_switcheroo_process_delayed_switch() - helper for delayed switching + * + * Process a delayed switch if one is pending. DRM drivers should call this + * from their ->lastclose callback. + * + * Return: 0 on success. -EINVAL if no delayed switch is pending, if the client + * has unregistered in the meantime or if there are other clients blocking the + * switch. If the actual switch fails, an error is reported and 0 is returned. + */ int vga_switcheroo_process_delayed_switch(void) { struct vga_switcheroo_client *client; @@ -589,6 +781,39 @@ err: } EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); +/** + * DOC: Driver power control + * + * In this mode of use, the discrete GPU automatically powers up and down at + * the discretion of the driver's runtime pm. On muxed machines, the user may + * still influence the muxer state by way of the debugfs interface, however + * the ON and OFF commands become a no-op for the discrete GPU. + * + * This mode is the default on Nvidia HybridPower/Optimus and ATI PowerXpress. + * Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel + * command line disables it. + * + * When the driver decides to power up or down, it notifies vga_switcheroo + * thereof so that it can (a) power the audio device on the GPU up or down, + * and (b) update its internal power state representation for the device. + * This is achieved by vga_switcheroo_set_dynamic_switch(). + * + * After the GPU has been suspended, the handler needs to be called to cut + * power to the GPU. Likewise it needs to reinstate power before the GPU + * can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(), + * which augments the GPU's suspend/resume functions by the requisite + * calls to the handler. + * + * When the audio device resumes, the GPU needs to be woken. This is achieved + * by vga_switcheroo_init_domain_pm_optimus_hdmi_audio(), which augments the + * audio device's resume function. + * + * On muxed machines, if the mux is initially switched to the discrete GPU, + * the user ends up with a black screen when the GPU powers down after boot. + * As a workaround, the mux is forced to the integrated GPU on runtime suspend, + * cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917 + */ + static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switcheroo_state state) { @@ -607,8 +832,17 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev, vgasr_priv.handler->power_state(client->id, state); } -/* force a PCI device to a certain state - mainly to turn off audio clients */ - +/** + * vga_switcheroo_set_dynamic_switch() - helper for driver power control + * @pdev: client pci device + * @dynamic: new power state + * + * Helper for GPUs whose power state is controlled by the driver's runtime pm. + * When the driver decides to power up or down, it notifies vga_switcheroo + * thereof using this helper so that it can (a) power the audio device on + * the GPU up or down, and (b) update its internal power state representation + * for the device. + */ void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) { @@ -654,8 +888,18 @@ static int vga_switcheroo_runtime_resume(struct device *dev) return 0; } -/* this version is for the case where the power switch is separate - to the device being powered down. */ +/** + * vga_switcheroo_init_domain_pm_ops() - helper for driver power control + * @dev: vga client device + * @domain: power domain + * + * Helper for GPUs whose power state is controlled by the driver's runtime pm. + * After the GPU has been suspended, the handler needs to be called to cut + * power to the GPU. Likewise it needs to reinstate power before the GPU + * can resume. To this end, this helper augments the suspend/resume functions + * by the requisite calls to the handler. It needs only be called on platforms + * where the power switch is separate to the device being powered down. + */ int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { @@ -709,6 +953,19 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev) return ret; } +/** + * vga_switcheroo_init_domain_pm_optimus_hdmi_audio() - helper for driver + * power control + * @dev: audio client device + * @domain: power domain + * + * Helper for GPUs whose power state is controlled by the driver's runtime pm. + * When the audio device resumes, the GPU needs to be woken. This helper + * augments the audio device's resume function to do that. + * + * Return: 0 on success, -EINVAL if no power management operations are + * defined for this device. + */ int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index b483abd34493..fe90bfc3b510 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -1,10 +1,31 @@ /* + * vga_switcheroo.h - Support for laptop with dual GPU using one set of outputs + * * Copyright (c) 2010 Red Hat Inc. * Author : Dave Airlie * - * Licensed under GPLv2 + * Copyright (c) 2015 Lukas Wunner + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS + * IN THE SOFTWARE. * - * vga_switcheroo.h - Support for laptop with dual GPU using one set of outputs */ #ifndef _LINUX_VGA_SWITCHEROO_H_ @@ -14,6 +35,20 @@ struct pci_dev; +/** + * enum vga_switcheroo_state - client power state + * @VGA_SWITCHEROO_OFF: off + * @VGA_SWITCHEROO_ON: on + * @VGA_SWITCHEROO_INIT: client has registered with vga_switcheroo but + * vga_switcheroo is not enabled, i.e. no second client or no handler + * has registered. Only used in vga_switcheroo_get_client_state() which + * in turn is only called from hda_intel.c + * @VGA_SWITCHEROO_NOT_FOUND: client has not registered with vga_switcheroo. + * Only used in vga_switcheroo_get_client_state() which in turn is only + * called from hda_intel.c + * + * Client power state. + */ enum vga_switcheroo_state { VGA_SWITCHEROO_OFF, VGA_SWITCHEROO_ON, @@ -22,20 +57,64 @@ enum vga_switcheroo_state { VGA_SWITCHEROO_NOT_FOUND, }; +/** + * enum vga_switcheroo_client_id - client identifier + * @VGA_SWITCHEROO_IGD: integrated graphics device + * @VGA_SWITCHEROO_DIS: discrete graphics device + * @VGA_SWITCHEROO_MAX_CLIENTS: currently no more than two GPUs are supported + * + * Client identifier. Audio clients use the same identifier & 0x100. + */ enum vga_switcheroo_client_id { VGA_SWITCHEROO_IGD, VGA_SWITCHEROO_DIS, VGA_SWITCHEROO_MAX_CLIENTS, }; +/** + * struct vga_switcheroo_handler - handler callbacks + * @init: initialize handler. + * Optional. This gets called when vga_switcheroo is enabled, i.e. when + * two vga clients have registered. It allows the handler to perform + * some delayed initialization that depends on the existence of the + * vga clients. Currently only the radeon and amdgpu drivers use this. + * The return value is ignored + * @switchto: switch outputs to given client. + * Mandatory. For muxless machines this should be a no-op. Returning 0 + * denotes success, anything else failure (in which case the switch is + * aborted) + * @power_state: cut or reinstate power of given client. + * Optional. The return value is ignored + * @get_client_id: determine if given pci device is integrated or discrete GPU. + * Mandatory + * + * Handler callbacks. The multiplexer itself. The @switchto and @get_client_id + * methods are mandatory, all others may be set to NULL. + */ struct vga_switcheroo_handler { + int (*init)(void); int (*switchto)(enum vga_switcheroo_client_id id); int (*power_state)(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state); - int (*init)(void); int (*get_client_id)(struct pci_dev *pdev); }; +/** + * struct vga_switcheroo_client_ops - client callbacks + * @set_gpu_state: do the equivalent of suspend/resume for the card. + * Mandatory. This should not cut power to the discrete GPU, + * which is the job of the handler + * @reprobe: poll outputs. + * Optional. This gets called after waking the GPU and switching + * the outputs to it + * @can_switch: check if the device is in a position to switch now. + * Mandatory. The client should return false if a user space process + * has one of its device files open + * + * Client callbacks. A client can be either a GPU or an audio device on a GPU. + * The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be + * set to NULL. For audio clients, the @reprobe member is bogus. + */ struct vga_switcheroo_client_ops { void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state); void (*reprobe)(struct pci_dev *dev); -- cgit v1.3-6-gb490 From a1da67b8117ddbe88c770b48b5b1527393b8c9c0 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Fri, 18 Sep 2015 11:30:41 +0200 Subject: ieee802154: header_ops: fix frame control setting Sometimes upper-layer protocols wants to generate a new mac header by filling "struct ieee802154_hdr" only. These upper-layers sets for the address settings the source and dest fields, but not the fc fields for indicate the source and dest address mode. This patch changes the "ieee802154_hdr_push" function so the fc address fields are set according the source and dest fields of "struct ieee802154_hdr". Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/ieee802154_netdev.h | 2 +- net/ieee802154/header_ops.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index 2c10a9f0c6d9..95a71bc113b3 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h @@ -99,7 +99,7 @@ struct ieee802154_hdr { * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame * version, if SECEN is set. */ -int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr); +int ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr); /* pulls the entire 802.15.4 header off of the skb, including the security * header, and performs pan id decompression diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c index a051b6993177..d8443b057022 100644 --- a/net/ieee802154/header_ops.c +++ b/net/ieee802154/header_ops.c @@ -83,35 +83,35 @@ ieee802154_hdr_push_sechdr(u8 *buf, const struct ieee802154_sechdr *hdr) } int -ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr) +ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr) { u8 buf[MAC802154_FRAME_HARD_HEADER_LEN]; int pos = 2; int rc; - struct ieee802154_hdr_fc fc = hdr->fc; + struct ieee802154_hdr_fc *fc = &hdr->fc; buf[pos++] = hdr->seq; - fc.dest_addr_mode = hdr->dest.mode; + fc->dest_addr_mode = hdr->dest.mode; rc = ieee802154_hdr_push_addr(buf + pos, &hdr->dest, false); if (rc < 0) return -EINVAL; pos += rc; - fc.source_addr_mode = hdr->source.mode; + fc->source_addr_mode = hdr->source.mode; if (hdr->source.pan_id == hdr->dest.pan_id && hdr->dest.mode != IEEE802154_ADDR_NONE) - fc.intra_pan = true; + fc->intra_pan = true; - rc = ieee802154_hdr_push_addr(buf + pos, &hdr->source, fc.intra_pan); + rc = ieee802154_hdr_push_addr(buf + pos, &hdr->source, fc->intra_pan); if (rc < 0) return -EINVAL; pos += rc; - if (fc.security_enabled) { - fc.version = 1; + if (fc->security_enabled) { + fc->version = 1; rc = ieee802154_hdr_push_sechdr(buf + pos, &hdr->sec); if (rc < 0) @@ -120,7 +120,7 @@ ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr) pos += rc; } - memcpy(buf, &fc, 2); + memcpy(buf, fc, 2); memcpy(skb_push(skb, pos), buf, pos); -- cgit v1.3-6-gb490 From 838b83d63d2909f9136f3030dc4fffa8230c31da Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Fri, 18 Sep 2015 11:30:42 +0200 Subject: ieee802154: introduce wpan_dev_header_ops The current header_ops callback structure of net device are used mostly from 802.15.4 upper-layers. Because this callback structure is a very generic one, which is also used by e.g. DGRAM AF_PACKET sockets, we can't make this callback structure 802.15.4 specific which is currently is. I saw the smallest "constraint" for calling this callback with dev_hard_header/dev_parse_header by AF_PACKET which assign a 8 byte array for address void pointers. Currently 802.15.4 specific protocols like af802154 and 6LoWPAN will assign the "struct ieee802154_addr" as these parameters which is greater than 8 bytes. The current callback implementation for header_ops.create assumes always a complete "struct ieee802154_addr" which AF_PACKET can't never handled and is greater than 8 bytes. For that reason we introduce now a "generic" create/parse header_ops callback which allows handling with intra-pan extended addresses only. This allows a small use-case with AF_PACKET to send "somehow" a valid dataframe over DGRAM. To keeping the current dev_hard_header behaviour we introduce a similar callback structure "wpan_dev_header_ops" which contains 802.15.4 specific upper-layer header creation functionality, which can be called by wpan_dev_hard_header. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/cfg802154.h | 33 +++++++++++++++ include/net/ieee802154_netdev.h | 9 ---- net/ieee802154/6lowpan/tx.c | 8 ++-- net/ieee802154/socket.c | 4 +- net/mac802154/iface.c | 91 +++++++++++++++++++++++++++++++++++------ 5 files changed, 118 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 76b1ffaea863..242273ccf34b 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -167,6 +167,26 @@ struct wpan_phy { char priv[0] __aligned(NETDEV_ALIGN); }; +struct ieee802154_addr { + u8 mode; + __le16 pan_id; + union { + __le16 short_addr; + __le64 extended_addr; + }; +}; + +struct wpan_dev_header_ops { + /* TODO create callback currently assumes ieee802154_mac_cb inside + * skb->cb. This should be changed to give these information as + * parameter. + */ + int (*create)(struct sk_buff *skb, struct net_device *dev, + const struct ieee802154_addr *daddr, + const struct ieee802154_addr *saddr, + unsigned int len); +}; + struct wpan_dev { struct wpan_phy *wpan_phy; int iftype; @@ -175,6 +195,8 @@ struct wpan_dev { struct list_head list; struct net_device *netdev; + const struct wpan_dev_header_ops *header_ops; + /* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */ struct net_device *lowpan_dev; @@ -205,6 +227,17 @@ struct wpan_dev { #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) +static inline int +wpan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, + const struct ieee802154_addr *daddr, + const struct ieee802154_addr *saddr, + unsigned int len) +{ + struct wpan_dev *wpan_dev = dev->ieee802154_ptr; + + return wpan_dev->header_ops->create(skb, dev, daddr, saddr, len); +} + struct wpan_phy * wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size); static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev) diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index 95a71bc113b3..aebb9d8d7a11 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h @@ -50,15 +50,6 @@ struct ieee802154_sechdr { }; }; -struct ieee802154_addr { - u8 mode; - __le16 pan_id; - union { - __le16 short_addr; - __le64 extended_addr; - }; -}; - struct ieee802154_hdr_fc { #if defined(__LITTLE_ENDIAN_BITFIELD) u16 type:3, diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c index 54939d031ea5..6067e064a3fe 100644 --- a/net/ieee802154/6lowpan/tx.c +++ b/net/ieee802154/6lowpan/tx.c @@ -87,8 +87,8 @@ lowpan_alloc_frag(struct sk_buff *skb, int size, skb_reset_network_header(frag); *mac_cb(frag) = *mac_cb(skb); - rc = dev_hard_header(frag, wdev, 0, &master_hdr->dest, - &master_hdr->source, size); + rc = wpan_dev_hard_header(frag, wdev, &master_hdr->dest, + &master_hdr->source, size); if (rc < 0) { kfree_skb(frag); return ERR_PTR(rc); @@ -228,8 +228,8 @@ static int lowpan_header(struct sk_buff *skb, struct net_device *ldev, cb->ackreq = wpan_dev->ackreq; } - return dev_hard_header(skb, lowpan_dev_info(ldev)->wdev, ETH_P_IPV6, - (void *)&da, (void *)&sa, 0); + return wpan_dev_hard_header(skb, lowpan_dev_info(ldev)->wdev, &da, &sa, + 0); } netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev) diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c index b6eacf30ee7a..be77f211ce87 100644 --- a/net/ieee802154/socket.c +++ b/net/ieee802154/socket.c @@ -676,8 +676,8 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) cb->seclevel = ro->seclevel; cb->seclevel_override = ro->seclevel_override; - err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr, - ro->bound ? &ro->src_addr : NULL, size); + err = wpan_dev_hard_header(skb, dev, &dst_addr, + ro->bound ? &ro->src_addr : NULL, size); if (err < 0) goto out_skb; diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index ed26952f9e14..8afe26d72971 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -367,12 +367,11 @@ static int mac802154_set_header_security(struct ieee802154_sub_if_data *sdata, return 0; } -static int mac802154_header_create(struct sk_buff *skb, - struct net_device *dev, - unsigned short type, - const void *daddr, - const void *saddr, - unsigned len) +static int ieee802154_header_create(struct sk_buff *skb, + struct net_device *dev, + const struct ieee802154_addr *daddr, + const struct ieee802154_addr *saddr, + unsigned len) { struct ieee802154_hdr hdr; struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); @@ -423,24 +422,91 @@ static int mac802154_header_create(struct sk_buff *skb, return hlen; } +static const struct wpan_dev_header_ops ieee802154_header_ops = { + .create = ieee802154_header_create, +}; + +/* This header create functionality assumes a 8 byte array for + * source and destination pointer at maximum. To adapt this for + * the 802.15.4 dataframe header we use extended address handling + * here only and intra pan connection. fc fields are mostly fallback + * handling. For provide dev_hard_header for dgram sockets. + */ +static int mac802154_header_create(struct sk_buff *skb, + struct net_device *dev, + unsigned short type, + const void *daddr, + const void *saddr, + unsigned len) +{ + struct ieee802154_hdr hdr; + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + struct wpan_dev *wpan_dev = &sdata->wpan_dev; + struct ieee802154_mac_cb cb = { }; + int hlen; + + if (!daddr) + return -EINVAL; + + memset(&hdr.fc, 0, sizeof(hdr.fc)); + hdr.fc.type = IEEE802154_FC_TYPE_DATA; + hdr.fc.ack_request = wpan_dev->ackreq; + hdr.seq = atomic_inc_return(&dev->ieee802154_ptr->dsn) & 0xFF; + + /* TODO currently a workaround to give zero cb block to set + * security parameters defaults according MIB. + */ + if (mac802154_set_header_security(sdata, &hdr, &cb) < 0) + return -EINVAL; + + hdr.dest.pan_id = wpan_dev->pan_id; + hdr.dest.mode = IEEE802154_ADDR_LONG; + memcpy(&hdr.dest.extended_addr, daddr, IEEE802154_EXTENDED_ADDR_LEN); + + hdr.source.pan_id = hdr.dest.pan_id; + hdr.source.mode = IEEE802154_ADDR_LONG; + + if (!saddr) + hdr.source.extended_addr = wpan_dev->extended_addr; + else + memcpy(&hdr.source.extended_addr, saddr, + IEEE802154_EXTENDED_ADDR_LEN); + + hlen = ieee802154_hdr_push(skb, &hdr); + if (hlen < 0) + return -EINVAL; + + skb_reset_mac_header(skb); + skb->mac_len = hlen; + + if (len > ieee802154_max_payload(&hdr)) + return -EMSGSIZE; + + return hlen; +} + static int mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) { struct ieee802154_hdr hdr; - struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr; if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) { pr_debug("malformed packet\n"); return 0; } - *addr = hdr.source; - return sizeof(*addr); + if (hdr.source.mode == IEEE802154_ADDR_LONG) { + memcpy(haddr, &hdr.source.extended_addr, + IEEE802154_EXTENDED_ADDR_LEN); + return IEEE802154_EXTENDED_ADDR_LEN; + } + + return 0; } -static struct header_ops mac802154_header_ops = { - .create = mac802154_header_create, - .parse = mac802154_header_parse, +static const struct header_ops mac802154_header_ops = { + .create = mac802154_header_create, + .parse = mac802154_header_parse, }; static const struct net_device_ops mac802154_wpan_ops = { @@ -513,6 +579,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, sdata->dev->netdev_ops = &mac802154_wpan_ops; sdata->dev->ml_priv = &mac802154_mlme_wpan; wpan_dev->promiscuous_mode = false; + wpan_dev->header_ops = &ieee802154_header_ops; mutex_init(&sdata->sec_mtx); -- cgit v1.3-6-gb490 From 87a93e4eceb495f93e3f37b100334d2641765b6c Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Fri, 18 Sep 2015 11:30:43 +0200 Subject: ieee802154: change needed headroom/tailroom This patch cleanups needed_headroom, needed_tailroom and hard_header_len fields for wpan and lowpan interfaces. For wpan interfaces the worst case mac header len should be part of needed_headroom, currently this is set as hard_header_len, but hard_header_len should be set to the minimum header length which xmit call assumes and this is the minimum frame length of 802.15.4. The hard_header_len value will check inside send callbacl of AF_PACKET raw sockets. For lowpan interfaces, if fragmentation isn't needed the skb will call dev_hard_header for 802154 layer and queue it afterwards. This happens without new skb allocation, so we need the same headroom and tailroom lengths like 802154 inside 802154 6lowpan layer. At least we assume as minimum header length an ipv6 header size. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 11 +++++++++++ include/net/6lowpan.h | 8 ++++++++ include/net/mac802154.h | 8 -------- net/6lowpan/nhc.h | 2 -- net/ieee802154/6lowpan/core.c | 14 +++++++++++--- net/ieee802154/6lowpan/tx.c | 12 ++++++++++-- net/ieee802154/header_ops.c | 2 +- net/mac802154/iface.c | 17 ++++++++++++++--- net/mac802154/tx.c | 3 --- 9 files changed, 55 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index db01492814d3..205ce4e1ac32 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -31,6 +31,17 @@ #define IEEE802154_ACK_PSDU_LEN 5 #define IEEE802154_MIN_PSDU_LEN 9 #define IEEE802154_FCS_LEN 2 +#define IEEE802154_MAX_AUTH_TAG_LEN 16 + +/* General MAC frame format: + * 2 bytes: Frame Control + * 1 byte: Sequence Number + * 20 bytes: Addressing fields + * 14 bytes: Auxiliary Security Header + */ +#define IEEE802154_MAX_HEADER_LEN (2 + 1 + 20 + 14) +#define IEEE802154_MIN_HEADER_LEN (IEEE802154_ACK_PSDU_LEN - \ + IEEE802154_FCS_LEN) #define IEEE802154_PAN_ID_BROADCAST 0xffff #define IEEE802154_ADDR_SHORT_BROADCAST 0xffff diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index eeae5eb58754..c17f556644fc 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -61,6 +61,14 @@ #define UIP_PROTO_UDP 17 /* ipv6 next header value for UDP */ #define UIP_FRAGH_LEN 8 /* ipv6 fragment header size */ +#define LOWPAN_NHC_MAX_ID_LEN 1 +/* Max IPHC Header len without IPv6 hdr specific inline data. + * Useful for getting the "extra" bytes we need at worst case compression. + * + * LOWPAN_IPHC + CID + LOWPAN_NHC_MAX_ID_LEN + */ +#define LOWPAN_IPHC_MAX_HEADER_LEN (2 + 1 + LOWPAN_NHC_MAX_ID_LEN) + /* * ipv6 address based on mac * second bit-flip (Universe/Local) is done according RFC2464 diff --git a/include/net/mac802154.h b/include/net/mac802154.h index 32bd7c0467d4..2c478501ad14 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -23,14 +23,6 @@ #include -/* General MAC frame format: - * 2 bytes: Frame Control - * 1 byte: Sequence Number - * 20 bytes: Addressing fields - * 14 bytes: Auxiliary Security Header - */ -#define MAC802154_FRAME_HARD_HEADER_LEN (2 + 1 + 20 + 14) - /** * enum ieee802154_hw_addr_filt_flags - hardware address filtering flags * diff --git a/net/6lowpan/nhc.h b/net/6lowpan/nhc.h index ed44938eb5de..c249f17fa37b 100644 --- a/net/6lowpan/nhc.h +++ b/net/6lowpan/nhc.h @@ -8,8 +8,6 @@ #include #include -#define LOWPAN_NHC_MAX_ID_LEN 1 - /** * LOWPAN_NHC - helper macro to generate nh id fields and lowpan_nhc struct * diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 9f0cfa598e3a..44420ed95574 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -104,9 +104,8 @@ static void lowpan_setup(struct net_device *ldev) ldev->addr_len = IEEE802154_ADDR_LEN; memset(ldev->broadcast, 0xff, IEEE802154_ADDR_LEN); ldev->type = ARPHRD_6LOWPAN; - /* Frame Control + Sequence Number + Address fields + Security Header */ - ldev->hard_header_len = 2 + 1 + 20 + 14; - ldev->needed_tailroom = 2; /* FCS */ + /* We need an ipv6hdr as minimum len when calling xmit */ + ldev->hard_header_len = sizeof(struct ipv6hdr); ldev->mtu = IPV6_MIN_MTU; ldev->priv_flags |= IFF_NO_QUEUE; ldev->flags = IFF_BROADCAST | IFF_MULTICAST; @@ -156,6 +155,15 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev, lowpan_dev_info(ldev)->wdev = wdev; /* Set the lowpan hardware address to the wpan hardware address. */ memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN); + /* We need headroom for possible wpan_dev_hard_header call and tailroom + * for encryption/fcs handling. The lowpan interface will replace + * the IPv6 header with 6LoWPAN header. At worst case the 6LoWPAN + * header has LOWPAN_IPHC_MAX_HEADER_LEN more bytes than the IPv6 + * header. + */ + ldev->needed_headroom = LOWPAN_IPHC_MAX_HEADER_LEN + + wdev->needed_headroom; + ldev->needed_tailroom = wdev->needed_tailroom; lowpan_netdev_setup(ldev, LOWPAN_LLTYPE_IEEE802154); diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c index 6067e064a3fe..7e0563eaea98 100644 --- a/net/ieee802154/6lowpan/tx.c +++ b/net/ieee802154/6lowpan/tx.c @@ -10,6 +10,7 @@ #include #include +#include #include "6lowpan_i.h" @@ -36,6 +37,13 @@ lowpan_addr_info *lowpan_skb_priv(const struct sk_buff *skb) sizeof(struct lowpan_addr_info)); } +/* This callback will be called from AF_PACKET and IPv6 stack, the AF_PACKET + * sockets gives an 8 byte array for addresses only! + * + * TODO I think AF_PACKET DGRAM (sending/receiving) RAW (sending) makes no + * sense here. We should disable it, the right use-case would be AF_INET6 + * RAW/DGRAM sockets. + */ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev, unsigned short type, const void *_daddr, const void *_saddr, unsigned int len) @@ -77,13 +85,13 @@ lowpan_alloc_frag(struct sk_buff *skb, int size, struct sk_buff *frag; int rc; - frag = alloc_skb(wdev->hard_header_len + wdev->needed_tailroom + size, + frag = alloc_skb(wdev->needed_headroom + wdev->needed_tailroom + size, GFP_ATOMIC); if (likely(frag)) { frag->dev = wdev; frag->priority = skb->priority; - skb_reserve(frag, wdev->hard_header_len); + skb_reserve(frag, wdev->needed_headroom); skb_reset_network_header(frag); *mac_cb(frag) = *mac_cb(skb); diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c index d8443b057022..c7439f0fbbdf 100644 --- a/net/ieee802154/header_ops.c +++ b/net/ieee802154/header_ops.c @@ -85,7 +85,7 @@ ieee802154_hdr_push_sechdr(u8 *buf, const struct ieee802154_sechdr *hdr) int ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr) { - u8 buf[MAC802154_FRAME_HARD_HEADER_LEN]; + u8 buf[IEEE802154_MAX_HEADER_LEN]; int pos = 2; int rc; struct ieee802154_hdr_fc *fc = &hdr->fc; diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 8afe26d72971..b5a0936ce514 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -537,8 +537,18 @@ static void ieee802154_if_setup(struct net_device *dev) dev->addr_len = IEEE802154_EXTENDED_ADDR_LEN; memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN); - dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; - dev->needed_tailroom = 2 + 16; /* FCS + MIC */ + /* Let hard_header_len set to IEEE802154_MIN_HEADER_LEN. AF_PACKET + * will not send frames without any payload, but ack frames + * has no payload, so substract one that we can send a 3 bytes + * frame. The xmit callback assumes at least a hard header where two + * bytes fc and sequence field are set. + */ + dev->hard_header_len = IEEE802154_MIN_HEADER_LEN - 1; + /* The auth_tag header is for security and places in private payload + * room of mac frame which stucks between payload and FCS field. + */ + dev->needed_tailroom = IEEE802154_MAX_AUTH_TAG_LEN + + IEEE802154_FCS_LEN; dev->mtu = IEEE802154_MTU; dev->tx_queue_len = 300; dev->flags = IFF_NOARP | IFF_BROADCAST; @@ -617,7 +627,8 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, if (!ndev) return ERR_PTR(-ENOMEM); - ndev->needed_headroom = local->hw.extra_tx_headroom; + ndev->needed_headroom = local->hw.extra_tx_headroom + + IEEE802154_MAX_HEADER_LEN; ret = dev_alloc_name(ndev, ndev->name); if (ret < 0) diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index 7ed439172f30..66d7ecb7c56b 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c @@ -77,9 +77,6 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb) put_unaligned_le16(crc, skb_put(skb, 2)); } - if (skb_cow_head(skb, local->hw.extra_tx_headroom)) - goto err_tx; - /* Stop the netif queue on each sub_if_data object. */ ieee802154_stop_queue(&local->hw); -- cgit v1.3-6-gb490 From 79750ac4257763ff595a8b2cdc7ba580f0b0c8e0 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:33 +0200 Subject: ieee802154: add helpers for frame control checks This patch introduce two static inline functions. The first to get the frame control field from an sk_buff. The second is for checking on the acknowledgment request bit on the frame control field. Later we can introduce more functions to check on the frame control fields. These will deprecate the current behaviour which requires a host-byteorder conversion and manually bit handling. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 205ce4e1ac32..aca228b81464 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -25,6 +25,8 @@ #include #include +#include +#include #include #define IEEE802154_MTU 127 @@ -218,6 +220,7 @@ enum { /* frame control handling */ #define IEEE802154_FCTL_FTYPE 0x0003 +#define IEEE802154_FCTL_ACKREQ 0x0020 #define IEEE802154_FCTL_INTRA_PAN 0x0040 #define IEEE802154_FTYPE_DATA 0x0001 @@ -232,6 +235,15 @@ static inline int ieee802154_is_data(__le16 fc) cpu_to_le16(IEEE802154_FTYPE_DATA); } +/** + * ieee802154_is_ackreq - check if acknowledgment request bit is set + * @fc: frame control bytes in little-endian byteorder + */ +static inline bool ieee802154_is_ackreq(__le16 fc) +{ + return fc & cpu_to_le16(IEEE802154_FCTL_ACKREQ); +} + /** * ieee802154_is_intra_pan - check if intra pan id communication * @fc: frame control bytes in little-endian byteorder -- cgit v1.3-6-gb490 From 7ac8bf9bc9ba82aea763ef30671a34c6a2a39922 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 22 Sep 2015 11:56:04 +0200 Subject: EDAC: Carve out debugfs functionality ... into a separate compilation unit and drop a couple of CONFIG_EDAC_DEBUG ifdefferies. Rename edac_create_debug_nodes() to edac_create_debugfs_nodes(), while at it. No functionality change. Cc: Signed-off-by: Borislav Petkov --- drivers/edac/Makefile | 2 + drivers/edac/debugfs.c | 103 ++++++++++++++++++++++++++++++++++++++++ drivers/edac/edac_core.h | 2 + drivers/edac/edac_mc_sysfs.c | 110 +------------------------------------------ drivers/edac/edac_module.h | 2 + include/linux/edac.h | 2 - 6 files changed, 110 insertions(+), 111 deletions(-) create mode 100644 drivers/edac/debugfs.c (limited to 'include') diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index ae3c5f3ce405..dbf53e08bdd1 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -12,6 +12,8 @@ obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_core-y += edac_module.o edac_device_sysfs.o +edac_core-$(CONFIG_EDAC_DEBUG) += debugfs.o + ifdef CONFIG_PCI edac_core-y += edac_pci.o edac_pci_sysfs.o endif diff --git a/drivers/edac/debugfs.c b/drivers/edac/debugfs.c new file mode 100644 index 000000000000..bcd558d5cb48 --- /dev/null +++ b/drivers/edac/debugfs.c @@ -0,0 +1,103 @@ +#include "edac_module.h" + +static struct dentry *edac_debugfs; + +static ssize_t edac_fake_inject_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) +{ + struct device *dev = file->private_data; + struct mem_ctl_info *mci = to_mci(dev); + static enum hw_event_mc_err_type type; + u16 errcount = mci->fake_inject_count; + + if (!errcount) + errcount = 1; + + type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED + : HW_EVENT_ERR_CORRECTED; + + printk(KERN_DEBUG + "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n", + errcount, + (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE", + errcount > 1 ? "s" : "", + mci->fake_inject_layer[0], + mci->fake_inject_layer[1], + mci->fake_inject_layer[2] + ); + edac_mc_handle_error(type, mci, errcount, 0, 0, 0, + mci->fake_inject_layer[0], + mci->fake_inject_layer[1], + mci->fake_inject_layer[2], + "FAKE ERROR", "for EDAC testing only"); + + return count; +} + +static const struct file_operations debug_fake_inject_fops = { + .open = simple_open, + .write = edac_fake_inject_write, + .llseek = generic_file_llseek, +}; + +int __init edac_debugfs_init(void) +{ + edac_debugfs = debugfs_create_dir("edac", NULL); + if (IS_ERR(edac_debugfs)) { + edac_debugfs = NULL; + return -ENOMEM; + } + return 0; +} + +void edac_debugfs_exit(void) +{ + debugfs_remove(edac_debugfs); +} + +int edac_create_debugfs_nodes(struct mem_ctl_info *mci) +{ + struct dentry *d, *parent; + char name[80]; + int i; + + if (!edac_debugfs) + return -ENODEV; + + d = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs); + if (!d) + return -ENOMEM; + parent = d; + + for (i = 0; i < mci->n_layers; i++) { + sprintf(name, "fake_inject_%s", + edac_layer_name[mci->layers[i].type]); + d = debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_layer[i]); + if (!d) + goto nomem; + } + + d = debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_ue); + if (!d) + goto nomem; + + d = debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_count); + if (!d) + goto nomem; + + d = debugfs_create_file("fake_inject", S_IWUSR, parent, + &mci->dev, + &debug_fake_inject_fops); + if (!d) + goto nomem; + + mci->debugfs = parent; + return 0; +nomem: + debugfs_remove(mci->debugfs); + return -ENOMEM; +} diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index ad42587c3f4d..4861542163d7 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -94,6 +94,8 @@ do { \ #define edac_dev_name(dev) (dev)->dev_name +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) + /* * The following are the structures to provide for a generic * or abstract 'edac_device'. This set of structures and the diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 33df7d93c857..071f7fca5ff5 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -785,47 +785,6 @@ static ssize_t mci_max_location_show(struct device *dev, return p - data; } -#ifdef CONFIG_EDAC_DEBUG -static ssize_t edac_fake_inject_write(struct file *file, - const char __user *data, - size_t count, loff_t *ppos) -{ - struct device *dev = file->private_data; - struct mem_ctl_info *mci = to_mci(dev); - static enum hw_event_mc_err_type type; - u16 errcount = mci->fake_inject_count; - - if (!errcount) - errcount = 1; - - type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED - : HW_EVENT_ERR_CORRECTED; - - printk(KERN_DEBUG - "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n", - errcount, - (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE", - errcount > 1 ? "s" : "", - mci->fake_inject_layer[0], - mci->fake_inject_layer[1], - mci->fake_inject_layer[2] - ); - edac_mc_handle_error(type, mci, errcount, 0, 0, 0, - mci->fake_inject_layer[0], - mci->fake_inject_layer[1], - mci->fake_inject_layer[2], - "FAKE ERROR", "for EDAC testing only"); - - return count; -} - -static const struct file_operations debug_fake_inject_fops = { - .open = simple_open, - .write = edac_fake_inject_write, - .llseek = generic_file_llseek, -}; -#endif - /* default Control file */ static DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); @@ -896,71 +855,6 @@ static struct device_type mci_attr_type = { .release = mci_attr_release, }; -#ifdef CONFIG_EDAC_DEBUG -static struct dentry *edac_debugfs; - -int __init edac_debugfs_init(void) -{ - edac_debugfs = debugfs_create_dir("edac", NULL); - if (IS_ERR(edac_debugfs)) { - edac_debugfs = NULL; - return -ENOMEM; - } - return 0; -} - -void edac_debugfs_exit(void) -{ - debugfs_remove(edac_debugfs); -} - -static int edac_create_debug_nodes(struct mem_ctl_info *mci) -{ - struct dentry *d, *parent; - char name[80]; - int i; - - if (!edac_debugfs) - return -ENODEV; - - d = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs); - if (!d) - return -ENOMEM; - parent = d; - - for (i = 0; i < mci->n_layers; i++) { - sprintf(name, "fake_inject_%s", - edac_layer_name[mci->layers[i].type]); - d = debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent, - &mci->fake_inject_layer[i]); - if (!d) - goto nomem; - } - - d = debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent, - &mci->fake_inject_ue); - if (!d) - goto nomem; - - d = debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent, - &mci->fake_inject_count); - if (!d) - goto nomem; - - d = debugfs_create_file("fake_inject", S_IWUSR, parent, - &mci->dev, - &debug_fake_inject_fops); - if (!d) - goto nomem; - - mci->debugfs = parent; - return 0; -nomem: - debugfs_remove(mci->debugfs); - return -ENOMEM; -} -#endif - /* * Create a new Memory Controller kobject instance, * mc under the 'mc' directory @@ -1039,9 +933,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, goto fail_unregister_dimm; #endif -#ifdef CONFIG_EDAC_DEBUG - edac_create_debug_nodes(mci); -#endif + edac_create_debugfs_nodes(mci); return 0; fail_unregister_dimm: diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 26ecc52e073d..79a6c6e20819 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -63,12 +63,14 @@ extern void *edac_align_ptr(void **p, unsigned size, int n_elems); #ifdef CONFIG_EDAC_DEBUG int edac_debugfs_init(void); void edac_debugfs_exit(void); +int edac_create_debugfs_nodes(struct mem_ctl_info *mci); #else static inline int edac_debugfs_init(void) { return -ENODEV; } static inline void edac_debugfs_exit(void) {} +static inline int edac_create_debugfs_nodes(struct mem_ctl_info *mci) { return 0; } #endif /* diff --git a/include/linux/edac.h b/include/linux/edac.h index da3b72e95db3..b3d87e5822f8 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -769,12 +769,10 @@ struct mem_ctl_info { /* the internal state of this controller instance */ int op_state; -#ifdef CONFIG_EDAC_DEBUG struct dentry *debugfs; u8 fake_inject_layer[EDAC_MAX_LAYERS]; u32 fake_inject_ue; u16 fake_inject_count; -#endif }; /* -- cgit v1.3-6-gb490 From 2a1d3ab8986d1b2f598ffc42351d94166fa0f022 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 21 Sep 2015 11:01:10 +0200 Subject: genirq: Handle force threading of irqs with primary and thread handler Force threading of interrupts does not really deal with interrupts which are requested with a primary and a threaded handler. The current policy is to leave them alone and let the primary handler run in interrupt context, but we set the ONESHOT flag for those interrupts as well. Kohji Okuno debugged a problem with the SDHCI driver where the interrupt thread waits for a hardware interrupt to trigger, which can't work well because the hardware interrupt is masked due to the ONESHOT flag being set. He proposed to set the ONESHOT flag only if the interrupt does not provide a thread handler. Though that does not work either because these interrupts can be shared. So the other interrupt would rightfully get the ONESHOT flag set and therefor the same situation would happen again. To deal with this proper, we need to force thread the primary handler of such interrupts as well. That means that the primary interrupt handler is treated as any other primary interrupt handler which is not marked IRQF_NO_THREAD. The threaded handler becomes a separate thread so the SDHCI flow logic can be handled gracefully. The same issue was reported against 4.1-rt. Reported-and-tested-by: Kohji Okuno Reported-By: Michal Smucr Reported-and-tested-by: Nathan Sullivan Signed-off-by: Thomas Gleixner Cc: Sebastian Andrzej Siewior Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1509211058080.5606@nanos Signed-off-by: Thomas Gleixner --- include/linux/interrupt.h | 2 + kernel/irq/manage.c | 158 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 119 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index be7e75c945e9..ad16809c8596 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -102,6 +102,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); * @flags: flags (see IRQF_* above) * @thread_fn: interrupt handler function for threaded interrupts * @thread: thread pointer for threaded interrupts + * @secondary: pointer to secondary irqaction (force threading) * @thread_flags: flags related to @thread * @thread_mask: bitmask for keeping track of @thread activity * @dir: pointer to the proc/irq/NN/name entry @@ -113,6 +114,7 @@ struct irqaction { struct irqaction *next; irq_handler_t thread_fn; struct task_struct *thread; + struct irqaction *secondary; unsigned int irq; unsigned int flags; unsigned long thread_flags; diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f9a59f6cabd2..0a63c2b20bdd 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -730,6 +730,12 @@ static irqreturn_t irq_nested_primary_handler(int irq, void *dev_id) return IRQ_NONE; } +static irqreturn_t irq_forced_secondary_handler(int irq, void *dev_id) +{ + WARN(1, "Secondary action handler called for irq %d\n", irq); + return IRQ_NONE; +} + static int irq_wait_for_interrupt(struct irqaction *action) { set_current_state(TASK_INTERRUPTIBLE); @@ -756,7 +762,8 @@ static int irq_wait_for_interrupt(struct irqaction *action) static void irq_finalize_oneshot(struct irq_desc *desc, struct irqaction *action) { - if (!(desc->istate & IRQS_ONESHOT)) + if (!(desc->istate & IRQS_ONESHOT) || + action->handler == irq_forced_secondary_handler) return; again: chip_bus_lock(desc); @@ -910,6 +917,18 @@ static void irq_thread_dtor(struct callback_head *unused) irq_finalize_oneshot(desc, action); } +static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action) +{ + struct irqaction *secondary = action->secondary; + + if (WARN_ON_ONCE(!secondary)) + return; + + raw_spin_lock_irq(&desc->lock); + __irq_wake_thread(desc, secondary); + raw_spin_unlock_irq(&desc->lock); +} + /* * Interrupt handler thread */ @@ -940,6 +959,8 @@ static int irq_thread(void *data) action_ret = handler_fn(desc, action); if (action_ret == IRQ_HANDLED) atomic_inc(&desc->threads_handled); + if (action_ret == IRQ_WAKE_THREAD) + irq_wake_secondary(desc, action); wake_threads_waitq(desc); } @@ -984,20 +1005,36 @@ void irq_wake_thread(unsigned int irq, void *dev_id) } EXPORT_SYMBOL_GPL(irq_wake_thread); -static void irq_setup_forced_threading(struct irqaction *new) +static int irq_setup_forced_threading(struct irqaction *new) { if (!force_irqthreads) - return; + return 0; if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT)) - return; + return 0; new->flags |= IRQF_ONESHOT; - if (!new->thread_fn) { - set_bit(IRQTF_FORCED_THREAD, &new->thread_flags); - new->thread_fn = new->handler; - new->handler = irq_default_primary_handler; + /* + * Handle the case where we have a real primary handler and a + * thread handler. We force thread them as well by creating a + * secondary action. + */ + if (new->handler != irq_default_primary_handler && new->thread_fn) { + /* Allocate the secondary action */ + new->secondary = kzalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!new->secondary) + return -ENOMEM; + new->secondary->handler = irq_forced_secondary_handler; + new->secondary->thread_fn = new->thread_fn; + new->secondary->dev_id = new->dev_id; + new->secondary->irq = new->irq; + new->secondary->name = new->name; } + /* Deal with the primary handler */ + set_bit(IRQTF_FORCED_THREAD, &new->thread_flags); + new->thread_fn = new->handler; + new->handler = irq_default_primary_handler; + return 0; } static int irq_request_resources(struct irq_desc *desc) @@ -1017,6 +1054,48 @@ static void irq_release_resources(struct irq_desc *desc) c->irq_release_resources(d); } +static int +setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary) +{ + struct task_struct *t; + struct sched_param param = { + .sched_priority = MAX_USER_RT_PRIO/2, + }; + + if (!secondary) { + t = kthread_create(irq_thread, new, "irq/%d-%s", irq, + new->name); + } else { + t = kthread_create(irq_thread, new, "irq/%d-s-%s", irq, + new->name); + param.sched_priority -= 1; + } + + if (IS_ERR(t)) + return PTR_ERR(t); + + sched_setscheduler_nocheck(t, SCHED_FIFO, ¶m); + + /* + * We keep the reference to the task struct even if + * the thread dies to avoid that the interrupt code + * references an already freed task_struct. + */ + get_task_struct(t); + new->thread = t; + /* + * Tell the thread to set its affinity. This is + * important for shared interrupt handlers as we do + * not invoke setup_affinity() for the secondary + * handlers as everything is already set up. Even for + * interrupts marked with IRQF_NO_BALANCE this is + * correct as we want the thread to move to the cpu(s) + * on which the requesting code placed the interrupt. + */ + set_bit(IRQTF_AFFINITY, &new->thread_flags); + return 0; +} + /* * Internal function to register an irqaction - typically used to * allocate special interrupts that are part of the architecture. @@ -1037,6 +1116,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) if (!try_module_get(desc->owner)) return -ENODEV; + new->irq = irq; + /* * Check whether the interrupt nests into another interrupt * thread. @@ -1054,8 +1135,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) */ new->handler = irq_nested_primary_handler; } else { - if (irq_settings_can_thread(desc)) - irq_setup_forced_threading(new); + if (irq_settings_can_thread(desc)) { + ret = irq_setup_forced_threading(new); + if (ret) + goto out_mput; + } } /* @@ -1064,37 +1148,14 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) * thread. */ if (new->thread_fn && !nested) { - struct task_struct *t; - static const struct sched_param param = { - .sched_priority = MAX_USER_RT_PRIO/2, - }; - - t = kthread_create(irq_thread, new, "irq/%d-%s", irq, - new->name); - if (IS_ERR(t)) { - ret = PTR_ERR(t); + ret = setup_irq_thread(new, irq, false); + if (ret) goto out_mput; + if (new->secondary) { + ret = setup_irq_thread(new->secondary, irq, true); + if (ret) + goto out_thread; } - - sched_setscheduler_nocheck(t, SCHED_FIFO, ¶m); - - /* - * We keep the reference to the task struct even if - * the thread dies to avoid that the interrupt code - * references an already freed task_struct. - */ - get_task_struct(t); - new->thread = t; - /* - * Tell the thread to set its affinity. This is - * important for shared interrupt handlers as we do - * not invoke setup_affinity() for the secondary - * handlers as everything is already set up. Even for - * interrupts marked with IRQF_NO_BALANCE this is - * correct as we want the thread to move to the cpu(s) - * on which the requesting code placed the interrupt. - */ - set_bit(IRQTF_AFFINITY, &new->thread_flags); } if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { @@ -1267,7 +1328,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) irq, nmsk, omsk); } - new->irq = irq; *old_ptr = new; irq_pm_install_action(desc, new); @@ -1293,6 +1353,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) */ if (new->thread) wake_up_process(new->thread); + if (new->secondary) + wake_up_process(new->secondary->thread); register_irq_proc(irq, desc); new->dir = NULL; @@ -1323,6 +1385,13 @@ out_thread: kthread_stop(t); put_task_struct(t); } + if (new->secondary && new->secondary->thread) { + struct task_struct *t = new->secondary->thread; + + new->secondary->thread = NULL; + kthread_stop(t); + put_task_struct(t); + } out_mput: module_put(desc->owner); return ret; @@ -1430,9 +1499,14 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) if (action->thread) { kthread_stop(action->thread); put_task_struct(action->thread); + if (action->secondary && action->secondary->thread) { + kthread_stop(action->secondary->thread); + put_task_struct(action->secondary->thread); + } } module_put(desc->owner); + kfree(action->secondary); return action; } @@ -1576,8 +1650,10 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, retval = __setup_irq(irq, desc, action); chip_bus_sync_unlock(desc); - if (retval) + if (retval) { + kfree(action->secondary); kfree(action); + } #ifdef CONFIG_DEBUG_SHIRQ_FIXME if (!retval && (irqflags & IRQF_SHARED)) { -- cgit v1.3-6-gb490 From 69fb4dcada7704beeba86e3f401a66c726aa8504 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 1 Aug 2015 10:39:38 +0200 Subject: power: Add an axp20x-usb-power driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a driver for the usb power_supply bits of the axp20x PMICs. I initially started writing my own driver, before coming aware of Bruno Prémont's excellent earlier RFC with a driver for this. My driver was lacking CURRENT_MAX and VOLTAGE_MIN support Bruno's drvier has, so I've copied the code for those from his driver. Note that the AC-power-supply and battery charger bits will need separate drivers. Each one needs its own devictree child-node so that other devicetree nodes can reference the right power-supply, and thus each one will get its own mfd-cell / platform_device and platform-driver. Cc: Bruno Prémont Acked-by: Lee Jones Signed-off-by: Bruno Prémont Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/Kconfig | 7 ++ drivers/power/Makefile | 1 + drivers/power/axp20x_usb_power.c | 248 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/axp20x.h | 24 ++++ 4 files changed, 280 insertions(+) create mode 100644 drivers/power/axp20x_usb_power.c (limited to 'include') diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f8758d6febf8..914167e14d2e 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -472,6 +472,13 @@ config CHARGER_RT9455 help Say Y to enable support for Richtek RT9455 battery charger. +config AXP20X_POWER + tristate "AXP20x power supply driver" + depends on MFD_AXP20X + help + This driver provides support for the power supply features of + AXP20x PMIC. + source "drivers/power/reset/Kconfig" endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 5752ce818f51..fb4413e5dd37 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o obj-$(CONFIG_PDA_POWER) += pda_power.o obj-$(CONFIG_APM_POWER) += apm_power.o +obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o obj-$(CONFIG_MAX8925_POWER) += max8925_power.o obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o obj-$(CONFIG_WM831X_POWER) += wm831x_power.o diff --git a/drivers/power/axp20x_usb_power.c b/drivers/power/axp20x_usb_power.c new file mode 100644 index 000000000000..421a90b83567 --- /dev/null +++ b/drivers/power/axp20x_usb_power.c @@ -0,0 +1,248 @@ +/* + * AXP20x PMIC USB power supply status driver + * + * Copyright (C) 2015 Hans de Goede + * Copyright (C) 2014 Bruno Prémont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "axp20x-usb-power-supply" + +#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5) +#define AXP20X_PWR_STATUS_VBUS_USED BIT(4) + +#define AXP20X_USB_STATUS_VBUS_VALID BIT(2) + +#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000) +#define AXP20X_VBUS_CLIMIT_MASK 3 +#define AXP20X_VBUC_CLIMIT_900mA 0 +#define AXP20X_VBUC_CLIMIT_500mA 1 +#define AXP20X_VBUC_CLIMIT_100mA 2 +#define AXP20X_VBUC_CLIMIT_NONE 3 + +#define AXP20X_ADC_EN1_VBUS_CURR BIT(2) +#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3) + +#define AXP20X_VBUS_MON_VBUS_VALID BIT(3) + +struct axp20x_usb_power { + struct regmap *regmap; + struct power_supply *supply; +}; + +static irqreturn_t axp20x_usb_power_irq(int irq, void *devid) +{ + struct axp20x_usb_power *power = devid; + + power_supply_changed(power->supply); + + return IRQ_HANDLED; +} + +static int axp20x_usb_power_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct axp20x_usb_power *power = power_supply_get_drvdata(psy); + unsigned int input, v; + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); + if (ret) + return ret; + + val->intval = AXP20X_VBUS_VHOLD_uV(v); + return 0; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret = axp20x_read_variable_width(power->regmap, + AXP20X_VBUS_V_ADC_H, 12); + if (ret < 0) + return ret; + + val->intval = ret * 1700; /* 1 step = 1.7 mV */ + return 0; + case POWER_SUPPLY_PROP_CURRENT_MAX: + ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); + if (ret) + return ret; + + switch (v & AXP20X_VBUS_CLIMIT_MASK) { + case AXP20X_VBUC_CLIMIT_100mA: + val->intval = 100000; + break; + case AXP20X_VBUC_CLIMIT_500mA: + val->intval = 500000; + break; + case AXP20X_VBUC_CLIMIT_900mA: + val->intval = 900000; + break; + case AXP20X_VBUC_CLIMIT_NONE: + val->intval = -1; + break; + } + return 0; + case POWER_SUPPLY_PROP_CURRENT_NOW: + ret = axp20x_read_variable_width(power->regmap, + AXP20X_VBUS_I_ADC_H, 12); + if (ret < 0) + return ret; + + val->intval = ret * 375; /* 1 step = 0.375 mA */ + return 0; + default: + break; + } + + /* All the properties below need the input-status reg value */ + ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_HEALTH: + if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) { + val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; + break; + } + + ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v); + if (ret) + return ret; + + if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) { + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + break; + } + + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT); + break; + case POWER_SUPPLY_PROP_ONLINE: + val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED); + break; + default: + return -EINVAL; + } + + return 0; +} + +static enum power_supply_property axp20x_usb_power_properties[] = { + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, +}; + +static const struct power_supply_desc axp20x_usb_power_desc = { + .name = "axp20x-usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = axp20x_usb_power_properties, + .num_properties = ARRAY_SIZE(axp20x_usb_power_properties), + .get_property = axp20x_usb_power_get_property, +}; + +static int axp20x_usb_power_probe(struct platform_device *pdev) +{ + struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); + struct power_supply_config psy_cfg = {}; + struct axp20x_usb_power *power; + static const char * const irq_names[] = { "VBUS_PLUGIN", + "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" }; + int i, irq, ret; + + if (!of_device_is_available(pdev->dev.of_node)) + return -ENODEV; + + if (!axp20x) { + dev_err(&pdev->dev, "Parent drvdata not set\n"); + return -EINVAL; + } + + power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL); + if (!power) + return -ENOMEM; + + power->regmap = axp20x->regmap; + + /* Enable vbus valid checking */ + ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON, + AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID); + if (ret) + return ret; + + /* Enable vbus voltage and current measurement */ + ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1, + AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT, + AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT); + if (ret) + return ret; + + psy_cfg.of_node = pdev->dev.of_node; + psy_cfg.drv_data = power; + + power->supply = devm_power_supply_register(&pdev->dev, + &axp20x_usb_power_desc, &psy_cfg); + if (IS_ERR(power->supply)) + return PTR_ERR(power->supply); + + /* Request irqs after registering, as irqs may trigger immediately */ + for (i = 0; i < ARRAY_SIZE(irq_names); i++) { + irq = platform_get_irq_byname(pdev, irq_names[i]); + if (irq < 0) { + dev_warn(&pdev->dev, "No IRQ for %s: %d\n", + irq_names[i], irq); + continue; + } + irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq); + ret = devm_request_any_context_irq(&pdev->dev, irq, + axp20x_usb_power_irq, 0, DRVNAME, power); + if (ret < 0) + dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n", + irq_names[i], ret); + } + + return 0; +} + +static const struct of_device_id axp20x_usb_power_match[] = { + { .compatible = "x-powers,axp202-usb-power-supply" }, + { } +}; +MODULE_DEVICE_TABLE(of, axp20x_usb_power_match); + +static struct platform_driver axp20x_usb_power_driver = { + .probe = axp20x_usb_power_probe, + .driver = { + .name = DRVNAME, + .of_match_table = axp20x_usb_power_match, + }, +}; + +module_platform_driver(axp20x_usb_power_driver); + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index cc8ad1e1a307..b24c771cebd5 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -11,6 +11,8 @@ #ifndef __LINUX_MFD_AXP20X_H #define __LINUX_MFD_AXP20X_H +#include + enum { AXP152_ID = 0, AXP202_ID, @@ -438,4 +440,26 @@ struct axp288_extcon_pdata { struct gpio_desc *gpio_mux_cntl; }; +/* generic helper function for reading 9-16 bit wide regs */ +static inline int axp20x_read_variable_width(struct regmap *regmap, + unsigned int reg, unsigned int width) +{ + unsigned int reg_val, result; + int err; + + err = regmap_read(regmap, reg, ®_val); + if (err) + return err; + + result = reg_val << (width - 8); + + err = regmap_read(regmap, reg + 1, ®_val); + if (err) + return err; + + result |= reg_val; + + return result; +} + #endif /* __LINUX_MFD_AXP20X_H */ -- cgit v1.3-6-gb490 From 7bdbe400d1b2aac116513f90b75969ad2365fba6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 15 Aug 2015 22:39:49 +0300 Subject: nl80211: support vendor dumpit commands In order to transfer many items in vendor commands, support the dumpit netlink method for them. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 9 +++ net/wireless/nl80211.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) (limited to 'include') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f0889a247643..0f54c9ef4c7d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2971,12 +2971,21 @@ enum wiphy_vendor_command_flags { * @doit: callback for the operation, note that wdev is %NULL if the * flags didn't ask for a wdev and non-%NULL otherwise; the data * pointer may be %NULL if userspace provided no data at all + * @dumpit: dump callback, for transferring bigger/multiple items. The + * @storage points to cb->args[5], ie. is preserved over the multiple + * dumpit calls. + * It's recommended to not have the same sub command with both @doit and + * @dumpit, so that userspace can assume certain ones are get and others + * are used with dump requests. */ struct wiphy_vendor_command { struct nl80211_vendor_cmd_info info; u32 flags; int (*doit)(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + int (*dumpit)(struct wiphy *wiphy, struct wireless_dev *wdev, + struct sk_buff *skb, const void *data, int data_len, + unsigned long *storage); }; /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5d8748b4c8a2..a4e6c951950f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3,6 +3,7 @@ * * Copyright 2006-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2015 Intel Deutschland GmbH */ #include @@ -9938,6 +9939,9 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info) if (!wdev->netdev && !wdev->p2p_started) return -ENETDOWN; } + + if (!vcmd->doit) + return -EOPNOTSUPP; } else { wdev = NULL; } @@ -9957,6 +9961,193 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info) return -EOPNOTSUPP; } +static int nl80211_prepare_vendor_dump(struct sk_buff *skb, + struct netlink_callback *cb, + struct cfg80211_registered_device **rdev, + struct wireless_dev **wdev) +{ + u32 vid, subcmd; + unsigned int i; + int vcmd_idx = -1; + int err; + void *data = NULL; + unsigned int data_len = 0; + + rtnl_lock(); + + if (cb->args[0]) { + /* subtract the 1 again here */ + struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); + struct wireless_dev *tmp; + + if (!wiphy) { + err = -ENODEV; + goto out_unlock; + } + *rdev = wiphy_to_rdev(wiphy); + *wdev = NULL; + + if (cb->args[1]) { + list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { + if (tmp->identifier == cb->args[1] - 1) { + *wdev = tmp; + break; + } + } + } + + /* keep rtnl locked in successful case */ + return 0; + } + + err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, + nl80211_fam.attrbuf, nl80211_fam.maxattr, + nl80211_policy); + if (err) + goto out_unlock; + + if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] || + !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) { + err = -EINVAL; + goto out_unlock; + } + + *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), + nl80211_fam.attrbuf); + if (IS_ERR(*wdev)) + *wdev = NULL; + + *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), + nl80211_fam.attrbuf); + if (IS_ERR(*rdev)) { + err = PTR_ERR(*rdev); + goto out_unlock; + } + + vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]); + subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]); + + for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) { + const struct wiphy_vendor_command *vcmd; + + vcmd = &(*rdev)->wiphy.vendor_commands[i]; + + if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) + continue; + + if (!vcmd->dumpit) { + err = -EOPNOTSUPP; + goto out_unlock; + } + + vcmd_idx = i; + break; + } + + if (vcmd_idx < 0) { + err = -EOPNOTSUPP; + goto out_unlock; + } + + if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) { + data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]); + data_len = nla_len(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]); + } + + /* 0 is the first index - add 1 to parse only once */ + cb->args[0] = (*rdev)->wiphy_idx + 1; + /* add 1 to know if it was NULL */ + cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0; + cb->args[2] = vcmd_idx; + cb->args[3] = (unsigned long)data; + cb->args[4] = data_len; + + /* keep rtnl locked in successful case */ + return 0; + out_unlock: + rtnl_unlock(); + return err; +} + +static int nl80211_vendor_cmd_dump(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + unsigned int vcmd_idx; + const struct wiphy_vendor_command *vcmd; + void *data; + int data_len; + int err; + struct nlattr *vendor_data; + + err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev); + if (err) + return err; + + vcmd_idx = cb->args[2]; + data = (void *)cb->args[3]; + data_len = cb->args[4]; + vcmd = &rdev->wiphy.vendor_commands[vcmd_idx]; + + if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV)) { + if (!wdev) + return -EINVAL; + if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && + !wdev->netdev) + return -EINVAL; + + if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { + if (wdev->netdev && + !netif_running(wdev->netdev)) + return -ENETDOWN; + if (!wdev->netdev && !wdev->p2p_started) + return -ENETDOWN; + } + } + + while (1) { + void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, + NL80211_CMD_VENDOR); + if (!hdr) + break; + + if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + (wdev && nla_put_u64(skb, NL80211_ATTR_WDEV, + wdev_id(wdev)))) { + genlmsg_cancel(skb, hdr); + break; + } + + vendor_data = nla_nest_start(skb, NL80211_ATTR_VENDOR_DATA); + if (!vendor_data) { + genlmsg_cancel(skb, hdr); + break; + } + + err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len, + (unsigned long *)&cb->args[5]); + nla_nest_end(skb, vendor_data); + + if (err == -ENOBUFS || err == -ENOENT) { + genlmsg_cancel(skb, hdr); + break; + } else if (err) { + genlmsg_cancel(skb, hdr); + goto out; + } + + genlmsg_end(skb, hdr); + } + + err = skb->len; + out: + rtnl_unlock(); + return err; +} + struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy, enum nl80211_commands cmd, enum nl80211_attrs attr, @@ -10994,6 +11185,7 @@ static const struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_VENDOR, .doit = nl80211_vendor_cmd, + .dumpit = nl80211_vendor_cmd_dump, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, .internal_flags = NL80211_FLAG_NEED_WIPHY | -- cgit v1.3-6-gb490 From 1b09b5568e5f46c6dfb781d7c1dfad431a6d8ec1 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Sat, 15 Aug 2015 22:39:50 +0300 Subject: mac80211: introduce per vif frame registration API Currently the cfg80211's frame registration api receives wdev, however mac80211 assumes per device filter configuration and ignores wdev. Per device filtering is too wasteful, especially for multi-channel devices. Introduce new per vif frame registration API and use it for probe request registrations in ieee80211_mgmt_frame_register() Also call directly to ieee80211_configure_filter instead of using a work since it is now allowed to sleep in ieee80211_mgmt_frame_register. Signed-off-by: Andrei Otcheretianski Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/mac80211.h | 16 ++++++++++++++++ net/mac80211/cfg.c | 22 ++++++++++++++++++---- net/mac80211/driver-ops.h | 16 ++++++++++++++++ net/mac80211/trace.h | 30 ++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e3314e516681..167864503138 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -5,6 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 Intel Deutschland GmbH * * 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 @@ -1358,6 +1359,8 @@ enum ieee80211_vif_flags { * @debugfs_dir: debugfs dentry, can be used by drivers to create own per * interface debug files. Note that it will be NULL for the virtual * monitor interface (if that is requested.) + * @probe_req_reg: probe requests should be reported to mac80211 for this + * interface. * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *). * @txq: the multicast data TX queue (if driver uses the TXQ abstraction) @@ -1382,6 +1385,8 @@ struct ieee80211_vif { struct dentry *debugfs_dir; #endif + unsigned int probe_req_reg; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; @@ -2825,6 +2830,13 @@ enum ieee80211_reconfig_type { * See the section "Frame filtering" for more information. * This callback must be implemented and can sleep. * + * @config_iface_filter: Configure the interface's RX filter. + * This callback is optional and is used to configure which frames + * should be passed to mac80211. The filter_flags is the combination + * of FIF_* flags. The changed_flags is a bit mask that indicates + * which flags are changed. + * This callback can sleep. + * * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit * must be set or cleared for a given STA. Must be atomic. * @@ -3264,6 +3276,10 @@ struct ieee80211_ops { unsigned int changed_flags, unsigned int *total_flags, u64 multicast); + void (*config_iface_filter)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + unsigned int filter_flags, + unsigned int changed_flags); int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1ca972e5418b..9eab783701aa 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3516,18 +3516,32 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, u16 frame_type, bool reg) { struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); switch (frame_type) { case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: - if (reg) + if (reg) { local->probe_req_reg++; - else - local->probe_req_reg--; + sdata->vif.probe_req_reg++; + } else { + if (local->probe_req_reg) + local->probe_req_reg--; + + if (sdata->vif.probe_req_reg) + sdata->vif.probe_req_reg--; + } if (!local->open_count) break; - ieee80211_queue_work(&local->hw, &local->reconfig_filter); + if (sdata->vif.probe_req_reg == 1) + drv_config_iface_filter(local, sdata, FIF_PROBE_REQ, + FIF_PROBE_REQ); + else if (sdata->vif.probe_req_reg == 0) + drv_config_iface_filter(local, sdata, 0, + FIF_PROBE_REQ); + + ieee80211_configure_filter(local); break; default: break; diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 02d91332d7dd..157b20baf752 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -260,6 +260,22 @@ static inline void drv_configure_filter(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline void drv_config_iface_filter(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + unsigned int filter_flags, + unsigned int changed_flags) +{ + might_sleep(); + + trace_drv_config_iface_filter(local, sdata, filter_flags, + changed_flags); + if (local->ops->config_iface_filter) + local->ops->config_iface_filter(&local->hw, &sdata->vif, + filter_flags, + changed_flags); + trace_drv_return_void(local); +} + static inline int drv_set_tim(struct ieee80211_local *local, struct ieee80211_sta *sta, bool set) { diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 6f14591d8ca9..b5960b948f60 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -497,6 +497,36 @@ TRACE_EVENT(drv_configure_filter, ) ); +TRACE_EVENT(drv_config_iface_filter, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + unsigned int filter_flags, + unsigned int changed_flags), + + TP_ARGS(local, sdata, filter_flags, changed_flags), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __field(unsigned int, filter_flags) + __field(unsigned int, changed_flags) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + __entry->filter_flags = filter_flags; + __entry->changed_flags = changed_flags; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT + " filter_flags: %#x changed_flags: %#x", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->filter_flags, + __entry->changed_flags + ) +); + TRACE_EVENT(drv_set_tim, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta, bool set), -- cgit v1.3-6-gb490 From e3abc8ff0fc18b3925fd5d5c5fbd1613856f4e7c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 16 Aug 2015 11:13:22 +0300 Subject: mac80211: allow to transmit A-MSDU within A-MPDU Advertise the capability to send A-MSDU within A-MPDU in the AddBA request sent by mac80211. Let the driver know about the peer's capabilities. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 2 +- drivers/net/wireless/ath/carl9170/main.c | 2 +- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 2 +- drivers/net/wireless/cw1200/sta.c | 2 +- drivers/net/wireless/cw1200/sta.h | 2 +- drivers/net/wireless/iwlegacy/4965-mac.c | 2 +- drivers/net/wireless/iwlegacy/4965.h | 2 +- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/mediatek/mt7601u/main.c | 3 ++- drivers/net/wireless/mwl8k.c | 2 +- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 4 +++- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2800lib.h | 2 +- drivers/net/wireless/rtlwifi/core.c | 2 +- drivers/net/wireless/ti/wlcore/main.c | 2 +- include/linux/ieee80211.h | 1 + include/net/mac80211.h | 5 ++++- net/mac80211/agg-rx.c | 4 ++-- net/mac80211/agg-tx.c | 15 ++++++++++----- net/mac80211/driver-ops.h | 7 ++++--- net/mac80211/sta_info.h | 2 ++ net/mac80211/trace.h | 10 ++++++---- 27 files changed, 52 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 64674c955d44..b04e7694c105 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6144,7 +6144,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 172a9ff4aaab..a680a970b7f7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1659,7 +1659,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c27143ba9ffb..323eb33c3c6e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1856,7 +1856,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 170c209f99b8..19d3d64416bf 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1415,7 +1415,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 900e72a089d8..7c169abdbafe 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -859,7 +859,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index d2c5747e3ac9..bec2dc1ca2e4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -820,7 +820,7 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index b86500b4418f..95a7fdb3cc1c 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c @@ -2137,7 +2137,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { /* Aggregation is implemented fully in firmware, * including block ack negotiation. Do not allow diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h index b7e386b7662b..bebb3379017f 100644 --- a/drivers/net/wireless/cw1200/sta.h +++ b/drivers/net/wireless/cw1200/sta.h @@ -111,7 +111,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 44fa422f255e..6656215a13a9 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5984,7 +5984,7 @@ int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct il_priv *il = hw->priv; int ret = -EINVAL; diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 3a57f71b8ed5..8ab8706f9422 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -184,7 +184,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 453f7c315ab5..b3ad34e8bf5a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -731,7 +731,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index aa8c2b7f23c7..f70452c41d63 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -820,7 +820,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size) + u16 *ssn, u8 buf_size, bool amsdu) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 520bef80747f..2af2f3d0cc31 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1819,7 +1819,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index 169384b48b27..f715eee39851 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -335,7 +335,8 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) { struct mt7601u_dev *dev = hw->priv; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9420fc61c2e6..30e3aaae32e2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5423,7 +5423,7 @@ static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { int i, rc = 0; diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 7e804324bfa7..b5bcc933a2a6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -664,6 +664,7 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * @tid: Traffic identifier. * @ssn: Pointer to ssn value. * @buf_size: Buffer size (for kernel version > 2.6.38). + * @amsdu: is AMSDU in AMPDU allowed * * Return: status: 0 on success, negative error code on failure. */ @@ -673,7 +674,8 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_sta *sta, unsigned short tid, unsigned short *ssn, - unsigned char buf_size) + unsigned char buf_size, + bool amsdu) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9524564f873b..9733b31a780d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7937,7 +7937,7 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 1609b8a7f7eb..440790b92b19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -220,7 +220,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 585d0883c7e5..c925a4dff599 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -1373,7 +1373,7 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e819369d8f8f..ec7f6af3fab2 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5263,7 +5263,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index cfa906f28b7a..19eb9ecd6cf3 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1379,6 +1379,7 @@ struct ieee80211_ht_operation { /* block-ack parameters */ +#define IEEE80211_ADDBA_PARAM_AMSDU_MASK 0x0001 #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 167864503138..f28cbc0988eb 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3026,6 +3026,9 @@ enum ieee80211_reconfig_type { * buffer size of 8. Correct ways to retransmit #1 would be: * - TX: 1 or 18 or 81 * Even "189" would be wrong since 1 could be lost again. + * The @amsdu parameter is valid when the action is set to + * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability + * to receive A-MSDU within A-MPDU. * * Returns a negative error code on failure. * The callback can sleep. @@ -3363,7 +3366,7 @@ struct ieee80211_ops { struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int (*get_survey)(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void (*rfkill_poll)(struct ieee80211_hw *hw); diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 5c564a68fb50..6ebe8611eca5 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -79,7 +79,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, (int)reason); if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, - &sta->sta, tid, NULL, 0)) + &sta->sta, tid, NULL, 0, false)) sdata_info(sta->sdata, "HW problem - can not stop rx aggregation for %pM tid %d\n", sta->sta.addr, tid); @@ -321,7 +321,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num, 0); + &sta->sta, tid, &start_seq_num, 0, false); ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", sta->sta.addr, tid, ret); if (ret) { diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c8ba2e77737c..a758eb84e8f0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -97,7 +97,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; mgmt->u.action.u.addba_req.dialog_token = dialog_token; - capab = (u16)(1 << 1); /* bit 1 aggregation policy */ + capab = (u16)(1 << 0); /* bit 0 A-MSDU support */ + capab |= (u16)(1 << 1); /* bit 1 aggregation policy */ capab |= (u16)(tid << 2); /* bit 5:2 TID number */ capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ @@ -331,7 +332,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, return -EALREADY; ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, - &sta->sta, tid, NULL, 0); + &sta->sta, tid, NULL, 0, false); WARN_ON_ONCE(ret); return 0; } @@ -381,7 +382,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; ret = drv_ampdu_action(local, sta->sdata, action, - &sta->sta, tid, NULL, 0); + &sta->sta, tid, NULL, 0, false); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -469,7 +470,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) start_seq_num = sta->tid_seq[tid] >> 4; ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, - &sta->sta, tid, &start_seq_num, 0); + &sta->sta, tid, &start_seq_num, 0, false); if (ret) { ht_dbg(sdata, "BA request denied - HW unavailable for %pM tid %d\n", @@ -693,7 +694,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL, tid_tx->buf_size); + &sta->sta, tid, NULL, tid_tx->buf_size, + tid_tx->amsdu); /* * synchronize with TX path, while splicing the TX path @@ -918,8 +920,10 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, struct tid_ampdu_tx *tid_tx; u16 capab, tid; u8 buf_size; + bool amsdu; capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); + amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; @@ -968,6 +972,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, } tid_tx->buf_size = buf_size; + tid_tx->amsdu = amsdu; if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) ieee80211_agg_tx_operational(local, sta, tid); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 157b20baf752..31482e2cd25f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -734,7 +734,7 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size) + u16 *ssn, u8 buf_size, bool amsdu) { int ret = -EOPNOTSUPP; @@ -744,11 +744,12 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return -EIO; - trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); + trace_drv_ampdu_action(local, sdata, action, sta, tid, + ssn, buf_size, amsdu); if (local->ops->ampdu_action) ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, - sta, tid, ssn, buf_size); + sta, tid, ssn, buf_size, amsdu); trace_drv_return_int(local, ret); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b087c71ff7fe..d5ded8749ac4 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -133,6 +133,7 @@ enum ieee80211_agg_stop_reason { * @buf_size: reorder buffer size at receiver * @failed_bar_ssn: ssn of the last failed BAR tx attempt * @bar_pending: BAR needs to be re-sent + * @amsdu: support A-MSDU withing A-MDPU * * This structure's lifetime is managed by RCU, assignments to * the array holding it must hold the aggregation mutex. @@ -158,6 +159,7 @@ struct tid_ampdu_tx { u16 failed_bar_ssn; bool bar_pending; + bool amsdu; }; /** diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index b5960b948f60..314e3bd7fbdb 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -974,9 +974,9 @@ TRACE_EVENT(drv_ampdu_action, struct ieee80211_sub_if_data *sdata, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size), + u16 *ssn, u8 buf_size, bool amsdu), - TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size), + TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), TP_STRUCT__entry( LOCAL_ENTRY @@ -985,6 +985,7 @@ TRACE_EVENT(drv_ampdu_action, __field(u16, tid) __field(u16, ssn) __field(u8, buf_size) + __field(bool, amsdu) VIF_ENTRY ), @@ -996,12 +997,13 @@ TRACE_EVENT(drv_ampdu_action, __entry->tid = tid; __entry->ssn = ssn ? *ssn : 0; __entry->buf_size = buf_size; + __entry->amsdu = amsdu; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d", + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, - __entry->tid, __entry->buf_size + __entry->tid, __entry->buf_size, __entry->amsdu ) ); -- cgit v1.3-6-gb490 From 99e7ca44bb910f0cbfda5d9008e8517df0ebc939 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 15 Aug 2015 22:39:51 +0300 Subject: mac80211: allow the driver to advertise A-MSDU within A-MPDU Rx support Drivers may be interested in receiving A-MSDU within A-MDPU. Not all the devices may be able to do so, make it configurable. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/mac80211.h | 4 ++++ net/mac80211/agg-rx.c | 4 +++- net/mac80211/debugfs.c | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f28cbc0988eb..d62d6f41548b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1897,6 +1897,9 @@ struct ieee80211_txq { * @IEEE80211_HW_TDLS_WIDER_BW: The device/driver supports wider bandwidth * than then BSS bandwidth for a TDLS link on the base channel. * + * @IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU: The driver supports receiving A-MSDUs + * within A-MPDU. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -1930,6 +1933,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_CLONED_SKBS, IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS, IEEE80211_HW_TDLS_WIDER_BW, + IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 6ebe8611eca5..10ad4ac1fa0b 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -189,6 +189,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; + bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU); u16 capab; skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); @@ -217,7 +218,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; mgmt->u.action.u.addba_resp.dialog_token = dialog_token; - capab = (u16)(policy << 1); /* bit 1 aggregation policy */ + capab = (u16)(amsdu << 0); /* bit 0 A-MSDU support */ + capab |= (u16)(policy << 1); /* bit 1 aggregation policy */ capab |= (u16)(tid << 2); /* bit 5:2 TID number */ capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ced6bf3be8d6..41726fd4bb78 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -123,6 +123,7 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { FLAG(SUPPORTS_CLONED_SKBS), FLAG(SINGLE_SCAN_ON_ALL_BANDS), FLAG(TDLS_WIDER_BW), + FLAG(SUPPORTS_AMSDU_IN_AMPDU), /* keep last for the build bug below */ (void *)0x1 -- cgit v1.3-6-gb490 From 0edd5faeb07bfd3ec5402f9467e4c169dcd131e8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 28 Aug 2015 14:31:48 +0200 Subject: wireless: mark element IDs 8 and 9 reserved These were never used in the tree, and are marked as reserved in the IEEE 802.11 documentation (ANA). Signed-off-by: Johannes Berg --- drivers/net/wireless/ipw2x00/libipw_rx.c | 2 -- include/linux/ieee80211.h | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index a6877dd6ba73..cef7f7d79cd9 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1091,8 +1091,6 @@ static const char *get_info_element_string(u16 id) MFIE_STRING(TIM); MFIE_STRING(IBSS_PARAMS); MFIE_STRING(COUNTRY); - MFIE_STRING(HP_PARAMS); - MFIE_STRING(HP_TABLE); MFIE_STRING(REQUEST); MFIE_STRING(CHALLENGE); MFIE_STRING(PWR_CONSTRAINT); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 19eb9ecd6cf3..f79a02a69d26 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1746,8 +1746,7 @@ enum ieee80211_eid { WLAN_EID_TIM = 5, WLAN_EID_IBSS_PARAMS = 6, WLAN_EID_COUNTRY = 7, - WLAN_EID_HP_PARAMS = 8, - WLAN_EID_HP_TABLE = 9, + /* 8, 9 reserved */ WLAN_EID_REQUEST = 10, WLAN_EID_QBSS_LOAD = 11, WLAN_EID_EDCA_PARAM_SET = 12, -- cgit v1.3-6-gb490 From 5359d112dcb081fd7a5f2de287fa995f6ba0800c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 14 Sep 2015 13:56:17 +0200 Subject: Revert "mac80211: add pointer for driver use to key" This reverts commit f9a060f4b2003eb7350762e60dfc576447e44bad. No driver has turned up needing this functionality, and I've just implemented the functionality I wanted this for in a different way. Thus, remove it again, until somebody shows up with a need for having it. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d62d6f41548b..3424ac6efb2a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1497,10 +1497,8 @@ enum ieee80211_key_flags { * - Temporal Authenticator Rx MIC Key (64 bits) * @icv_len: The ICV length for this key type * @iv_len: The IV length for this key type - * @drv_priv: pointer for driver use */ struct ieee80211_key_conf { - void *drv_priv; atomic64_t tx_pn; u32 cipher; u8 icv_len; -- cgit v1.3-6-gb490 From 75ea8ca844fd35ce365e35e1617b239892d31f72 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Sun, 20 Sep 2015 00:13:37 +0200 Subject: power: charger-manager: comment spelling fixes By accident I stumbled over a few misspelled words in the charger-manager header file which this patch fixes. Namely: - Extcon rather than Exton - constraint rather than constratint - existence rather than existance - difference rather than diffential While at it also add a missing space before a closing comment star forward-slash. Signed-off-by: Marcel Ziswiler Signed-off-by: Sebastian Reichel --- include/linux/power/charger-manager.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h index eadf28cb2fc9..c4fa907c8f14 100644 --- a/include/linux/power/charger-manager.h +++ b/include/linux/power/charger-manager.h @@ -65,7 +65,7 @@ struct charger_cable { const char *extcon_name; const char *name; - /* The charger-manager use Exton framework*/ + /* The charger-manager use Extcon framework */ struct extcon_specific_cable_nb extcon_dev; struct work_struct wq; struct notifier_block nb; @@ -94,7 +94,7 @@ struct charger_cable { * the charger will be maintained with disabled state. * @cables: * the array of charger cables to enable/disable charger - * and set current limit according to constratint data of + * and set current limit according to constraint data of * struct charger_cable if only charger cable included * in the array of charger cables is attached/detached. * @num_cables: the number of charger cables. @@ -148,7 +148,7 @@ struct charger_regulator { * @polling_interval_ms: interval in millisecond at which * charger manager will monitor battery health * @battery_present: - * Specify where information for existance of battery can be obtained + * Specify where information for existence of battery can be obtained * @psy_charger_stat: the names of power-supply for chargers * @num_charger_regulator: the number of entries in charger_regulators * @charger_regulators: array of charger regulators @@ -156,7 +156,7 @@ struct charger_regulator { * @thermal_zone : the name of thermal zone for battery * @temp_min : Minimum battery temperature for charging. * @temp_max : Maximum battery temperature for charging. - * @temp_diff : Temperature diffential to restart charging. + * @temp_diff : Temperature difference to restart charging. * @measure_battery_temp: * true: measure battery temperature * false: measure ambient temperature -- cgit v1.3-6-gb490 From 917536aeb88d34e06c1353b0dd144f0987bb66bd Mon Sep 17 00:00:00 2001 From: John Lin Date: Mon, 21 Sep 2015 14:12:01 +0800 Subject: ASoC: rt5645: Add jd_invert for Broadwell Broadwell can not triger the IRQ falling and rising simultaneously, so it can not detect jack-in and jack-out simultaneously. We add a flag "jd_invert" to platform data. If this flag is set, codec IRQ will be set to invert that forces IRQ as pulse when jack-in and jack-out. Signed-off-by: John Lin Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- include/sound/rt5645.h | 2 ++ sound/soc/codecs/rt5645.c | 7 +++++++ sound/soc/codecs/rt5645.h | 4 ++++ 3 files changed, 13 insertions(+) (limited to 'include') diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index 22734bc3ffd4..a5cf6152e778 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h @@ -21,6 +21,8 @@ struct rt5645_platform_data { /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ unsigned int jd_mode; + /* Invert JD when jack insert */ + bool jd_invert; }; #endif diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index e83068886c70..b0d96b6d21de 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2829,6 +2829,9 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) snd_soc_dapm_sync(dapm); rt5645->jack_type = SND_JACK_HEADPHONE; } + if (rt5645->pdata.jd_invert) + regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, + RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); } else { /* jack out */ rt5645->jack_type = 0; @@ -2844,6 +2847,9 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) snd_soc_dapm_disable_pin(dapm, "LDO2"); snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); snd_soc_dapm_sync(dapm); + if (rt5645->pdata.jd_invert) + regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, + RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR); } return rt5645->jack_type; @@ -3213,6 +3219,7 @@ static struct rt5645_platform_data buddy_platform_data = { .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5, .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, .jd_mode = 3, + .jd_invert = true, }; static int buddy_quirk_cb(const struct dmi_system_id *id) diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index 0e4cfc6ac649..90325d9256ff 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h @@ -1626,6 +1626,10 @@ #define RT5645_OT_P_NOR (0x0 << 10) #define RT5645_OT_P_INV (0x1 << 10) #define RT5645_IRQ_JD_1_1_EN (0x1 << 9) +#define RT5645_JD_1_1_MASK (0x1 << 7) +#define RT5645_JD_1_1_SFT 7 +#define RT5645_JD_1_1_NOR (0x0 << 7) +#define RT5645_JD_1_1_INV (0x1 << 7) /* IRQ Control 2 (0xbe) */ #define RT5645_IRQ_MB1_OC_MASK (0x1 << 15) -- cgit v1.3-6-gb490 From 4530eddb59494b89650d6bcd980fc7f7717ad80c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 11 Sep 2015 15:00:19 -0400 Subject: cgroup, memcg, cpuset: implement cgroup_taskset_for_each_leader() It wasn't explicitly documented but, when a process is being migrated, cpuset and memcg depend on cgroup_taskset_first() returning the threadgroup leader; however, this approach is somewhat ghetto and would no longer work for the planned multi-process migration. This patch introduces explicit cgroup_taskset_for_each_leader() which iterates over only the threadgroup leaders and replaces cgroup_taskset_first() usages for accessing the leader with it. This prepares both memcg and cpuset for multi-process migration. This patch also updates the documentation for cgroup_taskset_for_each() to clarify the iteration rules and removes comments mentioning task ordering in tasksets. v2: A previous patch which added threadgroup leader test was dropped. Patch updated accordingly. Signed-off-by: Tejun Heo Acked-by: Zefan Li Acked-by: Michal Hocko Cc: Johannes Weiner --- include/linux/cgroup.h | 22 ++++++++++++++++++++++ kernel/cgroup.c | 11 ----------- kernel/cpuset.c | 9 ++++----- mm/memcontrol.c | 17 +++++++++++++++-- 4 files changed, 41 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index fb717f2cba5b..e9c3eac074e2 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -232,11 +232,33 @@ void css_task_iter_end(struct css_task_iter *it); * cgroup_taskset_for_each - iterate cgroup_taskset * @task: the loop cursor * @tset: taskset to iterate + * + * @tset may contain multiple tasks and they may belong to multiple + * processes. When there are multiple tasks in @tset, if a task of a + * process is in @tset, all tasks of the process are in @tset. Also, all + * are guaranteed to share the same source and destination csses. + * + * Iteration is not in any specific order. */ #define cgroup_taskset_for_each(task, tset) \ for ((task) = cgroup_taskset_first((tset)); (task); \ (task) = cgroup_taskset_next((tset))) +/** + * cgroup_taskset_for_each_leader - iterate group leaders in a cgroup_taskset + * @leader: the loop cursor + * @tset: takset to iterate + * + * Iterate threadgroup leaders of @tset. For single-task migrations, @tset + * may not contain any. + */ +#define cgroup_taskset_for_each_leader(leader, tset) \ + for ((leader) = cgroup_taskset_first((tset)); (leader); \ + (leader) = cgroup_taskset_next((tset))) \ + if ((leader) != (leader)->group_leader) \ + ; \ + else + /* * Inline functions. */ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0be276ffe08a..7f4b85af03dc 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2217,13 +2217,6 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp, get_css_set(new_cset); rcu_assign_pointer(tsk->cgroups, new_cset); - - /* - * Use move_tail so that cgroup_taskset_first() still returns the - * leader after migration. This works because cgroup_migrate() - * ensures that the dst_cset of the leader is the first on the - * tset's dst_csets list. - */ list_move_tail(&tsk->cg_list, &new_cset->mg_tasks); /* @@ -2419,10 +2412,6 @@ static int cgroup_migrate(struct cgroup *cgrp, struct task_struct *leader, if (!cset->mg_src_cgrp) goto next; - /* - * cgroup_taskset_first() must always return the leader. - * Take care to avoid disturbing the ordering. - */ list_move_tail(&task->cg_list, &cset->mg_tasks); if (list_empty(&cset->mg_node)) list_add_tail(&cset->mg_node, &tset.src_csets); diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 0b361a0b58f6..e4d999929903 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1488,7 +1488,7 @@ static void cpuset_attach(struct cgroup_subsys_state *css, /* static buf protected by cpuset_mutex */ static nodemask_t cpuset_attach_nodemask_to; struct task_struct *task; - struct task_struct *leader = cgroup_taskset_first(tset); + struct task_struct *leader; struct cpuset *cs = css_cs(css); struct cpuset *oldcs = cpuset_attach_old_cs; @@ -1514,12 +1514,11 @@ static void cpuset_attach(struct cgroup_subsys_state *css, } /* - * Change mm, possibly for multiple threads in a threadgroup. This - * is expensive and may sleep and should be moved outside migration - * path proper. + * Change mm for all threadgroup leaders. This is expensive and may + * sleep and should be moved outside migration path proper. */ cpuset_attach_nodemask_to = cs->effective_mems; - if (thread_group_leader(leader)) { + cgroup_taskset_for_each_leader(leader, tset) { struct mm_struct *mm = get_task_mm(leader); if (mm) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9f331402e502..33c8dad6830f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4828,7 +4828,7 @@ static int mem_cgroup_can_attach(struct cgroup_subsys_state *css, { struct mem_cgroup *memcg = mem_cgroup_from_css(css); struct mem_cgroup *from; - struct task_struct *p; + struct task_struct *leader, *p; struct mm_struct *mm; unsigned long move_flags; int ret = 0; @@ -4842,7 +4842,20 @@ static int mem_cgroup_can_attach(struct cgroup_subsys_state *css, if (!move_flags) return 0; - p = cgroup_taskset_first(tset); + /* + * Multi-process migrations only happen on the default hierarchy + * where charge immigration is not used. Perform charge + * immigration if @tset contains a leader and whine if there are + * multiple. + */ + p = NULL; + cgroup_taskset_for_each_leader(leader, tset) { + WARN_ON_ONCE(p); + p = leader; + } + if (!p) + return 0; + from = mem_cgroup_from_task(p); VM_BUG_ON(from == memcg); -- cgit v1.3-6-gb490 From 4ad2ddce1a096dea71d42969515d3a64f0d9246f Mon Sep 17 00:00:00 2001 From: Stefan Koch Date: Tue, 25 Aug 2015 21:10:05 +0200 Subject: usb: interface authorization: Declare authorized attribute The attribute authorized shows the authorization state for an interface. Signed-off-by: Stefan Koch Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/usb.h b/include/linux/usb.h index 447fe29b55b4..3deccab2ce0a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -178,6 +178,7 @@ struct usb_interface { unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */ unsigned needs_binding:1; /* needs delayed unbind/rebind */ unsigned resetting_device:1; /* true: bandwidth alloc after reset */ + unsigned authorized:1; /* used for interface authorization */ struct device dev; /* interface specific device info */ struct device *usb_dev; -- cgit v1.3-6-gb490 From 6b2bd3c8c69c4817a9a2feb4597021d486c105f4 Mon Sep 17 00:00:00 2001 From: Stefan Koch Date: Tue, 25 Aug 2015 21:10:06 +0200 Subject: usb: interface authorization: Introduces the default interface authorization Interfaces are allowed per default. This can disabled or enabled (again) by writing 0 or 1 to /sys/bus/usb/devices/usbX/interface_authorized_default Signed-off-by: Stefan Koch Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/core/message.c | 1 + include/linux/usb/hcd.h | 9 +++++++++ 3 files changed, 57 insertions(+) (limited to 'include') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 4d64e5c499e1..83df1dde9c08 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -882,9 +882,53 @@ static ssize_t authorized_default_store(struct device *dev, } static DEVICE_ATTR_RW(authorized_default); +/* + * interface_authorized_default_show - show default authorization status + * for USB interfaces + * + * note: interface_authorized_default is the default value + * for initializing the authorized attribute of interfaces + */ +static ssize_t interface_authorized_default_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_device *usb_dev = to_usb_device(dev); + struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus); + + return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd)); +} + +/* + * interface_authorized_default_store - store default authorization status + * for USB interfaces + * + * note: interface_authorized_default is the default value + * for initializing the authorized attribute of interfaces + */ +static ssize_t interface_authorized_default_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_device *usb_dev = to_usb_device(dev); + struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus); + int rc = count; + bool val; + + if (strtobool(buf, &val) != 0) + return -EINVAL; + + if (val) + set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags); + else + clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags); + + return rc; +} +static DEVICE_ATTR_RW(interface_authorized_default); + /* Group all the USB bus attributes */ static struct attribute *usb_bus_attrs[] = { &dev_attr_authorized_default.attr, + &dev_attr_interface_authorized_default.attr, NULL, }; @@ -2682,6 +2726,9 @@ int usb_add_hcd(struct usb_hcd *hcd, hcd->authorized_default = authorized_default; set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* per default all interfaces are authorized */ + set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags); + /* HC is in reset state, but accessible. Now do the one-time init, * bottom up so that hcds can customize the root hubs before hub_wq * starts talking to them. (Note, bus id is assigned early too.) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f368d2053da5..3d25d89671d7 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1807,6 +1807,7 @@ free_interfaces: intfc = cp->intf_cache[i]; intf->altsetting = intfc->altsetting; intf->num_altsetting = intfc->num_altsetting; + intf->authorized = !!HCD_INTF_AUTHORIZED(hcd); kref_get(&intfc->ref); alt = usb_altnum_to_altsetting(intf, 0); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index d2784c10bfe2..36ce3d215cad 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -120,6 +120,7 @@ struct usb_hcd { #define HCD_FLAG_WAKEUP_PENDING 4 /* root hub is resuming? */ #define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ #define HCD_FLAG_DEAD 6 /* controller has died? */ +#define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */ /* The flags can be tested using these macros; they are likely to * be slightly faster than test_bit(). @@ -131,6 +132,14 @@ struct usb_hcd { #define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING)) #define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD)) + /* + * Specifies if interfaces are authorized by default + * or they require explicit user space authorization; this bit is + * settable through /sys/class/usb_host/X/interface_authorized_default + */ +#define HCD_INTF_AUTHORIZED(hcd) \ + ((hcd)->flags & (1U << HCD_FLAG_INTF_AUTHORIZED)) + /* Flags that get set only during HCD registration or removal. */ unsigned rh_registered:1;/* is root hub registered? */ unsigned rh_pollable:1; /* may we poll the root hub? */ -- cgit v1.3-6-gb490 From ff8e2c560eca32043ed097099debac488a4bd99f Mon Sep 17 00:00:00 2001 From: Stefan Koch Date: Tue, 25 Aug 2015 21:10:11 +0200 Subject: usb: interface authorization: Use a flag for the default device authorization With this patch a flag instead of a variable is used for the default device authorization. Signed-off-by: Stefan Koch Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 31 +++++++++++++++++++++---------- drivers/usb/core/usb.c | 2 +- include/linux/usb/hcd.h | 16 +++++++++------- 3 files changed, 31 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 83df1dde9c08..86b3d1190500 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -854,10 +854,10 @@ static ssize_t authorized_default_show(struct device *dev, { struct usb_device *rh_usb_dev = to_usb_device(dev); struct usb_bus *usb_bus = rh_usb_dev->bus; - struct usb_hcd *usb_hcd; + struct usb_hcd *hcd; - usb_hcd = bus_to_hcd(usb_bus); - return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default); + hcd = bus_to_hcd(usb_bus); + return snprintf(buf, PAGE_SIZE, "%u\n", !!HCD_DEV_AUTHORIZED(hcd)); } static ssize_t authorized_default_store(struct device *dev, @@ -868,12 +868,16 @@ static ssize_t authorized_default_store(struct device *dev, unsigned val; struct usb_device *rh_usb_dev = to_usb_device(dev); struct usb_bus *usb_bus = rh_usb_dev->bus; - struct usb_hcd *usb_hcd; + struct usb_hcd *hcd; - usb_hcd = bus_to_hcd(usb_bus); + hcd = bus_to_hcd(usb_bus); result = sscanf(buf, "%u\n", &val); if (result == 1) { - usb_hcd->authorized_default = val ? 1 : 0; + if (val) + set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); + else + clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); + result = size; } else { result = -EINVAL; @@ -2720,10 +2724,17 @@ int usb_add_hcd(struct usb_hcd *hcd, dev_info(hcd->self.controller, "%s\n", hcd->product_desc); /* Keep old behaviour if authorized_default is not in [0, 1]. */ - if (authorized_default < 0 || authorized_default > 1) - hcd->authorized_default = hcd->wireless ? 0 : 1; - else - hcd->authorized_default = authorized_default; + if (authorized_default < 0 || authorized_default > 1) { + if (hcd->wireless) + clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); + else + set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); + } else { + if (authorized_default) + set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); + else + clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); + } set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); /* per default all interfaces are authorized */ diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 8d5b2f4113cd..f8bbd0b6d9fe 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -510,7 +510,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, if (root_hub) /* Root hub always ok [and always wired] */ dev->authorized = 1; else { - dev->authorized = usb_hcd->authorized_default; + dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd); dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0; } return dev; diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 36ce3d215cad..4d147277b30d 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -58,12 +58,6 @@ * * Since "struct usb_bus" is so thin, you can't share much code in it. * This framework is a layer over that, and should be more sharable. - * - * @authorized_default: Specifies if new devices are authorized to - * connect by default or they require explicit - * user space authorization; this bit is settable - * through /sys/class/usb_host/X/authorized_default. - * For the rest is RO, so we don't lock to r/w it. */ /*-------------------------------------------------------------------------*/ @@ -121,6 +115,7 @@ struct usb_hcd { #define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ #define HCD_FLAG_DEAD 6 /* controller has died? */ #define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */ +#define HCD_FLAG_DEV_AUTHORIZED 8 /* authorize devices? */ /* The flags can be tested using these macros; they are likely to * be slightly faster than test_bit(). @@ -140,6 +135,14 @@ struct usb_hcd { #define HCD_INTF_AUTHORIZED(hcd) \ ((hcd)->flags & (1U << HCD_FLAG_INTF_AUTHORIZED)) + /* + * Specifies if devices are authorized by default + * or they require explicit user space authorization; this bit is + * settable through /sys/class/usb_host/X/authorized_default + */ +#define HCD_DEV_AUTHORIZED(hcd) \ + ((hcd)->flags & (1U << HCD_FLAG_DEV_AUTHORIZED)) + /* Flags that get set only during HCD registration or removal. */ unsigned rh_registered:1;/* is root hub registered? */ unsigned rh_pollable:1; /* may we poll the root hub? */ @@ -150,7 +153,6 @@ struct usb_hcd { * support the new root-hub polling mechanism. */ unsigned uses_new_polling:1; unsigned wireless:1; /* Wireless USB HCD */ - unsigned authorized_default:1; unsigned has_tt:1; /* Integrated TT in root hub */ unsigned amd_resume_bug:1; /* AMD remote wakeup quirk */ unsigned can_do_streams:1; /* HC supports streams */ -- cgit v1.3-6-gb490 From 7dc87ff8815ef43717c936faea79013855e3dbef Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 7 Sep 2015 10:54:59 +0800 Subject: ARM: imx7d: add imx7d iomux-gpr field define Add imx7d iomux-gpr field define. Signed-off-by: Fugang Duan Signed-off-by: Shawn Guo --- include/linux/mfd/syscon/imx7-iomuxc-gpr.h | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 include/linux/mfd/syscon/imx7-iomuxc-gpr.h (limited to 'include') diff --git a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h new file mode 100644 index 000000000000..4585d6105d68 --- /dev/null +++ b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * + * 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. + */ + +#ifndef __LINUX_IMX7_IOMUXC_GPR_H +#define __LINUX_IMX7_IOMUXC_GPR_H + +#define IOMUXC_GPR0 0x00 +#define IOMUXC_GPR1 0x04 +#define IOMUXC_GPR2 0x08 +#define IOMUXC_GPR3 0x0c +#define IOMUXC_GPR4 0x10 +#define IOMUXC_GPR5 0x14 +#define IOMUXC_GPR6 0x18 +#define IOMUXC_GPR7 0x1c +#define IOMUXC_GPR8 0x20 +#define IOMUXC_GPR9 0x24 +#define IOMUXC_GPR10 0x28 +#define IOMUXC_GPR11 0x2c +#define IOMUXC_GPR12 0x30 +#define IOMUXC_GPR13 0x34 +#define IOMUXC_GPR14 0x38 +#define IOMUXC_GPR15 0x3c +#define IOMUXC_GPR16 0x40 +#define IOMUXC_GPR17 0x44 +#define IOMUXC_GPR18 0x48 +#define IOMUXC_GPR19 0x4c +#define IOMUXC_GPR20 0x50 +#define IOMUXC_GPR21 0x54 +#define IOMUXC_GPR22 0x58 + +/* For imx7d iomux gpr register field define */ +#define IMX7D_GPR1_IRQ_MASK (0x1 << 12) +#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK (0x1 << 13) +#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK (0x1 << 14) +#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13) +#define IMX7D_GPR1_ENET1_CLK_DIR_MASK (0x1 << 17) +#define IMX7D_GPR1_ENET2_CLK_DIR_MASK (0x1 << 18) +#define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17) + +#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI (0x1 << 4) + +#endif /* __LINUX_IMX7_IOMUXC_GPR_H */ -- cgit v1.3-6-gb490 From 0753f56e411a5e216c9899c21e54bd11dde17313 Mon Sep 17 00:00:00 2001 From: Sanchayan Maity Date: Mon, 7 Sep 2015 13:51:35 +0530 Subject: clk: clk-vf610: Add clock for Vybrid OCOTP controller Add clock support for Vybrid On-Chip One Time Programmable (OCOTP) controller. While the OCOTP block does not require explicit clock gating, for programming the OCOTP timing register the clock rate of ipg clock is required for timing calculations related to fuse and shadow register read sequence. We explicitly specify the ipg clock for OCOTP as a result. Signed-off-by: Sanchayan Maity Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-vf610.c | 1 + include/dt-bindings/clock/vf610-clock.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index bff45ead7389..d1b1c95177bb 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -387,6 +387,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7)); clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24); + clk[VF610_CLK_OCOTP] = imx_clk_gate("ocotp", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(5)); imx_check_clocks(clk, ARRAY_SIZE(clk)); diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index d19763439472..56c16aaea112 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -194,6 +194,7 @@ #define VF610_PLL7_BYPASS 181 #define VF610_CLK_SNVS 182 #define VF610_CLK_DAP 183 -#define VF610_CLK_END 184 +#define VF610_CLK_OCOTP 184 +#define VF610_CLK_END 185 #endif /* __DT_BINDINGS_CLOCK_VF610_H */ -- cgit v1.3-6-gb490 From 37587fadff8ce8f40a6952f0383c571a89b29d1d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 30 Jul 2015 13:22:43 -0700 Subject: arcnet: fix indentation of if_arcnet.h Standardized spacing is easier to read. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- include/uapi/linux/if_arcnet.h | 55 ++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/if_arcnet.h b/include/uapi/linux/if_arcnet.h index 46e34bd0e783..cfb642f8e7bd 100644 --- a/include/uapi/linux/if_arcnet.h +++ b/include/uapi/linux/if_arcnet.h @@ -19,7 +19,6 @@ #include #include - /* * These are the defined ARCnet Protocol ID's. */ @@ -57,42 +56,40 @@ * The RFC1201-specific components of an arcnet packet header. */ struct arc_rfc1201 { - __u8 proto; /* protocol ID field - varies */ - __u8 split_flag; /* for use with split packets */ - __be16 sequence; /* sequence number */ - __u8 payload[0]; /* space remaining in packet (504 bytes)*/ + __u8 proto; /* protocol ID field - varies */ + __u8 split_flag; /* for use with split packets */ + __be16 sequence; /* sequence number */ + __u8 payload[0]; /* space remaining in packet (504 bytes)*/ }; #define RFC1201_HDR_SIZE 4 - /* * The RFC1051-specific components. */ struct arc_rfc1051 { - __u8 proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */ - __u8 payload[0]; /* 507 bytes */ + __u8 proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */ + __u8 payload[0]; /* 507 bytes */ }; #define RFC1051_HDR_SIZE 1 - /* * The ethernet-encap-specific components. We have a real ethernet header * and some data. */ struct arc_eth_encap { - __u8 proto; /* Always ARC_P_ETHER */ - struct ethhdr eth; /* standard ethernet header (yuck!) */ - __u8 payload[0]; /* 493 bytes */ + __u8 proto; /* Always ARC_P_ETHER */ + struct ethhdr eth; /* standard ethernet header (yuck!) */ + __u8 payload[0]; /* 493 bytes */ }; #define ETH_ENCAP_HDR_SIZE 14 - struct arc_cap { __u8 proto; - __u8 cookie[sizeof(int)]; /* Actually NOT sent over the network */ + __u8 cookie[sizeof(int)]; + /* Actually NOT sent over the network */ union { __u8 ack; - __u8 raw[0]; /* 507 bytes */ + __u8 raw[0]; /* 507 bytes */ } mes; }; @@ -105,9 +102,9 @@ struct arc_cap { * driver. */ struct arc_hardware { - __u8 source, /* source ARCnet - filled in automagically */ - dest, /* destination ARCnet - 0 for broadcast */ - offset[2]; /* offset bytes (some weird semantics) */ + __u8 source; /* source ARCnet - filled in automagically */ + __u8 dest; /* destination ARCnet - 0 for broadcast */ + __u8 offset[2]; /* offset bytes (some weird semantics) */ }; #define ARC_HDR_SIZE 4 @@ -116,17 +113,17 @@ struct arc_hardware { * when you do a raw packet capture). */ struct archdr { - /* hardware requirements */ - struct arc_hardware hard; - - /* arcnet encapsulation-specific bits */ - union { - struct arc_rfc1201 rfc1201; - struct arc_rfc1051 rfc1051; - struct arc_eth_encap eth_encap; - struct arc_cap cap; - __u8 raw[0]; /* 508 bytes */ - } soft; + /* hardware requirements */ + struct arc_hardware hard; + + /* arcnet encapsulation-specific bits */ + union { + struct arc_rfc1201 rfc1201; + struct arc_rfc1051 rfc1051; + struct arc_eth_encap eth_encap; + struct arc_cap cap; + __u8 raw[0]; /* 508 bytes */ + } soft; }; #endif /* _LINUX_IF_ARCNET_H */ -- cgit v1.3-6-gb490 From cb334648a10c7fa6f0f163c22602f4dc1c6d56b4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:47 -0700 Subject: arcnet: Use normal kernel spacing style Standardized spacing is easier to read. git diff -w shows no differences. objdiff shows no differences. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 10 +- drivers/net/arcnet/arc-rimi.c | 30 ++-- drivers/net/arcnet/arcnet.c | 170 ++++++++++----------- drivers/net/arcnet/capmode.c | 36 ++--- drivers/net/arcnet/com20020-isa.c | 2 +- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020.c | 38 ++--- drivers/net/arcnet/com20020_cs.c | 306 +++++++++++++++++++------------------- drivers/net/arcnet/com90io.c | 24 +-- drivers/net/arcnet/com90xx.c | 32 ++-- drivers/net/arcnet/rfc1051.c | 12 +- drivers/net/arcnet/rfc1201.c | 36 ++--- include/linux/arcdevice.h | 90 +++++------ 13 files changed, 394 insertions(+), 394 deletions(-) (limited to 'include') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 705e6ce2eb90..49f5819a0367 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - "raw mode" packet encapsulation (no soft headers) - * + * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * @@ -109,7 +109,7 @@ static void rx(struct net_device *dev, int bufnum, skb_put(skb, length + ARC_HDR_SIZE); skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; skb_reset_mac_header(skb); skb_pull(skb, ARC_HDR_SIZE); @@ -136,7 +136,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { int hdr_size = ARC_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); /* * Set the source hardware address. @@ -150,7 +150,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* + /* * FIXME: fill in the last byte of the dest ipaddr here to better * comply with RFC1051 in "noarp" mode. */ @@ -192,7 +192,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length,ofs); + length, ofs); lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index b8b4c7ba884f..4644d46b6a5f 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards - * + * * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. @@ -56,27 +56,27 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse /* Handy defines for ARCnet specific stuff */ /* Amount of I/O memory used by the card */ -#define BUFFER_SIZE (512) -#define MIRROR_SIZE (BUFFER_SIZE*4) +#define BUFFER_SIZE (512) +#define MIRROR_SIZE (BUFFER_SIZE * 4) /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ -#define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ -#define _ADDR_LO (ioaddr+14) -#define _CONFIG (ioaddr+2) /* Configuration register */ +#define _INTMASK (ioaddr + 0) /* writable */ +#define _STATUS (ioaddr + 0) /* readable */ +#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ +#define _RESET (ioaddr + 8) /* software reset (on read) */ +#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ +#define _ADDR_LO (ioaddr + 14) +#define _CONFIG (ioaddr + 2) /* Configuration register */ #undef ASTATUS #undef ACOMMAND #undef AINTMASK #define ASTATUS() readb(_STATUS) -#define ACOMMAND(cmd) writeb((cmd),_COMMAND) -#define AINTMASK(msk) writeb((msk),_INTMASK) -#define SETCONF() writeb(lp->config,_CONFIG) +#define ACOMMAND(cmd) writeb((cmd), _COMMAND) +#define AINTMASK(msk) writeb((msk), _INTMASK) +#define SETCONF() writeb(lp->config, _CONFIG) /* @@ -90,7 +90,7 @@ static int __init arcrimi_probe(struct net_device *dev) BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n", - dev->dev_addr[0], dev->mem_start, dev->irq); + dev->dev_addr[0], dev->mem_start, dev->irq); if (dev->mem_start <= 0 || dev->irq <= 0) { BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you " diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 10f71c732b59..2a594d1c4b55 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - device-independent routines - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . @@ -20,12 +20,12 @@ * modified by SRC, incorporated herein by reference. * * ********************** - * + * * The change log is now in a file called ChangeLog in this directory. * * Sources: * - Crynwr arcnet.com/arcether.com packet drivers. - * - arcnet.c v0.00 dated 1/1/94 and apparently by + * - arcnet.c v0.00 dated 1/1/94 and apparently by * Donald Becker - it didn't work :) * - skeleton.c v0.05 dated 11/16/93 by Donald Becker * (from Linux Kernel 1.1.45) @@ -69,8 +69,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum); * arc_proto_default instead. It also must not be NULL; if you would like * to set it to NULL, set it to &arc_proto_null instead. */ - struct ArcProto *arc_proto_map[256], *arc_proto_default, - *arc_bcast_proto, *arc_raw_proto; +struct ArcProto *arc_proto_map[256], *arc_proto_default, + *arc_bcast_proto, *arc_raw_proto; static struct ArcProto arc_proto_null = { @@ -136,8 +136,8 @@ static int __init arcnet_init(void) BUGLVL(D_DURING) printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", - sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), - sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), + sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), + sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), sizeof(struct archdr)); return 0; @@ -184,11 +184,11 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, /* hw.copy_from_card expects IRQ context so take the IRQ lock to keep it single threaded */ - if(take_arcnet_lock) + if (take_arcnet_lock) spin_lock_irqsave(&lp->lock, flags); lp->hw.copy_from_card(dev, bufnum, 0, buf, 512); - if(take_arcnet_lock) + if (take_arcnet_lock) spin_unlock_irqrestore(&lp->lock, flags); /* if the offset[0] byte is nonzero, this is a 256-byte packet */ @@ -202,7 +202,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #else -#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) do { } while (0) +#define arcnet_dump_packet(dev, bufnum, desc, take_arcnet_lock) do { } while (0) #endif @@ -233,7 +233,7 @@ void arcnet_unregister_proto(struct ArcProto *proto) /* * Add a buffer to the queue. Only the interrupt handler is allowed to do * this, unless interrupts are disabled. - * + * * Note: we don't check for a full queue, since there aren't enough buffers * to more than fill it. */ @@ -248,7 +248,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum) BUGLVL(D_DURING) { BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", bufnum); - for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) + for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); BUGMSG2(D_DURING, "\n"); } @@ -284,7 +284,7 @@ static int get_arcbuf(struct net_device *dev) BUGLVL(D_DURING) { BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); - for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) + for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); BUGMSG2(D_DURING, "\n"); } @@ -346,7 +346,7 @@ struct net_device *alloc_arcdev(const char *name) dev = alloc_netdev(sizeof(struct arcnet_local), name && *name ? name : "arc%d", NET_NAME_UNKNOWN, arcdev_setup); - if(dev) { + if (dev) { struct arcnet_local *lp = netdev_priv(dev); spin_lock_init(&lp->lock); } @@ -367,7 +367,7 @@ int arcnet_open(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int count, newmtu, error; - BUGMSG(D_INIT,"opened."); + BUGMSG(D_INIT, "opened."); if (!try_module_get(lp->hw.owner)) return -ENODEV; @@ -431,24 +431,24 @@ int arcnet_open(struct net_device *dev) BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " "DOS networking programs!\n"); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (ASTATUS() & RESETflag) { - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); netif_start_queue(dev); @@ -489,29 +489,29 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, struct ArcProto *proto; BUGMSG(D_DURING, - "create header from %d to %d; protocol %d (%Xh); size %u.\n", - saddr ? *(uint8_t *) saddr : -1, - daddr ? *(uint8_t *) daddr : -1, + "create header from %d to %d; protocol %d (%Xh); size %u.\n", + saddr ? *(uint8_t *)saddr : -1, + daddr ? *(uint8_t *)daddr : -1, type, type, len); - if (skb->len!=0 && len != skb->len) + if (skb->len != 0 && len != skb->len) BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", skb->len, len); - /* Type is host order - ? */ - if(type == ETH_P_ARCNET) { - proto = arc_raw_proto; - BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix); - _daddr = daddr ? *(uint8_t *) daddr : 0; - } + /* Type is host order - ? */ + if (type == ETH_P_ARCNET) { + proto = arc_raw_proto; + BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix); + _daddr = daddr ? *(uint8_t *)daddr : 0; + } else if (!daddr) { /* * if the dest addr isn't provided, we can't choose an encapsulation! * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a * real header when we do rebuild_header. */ - *(uint16_t *) skb_push(skb, 2) = type; + *(uint16_t *)skb_push(skb, 2) = type; /* * XXX: Why not use skb->mac_len? */ @@ -522,7 +522,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, } else { /* otherwise, we can just add the header as usual. */ - _daddr = *(uint8_t *) daddr; + _daddr = *(uint8_t *)daddr; proto_num = lp->default_proto[_daddr]; proto = arc_proto_map[proto_num]; BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", @@ -538,7 +538,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, /* Called by the kernel in order to transmit a packet. */ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, - struct net_device *dev) + struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); struct archdr *pkt; @@ -550,14 +550,14 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, BUGMSG(D_DURING, "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", - ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol); + ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; proto = arc_proto_map[soft->proto]; BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", - skb->len, pkt->hard.dest); + skb->len, pkt->hard.dest); BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); /* fits in one packet? */ @@ -572,7 +572,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, spin_lock_irqsave(&lp->lock, flags); AINTMASK(0); - if(lp->next_tx == -1) + if (lp->next_tx == -1) txbuf = get_arcbuf(dev); else { txbuf = -1; @@ -594,9 +594,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, if (proto->continue_tx && proto->continue_tx(dev, txbuf)) { - BUGMSG(D_NORMAL, - "bug! continue_tx finished the first time! " - "(proto='%c')\n", proto->suffix); + BUGMSG(D_NORMAL, + "bug! continue_tx finished the first time! " + "(proto='%c')\n", proto->suffix); } } retval = NETDEV_TX_OK; @@ -606,14 +606,14 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, freeskb = 0; } - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); /* make sure we didn't ignore a TX IRQ while we were in here */ AINTMASK(0); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); - lp->intmask |= TXFREEflag|EXCNAKflag; + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + lp->intmask |= TXFREEflag | EXCNAKflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); spin_unlock_irqrestore(&lp->lock, flags); if (freeskb) { @@ -649,7 +649,7 @@ static int go_tx(struct net_device *dev) lp->lasttrans_dest = lp->lastload_dest; lp->lastload_dest = 0; lp->excnak_pending = 0; - lp->intmask |= TXFREEflag|EXCNAKflag; + lp->intmask |= TXFREEflag | EXCNAKflag; return 1; } @@ -676,12 +676,12 @@ void arcnet_timeout(struct net_device *dev) /* make sure we didn't miss a TX or a EXC NAK IRQ */ AINTMASK(0); - lp->intmask |= TXFREEflag|EXCNAKflag; + lp->intmask |= TXFREEflag | EXCNAKflag; AINTMASK(lp->intmask); - + spin_unlock_irqrestore(&lp->lock, flags); - if (time_after(jiffies, lp->last_timeout + 10*HZ)) { + if (time_after(jiffies, lp->last_timeout + 10 * HZ)) { BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", msg, status, lp->intmask, lp->lasttrans_dest); lp->last_timeout = jiffies; @@ -710,7 +710,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) lp = netdev_priv(dev); BUG_ON(!lp); - + spin_lock(&lp->lock); /* @@ -731,16 +731,16 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) boguscount = 5; do { status = ASTATUS(); - diagstatus = (status >> 8) & 0xFF; + diagstatus = (status >> 8) & 0xFF; BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", - __FILE__,__LINE__,__func__,status); + __FILE__, __LINE__, __func__, status); didsomething = 0; /* * RESET flag was enabled - card is resetting and if RX is * disabled, it's NOT because we just got a packet. - * + * * The card is in an undefined state. Clear it out and start over. */ if (status & RESETflag) { @@ -751,14 +751,14 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) /* get out of the interrupt handler! */ break; } - /* + /* * RX is inhibited - we must have received something. Prepare to * receive into the next buffer. - * + * * We don't actually copy the received packet from the card until * after the transmit handler runs (and possibly launches the next * tx); this should improve latency slightly if we get both types - * of interrupts at once. + * of interrupts at once. */ recbuf = -1; if (status & lp->intmask & NORXflag) { @@ -775,27 +775,27 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) didsomething++; } - if((diagstatus & EXCNAKflag)) { + if ((diagstatus & EXCNAKflag)) { BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", diagstatus); - ACOMMAND(NOTXcmd); /* disable transmit */ - lp->excnak_pending = 1; + ACOMMAND(NOTXcmd); /* disable transmit */ + lp->excnak_pending = 1; - ACOMMAND(EXCNAKclear); + ACOMMAND(EXCNAKclear); lp->intmask &= ~(EXCNAKflag); - didsomething++; - } + didsomething++; + } /* a transmit finished, and we're interested in it. */ if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { - lp->intmask &= ~(TXFREEflag|EXCNAKflag); + lp->intmask &= ~(TXFREEflag | EXCNAKflag); BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); if (lp->cur_tx != -1 && !lp->timed_out) { - if(!(status & TXACKflag)) { + if (!(status & TXACKflag)) { if (lp->lasttrans_dest != 0) { BUGMSG(D_EXTRA, "transmit was not acknowledged! " @@ -813,16 +813,16 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto && lp->outgoing.proto->ack_tx) { - int ackstatus; - if(status & TXACKflag) - ackstatus=2; - else if(lp->excnak_pending) - ackstatus=1; - else - ackstatus=0; - - lp->outgoing.proto - ->ack_tx(dev, ackstatus); + int ackstatus; + if (status & TXACKflag) + ackstatus = 2; + else if (lp->excnak_pending) + ackstatus = 1; + else + ackstatus = 0; + + lp->outgoing.proto + ->ack_tx(dev, ackstatus); } } if (lp->cur_tx != -1) @@ -842,11 +842,11 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ dev->stats.tx_bytes += lp->outgoing.skb->len; - if(!lp->outgoing.proto->ack_tx) - { - dev_kfree_skb_irq(lp->outgoing.skb); - lp->outgoing.proto = NULL; - } + if (!lp->outgoing.proto->ack_tx) + { + dev_kfree_skb_irq(lp->outgoing.skb); + lp->outgoing.proto = NULL; + } } lp->next_tx = txbuf; } @@ -871,8 +871,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", status); /* MYRECON bit is at bit 7 of diagstatus */ - if(diagstatus & 0x80) - BUGMSG(D_RECON,"Put out that recon myself\n"); + if (diagstatus & 0x80) + BUGMSG(D_RECON, "Put out that recon myself\n"); /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || @@ -889,7 +889,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", lp->num_recons, - (lp->last_recon - lp->first_recon) / HZ, + (lp->last_recon - lp->first_recon) / HZ, lp->network_down); /* if network is marked up; @@ -911,7 +911,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } } } else if (lp->network_down && - time_after(jiffies, lp->last_recon + HZ * 10)) { + time_after(jiffies, lp->last_recon + HZ * 10)) { if (lp->network_down) BUGMSG(D_NORMAL, "cabling restored?\n"); lp->first_recon = lp->last_recon = 0; @@ -920,7 +920,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); } - if(didsomething) { + if (didsomething) { retval |= IRQ_HANDLED; } } @@ -934,7 +934,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) AINTMASK(0); udelay(1); AINTMASK(lp->intmask); - + spin_unlock(&lp->lock); return retval; } @@ -1007,7 +1007,7 @@ static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { BUGMSG(D_PROTO, - "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", + "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", pkthdr->soft.rfc1201.proto, pkthdr->hard.source); } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 42fce91b71fc..95a6cf07965c 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -71,12 +71,12 @@ static void rx(struct net_device *dev, int bufnum, /* use these variables to be sure we count in bytes, not in sizeof(struct archdr) */ - pktbuf=(char*)pkt; - pkthdrbuf=(char*)pkthdr; - memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)); - memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int), - pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto), - sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto)); + pktbuf = (char *)pkt; + pkthdrbuf = (char *)pkthdr; + memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto)); + memcpy(pktbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto) + sizeof(int), + pkthdrbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto), + sizeof(struct archdr) - ARC_HDR_SIZE - sizeof(pkt->soft.cap.proto)); if (length > sizeof(pkt->soft)) lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), @@ -101,10 +101,10 @@ static int build_header(struct sk_buff *skb, uint8_t daddr) { int hdr_size = ARC_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", - *((int*)&pkt->soft.cap.cookie[0])); + *((int *)&pkt->soft.cap.cookie[0])); /* * Set the source hardware address. * @@ -148,7 +148,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, lp->next_tx, lp->cur_tx, bufnum); BUGMSG(D_PROTO, "Sending for cap packet %x.\n", - *((int*)&pkt->soft.cap.cookie[0])); + *((int *)&pkt->soft.cap.cookie[0])); if (length > XMTU) { /* should never happen! other people already check for this. */ @@ -166,7 +166,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length,ofs); + length, ofs); /* Copy the arcnet-header + the protocol byte down: */ lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); @@ -175,8 +175,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, /* Skip the extra integer we have written into it as a cookie but write the rest of the message: */ - lp->hw.copy_to_card(dev, bufnum, ofs+1, - ((unsigned char*)&pkt->soft.cap.mes),length-1); + lp->hw.copy_to_card(dev, bufnum, ofs + 1, + ((unsigned char *)&pkt->soft.cap.mes), length - 1); lp->lastload_dest = hard->dest; @@ -188,21 +188,21 @@ static int ack_tx(struct net_device *dev, int acked) struct arcnet_local *lp = netdev_priv(dev); struct sk_buff *ackskb; struct archdr *ackpkt; - int length=sizeof(struct arc_cap); + int length = sizeof(struct arc_cap); BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", - lp->outgoing.skb->protocol, acked); + lp->outgoing.skb->protocol, acked); BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); /* Now alloc a skb to send back up through the layers: */ - ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC); + ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (ackskb == NULL) { BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); goto free_outskb; } - skb_put(ackskb, length + ARC_HDR_SIZE ); + skb_put(ackskb, length + ARC_HDR_SIZE); ackskb->dev = dev; skb_reset_mac_header(ackskb); @@ -212,10 +212,10 @@ static int ack_tx(struct net_device *dev, int acked) skb_copy_from_linear_data(lp->outgoing.skb, ackpkt, ARC_HDR_SIZE + sizeof(struct arc_cap)); ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */ - ackpkt->soft.cap.mes.ack=acked; + ackpkt->soft.cap.mes.ack = acked; BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", - *((int*)&ackpkt->soft.cap.cookie[0])); + *((int *)&ackpkt->soft.cap.cookie[0])); ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 45c61a2c5fbd..d8746caf8e7a 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 chipset support - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 96edc1346124..e0f489a117f1 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -1,7 +1,7 @@ /* * Linux ARCnet driver - COM20020 PCI support * Contemporary Controls PCI20 and SOHARD SH-ARC PCI - * + * * Written 1994-1999 by Avery Pennarun, * based on an ISA version by David Woodhouse. * Written 1999-2000 by Martin Mares . diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 1a8437842fbc..cd2a5ca56ce5 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 chipset support - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999 by Martin Mares . @@ -108,7 +108,7 @@ int com20020_check(struct net_device *dev) { SET_SUBADR(SUB_SETUP2); outb(lp->setup2, _XREG); - + /* must now write the magic "restart operation" command */ mdelay(1); outb(0x18, _COMMAND); @@ -117,7 +117,7 @@ int com20020_check(struct net_device *dev) lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2); /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ SETCONF; - outb(0x42, ioaddr + BUS_ALIGN*7); + outb(0x42, ioaddr + BUS_ALIGN * 7); status = ASTATUS(); @@ -129,7 +129,7 @@ int com20020_check(struct net_device *dev) /* Enable TX */ outb(0x39, _CONFIG); - outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7); + outb(inb(ioaddr + BUS_ALIGN * 8), ioaddr + BUS_ALIGN * 7); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); @@ -193,7 +193,7 @@ int com20020_found(struct net_device *dev, int shared) lp->hw.close = com20020_close; if (!dev->dev_addr[0]) - dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */ + dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); /* FIXME: do this some other way! */ SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); @@ -202,7 +202,7 @@ int com20020_found(struct net_device *dev, int shared) { SET_SUBADR(SUB_SETUP2); outb(lp->setup2, _XREG); - + /* must now write the magic "restart operation" command */ mdelay(1); outb(0x18, _COMMAND); @@ -232,7 +232,7 @@ int com20020_found(struct net_device *dev, int shared) BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout); BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n", - lp->setup >> 1, + lp->setup >> 1, clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); if (register_netdev(dev)) { @@ -243,9 +243,9 @@ int com20020_found(struct net_device *dev, int shared) } -/* +/* * Do a hardware reset on the card, and set up necessary registers. - * + * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * @@ -258,15 +258,15 @@ static int com20020_reset(struct net_device *dev, int really_reset) u_char inbyte; BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", - __FILE__,__LINE__,__func__,dev,lp,dev->name); + __FILE__, __LINE__, __func__, dev, lp, dev->name); BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ SETCONF; - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (really_reset) { /* reset the card */ @@ -274,22 +274,22 @@ static int com20020_reset(struct net_device *dev, int really_reset) mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); /* verify that the ARCnet signature byte is present */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); com20020_copy_from_card(dev, 0, 0, &inbyte, 1); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (inbyte != TESTvalue) { - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* done! return success. */ return 0; @@ -299,7 +299,7 @@ static int com20020_reset(struct net_device *dev, int really_reset) static void com20020_setmask(struct net_device *dev, int mask) { u_int ioaddr = dev->base_addr; - BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr); + BUGMSG(D_DURING, "Setting mask to %x at %x\n", mask, ioaddr); AINTMASK(mask); } @@ -315,7 +315,7 @@ static int com20020_status(struct net_device *dev) { u_int ioaddr = dev->base_addr; - return ASTATUS() + (ADIAGSTATUS()<<8); + return ASTATUS() + (ADIAGSTATUS() << 8); } static void com20020_close(struct net_device *dev) diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 057d9582132a..f68752102379 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 PCMCIA support - * + * * Written 1994-1999 by Avery Pennarun, * based on an ISA version by David Woodhouse. * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4) @@ -19,14 +19,14 @@ * Director, National Security Agency. This software may only be used * and distributed according to the terms of the GNU General Public License as * modified by SRC, incorporated herein by reference. - * + * * ********************** * Changes: * Arnaldo Carvalho de Melo - 08/08/2000 * - reorganize kmallocs in com20020_attach, checking all for failure * and releasing the previous allocations if one fails * ********************** - * + * * For more details, see drivers/net/arcnet.c * * ********************** @@ -53,33 +53,33 @@ static void regdump(struct net_device *dev) { #ifdef DEBUG - int ioaddr = dev->base_addr; - int count; - - netdev_dbg(dev, "register dump:\n"); - for (count = ioaddr; count < ioaddr + 16; count++) - { - if (!(count % 16)) - pr_cont("%04X:", count); - pr_cont(" %02X", inb(count)); - } - pr_cont("\n"); - - netdev_dbg(dev, "buffer0 dump:\n"); + int ioaddr = dev->base_addr; + int count; + + netdev_dbg(dev, "register dump:\n"); + for (count = ioaddr; count < ioaddr + 16; count++) + { + if (!(count % 16)) + pr_cont("%04X:", count); + pr_cont(" %02X", inb(count)); + } + pr_cont("\n"); + + netdev_dbg(dev, "buffer0 dump:\n"); /* set up the address register */ - count = 0; + count = 0; outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); outb(count & 0xff, _ADDR_LO); - - for (count = 0; count < 256+32; count++) - { - if (!(count % 16)) - pr_cont("%04X:", count); - - /* copy the data */ - pr_cont(" %02X", inb(_MEMDATA)); - } - pr_cont("\n"); + + for (count = 0; count < 256 + 32; count++) + { + if (!(count % 16)) + pr_cont("%04X:", count); + + /* copy the data */ + pr_cont(" %02X", inb(_MEMDATA)); + } + pr_cont("\n"); #endif } @@ -114,169 +114,169 @@ static void com20020_detach(struct pcmcia_device *p_dev); static int com20020_probe(struct pcmcia_device *p_dev) { - struct com20020_dev *info; - struct net_device *dev; - struct arcnet_local *lp; + struct com20020_dev *info; + struct net_device *dev; + struct arcnet_local *lp; - dev_dbg(&p_dev->dev, "com20020_attach()\n"); + dev_dbg(&p_dev->dev, "com20020_attach()\n"); - /* Create new network device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - goto fail_alloc_info; + /* Create new network device */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto fail_alloc_info; - dev = alloc_arcdev(""); - if (!dev) - goto fail_alloc_dev; + dev = alloc_arcdev(""); + if (!dev) + goto fail_alloc_dev; - lp = netdev_priv(dev); - lp->timeout = timeout; - lp->backplane = backplane; - lp->clockp = clockp; - lp->clockm = clockm & 3; - lp->hw.owner = THIS_MODULE; + lp = netdev_priv(dev); + lp->timeout = timeout; + lp->backplane = backplane; + lp->clockp = clockp; + lp->clockm = clockm & 3; + lp->hw.owner = THIS_MODULE; - /* fill in our module parameters as defaults */ - dev->dev_addr[0] = node; + /* fill in our module parameters as defaults */ + dev->dev_addr[0] = node; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->resource[0]->end = 16; - p_dev->config_flags |= CONF_ENABLE_IRQ; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[0]->end = 16; + p_dev->config_flags |= CONF_ENABLE_IRQ; - info->dev = dev; - p_dev->priv = info; + info->dev = dev; + p_dev->priv = info; - return com20020_config(p_dev); + return com20020_config(p_dev); fail_alloc_dev: - kfree(info); + kfree(info); fail_alloc_info: - return -ENOMEM; + return -ENOMEM; } /* com20020_attach */ static void com20020_detach(struct pcmcia_device *link) { - struct com20020_dev *info = link->priv; - struct net_device *dev = info->dev; + struct com20020_dev *info = link->priv; + struct net_device *dev = info->dev; - dev_dbg(&link->dev, "detach...\n"); + dev_dbg(&link->dev, "detach...\n"); - dev_dbg(&link->dev, "com20020_detach\n"); + dev_dbg(&link->dev, "com20020_detach\n"); - dev_dbg(&link->dev, "unregister...\n"); + dev_dbg(&link->dev, "unregister...\n"); - unregister_netdev(dev); + unregister_netdev(dev); - /* - * this is necessary because we register our IRQ separately - * from card services. - */ - if (dev->irq) - free_irq(dev->irq, dev); + /* + * this is necessary because we register our IRQ separately + * from card services. + */ + if (dev->irq) + free_irq(dev->irq, dev); - com20020_release(link); + com20020_release(link); - /* Unlink device structure, free bits */ - dev_dbg(&link->dev, "unlinking...\n"); - if (link->priv) - { - dev = info->dev; - if (dev) + /* Unlink device structure, free bits */ + dev_dbg(&link->dev, "unlinking...\n"); + if (link->priv) { - dev_dbg(&link->dev, "kfree...\n"); - free_netdev(dev); + dev = info->dev; + if (dev) + { + dev_dbg(&link->dev, "kfree...\n"); + free_netdev(dev); + } + dev_dbg(&link->dev, "kfree2...\n"); + kfree(info); } - dev_dbg(&link->dev, "kfree2...\n"); - kfree(info); - } } /* com20020_detach */ static int com20020_config(struct pcmcia_device *link) { - struct arcnet_local *lp; - struct com20020_dev *info; - struct net_device *dev; - int i, ret; - int ioaddr; + struct arcnet_local *lp; + struct com20020_dev *info; + struct net_device *dev; + int i, ret; + int ioaddr; + + info = link->priv; + dev = info->dev; - info = link->priv; - dev = info->dev; + dev_dbg(&link->dev, "config...\n"); - dev_dbg(&link->dev, "config...\n"); + dev_dbg(&link->dev, "com20020_config\n"); - dev_dbg(&link->dev, "com20020_config\n"); + dev_dbg(&link->dev, "baseport1 is %Xh\n", + (unsigned int)link->resource[0]->start); - dev_dbg(&link->dev, "baseport1 is %Xh\n", - (unsigned int) link->resource[0]->start); + i = -ENODEV; + link->io_lines = 16; - i = -ENODEV; - link->io_lines = 16; + if (!link->resource[0]->start) + { + for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) + { + link->resource[0]->start = ioaddr; + i = pcmcia_request_io(link); + if (i == 0) + break; + } + } + else + i = pcmcia_request_io(link); + + if (i != 0) + { + dev_dbg(&link->dev, "requestIO failed totally!\n"); + goto failed; + } + + ioaddr = dev->base_addr = link->resource[0]->start; + dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); + + dev_dbg(&link->dev, "request IRQ %d\n", + link->irq); + if (!link->irq) + { + dev_dbg(&link->dev, "requestIRQ failed totally!\n"); + goto failed; + } - if (!link->resource[0]->start) - { - for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) + dev->irq = link->irq; + + ret = pcmcia_enable_device(link); + if (ret) + goto failed; + + if (com20020_check(dev)) { - link->resource[0]->start = ioaddr; - i = pcmcia_request_io(link); - if (i == 0) - break; + regdump(dev); + goto failed; } - } - else - i = pcmcia_request_io(link); - - if (i != 0) - { - dev_dbg(&link->dev, "requestIO failed totally!\n"); - goto failed; - } - - ioaddr = dev->base_addr = link->resource[0]->start; - dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); - - dev_dbg(&link->dev, "request IRQ %d\n", - link->irq); - if (!link->irq) - { - dev_dbg(&link->dev, "requestIRQ failed totally!\n"); - goto failed; - } - - dev->irq = link->irq; - - ret = pcmcia_enable_device(link); - if (ret) - goto failed; - - if (com20020_check(dev)) - { - regdump(dev); - goto failed; - } - - lp = netdev_priv(dev); - lp->card_name = "PCMCIA COM20020"; - lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ - - SET_NETDEV_DEV(dev, &link->dev); - - i = com20020_found(dev, 0); /* calls register_netdev */ - - if (i != 0) { - dev_notice(&link->dev, - "com20020_found() failed\n"); - goto failed; - } - - netdev_dbg(dev, "port %#3lx, irq %d\n", - dev->base_addr, dev->irq); - return 0; + + lp = netdev_priv(dev); + lp->card_name = "PCMCIA COM20020"; + lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ + + SET_NETDEV_DEV(dev, &link->dev); + + i = com20020_found(dev, 0); /* calls register_netdev */ + + if (i != 0) { + dev_notice(&link->dev, + "com20020_found() failed\n"); + goto failed; + } + + netdev_dbg(dev, "port %#3lx, irq %d\n", + dev->base_addr, dev->irq); + return 0; failed: - dev_dbg(&link->dev, "com20020_config failed...\n"); - com20020_release(link); - return -ENODEV; + dev_dbg(&link->dev, "com20020_config failed...\n"); + com20020_release(link); + return -ENODEV; } /* com20020_config */ static void com20020_release(struct pcmcia_device *link) @@ -312,9 +312,9 @@ static int com20020_resume(struct pcmcia_device *link) static const struct pcmcia_device_id com20020_ids[] = { PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", - "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), + "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), PCMCIA_DEVICE_PROD_ID12("SoHard AG", - "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7), + "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, com20020_ids); diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 487d780ebbdf..23ac9edbe91c 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers) - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . @@ -60,23 +60,23 @@ static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offse #define ARCNET_TOTAL_SIZE 16 /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ -#define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ -#define _ADDR_LO (ioaddr+14) -#define _CONFIG (ioaddr+2) /* Configuration register */ +#define _INTMASK (ioaddr + 0) /* writable */ +#define _STATUS (ioaddr + 0) /* readable */ +#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ +#define _RESET (ioaddr + 8) /* software reset (on read) */ +#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ +#define _ADDR_LO (ioaddr + 14) +#define _CONFIG (ioaddr + 2) /* Configuration register */ #undef ASTATUS #undef ACOMMAND #undef AINTMASK #define ASTATUS() inb(_STATUS) -#define ACOMMAND(cmd) outb((cmd),_COMMAND) -#define AINTMASK(msk) outb((msk),_INTMASK) -#define SETCONF() outb((lp->config),_CONFIG) +#define ACOMMAND(cmd) outb((cmd), _COMMAND) +#define AINTMASK(msk) outb((msk), _INTMASK) +#define SETCONF() outb((lp->config), _CONFIG) /**************************************************************************** diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index b80fbe40aa0e..a4c5d5909b13 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM90xx chipset (memory-mapped buffers) - * + * * Written 1994-1999 by Avery Pennarun. * Written 1999 by Martin Mares . * Derived from skeleton.c by Donald Becker. @@ -77,25 +77,25 @@ static int numcards; /* Amount of I/O memory used by the card */ #define BUFFER_SIZE (512) -#define MIRROR_SIZE (BUFFER_SIZE*4) +#define MIRROR_SIZE (BUFFER_SIZE * 4) /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ -#define _CONFIG (ioaddr+2) /* Configuration register */ -#define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ -#define _ADDR_LO (ioaddr+14) +#define _INTMASK (ioaddr + 0) /* writable */ +#define _STATUS (ioaddr + 0) /* readable */ +#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ +#define _CONFIG (ioaddr + 2) /* Configuration register */ +#define _RESET (ioaddr + 8) /* software reset (on read) */ +#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ +#define _ADDR_LO (ioaddr + 14) #undef ASTATUS #undef ACOMMAND #undef AINTMASK #define ASTATUS() inb(_STATUS) -#define ACOMMAND(cmd) outb((cmd),_COMMAND) -#define AINTMASK(msk) outb((msk),_INTMASK) +#define ACOMMAND(cmd) outb((cmd), _COMMAND) +#define AINTMASK(msk) outb((msk), _INTMASK) static int com90xx_skip_probe __initdata = 0; @@ -127,12 +127,12 @@ static void __init com90xx_probe(void) if (!io && !irq && !shmem && !*device && com90xx_skip_probe) return; - shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long), + shmems = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(unsigned long), GFP_KERNEL); if (!shmems) return; - iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *), - GFP_KERNEL); + iomem = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(void __iomem *), + GFP_KERNEL); if (!iomem) { kfree(shmems); return; @@ -579,7 +579,7 @@ static void com90xx_setmask(struct net_device *dev, int mask) /* * Do a hardware reset on the card, and set up necessary registers. - * + * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index f81db4070a57..ae1ded286897 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - RFC1051 ("simple" standard) packet encapsulation - * + * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * @@ -84,12 +84,12 @@ MODULE_LICENSE("GPL"); /* * Determine a packet's protocol ID. - * + * * With ARCnet we have to convert everything to Ethernet-style stuff. */ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) { - struct archdr *pkt = (struct archdr *) skb->data; + struct archdr *pkt = (struct archdr *)skb->data; struct arc_rfc1051 *soft = &pkt->soft.rfc1051; int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; @@ -146,7 +146,7 @@ static void rx(struct net_device *dev, int bufnum, skb_put(skb, length + ARC_HDR_SIZE); skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; /* up to sizeof(pkt->soft) has already been copied from the card */ memcpy(pkt, pkthdr, sizeof(struct archdr)); @@ -169,7 +169,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); struct arc_rfc1051 *soft = &pkt->soft.rfc1051; /* set the protocol ID according to RFC1051 */ @@ -201,7 +201,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* + /* * FIXME: fill in the last byte of the dest ipaddr here to better * comply with RFC1051 in "noarp" mode. */ diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index b71431aae084..bf2a8cb3f0e2 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - RFC1201 (standard) packet encapsulation - * + * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * @@ -86,12 +86,12 @@ module_exit(arcnet_rfc1201_exit); /* * Determine a packet's protocol ID. - * + * * With ARCnet we have to convert everything to Ethernet-style stuff. */ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) { - struct archdr *pkt = (struct archdr *) skb->data; + struct archdr *pkt = (struct archdr *)skb->data; struct arc_rfc1201 *soft = &pkt->soft.rfc1201; int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; @@ -169,7 +169,7 @@ static void rx(struct net_device *dev, int bufnum, if (in->skb) { /* already assembling one! */ BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, soft->sequence); + in->sequence, soft->split_flag, soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); dev->stats.rx_errors++; @@ -187,7 +187,7 @@ static void rx(struct net_device *dev, int bufnum, skb_put(skb, length + ARC_HDR_SIZE); skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; /* up to sizeof(pkt->soft) has already been copied from the card */ @@ -203,11 +203,11 @@ static void rx(struct net_device *dev, int bufnum, * (which is impossible to fumble) and insert it ourselves. */ if (soft->proto == ARC_P_ARP) { - struct arphdr *arp = (struct arphdr *) soft->payload; + struct arphdr *arp = (struct arphdr *)soft->payload; /* make sure addresses are the right length */ if (arp->ar_hln == 1 && arp->ar_pln == 4) { - uint8_t *cptr = (uint8_t *) arp + sizeof(struct arphdr); + uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr); if (!*cptr) { /* is saddr = 00? */ BUGMSG(D_EXTRA, @@ -274,7 +274,7 @@ static void rx(struct net_device *dev, int bufnum, dev_kfree_skb_irq(in->skb); } in->sequence = soft->sequence; - in->numpackets = ((unsigned) soft->split_flag >> 1) + 2; + in->numpackets = ((unsigned)soft->split_flag >> 1) + 2; in->lastpacket = 1; if (in->numpackets > 16) { @@ -294,7 +294,7 @@ static void rx(struct net_device *dev, int bufnum, return; } skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; memcpy(pkt, pkthdr, ARC_HDR_SIZE + RFC1201_HDR_SIZE); @@ -302,7 +302,7 @@ static void rx(struct net_device *dev, int bufnum, soft->split_flag = 0; /* end result won't be split */ } else { /* not first packet */ - int packetnum = ((unsigned) soft->split_flag >> 1) + 1; + int packetnum = ((unsigned)soft->split_flag >> 1) + 1; /* * if we're not assembling, there's no point trying to @@ -341,7 +341,7 @@ static void rx(struct net_device *dev, int bufnum, in->lastpacket = in->numpackets = 0; return; } - pkt = (struct archdr *) in->skb->data; + pkt = (struct archdr *)in->skb->data; soft = &pkt->soft.rfc1201; } @@ -357,10 +357,10 @@ static void rx(struct net_device *dev, int bufnum, in->skb = NULL; in->lastpacket = in->numpackets = 0; - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", - skb->len, pkt->hard.source); - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", - skb->len, pkt->hard.source); + BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", + skb->len, pkt->hard.source); + BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", + skb->len, pkt->hard.source); BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); @@ -376,7 +376,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, { struct arcnet_local *lp = netdev_priv(dev); int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); struct arc_rfc1201 *soft = &pkt->soft.rfc1201; /* set the protocol ID according to RFC1201 */ @@ -424,7 +424,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* + /* * FIXME: fill in the last byte of the dest ipaddr here to better * comply with RFC1051 in "noarp" mode. For now, always broadcasting * will probably at least get packets sent out :) @@ -517,7 +517,7 @@ static int continue_tx(struct net_device *dev, int bufnum) int seglen; BUGMSG(D_DURING, - "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", + "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", out->segnum, out->numsegs, soft->sequence); /* the "new" soft header comes right before the data chunk */ diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index df0356220730..ccfd1d2f984b 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -51,7 +51,7 @@ /* * Debugging bitflags: each option can be enabled individually. - * + * * Note: only debug flags included in the ARCNET_DEBUG_MAX define will * actually be available. GCC will (at least, GCC 2.7.0 will) notice * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize @@ -77,33 +77,33 @@ #endif #ifndef ARCNET_DEBUG -#define ARCNET_DEBUG (D_NORMAL|D_EXTRA) +#define ARCNET_DEBUG (D_NORMAL | D_EXTRA) #endif extern int arcnet_debug; /* macros to simplify debug checking */ -#define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x)) -#define BUGMSG2(x,msg,args...) do { BUGLVL(x) printk(msg, ## args); } while (0) -#define BUGMSG(x,msg,args...) \ - BUGMSG2(x, "%s%6s: " msg, \ - x==D_NORMAL ? KERN_WARNING \ - : x < D_DURING ? KERN_INFO : KERN_DEBUG, \ - dev->name , ## args) +#define BUGLVL(x) if ((ARCNET_DEBUG_MAX) & arcnet_debug & (x)) +#define BUGMSG2(x, msg, args...) do { BUGLVL(x) printk(msg, ## args); } while (0) +#define BUGMSG(x, msg, args...) \ + BUGMSG2(x, "%s%6s: " msg, \ + x == D_NORMAL ? KERN_WARNING \ + : x < D_DURING ? KERN_INFO : KERN_DEBUG, \ + dev->name, ## args) /* see how long a function call takes to run, expressed in CPU cycles */ -#define TIME(name, bytes, call) BUGLVL(D_TIMING) { \ - unsigned long _x, _y; \ - _x = get_cycles(); \ - call; \ - _y = get_cycles(); \ - BUGMSG(D_TIMING, \ - "%s: %d bytes in %lu cycles == " \ - "%lu Kbytes/100Mcycle\n",\ - name, bytes, _y - _x, \ - 100000000 / 1024 * bytes / (_y - _x + 1));\ - } \ - else { \ - call;\ +#define TIME(name, bytes, call) BUGLVL(D_TIMING) { \ + unsigned long _x, _y; \ + _x = get_cycles(); \ + call; \ + _y = get_cycles(); \ + BUGMSG(D_TIMING, \ + "%s: %d bytes in %lu cycles == " \ + "%lu Kbytes/100Mcycle\n", \ + name, bytes, _y - _x, \ + 100000000 / 1024 * bytes / (_y - _x + 1)); \ + } \ + else { \ + call; \ } @@ -189,16 +189,16 @@ struct ArcProto { int mtu; /* largest possible packet */ int is_ip; /* This is a ip plugin - not a raw thing */ - void (*rx) (struct net_device * dev, int bufnum, - struct archdr * pkthdr, int length); - int (*build_header) (struct sk_buff * skb, struct net_device *dev, - unsigned short ethproto, uint8_t daddr); + void (*rx)(struct net_device *dev, int bufnum, + struct archdr *pkthdr, int length); + int (*build_header)(struct sk_buff *skb, struct net_device *dev, + unsigned short ethproto, uint8_t daddr); /* these functions return '1' if the skb can now be freed */ - int (*prepare_tx) (struct net_device * dev, struct archdr * pkt, int length, - int bufnum); - int (*continue_tx) (struct net_device * dev, int bufnum); - int (*ack_tx) (struct net_device * dev, int acked); + int (*prepare_tx)(struct net_device *dev, struct archdr *pkt, int length, + int bufnum); + int (*continue_tx)(struct net_device *dev, int bufnum); + int (*ack_tx)(struct net_device *dev, int acked); }; extern struct ArcProto *arc_proto_map[256], *arc_proto_default, @@ -263,13 +263,13 @@ struct arcnet_local { * situations in which we (for example) want to pre-load a transmit * buffer, or start receiving while we copy a received packet to * memory. - * + * * The rules: only the interrupt handler is allowed to _add_ buffers to * the queue; thus, this doesn't require a lock. Both the interrupt * handler and the transmit function will want to _remove_ buffers, so * we need to handle the situation where they try to do it at the same * time. - * + * * If next_buf == first_free_buf, the queue is empty. Since there are * only four possible buffers, the queue should never be full. */ @@ -298,17 +298,17 @@ struct arcnet_local { /* hardware-specific functions */ struct { struct module *owner; - void (*command) (struct net_device * dev, int cmd); - int (*status) (struct net_device * dev); - void (*intmask) (struct net_device * dev, int mask); - int (*reset) (struct net_device * dev, int really_reset); - void (*open) (struct net_device * dev); - void (*close) (struct net_device * dev); - - void (*copy_to_card) (struct net_device * dev, int bufnum, int offset, - void *buf, int count); - void (*copy_from_card) (struct net_device * dev, int bufnum, int offset, - void *buf, int count); + void (*command)(struct net_device *dev, int cmd); + int (*status)(struct net_device *dev); + void (*intmask)(struct net_device *dev, int mask); + int (*reset)(struct net_device *dev, int really_reset); + void (*open)(struct net_device *dev); + void (*close)(struct net_device *dev); + + void (*copy_to_card)(struct net_device *dev, int bufnum, int offset, + void *buf, int count); + void (*copy_from_card)(struct net_device *dev, int bufnum, int offset, + void *buf, int count); } hw; void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ @@ -325,7 +325,7 @@ struct arcnet_local { #if ARCNET_DEBUG_MAX & D_SKB void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #else -#define arcnet_dump_skb(dev,skb,desc) ; +#define arcnet_dump_skb(dev, skb, desc) ; #endif void arcnet_unregister_proto(struct ArcProto *proto); @@ -335,7 +335,7 @@ struct net_device *alloc_arcdev(const char *name); int arcnet_open(struct net_device *dev); int arcnet_close(struct net_device *dev); netdev_tx_t arcnet_send_packet(struct sk_buff *skb, - struct net_device *dev); + struct net_device *dev); void arcnet_timeout(struct net_device *dev); #endif /* __KERNEL__ */ -- cgit v1.3-6-gb490 From 01a1d5ac4e1a5890fd6c0d0ae900e1b6e4f851d6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:48 -0700 Subject: arcnet: Add and remove blank lines Use a more current kernel line style. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 5 ----- drivers/net/arcnet/arc-rimi.c | 8 +++----- drivers/net/arcnet/arcnet.c | 23 +++-------------------- drivers/net/arcnet/capmode.c | 3 --- drivers/net/arcnet/com20020-isa.c | 1 - drivers/net/arcnet/com20020-pci.c | 2 -- drivers/net/arcnet/com20020.c | 8 ++------ drivers/net/arcnet/com20020_cs.c | 4 +--- drivers/net/arcnet/com90io.c | 12 +----------- drivers/net/arcnet/com90xx.c | 13 +++---------- drivers/net/arcnet/rfc1051.c | 7 ------- drivers/net/arcnet/rfc1201.c | 8 -------- include/linux/arcdevice.h | 12 ------------ 13 files changed, 13 insertions(+), 93 deletions(-) (limited to 'include') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 49f5819a0367..251a98b0bf78 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -35,7 +35,6 @@ #define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n" - static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); static int build_header(struct sk_buff *skb, struct net_device *dev, @@ -54,7 +53,6 @@ static struct ArcProto rawmode_proto = .ack_tx = NULL }; - static int __init arcnet_raw_init(void) { int count; @@ -83,7 +81,6 @@ module_exit(arcnet_raw_exit); MODULE_LICENSE("GPL"); - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -127,7 +124,6 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } - /* * Create the ARCnet hard/soft headers for raw mode. * There aren't any soft headers in raw mode - not even the protocol id. @@ -163,7 +159,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return hdr_size; /* success */ } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 4644d46b6a5f..e8c15016bb8e 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -36,10 +36,8 @@ #include #include - #define VERSION "arcnet: RIM I (entirely mem-mapped) support\n" - /* Internal function declarations */ static int arcrimi_probe(struct net_device *dev); @@ -78,7 +76,6 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse #define AINTMASK(msk) writeb((msk), _INTMASK) #define SETCONF() writeb(lp->config, _CONFIG) - /* * We cannot probe for a RIM I card; one reason is I don't know how to reset * them. In fact, we can't even get their node ID automatically. So, we @@ -249,7 +246,6 @@ err_free_irq: return -EIO; } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -308,15 +304,16 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; + TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } - static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; + TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } @@ -374,6 +371,7 @@ static void __exit arc_rimi_exit(void) static int __init arcrimi_setup(char *s) { int ints[8]; + s = get_options(s, 8, ints); if (!ints[0]) return 1; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 2a594d1c4b55..bb49753f8203 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -168,7 +168,6 @@ void arcnet_dump_skb(struct net_device *dev, EXPORT_SYMBOL(arcnet_dump_skb); #endif - /* * Dump the contents of an ARCnet buffer */ @@ -206,7 +205,6 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #endif - /* * Unregister a protocol driver from the arc_proto_map. Protocol drivers * are responsible for registering themselves, but the unregister routine @@ -229,7 +227,6 @@ void arcnet_unregister_proto(struct ArcProto *proto) } } - /* * Add a buffer to the queue. Only the interrupt handler is allowed to do * this, unless interrupts are disabled. @@ -254,7 +251,6 @@ static void release_arcbuf(struct net_device *dev, int bufnum) } } - /* * Get a buffer from the queue. If this returns -1, there are no buffers * available. @@ -281,7 +277,6 @@ static int get_arcbuf(struct net_device *dev) } } - BUGLVL(D_DURING) { BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) @@ -293,7 +288,6 @@ static int get_arcbuf(struct net_device *dev) return buf; } - static int choose_mtu(void) { int count, mtu = 65535; @@ -348,6 +342,7 @@ struct net_device *alloc_arcdev(const char *name) arcdev_setup); if (dev) { struct arcnet_local *lp = netdev_priv(dev); + spin_lock_init(&lp->lock); } @@ -380,7 +375,6 @@ int arcnet_open(struct net_device *dev) BUGMSG2(D_PROTO, "\n"); } - BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); /* try to put the card in a defined state - if it fails the first @@ -437,7 +431,6 @@ int arcnet_open(struct net_device *dev) ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); @@ -459,7 +452,6 @@ int arcnet_open(struct net_device *dev) return error; } - /* The inverse routine to arcnet_open - shuts down the card. */ int arcnet_close(struct net_device *dev) { @@ -479,7 +471,6 @@ int arcnet_close(struct net_device *dev) return 0; } - static int arcnet_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len) @@ -498,7 +489,6 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", skb->len, len); - /* Type is host order - ? */ if (type == ETH_P_ARCNET) { proto = arc_raw_proto; @@ -622,7 +612,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, return retval; /* no need to try again */ } - /* * Actually start transmitting a packet that was loaded into a buffer * by prepare_tx. This should _only_ be called by the interrupt handler. @@ -654,7 +643,6 @@ static int go_tx(struct net_device *dev) return 1; } - /* Called by the kernel when transmit times out */ void arcnet_timeout(struct net_device *dev) { @@ -691,7 +679,6 @@ void arcnet_timeout(struct net_device *dev) netif_wake_queue(dev); } - /* * The typical workload of the driver: Handle the network interface * interrupts. Establish which device needs attention, and call the correct @@ -787,7 +774,6 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) didsomething++; } - /* a transmit finished, and we're interested in it. */ if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~(TXFREEflag | EXCNAKflag); @@ -814,6 +800,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto && lp->outgoing.proto->ack_tx) { int ackstatus; + if (status & TXACKflag) ackstatus = 2; else if (lp->excnak_pending) @@ -838,6 +825,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) /* continue a split packet, if any */ if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) { int txbuf = get_arcbuf(dev); + if (txbuf != -1) { if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ @@ -930,7 +918,6 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) ASTATUS(), boguscount); BUGMSG(D_DURING, "\n"); - AINTMASK(0); udelay(1); AINTMASK(lp->intmask); @@ -939,7 +926,6 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) return retval; } - /* * This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. @@ -1002,7 +988,6 @@ static void arcnet_rx(struct net_device *dev, int bufnum) arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length); } - static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { @@ -1011,7 +996,6 @@ static void null_rx(struct net_device *dev, int bufnum, pkthdr->soft.rfc1201.proto, pkthdr->hard.source); } - static int null_build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { @@ -1025,7 +1009,6 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev, return 0; } - /* the "do nothing" prepare_tx function warns that there's nothing to do. */ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 95a6cf07965c..02815ff891f2 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -90,7 +90,6 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } - /* * Create the ARCnet hard/soft headers for cap mode. * There aren't any soft headers in cap mode - not even the protocol id. @@ -130,7 +129,6 @@ static int build_header(struct sk_buff *skb, return hdr_size; /* success */ } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { @@ -138,7 +136,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, struct arc_hardware *hard = &pkt->hard; int ofs; - /* hard header is not included in packet length */ length -= ARC_HDR_SIZE; /* And neither is the cookie field */ diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index d8746caf8e7a..c7d3377a45fe 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -43,7 +43,6 @@ #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" - /* * We cannot (yet) probe for an IO mapped card, although we can check that * it's where we were told it was, and even do autoirq. diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index e0f489a117f1..06621e95bd38 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -42,7 +42,6 @@ #include - #define VERSION "arcnet: COM20020 PCI support\n" /* Module parameters */ @@ -86,7 +85,6 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i INIT_LIST_HEAD(&priv->list_dev); - for (i = 0; i < ci->devcount; i++) { struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i]; struct com20020_dev *card; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index cd2a5ca56ce5..c749af6db94e 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -70,7 +70,6 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum, TIME("insb", count, insb(_MEMDATA, buf, count)); } - static void com20020_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { @@ -84,7 +83,6 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum, TIME("outsb", count, outsb(_MEMDATA, buf, count)); } - /* Reset the card and check some basic stuff during the detection stage. */ int com20020_check(struct net_device *dev) { @@ -242,7 +240,6 @@ int com20020_found(struct net_device *dev, int shared) return 0; } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -295,22 +292,21 @@ static int com20020_reset(struct net_device *dev, int really_reset) return 0; } - static void com20020_setmask(struct net_device *dev, int mask) { u_int ioaddr = dev->base_addr; + BUGMSG(D_DURING, "Setting mask to %x at %x\n", mask, ioaddr); AINTMASK(mask); } - static void com20020_command(struct net_device *dev, int cmd) { u_int ioaddr = dev->base_addr; + ACOMMAND(cmd); } - static int com20020_status(struct net_device *dev) { u_int ioaddr = dev->base_addr; diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index f68752102379..2eafb298626b 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -49,7 +49,6 @@ #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" - static void regdump(struct net_device *dev) { #ifdef DEBUG @@ -83,8 +82,6 @@ static void regdump(struct net_device *dev) #endif } - - /*====================================================================*/ /* Parameters that can be set with 'insmod' */ @@ -304,6 +301,7 @@ static int com20020_resume(struct pcmcia_device *link) if (link->open) { int ioaddr = dev->base_addr; struct arcnet_local *lp = netdev_priv(dev); + ARCRESET; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 23ac9edbe91c..11d2d0b4ccea 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -37,10 +37,8 @@ #include #include - #define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n" - /* Internal function declarations */ static int com90io_found(struct net_device *dev); @@ -53,7 +51,6 @@ static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); - /* Handy defines for ARCnet specific stuff */ /* The number of low I/O ports used by the card. */ @@ -78,7 +75,6 @@ static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offse #define AINTMASK(msk) outb((msk), _INTMASK) #define SETCONF() outb((lp->config), _CONFIG) - /**************************************************************************** * * * IO-mapped operation routines * @@ -111,7 +107,6 @@ static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datu #endif - static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) { int ioaddr = dev->base_addr; @@ -227,7 +222,6 @@ err_out: return -ENODEV; } - /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ @@ -279,7 +273,6 @@ static int __init com90io_found(struct net_device *dev) return 0; } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -319,7 +312,6 @@ static int com90io_reset(struct net_device *dev, int really_reset) return 0; } - static void com90io_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; @@ -327,7 +319,6 @@ static void com90io_command(struct net_device *dev, int cmd) ACOMMAND(cmd); } - static int com90io_status(struct net_device *dev) { short ioaddr = dev->base_addr; @@ -335,7 +326,6 @@ static int com90io_status(struct net_device *dev) return ASTATUS(); } - static void com90io_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; @@ -349,7 +339,6 @@ static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } - static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { @@ -369,6 +358,7 @@ MODULE_LICENSE("GPL"); static int __init com90io_setup(char *s) { int ints[4]; + s = get_options(s, 4, ints); if (!ints[0]) return 0; diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index a4c5d5909b13..f0f06a274045 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -35,10 +35,8 @@ #include #include - #define VERSION "arcnet: COM90xx chipset support\n" - /* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each * other. @@ -53,7 +51,6 @@ */ #undef FAST_PROBE - /* Internal function declarations */ static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *); static void com90xx_command(struct net_device *dev, int command); @@ -97,7 +94,6 @@ static int numcards; #define ACOMMAND(cmd) outb((cmd), _COMMAND) #define AINTMASK(msk) outb((msk), _INTMASK) - static int com90xx_skip_probe __initdata = 0; /* Module parameters */ @@ -308,6 +304,7 @@ static void __init com90xx_probe(void) numprint = -1; for (port = &ports[0]; port < ports + numports; port++) { int found = 0; + numprint++; numprint %= 8; if (!numprint) { @@ -552,7 +549,6 @@ err_free_dev: return -EIO; } - static void com90xx_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; @@ -560,7 +556,6 @@ static void com90xx_command(struct net_device *dev, int cmd) ACOMMAND(cmd); } - static int com90xx_status(struct net_device *dev) { short ioaddr = dev->base_addr; @@ -568,7 +563,6 @@ static int com90xx_status(struct net_device *dev) return ASTATUS(); } - static void com90xx_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; @@ -576,7 +570,6 @@ static void com90xx_setmask(struct net_device *dev, int mask) AINTMASK(mask); } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -625,19 +618,19 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; + TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } - static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; + TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } - MODULE_LICENSE("GPL"); static int __init com90xx_init(void) diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index ae1ded286897..49d35c972bca 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -34,7 +34,6 @@ #define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n" - static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); @@ -43,7 +42,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); - static struct ArcProto rfc1051_proto = { .suffix = 's', @@ -56,7 +54,6 @@ static struct ArcProto rfc1051_proto = .ack_tx = NULL }; - static int __init arcnet_rfc1051_init(void) { printk(VERSION); @@ -120,7 +117,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_IP); } - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -161,7 +157,6 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } - /* * Create the ARCnet hard/soft headers for RFC1051. */ @@ -188,7 +183,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return 0; } - /* * Set the source hardware address. * @@ -214,7 +208,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return hdr_size; /* success */ } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index bf2a8cb3f0e2..15f103a8a9db 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -34,7 +34,6 @@ MODULE_LICENSE("GPL"); #define VERSION "arcnet: RFC1201 \"standard\" (`a') encapsulation support loaded.\n" - static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); @@ -56,7 +55,6 @@ static struct ArcProto rfc1201_proto = .ack_tx = NULL }; - static int __init arcnet_rfc1201_init(void) { printk(VERSION); @@ -129,7 +127,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_IP); } - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -369,7 +366,6 @@ static void rx(struct net_device *dev, int bufnum, } } - /* Create the ARCnet hard/soft headers for RFC1201. */ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) @@ -437,7 +433,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return hdr_size; } - static void load_pkt(struct net_device *dev, struct arc_hardware *hard, struct arc_rfc1201 *soft, int softlen, int bufnum) { @@ -470,7 +465,6 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard, lp->lastload_dest = hard->dest; } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { @@ -478,7 +472,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, const int maxsegsize = XMTU - RFC1201_HDR_SIZE; struct Outgoing *out; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); @@ -506,7 +499,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, return 1; /* done */ } - static int continue_tx(struct net_device *dev, int bufnum) { struct arcnet_local *lp = netdev_priv(dev); diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index ccfd1d2f984b..78687885eb81 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -34,7 +34,6 @@ */ #define RECON_THRESHOLD 30 - /* * Define this to the minimum "timeout" value. If a transmit takes longer * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large @@ -44,11 +43,9 @@ */ #define TX_TIMEOUT (HZ * 200 / 1000) - /* Display warnings about the driver being an ALPHA version. */ #undef ALPHA_WARNING - /* * Debugging bitflags: each option can be enabled individually. * @@ -106,7 +103,6 @@ extern int arcnet_debug; call; \ } - /* * Time needed to reset the card - in ms (milliseconds). This works on my * SMC PC100. I can't find a reference that tells me just how long I @@ -182,7 +178,6 @@ extern int arcnet_debug; #define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit, but default is 2.5MBit. */ - /* information needed to define an encapsulation driver */ struct ArcProto { char suffix; /* a for RFC1201, e for ether-encap, etc. */ @@ -204,7 +199,6 @@ struct ArcProto { extern struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto, *arc_raw_proto; - /* * "Incoming" is information needed for each address that could be sending * to us. Mostly for partially-received split packets. @@ -216,7 +210,6 @@ struct Incoming { numpackets; /* number of packets in split */ }; - /* only needed for RFC1201 */ struct Outgoing { struct ArcProto *proto; /* protocol driver that owns this: @@ -230,7 +223,6 @@ struct Outgoing { numsegs; /* number of segments */ }; - struct arcnet_local { uint8_t config, /* current value of CONFIG register */ timeout, /* Extended timeout for COM20020 */ @@ -251,7 +243,6 @@ struct arcnet_local { char *card_name; /* card ident string */ int card_flags; /* special card features */ - /* On preemtive and SMB a lock is needed */ spinlock_t lock; @@ -314,14 +305,11 @@ struct arcnet_local { void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ }; - #define ARCRESET(x) (lp->hw.reset(dev, (x))) #define ACOMMAND(x) (lp->hw.command(dev, (x))) #define ASTATUS() (lp->hw.status(dev)) #define AINTMASK(x) (lp->hw.intmask(dev, (x))) - - #if ARCNET_DEBUG_MAX & D_SKB void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #else -- cgit v1.3-6-gb490 From d77510f3436e0db9b5e72fa8159ce26c3ac88d2d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:53 -0700 Subject: arcnet: Neaten BUGMSG macro defines These macros are actually printk and pr_cont uses with a flag. Add a new BUGLVL_TEST macro which is just the "should use" test and not an odd "if ()" macro to simplify uses in a new patch. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- include/linux/arcdevice.h | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index 78687885eb81..ad610208fbba 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -78,14 +78,24 @@ #endif extern int arcnet_debug; +#define BUGLVL_TEST(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) +#define BUGLVL(x) if (BUGLVL_TEST(x)) + /* macros to simplify debug checking */ -#define BUGLVL(x) if ((ARCNET_DEBUG_MAX) & arcnet_debug & (x)) -#define BUGMSG2(x, msg, args...) do { BUGLVL(x) printk(msg, ## args); } while (0) -#define BUGMSG(x, msg, args...) \ - BUGMSG2(x, "%s%6s: " msg, \ - x == D_NORMAL ? KERN_WARNING \ - : x < D_DURING ? KERN_INFO : KERN_DEBUG, \ - dev->name, ## args) +#define BUGMSG(x, fmt, ...) \ +do { \ + if (BUGLVL_TEST(x)) \ + printk("%s%6s: " fmt, \ + (x) == D_NORMAL ? KERN_WARNING : \ + (x) < D_DURING ? KERN_INFO : KERN_DEBUG, \ + dev->name, ##__VA_ARGS__); \ +} while (0) + +#define BUGMSG2(x, fmt, ...) \ +do { \ + if (BUGLVL_TEST(x)) \ + printk(fmt, ##__VA_ARGS__); \ +} while (0) /* see how long a function call takes to run, expressed in CPU cycles */ #define TIME(name, bytes, call) BUGLVL(D_TIMING) { \ -- cgit v1.3-6-gb490 From 72aeea4841c037b9b3abf65859673cbd7b6664a9 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:54 -0700 Subject: arcnet: Expand odd BUGLVL macro with if and uses Don't hide what should be obvious. Make the macro a simple test instead of using if and test. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 3 ++- drivers/net/arcnet/arc-rimi.c | 20 +++++++++------- drivers/net/arcnet/arcnet.c | 29 ++++++++++++----------- drivers/net/arcnet/capmode.c | 9 ++++--- drivers/net/arcnet/com20020-isa.c | 3 ++- drivers/net/arcnet/com20020-pci.c | 3 ++- drivers/net/arcnet/com20020.c | 3 ++- drivers/net/arcnet/com90io.c | 6 +++-- drivers/net/arcnet/com90xx.c | 49 +++++++++++++++++++++++++-------------- drivers/net/arcnet/rfc1051.c | 3 ++- drivers/net/arcnet/rfc1201.c | 6 +++-- include/linux/arcdevice.h | 17 +++++++------- 12 files changed, 93 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index efdd8e95a2bf..998c8356e576 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -117,7 +117,8 @@ static void rx(struct net_device *dev, int bufnum, pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = cpu_to_be16(ETH_P_ARCNET); netif_rx(skb); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index c7ab23e8ec6a..cd47a1b3008c 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -82,18 +82,21 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse */ static int __init arcrimi_probe(struct net_device *dev) { - BUGLVL(D_NORMAL) printk(VERSION); - BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); - - BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n", - dev->dev_addr[0], dev->mem_start, dev->irq); + if (BUGLVL(D_NORMAL)) { + printk(VERSION); + printk("E-mail me if you actually test the RIM I driver, please!\n"); + printk("Given: node %02Xh, shmem %lXh, irq %d\n", + dev->dev_addr[0], dev->mem_start, dev->irq); + } if (dev->mem_start <= 0 || dev->irq <= 0) { - BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you must specify the shmem and irq!\n"); + if (BUGLVL(D_NORMAL)) + printk("No autoprobe for RIM I; you must specify the shmem and irq!\n"); return -ENODEV; } if (dev->dev_addr[0] == 0) { - BUGLVL(D_NORMAL) printk("You need to specify your card's station ID!\n"); + if (BUGLVL(D_NORMAL)) + printk("You need to specify your card's station ID!\n"); return -ENODEV; } /* Grab the memory region at mem_start for MIRROR_SIZE bytes. @@ -102,7 +105,8 @@ static int __init arcrimi_probe(struct net_device *dev) * will be taken. */ if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) { - BUGLVL(D_NORMAL) printk("Card memory already allocated\n"); + if (BUGLVL(D_NORMAL)) + printk("Card memory already allocated\n"); return -ENODEV; } return arcrimi_found(dev); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 605b4a7abecc..7a90b8a45a37 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -117,7 +117,7 @@ static int __init arcnet_init(void) printk("arcnet loaded.\n"); #ifdef ALPHA_WARNING - BUGLVL(D_EXTRA) { + if (BUGLVL(D_EXTRA)) { printk("arcnet: ***\n" "arcnet: * Read arcnet.txt for important release notes!\n" "arcnet: *\n" @@ -132,11 +132,11 @@ static int __init arcnet_init(void) for (count = 0; count < 256; count++) arc_proto_map[count] = arc_proto_default; - BUGLVL(D_DURING) - printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", - sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), - sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), - sizeof(struct archdr)); + if (BUGLVL(D_DURING)) + printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", + sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), + sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), + sizeof(struct archdr)); return 0; } @@ -235,7 +235,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum) lp->buf_queue[lp->first_free_buf++] = bufnum; lp->first_free_buf %= 5; - BUGLVL(D_DURING) { + if (BUGLVL(D_DURING)) { BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", bufnum); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) @@ -268,7 +268,7 @@ static int get_arcbuf(struct net_device *dev) } } - BUGLVL(D_DURING) { + if (BUGLVL(D_DURING)) { BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); @@ -356,7 +356,7 @@ int arcnet_open(struct net_device *dev) if (!try_module_get(lp->hw.owner)) return -ENODEV; - BUGLVL(D_PROTO) { + if (BUGLVL(D_PROTO)) { BUGMSG(D_PROTO, "protocol map (default is '%c'): ", arc_proto_default->suffix); for (count = 0; count < 256; count++) @@ -531,7 +531,8 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", skb->len, pkt->hard.dest); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "tx"); /* fits in one packet? */ if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) { @@ -609,7 +610,8 @@ static int go_tx(struct net_device *dev) if (lp->cur_tx != -1 || lp->next_tx == -1) return 0; - BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); + if (BUGLVL(D_TX)) + arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); lp->cur_tx = lp->next_tx; lp->next_tx = -1; @@ -822,7 +824,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } /* now process the received packet, if any */ if (recbuf != -1) { - BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0); + if (BUGLVL(D_RX)) + arcnet_dump_packet(dev, recbuf, "rx irq", 0); arcnet_rx(dev, recbuf); release_arcbuf(dev, recbuf); @@ -938,7 +941,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum) /* call the right receiver for the protocol */ if (arc_proto_map[soft->proto]->is_ip) { - BUGLVL(D_PROTO) { + if (BUGLVL(D_PROTO)) { struct ArcProto *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]], *newp = arc_proto_map[soft->proto]; diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 8391324f684b..e7ec907f4680 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -84,7 +84,8 @@ static void rx(struct net_device *dev, int bufnum, + sizeof(int), length - sizeof(pkt->soft)); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = cpu_to_be16(ETH_P_ARCNET); netif_rx(skb); @@ -190,7 +191,8 @@ static int ack_tx(struct net_device *dev, int acked) BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", lp->outgoing.skb->protocol, acked); - BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); /* Now alloc a skb to send back up through the layers: */ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); @@ -216,7 +218,8 @@ static int ack_tx(struct net_device *dev, int acked) ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); - BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); netif_rx(ackskb); free_outskb: diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 6e38a19d7210..af87c7482478 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -53,7 +53,8 @@ static int __init com20020isa_probe(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int err; - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); ioaddr = dev->base_addr; if (!ioaddr) { diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 72334b59aa26..c8184de4480d 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -402,7 +402,8 @@ static struct pci_driver com20020pci_driver = { static int __init com20020pci_init(void) { - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); return pci_register_driver(&com20020pci_driver); } diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 63697272f146..3170e8ebb7fa 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -365,7 +365,8 @@ MODULE_LICENSE("GPL"); static int __init com20020_module_init(void) { - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); return 0; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 6ec36f9975ba..33a8531e90c7 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -145,8 +145,10 @@ static int __init com90io_probe(struct net_device *dev) int ioaddr = dev->base_addr, status; unsigned long airqmask; - BUGLVL(D_NORMAL) printk(VERSION); - BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n"); + if (BUGLVL(D_NORMAL)) { + printk(VERSION); + printk("E-mail me if you actually test this driver, please!\n"); + } if (!ioaddr) { BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you must specify the base address!\n"); diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 4781cd696dd1..b5e1c1904f13 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -133,7 +133,8 @@ static void __init com90xx_probe(void) return; } - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); /* set up the arrays where we'll store the possible probe addresses */ numports = numshmems = 0; @@ -166,14 +167,16 @@ static void __init com90xx_probe(void) if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { BUGMSG2(D_INIT_REASONS, "(request_region)\n"); BUGMSG2(D_INIT_REASONS, "S1: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; *port-- = ports[--numports]; continue; } if (ASTATUS() == 0xFF) { BUGMSG2(D_INIT_REASONS, "(empty)\n"); BUGMSG2(D_INIT_REASONS, "S1: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -182,7 +185,8 @@ static void __init com90xx_probe(void) BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "S1: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; } BUGMSG2(D_INIT, "\n"); @@ -227,21 +231,24 @@ static void __init com90xx_probe(void) if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) { BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; goto out; } base = ioremap(*p, MIRROR_SIZE); if (!base) { BUGMSG2(D_INIT_REASONS, "(ioremap)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; goto out1; } if (readb(base) != TESTvalue) { BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", readb(base), TESTvalue); BUGMSG2(D_INIT_REASONS, "S3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; goto out2; } /* By writing 0x42 to the TESTvalue location, we also make @@ -257,7 +264,8 @@ static void __init com90xx_probe(void) } BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "S3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; iomem[index] = base; continue; out2: @@ -319,7 +327,8 @@ static void __init com90xx_probe(void) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); BUGMSG2(D_INIT_REASONS, "S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -330,7 +339,8 @@ static void __init com90xx_probe(void) BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", status); BUGMSG2(D_INIT_REASONS, "S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -352,7 +362,8 @@ static void __init com90xx_probe(void) if (airq <= 0) { BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); BUGMSG2(D_INIT_REASONS, "S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -406,16 +417,20 @@ static void __init com90xx_probe(void) } if (openparen) { - BUGLVL(D_INIT) printk("no matching shmem)\n"); - BUGLVL(D_INIT_REASONS) printk("S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT)) + printk("no matching shmem)\n"); + if (BUGLVL(D_INIT_REASONS)) { + printk("S5: "); + numprint = 0; + } } if (!found) release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; } - BUGLVL(D_INIT_REASONS) printk("\n"); + if (BUGLVL(D_INIT_REASONS)) + printk("\n"); /* Now put back TESTvalue on all leftover shmems. */ for (index = 0; index < numshmems; index++) { @@ -603,8 +618,8 @@ static int com90xx_reset(struct net_device *dev, int really_reset) ACOMMAND(CONFIGcmd | EXTconf); /* clean out all the memory to make debugging make more sense :) */ - BUGLVL(D_DURING) - memset_io(lp->mem_start, 0x42, 2048); + if (BUGLVL(D_DURING)) + memset_io(lp->mem_start, 0x42, 2048); /* done! return success. */ return 0; diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index e78b76535acc..824d71fcfd53 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -149,7 +149,8 @@ static void rx(struct net_device *dev, int bufnum, pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); netif_rx(skb); diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 4ebfbcbe5de3..d052976ebdfa 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -221,7 +221,8 @@ static void rx(struct net_device *dev, int bufnum, dev->stats.rx_crc_errors++; } } - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); netif_rx(skb); @@ -353,7 +354,8 @@ static void rx(struct net_device *dev, int bufnum, skb->len, pkt->hard.source); BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", skb->len, pkt->hard.source); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); netif_rx(skb); diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index ad610208fbba..f07c66383b88 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -78,13 +78,12 @@ #endif extern int arcnet_debug; -#define BUGLVL_TEST(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) -#define BUGLVL(x) if (BUGLVL_TEST(x)) +#define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) /* macros to simplify debug checking */ #define BUGMSG(x, fmt, ...) \ do { \ - if (BUGLVL_TEST(x)) \ + if (BUGLVL(x)) \ printk("%s%6s: " fmt, \ (x) == D_NORMAL ? KERN_WARNING : \ (x) < D_DURING ? KERN_INFO : KERN_DEBUG, \ @@ -93,12 +92,14 @@ do { \ #define BUGMSG2(x, fmt, ...) \ do { \ - if (BUGLVL_TEST(x)) \ + if (BUGLVL(x)) \ printk(fmt, ##__VA_ARGS__); \ } while (0) /* see how long a function call takes to run, expressed in CPU cycles */ -#define TIME(name, bytes, call) BUGLVL(D_TIMING) { \ +#define TIME(name, bytes, call) \ +do { \ + if (BUGLVL(D_TIMING)) { \ unsigned long _x, _y; \ _x = get_cycles(); \ call; \ @@ -108,10 +109,10 @@ do { \ "%lu Kbytes/100Mcycle\n", \ name, bytes, _y - _x, \ 100000000 / 1024 * bytes / (_y - _x + 1)); \ - } \ - else { \ + } else { \ call; \ - } + } \ +} while (0) /* * Time needed to reset the card - in ms (milliseconds). This works on my -- cgit v1.3-6-gb490 From a34c0932c3b2f28542825ffc5280d562c49ad42d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:55 -0700 Subject: arcnet: Convert BUGMSG and BUGMSG2 to arc_prink and arc_cont These macros don't actually represent BUG uses but are more commonly used as logging macros, so use a more kernel style macro. Convert the BUGMSG from a netdev_ like use to actually use netdev_. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 16 +-- drivers/net/arcnet/arc-rimi.c | 24 +++-- drivers/net/arcnet/arcnet.c | 212 ++++++++++++++++++++------------------ drivers/net/arcnet/capmode.c | 35 ++++--- drivers/net/arcnet/com20020-isa.c | 15 +-- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020.c | 64 ++++++------ drivers/net/arcnet/com90io.c | 43 ++++---- drivers/net/arcnet/com90xx.c | 119 ++++++++++----------- drivers/net/arcnet/rfc1051.c | 16 +-- drivers/net/arcnet/rfc1201.c | 104 ++++++++++--------- include/linux/arcdevice.h | 32 +++--- 12 files changed, 355 insertions(+), 327 deletions(-) (limited to 'include') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 998c8356e576..034c8988f987 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -89,7 +89,7 @@ static void rx(struct net_device *dev, int bufnum, struct archdr *pkt = pkthdr; int ofs; - BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length); if (length > MTU) ofs = 512 - length; @@ -98,7 +98,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -163,15 +163,15 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, struct arc_hardware *hard = &pkt->hard; int ofs; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ if (length > XMTU) { /* should never happen! other people already check for this. */ - BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", - length, XMTU); + arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); length = XMTU; } if (length >= MinTU) { @@ -184,8 +184,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; } - BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length, ofs); + arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n", + length, ofs); lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index cd47a1b3008c..25f84b7437f3 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -147,7 +147,7 @@ static int __init arcrimi_found(struct net_device *dev) p = ioremap(dev->mem_start, MIRROR_SIZE); if (!p) { release_mem_region(dev->mem_start, MIRROR_SIZE); - BUGMSG(D_NORMAL, "Can't ioremap\n"); + arc_printk(D_NORMAL, dev, "Can't ioremap\n"); return -ENODEV; } @@ -155,7 +155,7 @@ static int __init arcrimi_found(struct net_device *dev) if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (RIM I)", dev)) { iounmap(p); release_mem_region(dev->mem_start, MIRROR_SIZE); - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } @@ -210,23 +210,24 @@ static int __init arcrimi_found(struct net_device *dev) if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) { - BUGMSG(D_NORMAL, "Card memory already allocated\n"); + arc_printk(D_NORMAL, dev, "Card memory already allocated\n"); goto err_free_irq; } lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { - BUGMSG(D_NORMAL, "Can't remap device memory!\n"); + arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_release_mem; } /* get and check the station ID from offset 1 in shmem */ dev->dev_addr[0] = readb(lp->mem_start + 1); - BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n", - dev->dev_addr[0], - dev->irq, dev->mem_start, - (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); + arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n", + dev->dev_addr[0], + dev->irq, dev->mem_start, + (dev->mem_end - dev->mem_start + 1) / mirror_size, + mirror_size); err = register_netdev(dev); if (err) @@ -255,7 +256,8 @@ static int arcrimi_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->mem_start + 0x800; - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); + arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", + dev->name, ASTATUS()); if (really_reset) { writeb(TESTvalue, ioaddr - 0x800); /* fake reset */ @@ -301,7 +303,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; - TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); + TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, @@ -310,7 +312,7 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; - TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); + TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } static int node; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 7a90b8a45a37..2aab7e2f7e4a 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -236,11 +236,11 @@ static void release_arcbuf(struct net_device *dev, int bufnum) lp->first_free_buf %= 5; if (BUGLVL(D_DURING)) { - BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", - bufnum); + arc_printk(D_DURING, dev, "release_arcbuf: freed #%d; buffer queue is now: ", + bufnum); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) - BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); - BUGMSG2(D_DURING, "\n"); + arc_cont(D_DURING, "#%d ", lp->buf_queue[i]); + arc_cont(D_DURING, "\n"); } } @@ -254,14 +254,14 @@ static int get_arcbuf(struct net_device *dev) if (!atomic_dec_and_test(&lp->buf_lock)) { /* already in this function */ - BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", - lp->buf_lock.counter); + arc_printk(D_NORMAL, dev, "get_arcbuf: overlap (%d)!\n", + lp->buf_lock.counter); } else { /* we can continue */ if (lp->next_buf >= 5) lp->next_buf -= 5; if (lp->next_buf == lp->first_free_buf) { - BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n"); + arc_printk(D_NORMAL, dev, "get_arcbuf: BUG: no buffers are available??\n"); } else { buf = lp->buf_queue[lp->next_buf++]; lp->next_buf %= 5; @@ -269,10 +269,11 @@ static int get_arcbuf(struct net_device *dev) } if (BUGLVL(D_DURING)) { - BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); + arc_printk(D_DURING, dev, "get_arcbuf: got #%d; buffer queue is now: ", + buf); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) - BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); - BUGMSG2(D_DURING, "\n"); + arc_cont(D_DURING, "#%d ", lp->buf_queue[i]); + arc_cont(D_DURING, "\n"); } atomic_inc(&lp->buf_lock); @@ -351,20 +352,20 @@ int arcnet_open(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int count, newmtu, error; - BUGMSG(D_INIT, "opened."); + arc_printk(D_INIT, dev, "opened."); if (!try_module_get(lp->hw.owner)) return -ENODEV; if (BUGLVL(D_PROTO)) { - BUGMSG(D_PROTO, "protocol map (default is '%c'): ", - arc_proto_default->suffix); + arc_printk(D_PROTO, dev, "protocol map (default is '%c'): ", + arc_proto_default->suffix); for (count = 0; count < 256; count++) - BUGMSG2(D_PROTO, "%c", arc_proto_map[count]->suffix); - BUGMSG2(D_PROTO, "\n"); + arc_cont(D_PROTO, "%c", arc_proto_map[count]->suffix); + arc_cont(D_PROTO, "\n"); } - BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); + arc_printk(D_INIT, dev, "arcnet_open: resetting card.\n"); /* try to put the card in a defined state - if it fails the first * time, actually reset it. @@ -377,7 +378,7 @@ int arcnet_open(struct net_device *dev) if (newmtu < dev->mtu) dev->mtu = newmtu; - BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu); + arc_printk(D_INIT, dev, "arcnet_open: mtu: %d.\n", dev->mtu); /* autodetect the encapsulation for each host. */ memset(lp->default_proto, 0, sizeof(lp->default_proto)); @@ -408,27 +409,28 @@ int arcnet_open(struct net_device *dev) lp->hw.open(dev); if (dev->dev_addr[0] == 0) - BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved for broadcasts!\n"); + arc_printk(D_NORMAL, dev, "WARNING! Station address 00 is reserved for broadcasts!\n"); else if (dev->dev_addr[0] == 255) - BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse DOS networking programs!\n"); + arc_printk(D_NORMAL, dev, "WARNING! Station address FF may confuse DOS networking programs!\n"); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (ASTATUS() & RESETflag) { - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", + __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); netif_start_queue(dev); @@ -466,20 +468,21 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, uint8_t _daddr, proto_num; struct ArcProto *proto; - BUGMSG(D_DURING, - "create header from %d to %d; protocol %d (%Xh); size %u.\n", - saddr ? *(uint8_t *)saddr : -1, - daddr ? *(uint8_t *)daddr : -1, - type, type, len); + arc_printk(D_DURING, dev, + "create header from %d to %d; protocol %d (%Xh); size %u.\n", + saddr ? *(uint8_t *)saddr : -1, + daddr ? *(uint8_t *)daddr : -1, + type, type, len); if (skb->len != 0 && len != skb->len) - BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", - skb->len, len); + arc_printk(D_NORMAL, dev, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", + skb->len, len); /* Type is host order - ? */ if (type == ETH_P_ARCNET) { proto = arc_raw_proto; - BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix); + arc_printk(D_DEBUG, dev, "arc_raw_proto used. proto='%c'\n", + proto->suffix); _daddr = daddr ? *(uint8_t *)daddr : 0; } else if (!daddr) { /* if the dest addr isn't provided, we can't choose an @@ -490,19 +493,19 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, *(uint16_t *)skb_push(skb, 2) = type; /* XXX: Why not use skb->mac_len? */ if (skb->network_header - skb->mac_header != 2) - BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", - (int)(skb->network_header - skb->mac_header)); + arc_printk(D_NORMAL, dev, "arcnet_header: Yikes! diff (%u) is not 2!\n", + skb->network_header - skb->mac_header); return -2; /* return error -- can't transmit yet! */ } else { /* otherwise, we can just add the header as usual. */ _daddr = *(uint8_t *)daddr; proto_num = lp->default_proto[_daddr]; proto = arc_proto_map[proto_num]; - BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", - proto_num, proto->suffix); + arc_printk(D_DURING, dev, "building header for %02Xh using protocol '%c'\n", + proto_num, proto->suffix); if (proto == &arc_proto_null && arc_bcast_proto != proto) { - BUGMSG(D_DURING, "actually, let's use '%c' instead.\n", - arc_bcast_proto->suffix); + arc_printk(D_DURING, dev, "actually, let's use '%c' instead.\n", + arc_bcast_proto->suffix); proto = arc_bcast_proto; } } @@ -521,22 +524,22 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, unsigned long flags; int freeskb, retval; - BUGMSG(D_DURING, - "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", - ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); + arc_printk(D_DURING, dev, + "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", + ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; proto = arc_proto_map[soft->proto]; - BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", - skb->len, pkt->hard.dest); + arc_printk(D_SKB_SIZE, dev, "skb: transmitting %d bytes to %02X\n", + skb->len, pkt->hard.dest); if (BUGLVL(D_SKB)) arcnet_dump_skb(dev, skb, "tx"); /* fits in one packet? */ if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) { - BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n"); + arc_printk(D_NORMAL, dev, "fixme: packet too large: compensating badly!\n"); dev_kfree_skb(skb); return NETDEV_TX_OK; /* don't try again */ } @@ -569,9 +572,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, if (proto->continue_tx && proto->continue_tx(dev, txbuf)) { - BUGMSG(D_NORMAL, - "bug! continue_tx finished the first time! (proto='%c')\n", - proto->suffix); + arc_printk(D_NORMAL, dev, + "bug! continue_tx finished the first time! (proto='%c')\n", + proto->suffix); } } retval = NETDEV_TX_OK; @@ -581,14 +584,16 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, freeskb = 0; } - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); + arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", + __FILE__, __LINE__, __func__, ASTATUS()); /* make sure we didn't ignore a TX IRQ while we were in here */ AINTMASK(0); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask |= TXFREEflag | EXCNAKflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); + arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", + __FILE__, __LINE__, __func__, ASTATUS()); spin_unlock_irqrestore(&lp->lock, flags); if (freeskb) @@ -604,8 +609,8 @@ static int go_tx(struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); - BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", - ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); + arc_printk(D_DURING, dev, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", + ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); if (lp->cur_tx != -1 || lp->next_tx == -1) return 0; @@ -655,8 +660,8 @@ void arcnet_timeout(struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); if (time_after(jiffies, lp->last_timeout + 10 * HZ)) { - BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", - msg, status, lp->intmask, lp->lasttrans_dest); + arc_printk(D_EXTRA, dev, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", + msg, status, lp->intmask, lp->lasttrans_dest); lp->last_timeout = jiffies; } @@ -675,9 +680,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) int recbuf, status, diagstatus, didsomething, boguscount; int retval = IRQ_NONE; - BUGMSG(D_DURING, "\n"); + arc_printk(D_DURING, dev, "\n"); - BUGMSG(D_DURING, "in arcnet_interrupt\n"); + arc_printk(D_DURING, dev, "in arcnet_interrupt\n"); lp = netdev_priv(dev); BUG_ON(!lp); @@ -695,16 +700,16 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) return retval; } - BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", - ASTATUS(), lp->intmask); + arc_printk(D_DURING, dev, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", + ASTATUS(), lp->intmask); boguscount = 5; do { status = ASTATUS(); diagstatus = (status >> 8) & 0xFF; - BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", - __FILE__, __LINE__, __func__, status); + arc_printk(D_DEBUG, dev, "%s: %d: %s: status=%x\n", + __FILE__, __LINE__, __func__, status); didsomething = 0; /* RESET flag was enabled - card is resetting and if RX is @@ -714,7 +719,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) * Clear it out and start over. */ if (status & RESETflag) { - BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status); + arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n", + status); arcnet_close(dev); arcnet_open(dev); @@ -732,21 +738,21 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) recbuf = -1; if (status & lp->intmask & NORXflag) { recbuf = lp->cur_rx; - BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n", - recbuf, status); + arc_printk(D_DURING, dev, "Buffer #%d: receive irq (status=%Xh)\n", + recbuf, status); lp->cur_rx = get_arcbuf(dev); if (lp->cur_rx != -1) { - BUGMSG(D_DURING, "enabling receive to buffer #%d\n", - lp->cur_rx); + arc_printk(D_DURING, dev, "enabling receive to buffer #%d\n", + lp->cur_rx); ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts); } didsomething++; } if ((diagstatus & EXCNAKflag)) { - BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", - diagstatus); + arc_printk(D_DURING, dev, "EXCNAK IRQ (diagstat=%Xh)\n", + diagstatus); ACOMMAND(NOTXcmd); /* disable transmit */ lp->excnak_pending = 1; @@ -760,20 +766,22 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~(TXFREEflag | EXCNAKflag); - BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); + arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n", status); if (lp->cur_tx != -1 && !lp->timed_out) { if (!(status & TXACKflag)) { if (lp->lasttrans_dest != 0) { - BUGMSG(D_EXTRA, - "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", - status, lp->lasttrans_dest); + arc_printk(D_EXTRA, dev, + "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", + status, + lp->lasttrans_dest); dev->stats.tx_errors++; dev->stats.tx_carrier_errors++; } else { - BUGMSG(D_DURING, - "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", - status, lp->lasttrans_dest); + arc_printk(D_DURING, dev, + "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", + status, + lp->lasttrans_dest); } } @@ -836,29 +844,29 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) ACOMMAND(CFLAGScmd | CONFIGclear); dev->stats.tx_carrier_errors++; - BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", - status); + arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", + status); /* MYRECON bit is at bit 7 of diagstatus */ if (diagstatus & 0x80) - BUGMSG(D_RECON, "Put out that recon myself\n"); + arc_printk(D_RECON, dev, "Put out that recon myself\n"); /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || time_after(jiffies, lp->last_recon + HZ * 10)) { if (lp->network_down) - BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n"); + arc_printk(D_NORMAL, dev, "reconfiguration detected: cabling restored?\n"); lp->first_recon = lp->last_recon = jiffies; lp->num_recons = lp->network_down = 0; - BUGMSG(D_DURING, "recon: clearing counters.\n"); + arc_printk(D_DURING, dev, "recon: clearing counters.\n"); } else { /* add to current RECON counter */ lp->last_recon = jiffies; lp->num_recons++; - BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", - lp->num_recons, - (lp->last_recon - lp->first_recon) / HZ, - lp->network_down); + arc_printk(D_DURING, dev, "recon: counter=%d, time=%lds, net=%d\n", + lp->num_recons, + (lp->last_recon - lp->first_recon) / HZ, + lp->network_down); /* if network is marked up; * and first_recon and last_recon are 60+ apart; @@ -870,7 +878,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) (lp->last_recon - lp->first_recon) <= HZ * 60 && lp->num_recons >= RECON_THRESHOLD) { lp->network_down = 1; - BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n"); + arc_printk(D_NORMAL, dev, "many reconfigurations detected: cabling problem?\n"); } else if (!lp->network_down && lp->last_recon - lp->first_recon > HZ * 60) { /* reset counters if we've gone for over a minute. */ @@ -881,20 +889,20 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } else if (lp->network_down && time_after(jiffies, lp->last_recon + HZ * 10)) { if (lp->network_down) - BUGMSG(D_NORMAL, "cabling restored?\n"); + arc_printk(D_NORMAL, dev, "cabling restored?\n"); lp->first_recon = lp->last_recon = 0; lp->num_recons = lp->network_down = 0; - BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); + arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n"); } if (didsomething) retval |= IRQ_HANDLED; } while (--boguscount && didsomething); - BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n", - ASTATUS(), boguscount); - BUGMSG(D_DURING, "\n"); + arc_printk(D_DURING, dev, "arcnet_interrupt complete (status=%Xh, count=%d)\n", + ASTATUS(), boguscount); + arc_printk(D_DURING, dev, "\n"); AINTMASK(0); udelay(1); @@ -933,8 +941,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum) lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); } - BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n", - bufnum, pkt.hard.source, pkt.hard.dest, length); + arc_printk(D_DURING, dev, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n", + bufnum, pkt.hard.source, pkt.hard.dest, length); dev->stats.rx_packets++; dev->stats.rx_bytes += length + ARC_HDR_SIZE; @@ -947,10 +955,10 @@ static void arcnet_rx(struct net_device *dev, int bufnum) *newp = arc_proto_map[soft->proto]; if (oldp != newp) { - BUGMSG(D_PROTO, - "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", - soft->proto, pkt.hard.source, - newp->suffix, oldp->suffix); + arc_printk(D_PROTO, dev, + "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", + soft->proto, pkt.hard.source, + newp->suffix, oldp->suffix); } } @@ -967,9 +975,9 @@ static void arcnet_rx(struct net_device *dev, int bufnum) static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { - BUGMSG(D_PROTO, - "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", - pkthdr->soft.rfc1201.proto, pkthdr->hard.source); + arc_printk(D_PROTO, dev, + "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", + pkthdr->soft.rfc1201.proto, pkthdr->hard.source); } static int null_build_header(struct sk_buff *skb, struct net_device *dev, @@ -977,9 +985,9 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev, { struct arcnet_local *lp = netdev_priv(dev); - BUGMSG(D_PROTO, - "tx: can't build header for encap %02Xh; load a protocol driver.\n", - lp->default_proto[daddr]); + arc_printk(D_PROTO, dev, + "tx: can't build header for encap %02Xh; load a protocol driver.\n", + lp->default_proto[daddr]); /* always fails */ return 0; @@ -992,7 +1000,7 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, struct arcnet_local *lp = netdev_priv(dev); struct arc_hardware newpkt; - BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n"); + arc_printk(D_PROTO, dev, "tx: no encap for this host; load a protocol driver.\n"); /* send a packet to myself -- will never get received, of course */ newpkt.source = newpkt.dest = dev->dev_addr[0]; diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index e7ec907f4680..d62d1accf4b6 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -47,7 +47,8 @@ static void rx(struct net_device *dev, int bufnum, char *pktbuf, *pkthdrbuf; int ofs; - BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's a raw(cap) packet (length=%d)\n", + length); if (length >= MinTU) ofs = 512 - length; @@ -56,7 +57,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -102,8 +103,8 @@ static int build_header(struct sk_buff *skb, int hdr_size = ARC_HDR_SIZE; struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); - BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", - *((int *)&pkt->soft.cap.cookie[0])); + arc_printk(D_PROTO, dev, "Preparing header for cap packet %x.\n", + *((int *)&pkt->soft.cap.cookie[0])); /* Set the source hardware address. * @@ -140,16 +141,16 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, /* And neither is the cookie field */ length -= sizeof(int); - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); - BUGMSG(D_PROTO, "Sending for cap packet %x.\n", - *((int *)&pkt->soft.cap.cookie[0])); + arc_printk(D_PROTO, dev, "Sending for cap packet %x.\n", + *((int *)&pkt->soft.cap.cookie[0])); if (length > XMTU) { /* should never happen! other people already check for this. */ - BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", - length, XMTU); + arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); length = XMTU; } if (length > MinTU) { @@ -162,8 +163,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; } - BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length, ofs); + arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n", + length, ofs); /* Copy the arcnet-header + the protocol byte down: */ lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); @@ -188,8 +189,8 @@ static int ack_tx(struct net_device *dev, int acked) struct archdr *ackpkt; int length = sizeof(struct arc_cap); - BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", - lp->outgoing.skb->protocol, acked); + arc_printk(D_DURING, dev, "capmode: ack_tx: protocol: %x: result: %d\n", + lp->outgoing.skb->protocol, acked); if (BUGLVL(D_SKB)) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); @@ -197,7 +198,7 @@ static int ack_tx(struct net_device *dev, int acked) /* Now alloc a skb to send back up through the layers: */ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (ackskb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, can't acknowledge\n"); goto free_outskb; } @@ -213,8 +214,8 @@ static int ack_tx(struct net_device *dev, int acked) ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */ ackpkt->soft.cap.mes.ack = acked; - BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", - *((int *)&ackpkt->soft.cap.cookie[0])); + arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n", + *((int *)&ackpkt->soft.cap.cookie[0])); ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index af87c7482478..c3748f7c5081 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -58,16 +58,16 @@ static int __init com20020isa_probe(struct net_device *dev) ioaddr = dev->base_addr; if (!ioaddr) { - BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n"); + arc_printk(D_NORMAL, dev, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { - BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n", - ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); + arc_printk(D_NORMAL, dev, "IO region %xh-%xh already allocated.\n", + ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } if (ASTATUS() == 0xFF) { - BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr); + arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr); err = -ENODEV; goto out; } @@ -81,7 +81,8 @@ static int __init com20020isa_probe(struct net_device *dev) * card has just reset and the NORXflag is on until * we tell it to start receiving. */ - BUGMSG(D_INIT_REASONS, "intmask was %02Xh\n", inb(_INTMASK)); + arc_printk(D_INIT_REASONS, dev, "intmask was %02Xh\n", + inb(_INTMASK)); outb(0, _INTMASK); airqmask = probe_irq_on(); outb(NORXflag, _INTMASK); @@ -90,14 +91,14 @@ static int __init com20020isa_probe(struct net_device *dev) dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { - BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed first time\n"); + arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n"); airqmask = probe_irq_on(); outb(NORXflag, _INTMASK); udelay(5); outb(0, _INTMASK); dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { - BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n"); + arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n"); err = -ENODEV; goto out; } diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index c8184de4480d..0d0cc6a9c618 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -99,7 +99,7 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i lp = netdev_priv(dev); - BUGMSG(D_NORMAL, "%s Controls\n", ci->name); + arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name); ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset; r = devm_request_region(&pdev->dev, ioaddr, cm->size, diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 3170e8ebb7fa..b0b8a0be08e5 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -68,7 +68,7 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum, outb(ofs & 0xff, _ADDR_LO); /* copy the data */ - TIME("insb", count, insb(_MEMDATA, buf, count)); + TIME(dev, "insb", count, insb(_MEMDATA, buf, count)); } static void com20020_copy_to_card(struct net_device *dev, int bufnum, @@ -81,7 +81,7 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum, outb(ofs & 0xff, _ADDR_LO); /* copy the data */ - TIME("outsb", count, outsb(_MEMDATA, buf, count)); + TIME(dev, "outsb", count, outsb(_MEMDATA, buf, count)); } /* Reset the card and check some basic stuff during the detection stage. */ @@ -120,10 +120,10 @@ int com20020_check(struct net_device *dev) status = ASTATUS(); if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) { - BUGMSG(D_NORMAL, "status invalid (%Xh).\n", status); + arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status); return -ENODEV; } - BUGMSG(D_INIT_REASONS, "status after reset: %X\n", status); + arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); /* Enable TX */ outb(0x39, _CONFIG); @@ -132,16 +132,16 @@ int com20020_check(struct net_device *dev) ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); status = ASTATUS(); - BUGMSG(D_INIT_REASONS, "status after reset acknowledged: %X\n", - status); + arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n", + status); /* Read first location of memory */ outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI); outb(0, _ADDR_LO); if ((status = inb(_MEMDATA)) != TESTvalue) { - BUGMSG(D_NORMAL, "Signature byte not found (%02Xh != D1h).\n", - status); + arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n", + status); return -ENODEV; } return 0; @@ -213,24 +213,25 @@ int com20020_found(struct net_device *dev, int shared) /* reserve the irq */ if (request_irq(dev->irq, arcnet_interrupt, shared, "arcnet (COM20020)", dev)) { - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } dev->base_addr = ioaddr; - BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n", - lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); + arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n", + lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); if (lp->backplane) - BUGMSG(D_NORMAL, "Using backplane mode.\n"); + arc_printk(D_NORMAL, dev, "Using backplane mode.\n"); if (lp->timeout != 3) - BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout); + arc_printk(D_NORMAL, dev, "Using extended timeout value of %d\n", + lp->timeout); - BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n", - lp->setup >> 1, - clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); + arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n", + lp->setup >> 1, + clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); if (register_netdev(dev)) { free_irq(dev->irq, dev); @@ -252,16 +253,16 @@ static int com20020_reset(struct net_device *dev, int really_reset) u_int ioaddr = dev->base_addr; u_char inbyte; - BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", - __FILE__, __LINE__, __func__, dev, lp, dev->name); - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", - dev->name, ASTATUS()); + arc_printk(D_DEBUG, dev, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", + __FILE__, __LINE__, __func__, dev, lp, dev->name); + arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", + dev->name, ASTATUS()); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ SETCONF; - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (really_reset) { /* reset the card */ @@ -269,22 +270,23 @@ static int com20020_reset(struct net_device *dev, int really_reset) mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); /* verify that the ARCnet signature byte is present */ - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); com20020_copy_from_card(dev, 0, 0, &inbyte, 1); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (inbyte != TESTvalue) { - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", + __FILE__, __LINE__, __func__); + arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* done! return success. */ return 0; @@ -294,7 +296,7 @@ static void com20020_setmask(struct net_device *dev, int mask) { u_int ioaddr = dev->base_addr; - BUGMSG(D_DURING, "Setting mask to %x at %x\n", mask, ioaddr); + arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr); AINTMASK(mask); } @@ -336,7 +338,7 @@ static void com20020_set_mc_list(struct net_device *dev) if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */ if (!(lp->setup & PROMISCset)) - BUGMSG(D_NORMAL, "Setting promiscuous flag...\n"); + arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); lp->setup |= PROMISCset; outb(lp->setup, _XREG); @@ -344,7 +346,7 @@ static void com20020_set_mc_list(struct net_device *dev) /* Disable promiscuous mode, use normal mode */ { if ((lp->setup & PROMISCset)) - BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n"); + arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); lp->setup &= ~PROMISCset; outb(lp->setup, _XREG); diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 33a8531e90c7..ec2db8527862 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -151,16 +151,17 @@ static int __init com90io_probe(struct net_device *dev) } if (!ioaddr) { - BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you must specify the base address!\n"); + arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { - BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n", - ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); + arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n", + ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } if (ASTATUS() == 0xFF) { - BUGMSG(D_INIT_REASONS, "IO address %x empty\n", ioaddr); + arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n", + ioaddr); goto err_out; } inb(_RESET); @@ -169,19 +170,22 @@ static int __init com90io_probe(struct net_device *dev) status = ASTATUS(); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { - BUGMSG(D_INIT_REASONS, "Status invalid (%Xh).\n", status); + arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n", + status); goto err_out; } - BUGMSG(D_INIT_REASONS, "Status after reset: %X\n", status); + arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); - BUGMSG(D_INIT_REASONS, "Status after reset acknowledged: %X\n", status); + arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n", + status); status = ASTATUS(); if (status & RESETflag) { - BUGMSG(D_INIT_REASONS, "Eternal reset (status=%Xh)\n", status); + arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n", + status); goto err_out; } outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG); @@ -192,8 +196,8 @@ static int __init com90io_probe(struct net_device *dev) outb(0, _ADDR_LO); if ((status = inb(_MEMDATA)) != 0xd1) { - BUGMSG(D_INIT_REASONS, "Signature byte not found (%Xh instead).\n", - status); + arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n", + status); goto err_out; } if (!dev->irq) { @@ -209,7 +213,7 @@ static int __init com90io_probe(struct net_device *dev) dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { - BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed\n"); + arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n"); goto err_out; } } @@ -232,7 +236,7 @@ static int __init com90io_found(struct net_device *dev) /* Reserve the irq */ if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) { - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } /* Reserve the I/O region */ @@ -266,8 +270,8 @@ static int __init com90io_found(struct net_device *dev) return err; } - BUGMSG(D_NORMAL, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n", - dev->dev_addr[0], dev->base_addr, dev->irq); + arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n", + dev->dev_addr[0], dev->base_addr, dev->irq); return 0; } @@ -284,7 +288,8 @@ static int com90io_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); + arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", + dev->name, ASTATUS()); if (really_reset) { /* reset the card */ @@ -300,7 +305,7 @@ static int com90io_reset(struct net_device *dev, int really_reset) /* verify that the ARCnet signature byte is present */ if (get_buffer_byte(dev, 0) != TESTvalue) { - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ @@ -334,13 +339,15 @@ static void com90io_setmask(struct net_device *dev, int mask) static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { - TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); + TIME(dev, "put_whole_buffer", count, + put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { - TIME("get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); + TIME(dev, "get_whole_buffer", count, + get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } static int io; /* use the insmod io= irq= shmem= options */ diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index b5e1c1904f13..12534a3cb4ce 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -157,24 +157,24 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S1: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S1: "); } - BUGMSG2(D_INIT, "%Xh ", *port); + arc_cont(D_INIT, "%Xh ", *port); ioaddr = *port; if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { - BUGMSG2(D_INIT_REASONS, "(request_region)\n"); - BUGMSG2(D_INIT_REASONS, "S1: "); + arc_cont(D_INIT_REASONS, "(request_region)\n"); + arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; *port-- = ports[--numports]; continue; } if (ASTATUS() == 0xFF) { - BUGMSG2(D_INIT_REASONS, "(empty)\n"); - BUGMSG2(D_INIT_REASONS, "S1: "); + arc_cont(D_INIT_REASONS, "(empty)\n"); + arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -183,15 +183,15 @@ static void __init com90xx_probe(void) } inb(_RESET); /* begin resetting card */ - BUGMSG2(D_INIT_REASONS, "\n"); - BUGMSG2(D_INIT_REASONS, "S1: "); + arc_cont(D_INIT_REASONS, "\n"); + arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); if (!numports) { - BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); + arc_cont(D_NORMAL, "S1: No ARCnet cards found.\n"); kfree(shmems); kfree(iomem); return; @@ -205,12 +205,12 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S2: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S2: "); } - BUGMSG2(D_INIT, "%Xh ", *port); + arc_cont(D_INIT, "%Xh ", *port); } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); mdelay(RESETtime); /* Stage 3: abandon any shmem addresses that don't have the signature @@ -223,30 +223,30 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S3: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S3: "); } - BUGMSG2(D_INIT, "%lXh ", *p); + arc_cont(D_INIT, "%lXh ", *p); if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) { - BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); - BUGMSG2(D_INIT_REASONS, "Stage 3: "); + arc_cont(D_INIT_REASONS, "(request_mem_region)\n"); + arc_cont(D_INIT_REASONS, "Stage 3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; goto out; } base = ioremap(*p, MIRROR_SIZE); if (!base) { - BUGMSG2(D_INIT_REASONS, "(ioremap)\n"); - BUGMSG2(D_INIT_REASONS, "Stage 3: "); + arc_cont(D_INIT_REASONS, "(ioremap)\n"); + arc_cont(D_INIT_REASONS, "Stage 3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; goto out1; } if (readb(base) != TESTvalue) { - BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", - readb(base), TESTvalue); - BUGMSG2(D_INIT_REASONS, "S3: "); + arc_cont(D_INIT_REASONS, "(%02Xh != %02Xh)\n", + readb(base), TESTvalue); + arc_cont(D_INIT_REASONS, "S3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; goto out2; @@ -258,12 +258,12 @@ static void __init com90xx_probe(void) */ writeb(0x42, base); if (readb(base) != 0x42) { - BUGMSG2(D_INIT_REASONS, "(read only)\n"); - BUGMSG2(D_INIT_REASONS, "S3: "); + arc_cont(D_INIT_REASONS, "(read only)\n"); + arc_cont(D_INIT_REASONS, "S3: "); goto out2; } - BUGMSG2(D_INIT_REASONS, "\n"); - BUGMSG2(D_INIT_REASONS, "S3: "); + arc_cont(D_INIT_REASONS, "\n"); + arc_cont(D_INIT_REASONS, "S3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; iomem[index] = base; @@ -276,10 +276,10 @@ static void __init com90xx_probe(void) *p-- = shmems[--numshmems]; index--; } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); if (!numshmems) { - BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); + arc_cont(D_NORMAL, "S3: No ARCnet cards found.\n"); for (port = &ports[0]; port < ports + numports; port++) release_region(*port, ARCNET_TOTAL_SIZE); kfree(shmems); @@ -294,12 +294,12 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S4: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S4: "); } - BUGMSG2(D_INIT, "%lXh ", *p); + arc_cont(D_INIT, "%lXh ", *p); } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); /* Stage 5: for any ports that have the correct status, can disable * the RESET flag, and (if no irq is given) generate an autoirq, @@ -315,18 +315,18 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S5: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S5: "); } - BUGMSG2(D_INIT, "%Xh ", *port); + arc_cont(D_INIT, "%Xh ", *port); ioaddr = *port; status = ASTATUS(); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { - BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); - BUGMSG2(D_INIT_REASONS, "S5: "); + arc_cont(D_INIT_REASONS, "(status=%Xh)\n", status); + arc_cont(D_INIT_REASONS, "S5: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -336,9 +336,9 @@ static void __init com90xx_probe(void) ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); status = ASTATUS(); if (status & RESETflag) { - BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", - status); - BUGMSG2(D_INIT_REASONS, "S5: "); + arc_cont(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", + status); + arc_cont(D_INIT_REASONS, "S5: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -360,8 +360,8 @@ static void __init com90xx_probe(void) airq = probe_irq_off(airqmask); if (airq <= 0) { - BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); - BUGMSG2(D_INIT_REASONS, "S5: "); + arc_cont(D_INIT_REASONS, "(airq=%d)\n", airq); + arc_cont(D_INIT_REASONS, "S5: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -372,7 +372,7 @@ static void __init com90xx_probe(void) airq = irq; } - BUGMSG2(D_INIT, "(%d,", airq); + arc_cont(D_INIT, "(%d,", airq); openparen = 1; /* Everything seems okay. But which shmem, if any, puts @@ -399,7 +399,7 @@ static void __init com90xx_probe(void) void __iomem *base = iomem[index]; if (readb(base) == TESTvalue) { /* found one */ - BUGMSG2(D_INIT, "%lXh)\n", *p); + arc_cont(D_INIT, "%lXh)\n", *p); openparen = 0; /* register the card */ @@ -412,7 +412,7 @@ static void __init com90xx_probe(void) iomem[index] = iomem[numshmems]; break; /* go to the next I/O port */ } else { - BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base)); + arc_cont(D_INIT_REASONS, "%Xh-", readb(base)); } } @@ -476,7 +476,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem /* allocate struct net_device */ dev = alloc_arcdev(device); if (!dev) { - BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); + arc_cont(D_NORMAL, "com90xx: Can't allocate device!\n"); iounmap(p); release_mem_region(shmem, MIRROR_SIZE); return -ENOMEM; @@ -515,7 +515,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem /* reserve the irq */ if (request_irq(airq, arcnet_interrupt, 0, "arcnet (90xx)", dev)) { - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", airq); goto err_release_mem; } dev->irq = airq; @@ -531,7 +531,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem lp->hw.copy_from_card = com90xx_copy_from_card; lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { - BUGMSG(D_NORMAL, "Can't remap device memory!\n"); + arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_free_irq; } @@ -540,10 +540,11 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem dev->base_addr = ioaddr; - BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n", - dev->dev_addr[0], - dev->base_addr, dev->irq, dev->mem_start, - (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); + arc_printk(D_NORMAL, dev, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n", + dev->dev_addr[0], + dev->base_addr, dev->irq, dev->mem_start, + (dev->mem_end - dev->mem_start + 1) / mirror_size, + mirror_size); if (register_netdev(dev)) goto err_unmap; @@ -595,7 +596,7 @@ static int com90xx_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; - BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS()); + arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n", ASTATUS()); if (really_reset) { /* reset the card */ @@ -611,7 +612,7 @@ static int com90xx_reset(struct net_device *dev, int really_reset) /* verify that the ARCnet signature byte is present */ if (readb(lp->mem_start) != TESTvalue) { if (really_reset) - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ @@ -631,7 +632,7 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; - TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); + TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, @@ -640,7 +641,7 @@ static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offse struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; - TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); + TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } MODULE_LICENSE("GPL"); diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 824d71fcfd53..47c7d1a4ef4c 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -124,7 +124,7 @@ static void rx(struct net_device *dev, int bufnum, struct archdr *pkt = pkthdr; int ofs; - BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length); if (length >= MinTU) ofs = 512 - length; @@ -133,7 +133,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -173,8 +173,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, soft->proto = ARC_P_ARP_RFC1051; break; default: - BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n", - type, type); + arc_printk(D_NORMAL, dev, "RFC1051: I don't understand protocol %d (%Xh)\n", + type, type); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; return 0; @@ -210,15 +210,15 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, struct arc_hardware *hard = &pkt->hard; int ofs; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ if (length > XMTU) { /* should never happen! other people already check for this. */ - BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", - length, XMTU); + arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); length = XMTU; } if (length > MinTU) { diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index d052976ebdfa..97af7d92c020 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -136,7 +136,8 @@ static void rx(struct net_device *dev, int bufnum, int saddr = pkt->hard.source, ofs; struct Incoming *in = &lp->rfc1201.incoming[saddr]; - BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's an RFC1201 packet (length=%d)\n", + length); if (length >= MinTU) ofs = 512 - length; @@ -145,10 +146,10 @@ static void rx(struct net_device *dev, int bufnum, if (soft->split_flag == 0xFF) { /* Exception Packet */ if (length >= 4 + RFC1201_HDR_SIZE) { - BUGMSG(D_DURING, "compensating for exception packet\n"); + arc_printk(D_DURING, dev, "compensating for exception packet\n"); } else { - BUGMSG(D_EXTRA, "short RFC1201 exception packet from %02Xh", - saddr); + arc_printk(D_EXTRA, dev, "short RFC1201 exception packet from %02Xh", + saddr); return; } @@ -159,12 +160,13 @@ static void rx(struct net_device *dev, int bufnum, soft, sizeof(pkt->soft)); } if (!soft->split_flag) { /* not split */ - BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_RX, dev, "incoming is not split (splitflag=%d)\n", + soft->split_flag); if (in->skb) { /* already assembling one! */ - BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, soft->sequence); + arc_printk(D_EXTRA, dev, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", + in->sequence, soft->split_flag, + soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); dev->stats.rx_errors++; @@ -175,7 +177,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -205,18 +207,18 @@ static void rx(struct net_device *dev, int bufnum, uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr); if (!*cptr) { /* is saddr = 00? */ - BUGMSG(D_EXTRA, - "ARP source address was 00h, set to %02Xh.\n", - saddr); + arc_printk(D_EXTRA, dev, + "ARP source address was 00h, set to %02Xh\n", + saddr); dev->stats.rx_crc_errors++; *cptr = saddr; } else { - BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n", - *cptr); + arc_printk(D_DURING, dev, "ARP source address (%Xh) is fine.\n", + *cptr); } } else { - BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n", - arp->ar_hln, arp->ar_pln); + arc_printk(D_NORMAL, dev, "funny-shaped ARP packet. (%Xh, %Xh)\n", + arp->ar_hln, arp->ar_pln); dev->stats.rx_errors++; dev->stats.rx_crc_errors++; } @@ -245,13 +247,13 @@ static void rx(struct net_device *dev, int bufnum, * other way to be reliable. */ - BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n", - soft->split_flag, in->sequence); + arc_printk(D_RX, dev, "packet is split (splitflag=%d, seq=%d)\n", + soft->split_flag, in->sequence); if (in->skb && in->sequence != soft->sequence) { - BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", - saddr, in->sequence, soft->sequence, - soft->split_flag); + arc_printk(D_EXTRA, dev, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", + saddr, in->sequence, soft->sequence, + soft->split_flag); dev_kfree_skb_irq(in->skb); in->skb = NULL; dev->stats.rx_errors++; @@ -259,12 +261,12 @@ static void rx(struct net_device *dev, int bufnum, in->lastpacket = in->numpackets = 0; } if (soft->split_flag & 1) { /* first packet in split */ - BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_RX, dev, "brand new splitpacket (splitflag=%d)\n", + soft->split_flag); if (in->skb) { /* already assembling one! */ - BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, - soft->sequence); + arc_printk(D_EXTRA, dev, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", + in->sequence, soft->split_flag, + soft->sequence); dev->stats.rx_errors++; dev->stats.rx_missed_errors++; dev_kfree_skb_irq(in->skb); @@ -274,8 +276,8 @@ static void rx(struct net_device *dev, int bufnum, in->lastpacket = 1; if (in->numpackets > 16) { - BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_EXTRA, dev, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", + soft->split_flag); lp->rfc1201.aborted_seq = soft->sequence; dev->stats.rx_errors++; dev->stats.rx_length_errors++; @@ -284,7 +286,7 @@ static void rx(struct net_device *dev, int bufnum, in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "(split) memory squeeze, dropping packet.\n"); lp->rfc1201.aborted_seq = soft->sequence; dev->stats.rx_dropped++; return; @@ -305,9 +307,10 @@ static void rx(struct net_device *dev, int bufnum, */ if (!in->skb) { if (lp->rfc1201.aborted_seq != soft->sequence) { - BUGMSG(D_EXTRA, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", - soft->split_flag, soft->sequence, - lp->rfc1201.aborted_seq); + arc_printk(D_EXTRA, dev, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", + soft->split_flag, + soft->sequence, + lp->rfc1201.aborted_seq); dev->stats.rx_errors++; dev->stats.rx_missed_errors++; } @@ -317,15 +320,16 @@ static void rx(struct net_device *dev, int bufnum, if (packetnum != in->lastpacket) { /* not the right flag! */ /* harmless duplicate? ignore. */ if (packetnum <= in->lastpacket - 1) { - BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_EXTRA, dev, "duplicate splitpacket ignored! (splitflag=%d)\n", + soft->split_flag); dev->stats.rx_errors++; dev->stats.rx_frame_errors++; return; } /* "bad" duplicate, kill reassembly */ - BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, soft->sequence); + arc_printk(D_EXTRA, dev, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", + in->sequence, soft->split_flag, + soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); in->skb = NULL; @@ -350,10 +354,10 @@ static void rx(struct net_device *dev, int bufnum, in->skb = NULL; in->lastpacket = in->numpackets = 0; - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", - skb->len, pkt->hard.source); - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", - skb->len, pkt->hard.source); + arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (unsplit)\n", + skb->len, pkt->hard.source); + arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (split)\n", + skb->len, pkt->hard.source); if (BUGLVL(D_SKB)) arcnet_dump_skb(dev, skb, "rx"); @@ -395,8 +399,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, soft->proto = ARC_P_ATALK; break; default: - BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n", - type, type); + arc_printk(D_NORMAL, dev, "RFC1201: I don't understand protocol %d (%Xh)\n", + type, type); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; return 0; @@ -469,8 +473,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, const int maxsegsize = XMTU - RFC1201_HDR_SIZE; struct Outgoing *out; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ pkt->soft.rfc1201.split_flag = 0; @@ -484,9 +488,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize; out->segnum = 0; - BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n", - out->numsegs, out->length, - pkt->soft.rfc1201.sequence); + arc_printk(D_DURING, dev, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n", + out->numsegs, out->length, + pkt->soft.rfc1201.sequence); return 0; /* not done */ } @@ -505,9 +509,9 @@ static int continue_tx(struct net_device *dev, int bufnum) int maxsegsize = XMTU - RFC1201_HDR_SIZE; int seglen; - BUGMSG(D_DURING, - "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", - out->segnum, out->numsegs, soft->sequence); + arc_printk(D_DURING, dev, + "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", + out->segnum, out->numsegs, soft->sequence); /* the "new" soft header comes right before the data chunk */ newsoft = (struct arc_rfc1201 *) diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index f07c66383b88..a678027ff6c2 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -81,34 +81,36 @@ extern int arcnet_debug; #define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) /* macros to simplify debug checking */ -#define BUGMSG(x, fmt, ...) \ +#define arc_printk(x, dev, fmt, ...) \ do { \ - if (BUGLVL(x)) \ - printk("%s%6s: " fmt, \ - (x) == D_NORMAL ? KERN_WARNING : \ - (x) < D_DURING ? KERN_INFO : KERN_DEBUG, \ - dev->name, ##__VA_ARGS__); \ + if (BUGLVL(x)) { \ + if ((x) == D_NORMAL) \ + netdev_warn(dev, fmt, ##__VA_ARGS__); \ + else if ((x) < D_DURING) \ + netdev_info(dev, fmt, ##__VA_ARGS__); \ + else \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ + } \ } while (0) -#define BUGMSG2(x, fmt, ...) \ +#define arc_cont(x, fmt, ...) \ do { \ - if (BUGLVL(x)) \ - printk(fmt, ##__VA_ARGS__); \ + if (BUGLVL(x)) \ + pr_cont(fmt, ##__VA_ARGS__); \ } while (0) /* see how long a function call takes to run, expressed in CPU cycles */ -#define TIME(name, bytes, call) \ +#define TIME(dev, name, bytes, call) \ do { \ if (BUGLVL(D_TIMING)) { \ unsigned long _x, _y; \ _x = get_cycles(); \ call; \ _y = get_cycles(); \ - BUGMSG(D_TIMING, \ - "%s: %d bytes in %lu cycles == " \ - "%lu Kbytes/100Mcycle\n", \ - name, bytes, _y - _x, \ - 100000000 / 1024 * bytes / (_y - _x + 1)); \ + arc_printk(D_TIMING, dev, \ + "%s: %d bytes in %lu cycles == %lu Kbytes/100Mcycle\n", \ + name, bytes, _y - _x, \ + 100000000 / 1024 * bytes / (_y - _x + 1)); \ } else { \ call; \ } \ -- cgit v1.3-6-gb490 From 83df99b50f901cb7c72cf132a83f43bbaeb01362 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:01 -0700 Subject: arcnet: Convert arcnet_dump_skb macro to static inline Make sure the arguments are tested appropriately when not using this function. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- include/linux/arcdevice.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index a678027ff6c2..1d8e36e13616 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -326,7 +326,10 @@ struct arcnet_local { #if ARCNET_DEBUG_MAX & D_SKB void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #else -#define arcnet_dump_skb(dev, skb, desc) ; +static inline +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) +{ +} #endif void arcnet_unregister_proto(struct ArcProto *proto); -- cgit v1.3-6-gb490 From d6d7d3ed56e3bfe7fd34108dbe23f0610e3d8621 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:02 -0700 Subject: arcnet: Wrap some long lines Just neatening. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 3 ++- drivers/net/arcnet/arc-rimi.c | 11 ++++++----- drivers/net/arcnet/arcnet.c | 10 +++++++--- drivers/net/arcnet/capmode.c | 3 ++- drivers/net/arcnet/com20020-pci.c | 3 ++- drivers/net/arcnet/com20020.c | 14 ++++++++------ drivers/net/arcnet/com90io.c | 31 +++++++++++++++++++------------ drivers/net/arcnet/com90xx.c | 28 +++++++++++++++++----------- drivers/net/arcnet/rfc1051.c | 3 ++- drivers/net/arcnet/rfc1201.c | 15 ++++++++++----- include/linux/arcdevice.h | 12 ++++++------ 11 files changed, 81 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 40035ee8cb40..59b3083c19f9 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -165,7 +165,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); - length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; if (length > XMTU) { /* should never happen! other people already check for this. */ diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 7360214e3d3f..8fa5eb43f308 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -49,8 +49,8 @@ static void arcrimi_setmask(struct net_device *dev, int mask); static int arcrimi_reset(struct net_device *dev, int really_reset); static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); -static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count); +static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count); /* Handy defines for ARCnet specific stuff */ @@ -215,7 +215,8 @@ static int __init arcrimi_found(struct net_device *dev) goto err_free_irq; } - lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); + lp->mem_start = ioremap(dev->mem_start, + dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_release_mem; @@ -307,8 +308,8 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } -static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index a9535ec9c236..00074e781353 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -759,7 +759,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~(TXFREEflag | EXCNAKflag); - arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n", status); + arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n", + status); if (lp->cur_tx != -1 && !lp->timed_out) { if (!(status & TXACKflag)) { @@ -804,7 +805,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) go_tx(dev); /* continue a split packet, if any */ - if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) { + if (lp->outgoing.proto && + lp->outgoing.proto->continue_tx) { int txbuf = get_arcbuf(dev); if (txbuf != -1) { @@ -874,7 +876,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) arc_printk(D_NORMAL, dev, "many reconfigurations detected: cabling problem?\n"); } else if (!lp->network_down && lp->last_recon - lp->first_recon > HZ * 60) { - /* reset counters if we've gone for over a minute. */ + /* reset counters if we've gone for + * over a minute. + */ lp->first_recon = lp->last_recon; lp->num_recons = 1; } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index a898647ab05d..46a76dcc21aa 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -222,7 +222,8 @@ static int ack_tx(struct net_device *dev, int acked) free_outskb: dev_kfree_skb_irq(lp->outgoing.skb); - lp->outgoing.proto = NULL; /* We are always finished when in this protocol */ + lp->outgoing.proto = NULL; + /* We are always finished when in this protocol */ return 0; } diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index fc6809b43f8f..a28887dfcc9e 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -64,7 +64,8 @@ MODULE_LICENSE("GPL"); static void com20020pci_remove(struct pci_dev *pdev); -static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int com20020pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { struct com20020_pci_card_info *ci; struct net_device *dev; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index bea386222149..00f910cf7b81 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -192,8 +192,9 @@ int com20020_found(struct net_device *dev, int shared) lp->hw.copy_from_card = com20020_copy_from_card; lp->hw.close = com20020_close; + /* FIXME: do this some other way! */ if (!dev->dev_addr[0]) - dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); /* FIXME: do this some other way! */ + dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); @@ -269,7 +270,8 @@ static int com20020_reset(struct net_device *dev, int really_reset) if (really_reset) { /* reset the card */ ARCRESET; - mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ + mdelay(RESETtime * 2); + /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); @@ -338,15 +340,15 @@ static void com20020_set_mc_list(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; - if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */ + if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { + /* Enable promiscuous mode */ if (!(lp->setup & PROMISCset)) arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); lp->setup |= PROMISCset; outb(lp->setup, _XREG); - } else + } else { /* Disable promiscuous mode, use normal mode */ - { if ((lp->setup & PROMISCset)) arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); @@ -370,7 +372,7 @@ MODULE_LICENSE("GPL"); static int __init com20020_module_init(void) { if (BUGLVL(D_NORMAL)) - pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)\n"); + pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)"); return 0; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 11bc589aa8d1..9e779a53035d 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -49,8 +49,8 @@ static void com90io_setmask(struct net_device *dev, int mask); static int com90io_reset(struct net_device *dev, int really_reset); static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); -static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count); +static void com90io_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count); /* Handy defines for ARCnet specific stuff */ @@ -96,7 +96,8 @@ static u_char get_buffer_byte(struct net_device *dev, unsigned offset) } #ifdef ONE_AT_A_TIME_TX -static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datum) +static void put_buffer_byte(struct net_device *dev, unsigned offset, + u_char datum) { int ioaddr = dev->base_addr; @@ -108,7 +109,8 @@ static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datu #endif -static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) +static void get_whole_buffer(struct net_device *dev, unsigned offset, + unsigned length, char *dest) { int ioaddr = dev->base_addr; @@ -123,7 +125,8 @@ static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned l #endif } -static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) +static void put_whole_buffer(struct net_device *dev, unsigned offset, + unsigned length, char *dest) { int ioaddr = dev->base_addr; @@ -237,12 +240,14 @@ static int __init com90io_found(struct net_device *dev) int err; /* Reserve the irq */ - if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) { + if (request_irq(dev->irq, arcnet_interrupt, 0, + "arcnet (COM90xx-IO)", dev)) { arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } /* Reserve the I/O region */ - if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) { + if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, + "arcnet (COM90xx-IO)")) { free_irq(dev->irq, dev); return -EBUSY; } @@ -338,15 +343,15 @@ static void com90io_setmask(struct net_device *dev, int mask) AINTMASK(mask); } -static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90io_copy_to_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { TIME(dev, "put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } -static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90io_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { TIME(dev, "get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); @@ -418,7 +423,9 @@ static void __exit com90io_exit(void) unregister_netdev(dev); - /* Set the thing back to MMAP mode, in case the old driver is loaded later */ + /* In case the old driver is loaded later, + * set the thing back to MMAP mode + */ outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); free_irq(dev->irq, dev); diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 50c346b5d907..62100acfb6a7 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -60,8 +60,8 @@ static void com90xx_setmask(struct net_device *dev, int mask); static int com90xx_reset(struct net_device *dev, int really_reset); static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); -static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count); +static void com90xx_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count); /* Known ARCnet cards */ @@ -165,7 +165,8 @@ static void __init com90xx_probe(void) ioaddr = *port; - if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { + if (!request_region(*port, ARCNET_TOTAL_SIZE, + "arcnet (90xx)")) { arc_cont(D_INIT_REASONS, "(request_region)\n"); arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) @@ -467,7 +468,8 @@ static int check_mirror(unsigned long addr, size_t size) /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ -static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p) +static int __init com90xx_found(int ioaddr, int airq, u_long shmem, + void __iomem *p) { struct net_device *dev = NULL; struct arcnet_local *lp; @@ -511,7 +513,9 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem iounmap(p); release_mem_region(shmem, MIRROR_SIZE); - if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) + if (!request_mem_region(dev->mem_start, + dev->mem_end - dev->mem_start + 1, + "arcnet (90xx)")) goto err_free_dev; /* reserve the irq */ @@ -530,7 +534,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem lp->hw.owner = THIS_MODULE; lp->hw.copy_to_card = com90xx_copy_to_card; lp->hw.copy_from_card = com90xx_copy_from_card; - lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); + lp->mem_start = ioremap(dev->mem_start, + dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_free_irq; @@ -627,8 +632,8 @@ static int com90xx_reset(struct net_device *dev, int really_reset) return 0; } -static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90xx_copy_to_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; @@ -636,8 +641,8 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } -static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90xx_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; @@ -671,7 +676,8 @@ static void __exit com90xx_exit(void) free_irq(dev->irq, dev); iounmap(lp->mem_start); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); - release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); + release_mem_region(dev->mem_start, + dev->mem_end - dev->mem_start + 1); free_netdev(dev); } } diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index b76e458b19e0..691bee5bcd42 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -213,7 +213,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); - length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; if (length > XMTU) { /* should never happen! other people already check for this. */ diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 1d777c1e8383..aaa1966593aa 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -188,11 +188,14 @@ static void rx(struct net_device *dev, int bufnum, pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; - /* up to sizeof(pkt->soft) has already been copied from the card */ + /* up to sizeof(pkt->soft) has already + * been copied from the card + */ memcpy(pkt, pkthdr, sizeof(struct archdr)); if (length > sizeof(pkt->soft)) - lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), - pkt->soft.raw + sizeof(pkt->soft), + lp->hw.copy_from_card(dev, bufnum, + ofs + sizeof(pkt->soft), + pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); /* ARP packets have problems when sent from some DOS systems: @@ -318,7 +321,8 @@ static void rx(struct net_device *dev, int bufnum, return; } in->lastpacket++; - if (packetnum != in->lastpacket) { /* not the right flag! */ + /* if not the right flag */ + if (packetnum != in->lastpacket) { /* harmless duplicate? ignore. */ if (packetnum <= in->lastpacket - 1) { arc_printk(D_EXTRA, dev, "duplicate splitpacket ignored! (splitflag=%d)\n", @@ -477,7 +481,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); - length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; pkt->soft.rfc1201.split_flag = 0; /* need to do a split packet? */ diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index 1d8e36e13616..9ca135d0f114 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -203,8 +203,8 @@ struct ArcProto { unsigned short ethproto, uint8_t daddr); /* these functions return '1' if the skb can now be freed */ - int (*prepare_tx)(struct net_device *dev, struct archdr *pkt, int length, - int bufnum); + int (*prepare_tx)(struct net_device *dev, struct archdr *pkt, + int length, int bufnum); int (*continue_tx)(struct net_device *dev, int bufnum); int (*ack_tx)(struct net_device *dev, int acked); }; @@ -309,10 +309,10 @@ struct arcnet_local { void (*open)(struct net_device *dev); void (*close)(struct net_device *dev); - void (*copy_to_card)(struct net_device *dev, int bufnum, int offset, - void *buf, int count); - void (*copy_from_card)(struct net_device *dev, int bufnum, int offset, - void *buf, int count); + void (*copy_to_card)(struct net_device *dev, int bufnum, + int offset, void *buf, int count); + void (*copy_from_card)(struct net_device *dev, int bufnum, + int offset, void *buf, int count); } hw; void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ -- cgit v1.3-6-gb490 From 26c6d281688e8bb8154fa78c60e551d024f5d0b8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:03 -0700 Subject: arcnet: Move files out of include/linux These #include files don't need to be in the include/linux directory as they can be local to drivers/net/arcnet/ Move them and update the #include statements. Update the MAINTAINERS file pattern by deleting arcdevice from the NETWORKING block as arcnet is currently unmaintained. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- MAINTAINERS | 1 - drivers/net/arcnet/arc-rawmode.c | 3 +- drivers/net/arcnet/arc-rimi.c | 3 +- drivers/net/arcnet/arcdevice.h | 346 ++++++++++++++++++++++++++++++++++++++ drivers/net/arcnet/arcnet.c | 3 +- drivers/net/arcnet/capmode.c | 3 +- drivers/net/arcnet/com20020-isa.c | 6 +- drivers/net/arcnet/com20020-pci.c | 6 +- drivers/net/arcnet/com20020.c | 6 +- drivers/net/arcnet/com20020.h | 145 ++++++++++++++++ drivers/net/arcnet/com20020_cs.c | 7 +- drivers/net/arcnet/com90io.c | 3 +- drivers/net/arcnet/com90xx.c | 3 +- drivers/net/arcnet/rfc1051.c | 3 +- drivers/net/arcnet/rfc1201.c | 3 +- include/linux/arcdevice.h | 346 -------------------------------------- include/linux/com20020.h | 145 ---------------- 17 files changed, 519 insertions(+), 513 deletions(-) create mode 100644 drivers/net/arcnet/arcdevice.h create mode 100644 drivers/net/arcnet/com20020.h delete mode 100644 include/linux/arcdevice.h delete mode 100644 include/linux/com20020.h (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index 310da4295c70..c978a257f4aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7292,7 +7292,6 @@ S: Odd Fixes F: drivers/net/ F: include/linux/if_* F: include/linux/netdevice.h -F: include/linux/arcdevice.h F: include/linux/etherdevice.h F: include/linux/fcdevice.h F: include/linux/fddidevice.h diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 59b3083c19f9..35a747a7329e 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -33,7 +33,8 @@ #include #include #include -#include + +#include "arcdevice.h" static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 8fa5eb43f308..37406fffc001 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -37,7 +37,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* Internal function declarations */ diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h new file mode 100644 index 000000000000..9ca135d0f114 --- /dev/null +++ b/drivers/net/arcnet/arcdevice.h @@ -0,0 +1,346 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. NET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions used by the ARCnet driver. + * + * Authors: Avery Pennarun and David Woodhouse + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ +#ifndef _LINUX_ARCDEVICE_H +#define _LINUX_ARCDEVICE_H + +#include +#include + +#ifdef __KERNEL__ +#include + +/* + * RECON_THRESHOLD is the maximum number of RECON messages to receive + * within one minute before printing a "cabling problem" warning. The + * default value should be fine. + * + * After that, a "cabling restored" message will be printed on the next IRQ + * if no RECON messages have been received for 10 seconds. + * + * Do not define RECON_THRESHOLD at all if you want to disable this feature. + */ +#define RECON_THRESHOLD 30 + +/* + * Define this to the minimum "timeout" value. If a transmit takes longer + * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large + * network, or one with heavy network traffic, this timeout may need to be + * increased. The larger it is, though, the longer it will be between + * necessary transmits - don't set this too high. + */ +#define TX_TIMEOUT (HZ * 200 / 1000) + +/* Display warnings about the driver being an ALPHA version. */ +#undef ALPHA_WARNING + +/* + * Debugging bitflags: each option can be enabled individually. + * + * Note: only debug flags included in the ARCNET_DEBUG_MAX define will + * actually be available. GCC will (at least, GCC 2.7.0 will) notice + * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize + * them out. + */ +#define D_NORMAL 1 /* important operational info */ +#define D_EXTRA 2 /* useful, but non-vital information */ +#define D_INIT 4 /* show init/probe messages */ +#define D_INIT_REASONS 8 /* show reasons for discarding probes */ +#define D_RECON 32 /* print a message whenever token is lost */ +#define D_PROTO 64 /* debug auto-protocol support */ +/* debug levels below give LOTS of output during normal operation! */ +#define D_DURING 128 /* trace operations (including irq's) */ +#define D_TX 256 /* show tx packets */ +#define D_RX 512 /* show rx packets */ +#define D_SKB 1024 /* show skb's */ +#define D_SKB_SIZE 2048 /* show skb sizes */ +#define D_TIMING 4096 /* show time needed to copy buffers to card */ +#define D_DEBUG 8192 /* Very detailed debug line for line */ + +#ifndef ARCNET_DEBUG_MAX +#define ARCNET_DEBUG_MAX (127) /* change to ~0 if you want detailed debugging */ +#endif + +#ifndef ARCNET_DEBUG +#define ARCNET_DEBUG (D_NORMAL | D_EXTRA) +#endif +extern int arcnet_debug; + +#define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) + +/* macros to simplify debug checking */ +#define arc_printk(x, dev, fmt, ...) \ +do { \ + if (BUGLVL(x)) { \ + if ((x) == D_NORMAL) \ + netdev_warn(dev, fmt, ##__VA_ARGS__); \ + else if ((x) < D_DURING) \ + netdev_info(dev, fmt, ##__VA_ARGS__); \ + else \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) + +#define arc_cont(x, fmt, ...) \ +do { \ + if (BUGLVL(x)) \ + pr_cont(fmt, ##__VA_ARGS__); \ +} while (0) + +/* see how long a function call takes to run, expressed in CPU cycles */ +#define TIME(dev, name, bytes, call) \ +do { \ + if (BUGLVL(D_TIMING)) { \ + unsigned long _x, _y; \ + _x = get_cycles(); \ + call; \ + _y = get_cycles(); \ + arc_printk(D_TIMING, dev, \ + "%s: %d bytes in %lu cycles == %lu Kbytes/100Mcycle\n", \ + name, bytes, _y - _x, \ + 100000000 / 1024 * bytes / (_y - _x + 1)); \ + } else { \ + call; \ + } \ +} while (0) + +/* + * Time needed to reset the card - in ms (milliseconds). This works on my + * SMC PC100. I can't find a reference that tells me just how long I + * should wait. + */ +#define RESETtime (300) + +/* + * These are the max/min lengths of packet payload, not including the + * arc_hardware header, but definitely including the soft header. + * + * Note: packet sizes 254, 255, 256 are impossible because of the way + * ARCnet registers work That's why RFC1201 defines "exception" packets. + * In non-RFC1201 protocols, we have to just tack some extra bytes on the + * end. + */ +#define MTU 253 /* normal packet max size */ +#define MinTU 257 /* extended packet min size */ +#define XMTU 508 /* extended packet max size */ + +/* status/interrupt mask bit fields */ +#define TXFREEflag 0x01 /* transmitter available */ +#define TXACKflag 0x02 /* transmitted msg. ackd */ +#define RECONflag 0x04 /* network reconfigured */ +#define TESTflag 0x08 /* test flag */ +#define EXCNAKflag 0x08 /* excesive nak flag */ +#define RESETflag 0x10 /* power-on-reset */ +#define RES1flag 0x20 /* reserved - usually set by jumper */ +#define RES2flag 0x40 /* reserved - usually set by jumper */ +#define NORXflag 0x80 /* receiver inhibited */ + +/* Flags used for IO-mapped memory operations */ +#define AUTOINCflag 0x40 /* Increase location with each access */ +#define IOMAPflag 0x02 /* (for 90xx) Use IO mapped memory, not mmap */ +#define ENABLE16flag 0x80 /* (for 90xx) Enable 16-bit mode */ + +/* in the command register, the following bits have these meanings: + * 0-2 command + * 3-4 page number (for enable rcv/xmt command) + * 7 receive broadcasts + */ +#define NOTXcmd 0x01 /* disable transmitter */ +#define NORXcmd 0x02 /* disable receiver */ +#define TXcmd 0x03 /* enable transmitter */ +#define RXcmd 0x04 /* enable receiver */ +#define CONFIGcmd 0x05 /* define configuration */ +#define CFLAGScmd 0x06 /* clear flags */ +#define TESTcmd 0x07 /* load test flags */ + +/* flags for "clear flags" command */ +#define RESETclear 0x08 /* power-on-reset */ +#define CONFIGclear 0x10 /* system reconfigured */ + +#define EXCNAKclear 0x0E /* Clear and acknowledge the excive nak bit */ + +/* flags for "load test flags" command */ +#define TESTload 0x08 /* test flag (diagnostic) */ + +/* byte deposited into first address of buffers on reset */ +#define TESTvalue 0321 /* that's octal for 0xD1 :) */ + +/* for "enable receiver" command */ +#define RXbcasts 0x80 /* receive broadcasts */ + +/* flags for "define configuration" command */ +#define NORMALconf 0x00 /* 1-249 byte packets */ +#define EXTconf 0x08 /* 250-504 byte packets */ + +/* card feature flags, set during auto-detection. + * (currently only used by com20020pci) + */ +#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */ +#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit, + but default is 2.5MBit. */ + +/* information needed to define an encapsulation driver */ +struct ArcProto { + char suffix; /* a for RFC1201, e for ether-encap, etc. */ + int mtu; /* largest possible packet */ + int is_ip; /* This is a ip plugin - not a raw thing */ + + void (*rx)(struct net_device *dev, int bufnum, + struct archdr *pkthdr, int length); + int (*build_header)(struct sk_buff *skb, struct net_device *dev, + unsigned short ethproto, uint8_t daddr); + + /* these functions return '1' if the skb can now be freed */ + int (*prepare_tx)(struct net_device *dev, struct archdr *pkt, + int length, int bufnum); + int (*continue_tx)(struct net_device *dev, int bufnum); + int (*ack_tx)(struct net_device *dev, int acked); +}; + +extern struct ArcProto *arc_proto_map[256], *arc_proto_default, + *arc_bcast_proto, *arc_raw_proto; + +/* + * "Incoming" is information needed for each address that could be sending + * to us. Mostly for partially-received split packets. + */ +struct Incoming { + struct sk_buff *skb; /* packet data buffer */ + __be16 sequence; /* sequence number of assembly */ + uint8_t lastpacket, /* number of last packet (from 1) */ + numpackets; /* number of packets in split */ +}; + +/* only needed for RFC1201 */ +struct Outgoing { + struct ArcProto *proto; /* protocol driver that owns this: + * if NULL, no packet is pending. + */ + struct sk_buff *skb; /* buffer from upper levels */ + struct archdr *pkt; /* a pointer into the skb */ + uint16_t length, /* bytes total */ + dataleft, /* bytes left */ + segnum, /* segment being sent */ + numsegs; /* number of segments */ +}; + +struct arcnet_local { + uint8_t config, /* current value of CONFIG register */ + timeout, /* Extended timeout for COM20020 */ + backplane, /* Backplane flag for COM20020 */ + clockp, /* COM20020 clock divider */ + clockm, /* COM20020 clock multiplier flag */ + setup, /* Contents of setup1 register */ + setup2, /* Contents of setup2 register */ + intmask; /* current value of INTMASK register */ + uint8_t default_proto[256]; /* default encap to use for each host */ + int cur_tx, /* buffer used by current transmit, or -1 */ + next_tx, /* buffer where a packet is ready to send */ + cur_rx; /* current receive buffer */ + int lastload_dest, /* can last loaded packet be acked? */ + lasttrans_dest; /* can last TX'd packet be acked? */ + int timed_out; /* need to process TX timeout and drop packet */ + unsigned long last_timeout; /* time of last reported timeout */ + char *card_name; /* card ident string */ + int card_flags; /* special card features */ + + /* On preemtive and SMB a lock is needed */ + spinlock_t lock; + + /* + * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of + * which can be used for either sending or receiving. The new dynamic + * buffer management routines use a simple circular queue of available + * buffers, and take them as they're needed. This way, we simplify + * situations in which we (for example) want to pre-load a transmit + * buffer, or start receiving while we copy a received packet to + * memory. + * + * The rules: only the interrupt handler is allowed to _add_ buffers to + * the queue; thus, this doesn't require a lock. Both the interrupt + * handler and the transmit function will want to _remove_ buffers, so + * we need to handle the situation where they try to do it at the same + * time. + * + * If next_buf == first_free_buf, the queue is empty. Since there are + * only four possible buffers, the queue should never be full. + */ + atomic_t buf_lock; + int buf_queue[5]; + int next_buf, first_free_buf; + + /* network "reconfiguration" handling */ + unsigned long first_recon; /* time of "first" RECON message to count */ + unsigned long last_recon; /* time of most recent RECON */ + int num_recons; /* number of RECONs between first and last. */ + int network_down; /* do we think the network is down? */ + + int excnak_pending; /* We just got an excesive nak interrupt */ + + struct { + uint16_t sequence; /* sequence number (incs with each packet) */ + __be16 aborted_seq; + + struct Incoming incoming[256]; /* one from each address */ + } rfc1201; + + /* really only used by rfc1201, but we'll pretend it's not */ + struct Outgoing outgoing; /* packet currently being sent */ + + /* hardware-specific functions */ + struct { + struct module *owner; + void (*command)(struct net_device *dev, int cmd); + int (*status)(struct net_device *dev); + void (*intmask)(struct net_device *dev, int mask); + int (*reset)(struct net_device *dev, int really_reset); + void (*open)(struct net_device *dev); + void (*close)(struct net_device *dev); + + void (*copy_to_card)(struct net_device *dev, int bufnum, + int offset, void *buf, int count); + void (*copy_from_card)(struct net_device *dev, int bufnum, + int offset, void *buf, int count); + } hw; + + void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ +}; + +#define ARCRESET(x) (lp->hw.reset(dev, (x))) +#define ACOMMAND(x) (lp->hw.command(dev, (x))) +#define ASTATUS() (lp->hw.status(dev)) +#define AINTMASK(x) (lp->hw.intmask(dev, (x))) + +#if ARCNET_DEBUG_MAX & D_SKB +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); +#else +static inline +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) +{ +} +#endif + +void arcnet_unregister_proto(struct ArcProto *proto); +irqreturn_t arcnet_interrupt(int irq, void *dev_id); +struct net_device *alloc_arcdev(const char *name); + +int arcnet_open(struct net_device *dev); +int arcnet_close(struct net_device *dev); +netdev_tx_t arcnet_send_packet(struct sk_buff *skb, + struct net_device *dev); +void arcnet_timeout(struct net_device *dev); + +#endif /* __KERNEL__ */ +#endif /* _LINUX_ARCDEVICE_H */ diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 00074e781353..c8423ee24e71 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -50,9 +50,10 @@ #include #include #include -#include #include +#include "arcdevice.h" + /* "do nothing" functions for protocol drivers */ static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 46a76dcc21aa..2f2d0d94a80d 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -35,7 +35,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* packet receiver */ static void rx(struct net_device *dev, int bufnum, diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 352500b8d875..ab5202b506a6 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -39,11 +39,11 @@ #include #include #include -#include -#include - #include +#include "arcdevice.h" +#include "com20020.h" + /* We cannot (yet) probe for an IO mapped card, although we can check that * it's where we were told it was, and even do autoirq. */ diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index a28887dfcc9e..1a75a6982031 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -39,12 +39,12 @@ #include #include #include -#include -#include #include - #include +#include "arcdevice.h" +#include "com20020.h" + /* Module parameters */ static int node; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 00f910cf7b81..f46e22093c54 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -37,11 +37,11 @@ #include #include #include -#include -#include - #include +#include "arcdevice.h" +#include "com20020.h" + static char *clockrates[] = { "XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h new file mode 100644 index 000000000000..85898995b234 --- /dev/null +++ b/drivers/net/arcnet/com20020.h @@ -0,0 +1,145 @@ +/* + * Linux ARCnet driver - COM20020 chipset support - function declarations + * + * Written 1997 by David Woodhouse. + * Written 1994-1999 by Avery Pennarun. + * Derived from skeleton.c by Donald Becker. + * + * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) + * for sponsoring the further development of this driver. + * + * ********************** + * + * The original copyright of skeleton.c was as follows: + * + * skeleton.c Written 1993 by Donald Becker. + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. This software may only be used + * and distributed according to the terms of the GNU General Public License as + * modified by SRC, incorporated herein by reference. + * + * ********************** + * + * For more details, see drivers/net/arcnet.c + * + * ********************** + */ +#ifndef __COM20020_H +#define __COM20020_H + +int com20020_check(struct net_device *dev); +int com20020_found(struct net_device *dev, int shared); +extern const struct net_device_ops com20020_netdev_ops; + +/* The number of low I/O ports used by the card. */ +#define ARCNET_TOTAL_SIZE 8 + +/* various register addresses */ +#ifdef CONFIG_SA1100_CT6001 +#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */ +#else +#define BUS_ALIGN 1 +#endif + +#define PLX_PCI_MAX_CARDS 2 + +struct com20020_pci_channel_map { + u32 bar; + u32 offset; + u32 size; /* 0x00 - auto, e.g. length of entire bar */ +}; + +struct com20020_pci_card_info { + const char *name; + int devcount; + + struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; + + unsigned int flags; +}; + +struct com20020_priv { + struct com20020_pci_card_info *ci; + struct list_head list_dev; +}; + +struct com20020_dev { + struct list_head list; + struct net_device *dev; + + struct com20020_priv *pci_priv; + int index; +}; + +#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */ +#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */ +#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */ +#define _DIAGSTAT (ioaddr+BUS_ALIGN*1) /* diagnostic status register */ +#define _ADDR_HI (ioaddr+BUS_ALIGN*2) /* control registers for IO-mapped memory */ +#define _ADDR_LO (ioaddr+BUS_ALIGN*3) +#define _MEMDATA (ioaddr+BUS_ALIGN*4) /* data port for IO-mapped memory */ +#define _SUBADR (ioaddr+BUS_ALIGN*5) /* the extended port _XREG refers to */ +#define _CONFIG (ioaddr+BUS_ALIGN*6) /* configuration register */ +#define _XREG (ioaddr+BUS_ALIGN*7) /* extra registers (indexed by _CONFIG + or _SUBADR) */ + +/* in the ADDR_HI register */ +#define RDDATAflag 0x80 /* next access is a read (not a write) */ + +/* in the DIAGSTAT register */ +#define NEWNXTIDflag 0x02 /* ID to which token is passed has changed */ + +/* in the CONFIG register */ +#define RESETcfg 0x80 /* put card in reset state */ +#define TXENcfg 0x20 /* enable TX */ + +/* in SETUP register */ +#define PROMISCset 0x10 /* enable RCV_ALL */ +#define P1MODE 0x80 /* enable P1-MODE for Backplane */ +#define SLOWARB 0x01 /* enable Slow Arbitration for >=5Mbps */ + +/* COM2002x */ +#define SUB_TENTATIVE 0 /* tentative node ID */ +#define SUB_NODE 1 /* node ID */ +#define SUB_SETUP1 2 /* various options */ +#define SUB_TEST 3 /* test/diag register */ + +/* COM20022 only */ +#define SUB_SETUP2 4 /* sundry options */ +#define SUB_BUSCTL 5 /* bus control options */ +#define SUB_DMACOUNT 6 /* DMA count options */ + +#define SET_SUBADR(x) do { \ + if ((x) < 4) \ + { \ + lp->config = (lp->config & ~0x03) | (x); \ + SETCONF; \ + } \ + else \ + { \ + outb(x, _SUBADR); \ + } \ +} while (0) + +#undef ARCRESET +#undef ASTATUS +#undef ACOMMAND +#undef AINTMASK + +#define ARCRESET { outb(lp->config | 0x80, _CONFIG); \ + udelay(5); \ + outb(lp->config , _CONFIG); \ + } +#define ARCRESET0 { outb(0x18 | 0x80, _CONFIG); \ + udelay(5); \ + outb(0x18 , _CONFIG); \ + } + +#define ASTATUS() inb(_STATUS) +#define ADIAGSTATUS() inb(_DIAGSTAT) +#define ACOMMAND(cmd) outb((cmd),_COMMAND) +#define AINTMASK(msk) outb((msk),_INTMASK) + +#define SETCONF outb(lp->config, _CONFIG) + +#endif /* __COM20020_H */ diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 854169489b68..5fdde6946427 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -42,13 +42,12 @@ #include #include #include -#include -#include - +#include #include #include -#include +#include "arcdevice.h" +#include "com20020.h" static void regdump(struct net_device *dev) { diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 9e779a53035d..ce15d1911048 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -38,7 +38,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* Internal function declarations */ diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 62100acfb6a7..b672795acaa7 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -36,7 +36,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 691bee5bcd42..4b1a75469cb1 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -33,7 +33,8 @@ #include #include #include -#include + +#include "arcdevice.h" static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index aaa1966593aa..566da5ecdc9d 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -32,7 +32,8 @@ #include #include #include -#include + +#include "arcdevice.h" MODULE_LICENSE("GPL"); diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h deleted file mode 100644 index 9ca135d0f114..000000000000 --- a/include/linux/arcdevice.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. NET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions used by the ARCnet driver. - * - * Authors: Avery Pennarun and David Woodhouse - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ -#ifndef _LINUX_ARCDEVICE_H -#define _LINUX_ARCDEVICE_H - -#include -#include - -#ifdef __KERNEL__ -#include - -/* - * RECON_THRESHOLD is the maximum number of RECON messages to receive - * within one minute before printing a "cabling problem" warning. The - * default value should be fine. - * - * After that, a "cabling restored" message will be printed on the next IRQ - * if no RECON messages have been received for 10 seconds. - * - * Do not define RECON_THRESHOLD at all if you want to disable this feature. - */ -#define RECON_THRESHOLD 30 - -/* - * Define this to the minimum "timeout" value. If a transmit takes longer - * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large - * network, or one with heavy network traffic, this timeout may need to be - * increased. The larger it is, though, the longer it will be between - * necessary transmits - don't set this too high. - */ -#define TX_TIMEOUT (HZ * 200 / 1000) - -/* Display warnings about the driver being an ALPHA version. */ -#undef ALPHA_WARNING - -/* - * Debugging bitflags: each option can be enabled individually. - * - * Note: only debug flags included in the ARCNET_DEBUG_MAX define will - * actually be available. GCC will (at least, GCC 2.7.0 will) notice - * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize - * them out. - */ -#define D_NORMAL 1 /* important operational info */ -#define D_EXTRA 2 /* useful, but non-vital information */ -#define D_INIT 4 /* show init/probe messages */ -#define D_INIT_REASONS 8 /* show reasons for discarding probes */ -#define D_RECON 32 /* print a message whenever token is lost */ -#define D_PROTO 64 /* debug auto-protocol support */ -/* debug levels below give LOTS of output during normal operation! */ -#define D_DURING 128 /* trace operations (including irq's) */ -#define D_TX 256 /* show tx packets */ -#define D_RX 512 /* show rx packets */ -#define D_SKB 1024 /* show skb's */ -#define D_SKB_SIZE 2048 /* show skb sizes */ -#define D_TIMING 4096 /* show time needed to copy buffers to card */ -#define D_DEBUG 8192 /* Very detailed debug line for line */ - -#ifndef ARCNET_DEBUG_MAX -#define ARCNET_DEBUG_MAX (127) /* change to ~0 if you want detailed debugging */ -#endif - -#ifndef ARCNET_DEBUG -#define ARCNET_DEBUG (D_NORMAL | D_EXTRA) -#endif -extern int arcnet_debug; - -#define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) - -/* macros to simplify debug checking */ -#define arc_printk(x, dev, fmt, ...) \ -do { \ - if (BUGLVL(x)) { \ - if ((x) == D_NORMAL) \ - netdev_warn(dev, fmt, ##__VA_ARGS__); \ - else if ((x) < D_DURING) \ - netdev_info(dev, fmt, ##__VA_ARGS__); \ - else \ - netdev_dbg(dev, fmt, ##__VA_ARGS__); \ - } \ -} while (0) - -#define arc_cont(x, fmt, ...) \ -do { \ - if (BUGLVL(x)) \ - pr_cont(fmt, ##__VA_ARGS__); \ -} while (0) - -/* see how long a function call takes to run, expressed in CPU cycles */ -#define TIME(dev, name, bytes, call) \ -do { \ - if (BUGLVL(D_TIMING)) { \ - unsigned long _x, _y; \ - _x = get_cycles(); \ - call; \ - _y = get_cycles(); \ - arc_printk(D_TIMING, dev, \ - "%s: %d bytes in %lu cycles == %lu Kbytes/100Mcycle\n", \ - name, bytes, _y - _x, \ - 100000000 / 1024 * bytes / (_y - _x + 1)); \ - } else { \ - call; \ - } \ -} while (0) - -/* - * Time needed to reset the card - in ms (milliseconds). This works on my - * SMC PC100. I can't find a reference that tells me just how long I - * should wait. - */ -#define RESETtime (300) - -/* - * These are the max/min lengths of packet payload, not including the - * arc_hardware header, but definitely including the soft header. - * - * Note: packet sizes 254, 255, 256 are impossible because of the way - * ARCnet registers work That's why RFC1201 defines "exception" packets. - * In non-RFC1201 protocols, we have to just tack some extra bytes on the - * end. - */ -#define MTU 253 /* normal packet max size */ -#define MinTU 257 /* extended packet min size */ -#define XMTU 508 /* extended packet max size */ - -/* status/interrupt mask bit fields */ -#define TXFREEflag 0x01 /* transmitter available */ -#define TXACKflag 0x02 /* transmitted msg. ackd */ -#define RECONflag 0x04 /* network reconfigured */ -#define TESTflag 0x08 /* test flag */ -#define EXCNAKflag 0x08 /* excesive nak flag */ -#define RESETflag 0x10 /* power-on-reset */ -#define RES1flag 0x20 /* reserved - usually set by jumper */ -#define RES2flag 0x40 /* reserved - usually set by jumper */ -#define NORXflag 0x80 /* receiver inhibited */ - -/* Flags used for IO-mapped memory operations */ -#define AUTOINCflag 0x40 /* Increase location with each access */ -#define IOMAPflag 0x02 /* (for 90xx) Use IO mapped memory, not mmap */ -#define ENABLE16flag 0x80 /* (for 90xx) Enable 16-bit mode */ - -/* in the command register, the following bits have these meanings: - * 0-2 command - * 3-4 page number (for enable rcv/xmt command) - * 7 receive broadcasts - */ -#define NOTXcmd 0x01 /* disable transmitter */ -#define NORXcmd 0x02 /* disable receiver */ -#define TXcmd 0x03 /* enable transmitter */ -#define RXcmd 0x04 /* enable receiver */ -#define CONFIGcmd 0x05 /* define configuration */ -#define CFLAGScmd 0x06 /* clear flags */ -#define TESTcmd 0x07 /* load test flags */ - -/* flags for "clear flags" command */ -#define RESETclear 0x08 /* power-on-reset */ -#define CONFIGclear 0x10 /* system reconfigured */ - -#define EXCNAKclear 0x0E /* Clear and acknowledge the excive nak bit */ - -/* flags for "load test flags" command */ -#define TESTload 0x08 /* test flag (diagnostic) */ - -/* byte deposited into first address of buffers on reset */ -#define TESTvalue 0321 /* that's octal for 0xD1 :) */ - -/* for "enable receiver" command */ -#define RXbcasts 0x80 /* receive broadcasts */ - -/* flags for "define configuration" command */ -#define NORMALconf 0x00 /* 1-249 byte packets */ -#define EXTconf 0x08 /* 250-504 byte packets */ - -/* card feature flags, set during auto-detection. - * (currently only used by com20020pci) - */ -#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */ -#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit, - but default is 2.5MBit. */ - -/* information needed to define an encapsulation driver */ -struct ArcProto { - char suffix; /* a for RFC1201, e for ether-encap, etc. */ - int mtu; /* largest possible packet */ - int is_ip; /* This is a ip plugin - not a raw thing */ - - void (*rx)(struct net_device *dev, int bufnum, - struct archdr *pkthdr, int length); - int (*build_header)(struct sk_buff *skb, struct net_device *dev, - unsigned short ethproto, uint8_t daddr); - - /* these functions return '1' if the skb can now be freed */ - int (*prepare_tx)(struct net_device *dev, struct archdr *pkt, - int length, int bufnum); - int (*continue_tx)(struct net_device *dev, int bufnum); - int (*ack_tx)(struct net_device *dev, int acked); -}; - -extern struct ArcProto *arc_proto_map[256], *arc_proto_default, - *arc_bcast_proto, *arc_raw_proto; - -/* - * "Incoming" is information needed for each address that could be sending - * to us. Mostly for partially-received split packets. - */ -struct Incoming { - struct sk_buff *skb; /* packet data buffer */ - __be16 sequence; /* sequence number of assembly */ - uint8_t lastpacket, /* number of last packet (from 1) */ - numpackets; /* number of packets in split */ -}; - -/* only needed for RFC1201 */ -struct Outgoing { - struct ArcProto *proto; /* protocol driver that owns this: - * if NULL, no packet is pending. - */ - struct sk_buff *skb; /* buffer from upper levels */ - struct archdr *pkt; /* a pointer into the skb */ - uint16_t length, /* bytes total */ - dataleft, /* bytes left */ - segnum, /* segment being sent */ - numsegs; /* number of segments */ -}; - -struct arcnet_local { - uint8_t config, /* current value of CONFIG register */ - timeout, /* Extended timeout for COM20020 */ - backplane, /* Backplane flag for COM20020 */ - clockp, /* COM20020 clock divider */ - clockm, /* COM20020 clock multiplier flag */ - setup, /* Contents of setup1 register */ - setup2, /* Contents of setup2 register */ - intmask; /* current value of INTMASK register */ - uint8_t default_proto[256]; /* default encap to use for each host */ - int cur_tx, /* buffer used by current transmit, or -1 */ - next_tx, /* buffer where a packet is ready to send */ - cur_rx; /* current receive buffer */ - int lastload_dest, /* can last loaded packet be acked? */ - lasttrans_dest; /* can last TX'd packet be acked? */ - int timed_out; /* need to process TX timeout and drop packet */ - unsigned long last_timeout; /* time of last reported timeout */ - char *card_name; /* card ident string */ - int card_flags; /* special card features */ - - /* On preemtive and SMB a lock is needed */ - spinlock_t lock; - - /* - * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of - * which can be used for either sending or receiving. The new dynamic - * buffer management routines use a simple circular queue of available - * buffers, and take them as they're needed. This way, we simplify - * situations in which we (for example) want to pre-load a transmit - * buffer, or start receiving while we copy a received packet to - * memory. - * - * The rules: only the interrupt handler is allowed to _add_ buffers to - * the queue; thus, this doesn't require a lock. Both the interrupt - * handler and the transmit function will want to _remove_ buffers, so - * we need to handle the situation where they try to do it at the same - * time. - * - * If next_buf == first_free_buf, the queue is empty. Since there are - * only four possible buffers, the queue should never be full. - */ - atomic_t buf_lock; - int buf_queue[5]; - int next_buf, first_free_buf; - - /* network "reconfiguration" handling */ - unsigned long first_recon; /* time of "first" RECON message to count */ - unsigned long last_recon; /* time of most recent RECON */ - int num_recons; /* number of RECONs between first and last. */ - int network_down; /* do we think the network is down? */ - - int excnak_pending; /* We just got an excesive nak interrupt */ - - struct { - uint16_t sequence; /* sequence number (incs with each packet) */ - __be16 aborted_seq; - - struct Incoming incoming[256]; /* one from each address */ - } rfc1201; - - /* really only used by rfc1201, but we'll pretend it's not */ - struct Outgoing outgoing; /* packet currently being sent */ - - /* hardware-specific functions */ - struct { - struct module *owner; - void (*command)(struct net_device *dev, int cmd); - int (*status)(struct net_device *dev); - void (*intmask)(struct net_device *dev, int mask); - int (*reset)(struct net_device *dev, int really_reset); - void (*open)(struct net_device *dev); - void (*close)(struct net_device *dev); - - void (*copy_to_card)(struct net_device *dev, int bufnum, - int offset, void *buf, int count); - void (*copy_from_card)(struct net_device *dev, int bufnum, - int offset, void *buf, int count); - } hw; - - void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ -}; - -#define ARCRESET(x) (lp->hw.reset(dev, (x))) -#define ACOMMAND(x) (lp->hw.command(dev, (x))) -#define ASTATUS() (lp->hw.status(dev)) -#define AINTMASK(x) (lp->hw.intmask(dev, (x))) - -#if ARCNET_DEBUG_MAX & D_SKB -void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); -#else -static inline -void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) -{ -} -#endif - -void arcnet_unregister_proto(struct ArcProto *proto); -irqreturn_t arcnet_interrupt(int irq, void *dev_id); -struct net_device *alloc_arcdev(const char *name); - -int arcnet_open(struct net_device *dev); -int arcnet_close(struct net_device *dev); -netdev_tx_t arcnet_send_packet(struct sk_buff *skb, - struct net_device *dev); -void arcnet_timeout(struct net_device *dev); - -#endif /* __KERNEL__ */ -#endif /* _LINUX_ARCDEVICE_H */ diff --git a/include/linux/com20020.h b/include/linux/com20020.h deleted file mode 100644 index 85898995b234..000000000000 --- a/include/linux/com20020.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Linux ARCnet driver - COM20020 chipset support - function declarations - * - * Written 1997 by David Woodhouse. - * Written 1994-1999 by Avery Pennarun. - * Derived from skeleton.c by Donald Becker. - * - * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) - * for sponsoring the further development of this driver. - * - * ********************** - * - * The original copyright of skeleton.c was as follows: - * - * skeleton.c Written 1993 by Donald Becker. - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. This software may only be used - * and distributed according to the terms of the GNU General Public License as - * modified by SRC, incorporated herein by reference. - * - * ********************** - * - * For more details, see drivers/net/arcnet.c - * - * ********************** - */ -#ifndef __COM20020_H -#define __COM20020_H - -int com20020_check(struct net_device *dev); -int com20020_found(struct net_device *dev, int shared); -extern const struct net_device_ops com20020_netdev_ops; - -/* The number of low I/O ports used by the card. */ -#define ARCNET_TOTAL_SIZE 8 - -/* various register addresses */ -#ifdef CONFIG_SA1100_CT6001 -#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */ -#else -#define BUS_ALIGN 1 -#endif - -#define PLX_PCI_MAX_CARDS 2 - -struct com20020_pci_channel_map { - u32 bar; - u32 offset; - u32 size; /* 0x00 - auto, e.g. length of entire bar */ -}; - -struct com20020_pci_card_info { - const char *name; - int devcount; - - struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; - - unsigned int flags; -}; - -struct com20020_priv { - struct com20020_pci_card_info *ci; - struct list_head list_dev; -}; - -struct com20020_dev { - struct list_head list; - struct net_device *dev; - - struct com20020_priv *pci_priv; - int index; -}; - -#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */ -#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */ -#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */ -#define _DIAGSTAT (ioaddr+BUS_ALIGN*1) /* diagnostic status register */ -#define _ADDR_HI (ioaddr+BUS_ALIGN*2) /* control registers for IO-mapped memory */ -#define _ADDR_LO (ioaddr+BUS_ALIGN*3) -#define _MEMDATA (ioaddr+BUS_ALIGN*4) /* data port for IO-mapped memory */ -#define _SUBADR (ioaddr+BUS_ALIGN*5) /* the extended port _XREG refers to */ -#define _CONFIG (ioaddr+BUS_ALIGN*6) /* configuration register */ -#define _XREG (ioaddr+BUS_ALIGN*7) /* extra registers (indexed by _CONFIG - or _SUBADR) */ - -/* in the ADDR_HI register */ -#define RDDATAflag 0x80 /* next access is a read (not a write) */ - -/* in the DIAGSTAT register */ -#define NEWNXTIDflag 0x02 /* ID to which token is passed has changed */ - -/* in the CONFIG register */ -#define RESETcfg 0x80 /* put card in reset state */ -#define TXENcfg 0x20 /* enable TX */ - -/* in SETUP register */ -#define PROMISCset 0x10 /* enable RCV_ALL */ -#define P1MODE 0x80 /* enable P1-MODE for Backplane */ -#define SLOWARB 0x01 /* enable Slow Arbitration for >=5Mbps */ - -/* COM2002x */ -#define SUB_TENTATIVE 0 /* tentative node ID */ -#define SUB_NODE 1 /* node ID */ -#define SUB_SETUP1 2 /* various options */ -#define SUB_TEST 3 /* test/diag register */ - -/* COM20022 only */ -#define SUB_SETUP2 4 /* sundry options */ -#define SUB_BUSCTL 5 /* bus control options */ -#define SUB_DMACOUNT 6 /* DMA count options */ - -#define SET_SUBADR(x) do { \ - if ((x) < 4) \ - { \ - lp->config = (lp->config & ~0x03) | (x); \ - SETCONF; \ - } \ - else \ - { \ - outb(x, _SUBADR); \ - } \ -} while (0) - -#undef ARCRESET -#undef ASTATUS -#undef ACOMMAND -#undef AINTMASK - -#define ARCRESET { outb(lp->config | 0x80, _CONFIG); \ - udelay(5); \ - outb(lp->config , _CONFIG); \ - } -#define ARCRESET0 { outb(0x18 | 0x80, _CONFIG); \ - udelay(5); \ - outb(0x18 , _CONFIG); \ - } - -#define ASTATUS() inb(_STATUS) -#define ADIAGSTATUS() inb(_DIAGSTAT) -#define ACOMMAND(cmd) outb((cmd),_COMMAND) -#define AINTMASK(msk) outb((msk),_INTMASK) - -#define SETCONF outb(lp->config, _CONFIG) - -#endif /* __COM20020_H */ -- cgit v1.3-6-gb490 From 2726d6ce389788c7fe724961a6e1bfe569560088 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 2 Sep 2015 11:01:34 +0100 Subject: sched/deadline: Unify dl_time_before() usage Move dl_time_before() static definition in include/linux/sched/deadline.h so that it can be used by different parties without being re-defined. Reported-by: Luca Abeni Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1441188096-23021-3-git-send-email-juri.lelli@arm.com Signed-off-by: Ingo Molnar --- include/linux/sched/deadline.h | 5 +++++ kernel/sched/cpudeadline.c | 5 ----- kernel/sched/cpudeadline.h | 1 + kernel/sched/sched.h | 5 ----- 4 files changed, 6 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h index 9d303b8847df..9089a2ae913d 100644 --- a/include/linux/sched/deadline.h +++ b/include/linux/sched/deadline.h @@ -21,4 +21,9 @@ static inline int dl_task(struct task_struct *p) return dl_prio(p->prio); } +static inline bool dl_time_before(u64 a, u64 b) +{ + return (s64)(a - b) < 0; +} + #endif /* _SCHED_DEADLINE_H */ diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index c6acb07466bb..5a75b08cfd85 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -31,11 +31,6 @@ static inline int right_child(int i) return (i << 1) + 2; } -static inline int dl_time_before(u64 a, u64 b) -{ - return (s64)(a - b) < 0; -} - static void cpudl_exchange(struct cpudl *cp, int a, int b) { int cpu_a = cp->elements[a].cpu, cpu_b = cp->elements[b].cpu; diff --git a/kernel/sched/cpudeadline.h b/kernel/sched/cpudeadline.h index 1a0a6ef2fbe1..fcbdf83fed7e 100644 --- a/kernel/sched/cpudeadline.h +++ b/kernel/sched/cpudeadline.h @@ -2,6 +2,7 @@ #define _LINUX_CPUDL_H #include +#include #define IDX_INVALID -1 diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 3845a711c65e..af6f252e7e34 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -118,11 +118,6 @@ static inline int task_has_dl_policy(struct task_struct *p) return dl_policy(p->policy); } -static inline bool dl_time_before(u64 a, u64 b) -{ - return (s64)(a - b) < 0; -} - /* * Tells if entity @a should preempt entity @b. */ -- cgit v1.3-6-gb490 From 90fe65148ea76988d8d5acbf3e578aa74129a490 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 18 Sep 2015 15:04:59 +0200 Subject: atomic: Add atomic_long_t bitops When adding the atomic bitops, I seem to have forgotten about atomic_long_t, fix this. Signed-off-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar --- include/asm-generic/atomic-long.h | 24 ++++++++++++++---------- include/linux/atomic.h | 3 ++- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h index a94cbebbc33d..c7a5c1ad2ed3 100644 --- a/include/asm-generic/atomic-long.h +++ b/include/asm-generic/atomic-long.h @@ -112,19 +112,23 @@ static inline void atomic_long_dec(atomic_long_t *l) ATOMIC_LONG_PFX(_dec)(v); } -static inline void atomic_long_add(long i, atomic_long_t *l) -{ - ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; - - ATOMIC_LONG_PFX(_add)(i, v); +#define ATOMIC_LONG_OP(op) \ +static inline void \ +atomic_long_##op(long i, atomic_long_t *l) \ +{ \ + ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \ + \ + ATOMIC_LONG_PFX(_##op)(i, v); \ } -static inline void atomic_long_sub(long i, atomic_long_t *l) -{ - ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; +ATOMIC_LONG_OP(add) +ATOMIC_LONG_OP(sub) +ATOMIC_LONG_OP(and) +ATOMIC_LONG_OP(or) +ATOMIC_LONG_OP(xor) +ATOMIC_LONG_OP(andnot) - ATOMIC_LONG_PFX(_sub)(i, v); -} +#undef ATOMIC_LONG_OP static inline int atomic_long_sub_and_test(long i, atomic_long_t *l) { diff --git a/include/linux/atomic.h b/include/linux/atomic.h index 00a5763e850e..29dafa184aeb 100644 --- a/include/linux/atomic.h +++ b/include/linux/atomic.h @@ -451,7 +451,6 @@ static inline int atomic_dec_if_positive(atomic_t *v) } #endif -#include #ifdef CONFIG_GENERIC_ATOMIC64 #include #endif @@ -463,4 +462,6 @@ static inline void atomic64_andnot(long long i, atomic64_t *v) } #endif +#include + #endif /* _LINUX_ATOMIC_H */ -- cgit v1.3-6-gb490 From 62e8a3258bda118f24ff462fe04cfbe75b8189b5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 18 Sep 2015 11:13:10 +0200 Subject: atomic, arch: Audit atomic_{read,set}() This patch makes sure that atomic_{read,set}() are at least {READ,WRITE}_ONCE(). We already had the 'requirement' that atomic_read() should use ACCESS_ONCE(), and most archs had this, but a few were lacking. All are now converted to use READ_ONCE(). And, by a symmetry and general paranoia argument, upgrade atomic_set() to use WRITE_ONCE(). Signed-off-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Dmitry Vyukov Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: james.hogan@imgtec.com Cc: linux-kernel@vger.kernel.org Cc: oleg@redhat.com Cc: will.deacon@arm.com Signed-off-by: Ingo Molnar --- arch/alpha/include/asm/atomic.h | 8 ++++---- arch/arc/include/asm/atomic.h | 8 ++++---- arch/arm/include/asm/atomic.h | 4 ++-- arch/arm64/include/asm/atomic.h | 2 +- arch/avr32/include/asm/atomic.h | 4 ++-- arch/frv/include/asm/atomic.h | 4 ++-- arch/h8300/include/asm/atomic.h | 4 ++-- arch/hexagon/include/asm/atomic.h | 2 +- arch/ia64/include/asm/atomic.h | 8 ++++---- arch/m32r/include/asm/atomic.h | 4 ++-- arch/m68k/include/asm/atomic.h | 4 ++-- arch/metag/include/asm/atomic_lnkget.h | 2 +- arch/metag/include/asm/atomic_lock1.h | 2 +- arch/mips/include/asm/atomic.h | 8 ++++---- arch/mn10300/include/asm/atomic.h | 4 ++-- arch/parisc/include/asm/atomic.h | 2 +- arch/sh/include/asm/atomic.h | 4 ++-- arch/sparc/include/asm/atomic_64.h | 8 ++++---- arch/tile/include/asm/atomic.h | 2 +- arch/tile/include/asm/atomic_64.h | 6 +++--- arch/x86/include/asm/atomic.h | 4 ++-- arch/x86/include/asm/atomic64_64.h | 4 ++-- arch/xtensa/include/asm/atomic.h | 4 ++-- include/asm-generic/atomic.h | 4 ++-- 24 files changed, 53 insertions(+), 53 deletions(-) (limited to 'include') diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index e8c956098424..572b228c44c7 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -17,11 +17,11 @@ #define ATOMIC_INIT(i) { (i) } #define ATOMIC64_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic64_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic64_read(v) READ_ONCE((v)->counter) -#define atomic_set(v,i) ((v)->counter = (i)) -#define atomic64_set(v,i) ((v)->counter = (i)) +#define atomic_set(v,i) WRITE_ONCE((v)->counter, (i)) +#define atomic64_set(v,i) WRITE_ONCE((v)->counter, (i)) /* * To get proper branch prediction for the main line, we must branch diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h index c3ecda023e3a..7730d302cadb 100644 --- a/arch/arc/include/asm/atomic.h +++ b/arch/arc/include/asm/atomic.h @@ -17,11 +17,11 @@ #include #include -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) #ifdef CONFIG_ARC_HAS_LLSC -#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #ifdef CONFIG_ARC_STAR_9000923308 @@ -107,7 +107,7 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ #ifndef CONFIG_SMP /* violating atomic_xxx API locking protocol in UP for optimization sake */ -#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #else @@ -125,7 +125,7 @@ static inline void atomic_set(atomic_t *v, int i) unsigned long flags; atomic_ops_lock(flags); - v->counter = i; + WRITE_ONCE(v->counter, i); atomic_ops_unlock(flags); } diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index fe3ef397f5a4..2bf80afb7841 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -27,8 +27,8 @@ * strex/ldrex monitor on some implementations. The reason we can use it for * atomic_set() is the clrex or dummy strex done on every exception return. */ -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic_set(v,i) WRITE_ONCE(((v)->counter), (i)) #if __LINUX_ARM_ARCH__ >= 6 diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h index 35a67783cfa0..1e247ac2601a 100644 --- a/arch/arm64/include/asm/atomic.h +++ b/arch/arm64/include/asm/atomic.h @@ -54,7 +54,7 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) READ_ONCE((v)->counter) -#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #define atomic_xchg(v, new) xchg(&((v)->counter), (new)) #define atomic_cmpxchg(v, old, new) cmpxchg(&((v)->counter), (old), (new)) diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h index 97c9bdf83409..d74fd8ce980a 100644 --- a/arch/avr32/include/asm/atomic.h +++ b/arch/avr32/include/asm/atomic.h @@ -19,8 +19,8 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic_set(v, i) (((v)->counter) = i) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #define ATOMIC_OP_RETURN(op, asm_op, asm_con) \ static inline int __atomic_##op##_return(int i, atomic_t *v) \ diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h index 0da689def4cc..64f02d451aa8 100644 --- a/arch/frv/include/asm/atomic.h +++ b/arch/frv/include/asm/atomic.h @@ -32,8 +32,8 @@ */ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) static inline int atomic_inc_return(atomic_t *v) { diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h index 702ee539f87d..4435a445ae7e 100644 --- a/arch/h8300/include/asm/atomic.h +++ b/arch/h8300/include/asm/atomic.h @@ -11,8 +11,8 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic_set(v, i) (((v)->counter) = i) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #include diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h index 811d61f6422d..55696c4100d4 100644 --- a/arch/hexagon/include/asm/atomic.h +++ b/arch/hexagon/include/asm/atomic.h @@ -48,7 +48,7 @@ static inline void atomic_set(atomic_t *v, int new) * * Assumes all word reads on our architecture are atomic. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) /** * atomic_xchg - atomic diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index be4beeb77d57..8dfb5f6f6c35 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -21,11 +21,11 @@ #define ATOMIC_INIT(i) { (i) } #define ATOMIC64_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic64_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic64_read(v) READ_ONCE((v)->counter) -#define atomic_set(v,i) (((v)->counter) = (i)) -#define atomic64_set(v,i) (((v)->counter) = (i)) +#define atomic_set(v,i) WRITE_ONCE(((v)->counter), (i)) +#define atomic64_set(v,i) WRITE_ONCE(((v)->counter), (i)) #define ATOMIC_OP(op, c_op) \ static __inline__ int \ diff --git a/arch/m32r/include/asm/atomic.h b/arch/m32r/include/asm/atomic.h index 025e2a170493..ea35160d632b 100644 --- a/arch/m32r/include/asm/atomic.h +++ b/arch/m32r/include/asm/atomic.h @@ -28,7 +28,7 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) /** * atomic_set - set atomic variable @@ -37,7 +37,7 @@ * * Atomically sets the value of @v to @i. */ -#define atomic_set(v,i) (((v)->counter) = (i)) +#define atomic_set(v,i) WRITE_ONCE(((v)->counter), (i)) #ifdef CONFIG_CHIP_M32700_TS1 #define __ATOMIC_CLOBBER , "r4" diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index 039fac120cc0..4858178260f9 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h @@ -17,8 +17,8 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic_set(v, i) (((v)->counter) = i) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) /* * The ColdFire parts cannot do some immediate to memory operations, diff --git a/arch/metag/include/asm/atomic_lnkget.h b/arch/metag/include/asm/atomic_lnkget.h index 21c4c268b86c..a62581815624 100644 --- a/arch/metag/include/asm/atomic_lnkget.h +++ b/arch/metag/include/asm/atomic_lnkget.h @@ -3,7 +3,7 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_set(v, i) ((v)->counter = (i)) +#define atomic_set(v, i) WRITE_ONCE((v)->counter, (i)) #include diff --git a/arch/metag/include/asm/atomic_lock1.h b/arch/metag/include/asm/atomic_lock1.h index f8efe380fe8b..0295d9b8d5bf 100644 --- a/arch/metag/include/asm/atomic_lock1.h +++ b/arch/metag/include/asm/atomic_lock1.h @@ -10,7 +10,7 @@ static inline int atomic_read(const atomic_t *v) { - return (v)->counter; + return READ_ONCE((v)->counter); } /* diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 4c42fd9af777..f82d3af07931 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -30,7 +30,7 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) /* * atomic_set - set atomic variable @@ -39,7 +39,7 @@ * * Atomically sets the value of @v to @i. */ -#define atomic_set(v, i) ((v)->counter = (i)) +#define atomic_set(v, i) WRITE_ONCE((v)->counter, (i)) #define ATOMIC_OP(op, c_op, asm_op) \ static __inline__ void atomic_##op(int i, atomic_t * v) \ @@ -315,14 +315,14 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) * @v: pointer of type atomic64_t * */ -#define atomic64_read(v) ACCESS_ONCE((v)->counter) +#define atomic64_read(v) READ_ONCE((v)->counter) /* * atomic64_set - set atomic variable * @v: pointer of type atomic64_t * @i: required value */ -#define atomic64_set(v, i) ((v)->counter = (i)) +#define atomic64_set(v, i) WRITE_ONCE((v)->counter, (i)) #define ATOMIC64_OP(op, c_op, asm_op) \ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h index 375e59140c9c..ce318d5ab23b 100644 --- a/arch/mn10300/include/asm/atomic.h +++ b/arch/mn10300/include/asm/atomic.h @@ -34,7 +34,7 @@ * * Atomically reads the value of @v. Note that the guaranteed */ -#define atomic_read(v) (ACCESS_ONCE((v)->counter)) +#define atomic_read(v) READ_ONCE((v)->counter) /** * atomic_set - set atomic variable @@ -43,7 +43,7 @@ * * Atomically sets the value of @v to @i. Note that the guaranteed */ -#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #define ATOMIC_OP(op) \ static inline void atomic_##op(int i, atomic_t *v) \ diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 2536965d00ea..1d109990a022 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -67,7 +67,7 @@ static __inline__ void atomic_set(atomic_t *v, int i) static __inline__ int atomic_read(const atomic_t *v) { - return ACCESS_ONCE((v)->counter); + return READ_ONCE((v)->counter); } /* exported interface */ diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h index 05b9f74ce2d5..c399e1c55685 100644 --- a/arch/sh/include/asm/atomic.h +++ b/arch/sh/include/asm/atomic.h @@ -14,8 +14,8 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic_set(v,i) ((v)->counter = (i)) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic_set(v,i) WRITE_ONCE((v)->counter, (i)) #if defined(CONFIG_GUSA_RB) #include diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index 917084ace49d..f2fbf9e16faf 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -14,11 +14,11 @@ #define ATOMIC_INIT(i) { (i) } #define ATOMIC64_INIT(i) { (i) } -#define atomic_read(v) ACCESS_ONCE((v)->counter) -#define atomic64_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) +#define atomic64_read(v) READ_ONCE((v)->counter) -#define atomic_set(v, i) (((v)->counter) = i) -#define atomic64_set(v, i) (((v)->counter) = i) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) +#define atomic64_set(v, i) WRITE_ONCE(((v)->counter), (i)) #define ATOMIC_OP(op) \ void atomic_##op(int, atomic_t *); \ diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h index 709798460763..9fc0107a9c5e 100644 --- a/arch/tile/include/asm/atomic.h +++ b/arch/tile/include/asm/atomic.h @@ -34,7 +34,7 @@ */ static inline int atomic_read(const atomic_t *v) { - return ACCESS_ONCE(v->counter); + return READ_ONCE(v->counter); } /** diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h index 096a56d6ead4..51cabc26e387 100644 --- a/arch/tile/include/asm/atomic_64.h +++ b/arch/tile/include/asm/atomic_64.h @@ -24,7 +24,7 @@ /* First, the 32-bit atomic ops that are "real" on our 64-bit platform. */ -#define atomic_set(v, i) ((v)->counter = (i)) +#define atomic_set(v, i) WRITE_ONCE((v)->counter, (i)) /* * The smp_mb() operations throughout are to support the fact that @@ -82,8 +82,8 @@ static inline void atomic_xor(int i, atomic_t *v) #define ATOMIC64_INIT(i) { (i) } -#define atomic64_read(v) ((v)->counter) -#define atomic64_set(v, i) ((v)->counter = (i)) +#define atomic64_read(v) READ_ONCE((v)->counter) +#define atomic64_set(v, i) WRITE_ONCE((v)->counter, (i)) static inline void atomic64_add(long i, atomic64_t *v) { diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index fb52aa644aab..ae5fb83e6d91 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -24,7 +24,7 @@ */ static __always_inline int atomic_read(const atomic_t *v) { - return ACCESS_ONCE((v)->counter); + return READ_ONCE((v)->counter); } /** @@ -36,7 +36,7 @@ static __always_inline int atomic_read(const atomic_t *v) */ static __always_inline void atomic_set(atomic_t *v, int i) { - v->counter = i; + WRITE_ONCE(v->counter, i); } /** diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 50e33eff58de..037351022f54 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h @@ -18,7 +18,7 @@ */ static inline long atomic64_read(const atomic64_t *v) { - return ACCESS_ONCE((v)->counter); + return READ_ONCE((v)->counter); } /** @@ -30,7 +30,7 @@ static inline long atomic64_read(const atomic64_t *v) */ static inline void atomic64_set(atomic64_t *v, long i) { - v->counter = i; + WRITE_ONCE(v->counter, i); } /** diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index 93795d047303..fd8017ce298a 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h @@ -47,7 +47,7 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) /** * atomic_set - set atomic variable @@ -56,7 +56,7 @@ * * Atomically sets the value of @v to @i. */ -#define atomic_set(v,i) ((v)->counter = (i)) +#define atomic_set(v,i) WRITE_ONCE((v)->counter, (i)) #if XCHAL_HAVE_S32C1I #define ATOMIC_OP(op) \ diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index d4d7e337fdcb..74f1a3704d7a 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -127,7 +127,7 @@ ATOMIC_OP(xor, ^) * Atomically reads the value of @v. */ #ifndef atomic_read -#define atomic_read(v) ACCESS_ONCE((v)->counter) +#define atomic_read(v) READ_ONCE((v)->counter) #endif /** @@ -137,7 +137,7 @@ ATOMIC_OP(xor, ^) * * Atomically sets the value of @v to @i. */ -#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) #include -- cgit v1.3-6-gb490 From e3e72ab80a3fac0b88e07d358a2c75724ccd66b4 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 18 Sep 2015 13:22:52 +0200 Subject: atomic: Implement atomic_read_ctrl() Provide atomic_read_ctrl() to mirror READ_ONCE_CTRL(), such that we can more conveniently use atomics in control dependencies. Since we can assume atomic_read() implies a READ_ONCE(), we must only emit an extra smp_read_barrier_depends() in order to upgrade to READ_ONCE_CTRL() semantics. Requested-by: Dmitry Vyukov Signed-off-by: Peter Zijlstra (Intel) Acked-by: Will Deacon Cc: Andrew Morton Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: oleg@redhat.com Link: http://lkml.kernel.org/r/20150918115637.GM3604@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 17 +++++++++-------- include/asm-generic/atomic-long.h | 3 ++- include/linux/atomic.h | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 2ba8461b0631..41ffd7e9cdcf 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -637,7 +637,8 @@ as follows: b = p; /* BUG: Compiler and CPU can both reorder!!! */ Finally, the READ_ONCE_CTRL() includes an smp_read_barrier_depends() -that DEC Alpha needs in order to respect control depedencies. +that DEC Alpha needs in order to respect control depedencies. Alternatively +use one of atomic{,64}_read_ctrl(). So don't leave out the READ_ONCE_CTRL(). @@ -796,9 +797,9 @@ site: https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html. In summary: - (*) Control dependencies must be headed by READ_ONCE_CTRL(). - Or, as a much less preferable alternative, interpose - smp_read_barrier_depends() between a READ_ONCE() and the + (*) Control dependencies must be headed by READ_ONCE_CTRL(), + atomic{,64}_read_ctrl(). Or, as a much less preferable alternative, + interpose smp_read_barrier_depends() between a READ_ONCE() and the control-dependent write. (*) Control dependencies can order prior loads against later stores. @@ -820,10 +821,10 @@ In summary: and WRITE_ONCE() can help to preserve the needed conditional. (*) Control dependencies require that the compiler avoid reordering the - dependency into nonexistence. Careful use of READ_ONCE_CTRL() - or smp_read_barrier_depends() can help to preserve your control - dependency. Please see the Compiler Barrier section for more - information. + dependency into nonexistence. Careful use of READ_ONCE_CTRL(), + atomic{,64}_read_ctrl() or smp_read_barrier_depends() can help to + preserve your control dependency. Please see the Compiler Barrier + section for more information. (*) Control dependencies pair normally with other types of barriers. diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h index c7a5c1ad2ed3..8942cdc676a7 100644 --- a/include/asm-generic/atomic-long.h +++ b/include/asm-generic/atomic-long.h @@ -35,7 +35,7 @@ typedef atomic_t atomic_long_t; #endif #define ATOMIC_LONG_READ_OP(mo) \ -static inline long atomic_long_read##mo(atomic_long_t *l) \ +static inline long atomic_long_read##mo(const atomic_long_t *l) \ { \ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \ \ @@ -43,6 +43,7 @@ static inline long atomic_long_read##mo(atomic_long_t *l) \ } ATOMIC_LONG_READ_OP() ATOMIC_LONG_READ_OP(_acquire) +ATOMIC_LONG_READ_OP(_ctrl) #undef ATOMIC_LONG_READ_OP diff --git a/include/linux/atomic.h b/include/linux/atomic.h index 29dafa184aeb..e326469bb9d6 100644 --- a/include/linux/atomic.h +++ b/include/linux/atomic.h @@ -4,6 +4,15 @@ #include #include +#ifndef atomic_read_ctrl +static inline int atomic_read_ctrl(const atomic_t *v) +{ + int val = atomic_read(v); + smp_read_barrier_depends(); /* Enforce control dependency. */ + return val; +} +#endif + /* * Relaxed variants of xchg, cmpxchg and some atomic operations. * @@ -455,6 +464,15 @@ static inline int atomic_dec_if_positive(atomic_t *v) #include #endif +#ifndef atomic64_read_ctrl +static inline long long atomic64_read_ctrl(const atomic64_t *v) +{ + long long val = atomic64_read(v); + smp_read_barrier_depends(); /* Enforce control dependency. */ + return val; +} +#endif + #ifndef atomic64_andnot static inline void atomic64_andnot(long long i, atomic64_t *v) { -- cgit v1.3-6-gb490 From c6e1e7b5b7f031910850ddaf7bfa65ba3b4843ea Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Tue, 22 Sep 2015 12:48:59 +0200 Subject: sched/core: Make 'sched_domain_topology' declaration static The 'sched_domain_topology' variable is only used within kernel/sched/core.c. Make it static. Signed-off-by: Juergen Gross Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1442918939-9907-1-git-send-email-jgross@suse.com Signed-off-by: Ingo Molnar --- include/linux/sched.h | 2 -- kernel/sched/core.c | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index bd38b3ee9e83..699228bb0035 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1127,8 +1127,6 @@ struct sched_domain_topology_level { #endif }; -extern struct sched_domain_topology_level *sched_domain_topology; - extern void set_sched_topology(struct sched_domain_topology_level *tl); extern void wake_up_if_idle(int cpu); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1b30b5b24a4a..a91df6171f48 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6445,7 +6445,8 @@ static struct sched_domain_topology_level default_topology[] = { { NULL, }, }; -struct sched_domain_topology_level *sched_domain_topology = default_topology; +static struct sched_domain_topology_level *sched_domain_topology = + default_topology; #define for_each_sd_topology(tl) \ for (tl = sched_domain_topology; tl->mask; tl++) -- cgit v1.3-6-gb490 From 46ac51822a6a0b83ee3e408ee9edcb292fb8ced0 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 23 Sep 2015 09:26:27 -0400 Subject: tracing: Move non perf code out of perf.h Commit ee53bbd17257 "tracing: Move the perf code out of trace_event.h" moved more than just the perf code out of trace_event.h, but also removed a bit of the tracing code too. Move it back. Signed-off-by: Steven Rostedt --- include/trace/perf.h | 258 ------------------------------------------- include/trace/trace_events.h | 258 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+), 258 deletions(-) (limited to 'include') diff --git a/include/trace/perf.h b/include/trace/perf.h index 1b5443cebedc..26486fcd74ce 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -1,261 +1,3 @@ -/* - * Stage 4 of the trace events. - * - * Override the macros in to include the following: - * - * For those macros defined with TRACE_EVENT: - * - * static struct trace_event_call event_; - * - * static void trace_event_raw_event_(void *__data, proto) - * { - * struct trace_event_file *trace_file = __data; - * struct trace_event_call *event_call = trace_file->event_call; - * struct trace_event_data_offsets_ __maybe_unused __data_offsets; - * unsigned long eflags = trace_file->flags; - * enum event_trigger_type __tt = ETT_NONE; - * struct ring_buffer_event *event; - * struct trace_event_raw_ *entry; <-- defined in stage 1 - * struct ring_buffer *buffer; - * unsigned long irq_flags; - * int __data_size; - * int pc; - * - * if (!(eflags & EVENT_FILE_FL_TRIGGER_COND)) { - * if (eflags & EVENT_FILE_FL_TRIGGER_MODE) - * event_triggers_call(trace_file, NULL); - * if (eflags & EVENT_FILE_FL_SOFT_DISABLED) - * return; - * } - * - * local_save_flags(irq_flags); - * pc = preempt_count(); - * - * __data_size = trace_event_get_offsets_(&__data_offsets, args); - * - * event = trace_event_buffer_lock_reserve(&buffer, trace_file, - * event_->event.type, - * sizeof(*entry) + __data_size, - * irq_flags, pc); - * if (!event) - * return; - * entry = ring_buffer_event_data(event); - * - * { ; } <-- Here we assign the entries by the __field and - * __array macros. - * - * if (eflags & EVENT_FILE_FL_TRIGGER_COND) - * __tt = event_triggers_call(trace_file, entry); - * - * if (test_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, - * &trace_file->flags)) - * ring_buffer_discard_commit(buffer, event); - * else if (!filter_check_discard(trace_file, entry, buffer, event)) - * trace_buffer_unlock_commit(buffer, event, irq_flags, pc); - * - * if (__tt) - * event_triggers_post_call(trace_file, __tt); - * } - * - * static struct trace_event ftrace_event_type_ = { - * .trace = trace_raw_output_, <-- stage 2 - * }; - * - * static char print_fmt_[] = ; - * - * static struct trace_event_class __used event_class_