diff --git a/[refs] b/[refs] index cb2b4d170206..afca753ff9f9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9da060d0ed571bbff434c4a1ef3e48db99a37ee0 +refs/heads/master: f7f154f1246ccc5a0a7e9ce50932627d60a0c878 diff --git a/trunk/Documentation/device-mapper/dm-raid.txt b/trunk/Documentation/device-mapper/dm-raid.txt index b428556197c9..56fb62b09fc5 100644 --- a/trunk/Documentation/device-mapper/dm-raid.txt +++ b/trunk/Documentation/device-mapper/dm-raid.txt @@ -30,7 +30,6 @@ The target is named "raid" and it accepts the following parameters: raid10 Various RAID10 inspired algorithms chosen by additional params - RAID10: Striped Mirrors (aka 'Striping on top of mirrors') - RAID1E: Integrated Adjacent Stripe Mirroring - - RAID1E: Integrated Offset Stripe Mirroring - and other similar RAID10 variants Reference: Chapter 4 of @@ -65,15 +64,15 @@ The target is named "raid" and it accepts the following parameters: synchronisation state for each region. [raid10_copies <# copies>] - [raid10_format ] + [raid10_format near] These two options are used to alter the default layout of a RAID10 configuration. The number of copies is can be - specified, but the default is 2. There are also three - variations to how the copies are laid down - the default - is "near". Near copies are what most people think of with - respect to mirroring. If these options are left unspecified, - or 'raid10_copies 2' and/or 'raid10_format near' are given, - then the layouts for 2, 3 and 4 devices are: + specified, but the default is 2. There are other variations + to how the copies are laid down - the default and only current + option is "near". Near copies are what most people think of + with respect to mirroring. If these options are left + unspecified, or 'raid10_copies 2' and/or 'raid10_format near' + are given, then the layouts for 2, 3 and 4 devices are: 2 drives 3 drives 4 drives -------- ---------- -------------- A1 A1 A1 A1 A2 A1 A1 A2 A2 @@ -86,33 +85,6 @@ The target is named "raid" and it accepts the following parameters: 3-device layout is what might be called a 'RAID1E - Integrated Adjacent Stripe Mirroring'. - If 'raid10_copies 2' and 'raid10_format far', then the layouts - for 2, 3 and 4 devices are: - 2 drives 3 drives 4 drives - -------- -------------- -------------------- - A1 A2 A1 A2 A3 A1 A2 A3 A4 - A3 A4 A4 A5 A6 A5 A6 A7 A8 - A5 A6 A7 A8 A9 A9 A10 A11 A12 - .. .. .. .. .. .. .. .. .. - A2 A1 A3 A1 A2 A2 A1 A4 A3 - A4 A3 A6 A4 A5 A6 A5 A8 A7 - A6 A5 A9 A7 A8 A10 A9 A12 A11 - .. .. .. .. .. .. .. .. .. - - If 'raid10_copies 2' and 'raid10_format offset', then the - layouts for 2, 3 and 4 devices are: - 2 drives 3 drives 4 drives - -------- ------------ ----------------- - A1 A2 A1 A2 A3 A1 A2 A3 A4 - A2 A1 A3 A1 A2 A2 A1 A4 A3 - A3 A4 A4 A5 A6 A5 A6 A7 A8 - A4 A3 A6 A4 A5 A6 A5 A8 A7 - A5 A6 A7 A8 A9 A9 A10 A11 A12 - A6 A5 A9 A7 A8 A10 A9 A12 A11 - .. .. .. .. .. .. .. .. .. - Here we see layouts closely akin to 'RAID1E - Integrated - Offset Stripe Mirroring'. - <#raid_devs>: The number of devices composing the array. Each device consists of two entries. The first is the device containing the metadata (if any); the second is the one containing the @@ -170,5 +142,3 @@ Version History 1.3.0 Added support for RAID 10 1.3.1 Allow device replacement/rebuild for RAID 10 1.3.2 Fix/improve redundancy checking for RAID10 -1.4.0 Non-functional change. Removes arg from mapping function. -1.4.1 Add RAID10 "far" and "offset" algorithm support. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 95616582c728..e95b1e944eb7 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -114,6 +114,12 @@ Maintainers List (try to look for most precise areas first) ----------------------------------- +3C505 NETWORK DRIVER +M: Philip Blundell +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ethernet/i825xx/3c505* + 3C59X NETWORK DRIVER M: Steffen Klassert L: netdev@vger.kernel.org @@ -2355,6 +2361,12 @@ W: http://www.arm.linux.org.uk/ S: Maintained F: drivers/video/cyber2000fb.* +CYCLADES 2X SYNC CARD DRIVER +M: Arnaldo Carvalho de Melo +W: http://oops.ghostprotocols.net:81/blog +S: Maintained +F: drivers/net/wan/cycx* + CYCLADES ASYNC MUX DRIVER W: http://www.cyclades.com/ S: Orphan @@ -3055,6 +3067,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: drivers/video/s1d13xxxfb.c F: include/video/s1d13xxxfb.h +ETHEREXPRESS-16 NETWORK DRIVER +M: Philip Blundell +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ethernet/i825xx/eexpress.* + ETHERNET BRIDGE M: Stephen Hemminger L: bridge@lists.linux-foundation.org diff --git a/trunk/drivers/bcma/driver_pci_host.c b/trunk/drivers/bcma/driver_pci_host.c index 30629a3d44cc..d3bde6cec927 100644 --- a/trunk/drivers/bcma/driver_pci_host.c +++ b/trunk/drivers/bcma/driver_pci_host.c @@ -404,8 +404,6 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) return; } - spin_lock_init(&pc_host->cfgspace_lock); - pc->host_controller = pc_host; pc_host->pci_controller.io_resource = &pc_host->io_resource; pc_host->pci_controller.mem_resource = &pc_host->mem_resource; diff --git a/trunk/drivers/char/hw_random/core.c b/trunk/drivers/char/hw_random/core.c index 1bafb40ec8a2..69ae5972713c 100644 --- a/trunk/drivers/char/hw_random/core.c +++ b/trunk/drivers/char/hw_random/core.c @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -52,8 +53,12 @@ static struct hwrng *current_rng; static LIST_HEAD(rng_list); static DEFINE_MUTEX(rng_mutex); static int data_avail; -static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] - __cacheline_aligned; +static u8 *rng_buffer; + +static size_t rng_buffer_size(void) +{ + return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; +} static inline int hwrng_init(struct hwrng *rng) { @@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, if (!data_avail) { bytes_read = rng_get_data(current_rng, rng_buffer, - sizeof(rng_buffer), + rng_buffer_size(), !(filp->f_flags & O_NONBLOCK)); if (bytes_read < 0) { err = bytes_read; @@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) mutex_lock(&rng_mutex); + /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ + err = -ENOMEM; + if (!rng_buffer) { + rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); + if (!rng_buffer) + goto out_unlock; + } + /* Must not register two RNGs with the same name. */ err = -EEXIST; list_for_each_entry(tmp, &rng_list, list) { diff --git a/trunk/drivers/connector/cn_proc.c b/trunk/drivers/connector/cn_proc.c index 1110478dd0fd..fce2000eec31 100644 --- a/trunk/drivers/connector/cn_proc.c +++ b/trunk/drivers/connector/cn_proc.c @@ -313,12 +313,6 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, (task_active_pid_ns(current) != &init_pid_ns)) return; - /* Can only change if privileged. */ - if (!capable(CAP_NET_ADMIN)) { - err = EPERM; - goto out; - } - mc_op = (enum proc_cn_mcast_op *)msg->data; switch (*mc_op) { case PROC_CN_MCAST_LISTEN: @@ -331,8 +325,6 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, err = EINVAL; break; } - -out: cn_proc_ack(err, msg->seq, msg->ack); } diff --git a/trunk/drivers/gpio/gpio-ich.c b/trunk/drivers/gpio/gpio-ich.c index f9dbd503fc40..6f2306db8591 100644 --- a/trunk/drivers/gpio/gpio-ich.c +++ b/trunk/drivers/gpio/gpio-ich.c @@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr) return data & (1 << bit) ? 1 : 0; } -static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) { - return ichx_priv.use_gpio & (1 << (nr / 32)); + return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; } static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) diff --git a/trunk/drivers/gpio/gpiolib.c b/trunk/drivers/gpio/gpiolib.c index c2534d62911c..fff9786cdc64 100644 --- a/trunk/drivers/gpio/gpiolib.c +++ b/trunk/drivers/gpio/gpiolib.c @@ -88,14 +88,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); static void gpiod_free(struct gpio_desc *desc); static int gpiod_direction_input(struct gpio_desc *desc); static int gpiod_direction_output(struct gpio_desc *desc, int value); -static int gpiod_get_direction(const struct gpio_desc *desc); static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); -static int gpiod_get_value_cansleep(const struct gpio_desc *desc); +static int gpiod_get_value_cansleep(struct gpio_desc *desc); static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); -static int gpiod_get_value(const struct gpio_desc *desc); +static int gpiod_get_value(struct gpio_desc *desc); static void gpiod_set_value(struct gpio_desc *desc, int value); -static int gpiod_cansleep(const struct gpio_desc *desc); -static int gpiod_to_irq(const struct gpio_desc *desc); +static int gpiod_cansleep(struct gpio_desc *desc); +static int gpiod_to_irq(struct gpio_desc *desc); static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); static int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc); @@ -172,12 +171,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc) return 0; } -static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) +/* caller holds gpio_lock *OR* gpio is marked as requested */ +static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc) { - return desc ? desc->chip : NULL; + return desc->chip; } -/* caller holds gpio_lock *OR* gpio is marked as requested */ struct gpio_chip *gpio_to_chip(unsigned gpio) { return gpiod_to_chip(gpio_to_desc(gpio)); @@ -208,7 +207,7 @@ static int gpiochip_find_base(int ngpio) } /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ -static int gpiod_get_direction(const struct gpio_desc *desc) +static int gpiod_get_direction(struct gpio_desc *desc) { struct gpio_chip *chip; unsigned offset; @@ -224,13 +223,11 @@ static int gpiod_get_direction(const struct gpio_desc *desc) if (status > 0) { /* GPIOF_DIR_IN, or other positive */ status = 1; - /* FLAG_IS_OUT is just a cache of the result of get_direction(), - * so it does not affect constness per se */ - clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags); + clear_bit(FLAG_IS_OUT, &desc->flags); } if (status == 0) { /* GPIOF_DIR_OUT */ - set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags); + set_bit(FLAG_IS_OUT, &desc->flags); } return status; } @@ -266,7 +263,7 @@ static DEFINE_MUTEX(sysfs_lock); static ssize_t gpio_direction_show(struct device *dev, struct device_attribute *attr, char *buf) { - const struct gpio_desc *desc = dev_get_drvdata(dev); + struct gpio_desc *desc = dev_get_drvdata(dev); ssize_t status; mutex_lock(&sysfs_lock); @@ -657,11 +654,6 @@ static ssize_t export_store(struct class *class, goto done; desc = gpio_to_desc(gpio); - /* reject invalid GPIOs */ - if (!desc) { - pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); - return -EINVAL; - } /* No extra locking here; FLAG_SYSFS just signifies that the * request and export were done by on behalf of userspace, so @@ -698,14 +690,12 @@ static ssize_t unexport_store(struct class *class, if (status < 0) goto done; + status = -EINVAL; + desc = gpio_to_desc(gpio); /* reject bogus commands (gpio_unexport ignores them) */ - if (!desc) { - pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); - return -EINVAL; - } - - status = -EINVAL; + if (!desc) + goto done; /* No extra locking here; FLAG_SYSFS just signifies that the * request and export were done by on behalf of userspace, so @@ -856,10 +846,8 @@ static int gpiod_export_link(struct device *dev, const char *name, { int status = -EINVAL; - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } + if (!desc) + goto done; mutex_lock(&sysfs_lock); @@ -877,6 +865,7 @@ static int gpiod_export_link(struct device *dev, const char *name, mutex_unlock(&sysfs_lock); +done: if (status) pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), status); @@ -907,10 +896,8 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) struct device *dev = NULL; int status = -EINVAL; - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } + if (!desc) + goto done; mutex_lock(&sysfs_lock); @@ -927,6 +914,7 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) unlock: mutex_unlock(&sysfs_lock); +done: if (status) pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), status); @@ -952,8 +940,8 @@ static void gpiod_unexport(struct gpio_desc *desc) struct device *dev = NULL; if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return; + status = -EINVAL; + goto done; } mutex_lock(&sysfs_lock); @@ -974,7 +962,7 @@ static void gpiod_unexport(struct gpio_desc *desc) device_unregister(dev); put_device(dev); } - +done: if (status) pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), status); @@ -1396,13 +1384,12 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) int status = -EPROBE_DEFER; unsigned long flags; - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } - spin_lock_irqsave(&gpio_lock, flags); + if (!desc) { + status = -EINVAL; + goto done; + } chip = desc->chip; if (chip == NULL) goto done; @@ -1445,7 +1432,8 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) done: if (status) pr_debug("_gpio_request: gpio-%d (%s) status %d\n", - desc_to_gpio(desc), label ? : "?", status); + desc ? desc_to_gpio(desc) : -1, + label ? : "?", status); spin_unlock_irqrestore(&gpio_lock, flags); return status; } @@ -1628,13 +1616,10 @@ static int gpiod_direction_input(struct gpio_desc *desc) int status = -EINVAL; int offset; - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } - spin_lock_irqsave(&gpio_lock, flags); + if (!desc) + goto fail; chip = desc->chip; if (!chip || !chip->get || !chip->direction_input) goto fail; @@ -1670,9 +1655,13 @@ static int gpiod_direction_input(struct gpio_desc *desc) return status; fail: spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", __func__, - desc_to_gpio(desc), status); + if (status) { + int gpio = -1; + if (desc) + gpio = desc_to_gpio(desc); + pr_debug("%s: gpio-%d status %d\n", + __func__, gpio, status); + } return status; } @@ -1689,11 +1678,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) int status = -EINVAL; int offset; - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } - /* Open drain pin should not be driven to 1 */ if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) return gpiod_direction_input(desc); @@ -1704,6 +1688,8 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) spin_lock_irqsave(&gpio_lock, flags); + if (!desc) + goto fail; chip = desc->chip; if (!chip || !chip->set || !chip->direction_output) goto fail; @@ -1739,9 +1725,13 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) return status; fail: spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", __func__, - desc_to_gpio(desc), status); + if (status) { + int gpio = -1; + if (desc) + gpio = desc_to_gpio(desc); + pr_debug("%s: gpio-%d status %d\n", + __func__, gpio, status); + } return status; } @@ -1763,13 +1753,10 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) int status = -EINVAL; int offset; - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } - spin_lock_irqsave(&gpio_lock, flags); + if (!desc) + goto fail; chip = desc->chip; if (!chip || !chip->set || !chip->set_debounce) goto fail; @@ -1789,9 +1776,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) fail: spin_unlock_irqrestore(&gpio_lock, flags); - if (status) - pr_debug("%s: gpio-%d status %d\n", __func__, - desc_to_gpio(desc), status); + if (status) { + int gpio = -1; + if (desc) + gpio = desc_to_gpio(desc); + pr_debug("%s: gpio-%d status %d\n", + __func__, gpio, status); + } return status; } @@ -1833,14 +1824,12 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); * It returns the zero or nonzero value provided by the associated * gpio_chip.get() method; or zero if no such method is provided. */ -static int gpiod_get_value(const struct gpio_desc *desc) +static int gpiod_get_value(struct gpio_desc *desc) { struct gpio_chip *chip; int value; int offset; - if (!desc) - return 0; chip = desc->chip; offset = gpio_chip_hwgpio(desc); /* Should be using gpio_get_value_cansleep() */ @@ -1923,8 +1912,6 @@ static void gpiod_set_value(struct gpio_desc *desc, int value) { struct gpio_chip *chip; - if (!desc) - return; chip = desc->chip; /* Should be using gpio_set_value_cansleep() */ WARN_ON(chip->can_sleep); @@ -1951,10 +1938,8 @@ EXPORT_SYMBOL_GPL(__gpio_set_value); * This is used directly or indirectly to implement gpio_cansleep(). It * returns nonzero if access reading or writing the GPIO value can sleep. */ -static int gpiod_cansleep(const struct gpio_desc *desc) +static int gpiod_cansleep(struct gpio_desc *desc) { - if (!desc) - return 0; /* only call this on GPIOs that are valid! */ return desc->chip->can_sleep; } @@ -1974,13 +1959,11 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep); * It returns the number of the IRQ signaled by this (input) GPIO, * or a negative errno. */ -static int gpiod_to_irq(const struct gpio_desc *desc) +static int gpiod_to_irq(struct gpio_desc *desc) { struct gpio_chip *chip; int offset; - if (!desc) - return -EINVAL; chip = desc->chip; offset = gpio_chip_hwgpio(desc); return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; @@ -1997,15 +1980,13 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); * Common examples include ones connected to I2C or SPI chips. */ -static int gpiod_get_value_cansleep(const struct gpio_desc *desc) +static int gpiod_get_value_cansleep(struct gpio_desc *desc) { struct gpio_chip *chip; int value; int offset; might_sleep_if(extra_checks); - if (!desc) - return 0; chip = desc->chip; offset = gpio_chip_hwgpio(desc); value = chip->get ? chip->get(chip, offset) : 0; @@ -2024,8 +2005,6 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) struct gpio_chip *chip; might_sleep_if(extra_checks); - if (!desc) - return; chip = desc->chip; trace_gpio_value(desc_to_gpio(desc), 0, value); if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) diff --git a/trunk/drivers/isdn/hisax/st5481_usb.c b/trunk/drivers/isdn/hisax/st5481_usb.c index ead0a4fb7448..017c67ea3f4c 100644 --- a/trunk/drivers/isdn/hisax/st5481_usb.c +++ b/trunk/drivers/isdn/hisax/st5481_usb.c @@ -294,13 +294,13 @@ int st5481_setup_usb(struct st5481_adapter *adapter) // Allocate URBs and buffers for interrupt endpoint urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - goto err1; + return -ENOMEM; } intr->urb = urb; buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL); if (!buf) { - goto err2; + return -ENOMEM; } endpoint = &altsetting->endpoint[EP_INT-1]; @@ -313,14 +313,6 @@ int st5481_setup_usb(struct st5481_adapter *adapter) endpoint->desc.bInterval); return 0; -err2: - usb_free_urb(intr->urb); - intr->urb = NULL; -err1: - usb_free_urb(ctrl->urb); - ctrl->urb = NULL; - - return -ENOMEM; } /* diff --git a/trunk/drivers/md/Kconfig b/trunk/drivers/md/Kconfig index 4d8d90b4fe78..e30b490055aa 100644 --- a/trunk/drivers/md/Kconfig +++ b/trunk/drivers/md/Kconfig @@ -154,6 +154,17 @@ config MD_RAID456 If unsure, say Y. +config MULTICORE_RAID456 + bool "RAID-4/RAID-5/RAID-6 Multicore processing (EXPERIMENTAL)" + depends on MD_RAID456 + depends on SMP + depends on EXPERIMENTAL + ---help--- + Enable the raid456 module to dispatch per-stripe raid operations to a + thread pool. + + If unsure, say N. + config MD_MULTIPATH tristate "Multipath I/O support" depends on BLK_DEV_MD diff --git a/trunk/drivers/md/dm-raid.c b/trunk/drivers/md/dm-raid.c index 311e3d35b272..9a01d1e4c783 100644 --- a/trunk/drivers/md/dm-raid.c +++ b/trunk/drivers/md/dm-raid.c @@ -91,44 +91,15 @@ static struct raid_type { {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} }; -static char *raid10_md_layout_to_format(int layout) -{ - /* - * Bit 16 and 17 stand for "offset" and "use_far_sets" - * Refer to MD's raid10.c for details - */ - if ((layout & 0x10000) && (layout & 0x20000)) - return "offset"; - - if ((layout & 0xFF) > 1) - return "near"; - - return "far"; -} - static unsigned raid10_md_layout_to_copies(int layout) { - if ((layout & 0xFF) > 1) - return layout & 0xFF; - return (layout >> 8) & 0xFF; + return layout & 0xFF; } static int raid10_format_to_md_layout(char *format, unsigned copies) { - unsigned n = 1, f = 1; - - if (!strcmp("near", format)) - n = copies; - else - f = copies; - - if (!strcmp("offset", format)) - return 0x30000 | (f << 8) | n; - - if (!strcmp("far", format)) - return 0x20000 | (f << 8) | n; - - return (f << 8) | n; + /* 1 "far" copy, and 'copies' "near" copies */ + return (1 << 8) | (copies & 0xFF); } static struct raid_type *get_raid_type(char *name) @@ -381,7 +352,6 @@ static int validate_raid_redundancy(struct raid_set *rs) { unsigned i, rebuild_cnt = 0; unsigned rebuilds_per_group, copies, d; - unsigned group_size, last_group_start; for (i = 0; i < rs->md.raid_disks; i++) if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || @@ -409,6 +379,9 @@ static int validate_raid_redundancy(struct raid_set *rs) * as long as the failed devices occur in different mirror * groups (i.e. different stripes). * + * Right now, we only allow for "near" copies. When other + * formats are added, we will have to check those too. + * * When checking "near" format, make sure no adjacent devices * have failed beyond what can be handled. In addition to the * simple case where the number of devices is a multiple of the @@ -418,41 +391,14 @@ static int validate_raid_redundancy(struct raid_set *rs) * A A B B C * C D D E E */ - if (!strcmp("near", raid10_md_layout_to_format(rs->md.layout))) { - for (i = 0; i < rs->md.raid_disks * copies; i++) { - if (!(i % copies)) - rebuilds_per_group = 0; - d = i % rs->md.raid_disks; - if ((!rs->dev[d].rdev.sb_page || - !test_bit(In_sync, &rs->dev[d].rdev.flags)) && - (++rebuilds_per_group >= copies)) - goto too_many; - } - break; - } - - /* - * When checking "far" and "offset" formats, we need to ensure - * that the device that holds its copy is not also dead or - * being rebuilt. (Note that "far" and "offset" formats only - * support two copies right now. These formats also only ever - * use the 'use_far_sets' variant.) - * - * This check is somewhat complicated by the need to account - * for arrays that are not a multiple of (far) copies. This - * results in the need to treat the last (potentially larger) - * set differently. - */ - group_size = (rs->md.raid_disks / copies); - last_group_start = (rs->md.raid_disks / group_size) - 1; - last_group_start *= group_size; - for (i = 0; i < rs->md.raid_disks; i++) { - if (!(i % copies) && !(i > last_group_start)) + for (i = 0; i < rs->md.raid_disks * copies; i++) { + if (!(i % copies)) rebuilds_per_group = 0; - if ((!rs->dev[i].rdev.sb_page || - !test_bit(In_sync, &rs->dev[i].rdev.flags)) && + d = i % rs->md.raid_disks; + if ((!rs->dev[d].rdev.sb_page || + !test_bit(In_sync, &rs->dev[d].rdev.flags)) && (++rebuilds_per_group >= copies)) - goto too_many; + goto too_many; } break; default: @@ -487,7 +433,7 @@ static int validate_raid_redundancy(struct raid_set *rs) * * RAID10-only options: * [raid10_copies <# copies>] Number of copies. (Default: 2) - * [raid10_format ] Layout algorithm. (Default: near) + * [raid10_format ] Layout algorithm. (Default: near) */ static int parse_raid_params(struct raid_set *rs, char **argv, unsigned num_raid_params) @@ -574,9 +520,7 @@ static int parse_raid_params(struct raid_set *rs, char **argv, rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; return -EINVAL; } - if (strcmp("near", argv[i]) && - strcmp("far", argv[i]) && - strcmp("offset", argv[i])) { + if (strcmp("near", argv[i])) { rs->ti->error = "Invalid 'raid10_format' value given"; return -EINVAL; } @@ -700,15 +644,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv, return -EINVAL; } - /* - * If the format is not "near", we only support - * two copies at the moment. - */ - if (strcmp("near", raid10_format) && (raid10_copies > 2)) { - rs->ti->error = "Too many copies for given RAID10 format."; - return -EINVAL; - } - /* (Len * #mirrors) / #devices */ sectors_per_dev = rs->ti->len * raid10_copies; sector_div(sectors_per_dev, rs->md.raid_disks); @@ -919,30 +854,17 @@ static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev) /* * Reshaping is not currently allowed */ - if (le32_to_cpu(sb->level) != mddev->level) { - DMERR("Reshaping arrays not yet supported. (RAID level change)"); - return -EINVAL; - } - if (le32_to_cpu(sb->layout) != mddev->layout) { - DMERR("Reshaping arrays not yet supported. (RAID layout change)"); - DMERR(" 0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout); - DMERR(" Old layout: %s w/ %d copies", - raid10_md_layout_to_format(le32_to_cpu(sb->layout)), - raid10_md_layout_to_copies(le32_to_cpu(sb->layout))); - DMERR(" New layout: %s w/ %d copies", - raid10_md_layout_to_format(mddev->layout), - raid10_md_layout_to_copies(mddev->layout)); - return -EINVAL; - } - if (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors) { - DMERR("Reshaping arrays not yet supported. (stripe sectors change)"); + if ((le32_to_cpu(sb->level) != mddev->level) || + (le32_to_cpu(sb->layout) != mddev->layout) || + (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors)) { + DMERR("Reshaping arrays not yet supported."); return -EINVAL; } /* We can only change the number of devices in RAID1 right now */ if ((rs->raid_type->level != 1) && (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) { - DMERR("Reshaping arrays not yet supported. (device count change)"); + DMERR("Reshaping arrays not yet supported."); return -EINVAL; } @@ -1407,8 +1329,7 @@ static void raid_status(struct dm_target *ti, status_type_t type, raid10_md_layout_to_copies(rs->md.layout)); if (rs->print_flags & DMPF_RAID10_FORMAT) - DMEMIT(" raid10_format %s", - raid10_md_layout_to_format(rs->md.layout)); + DMEMIT(" raid10_format near"); DMEMIT(" %d", rs->md.raid_disks); for (i = 0; i < rs->md.raid_disks; i++) { @@ -1497,10 +1418,6 @@ static struct target_type raid_target = { static int __init dm_raid_init(void) { - DMINFO("Loading target version %u.%u.%u", - raid_target.version[0], - raid_target.version[1], - raid_target.version[2]); return dm_register_target(&raid_target); } diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index fcb878f88796..3db3d1b271f7 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -307,10 +307,6 @@ static void md_make_request(struct request_queue *q, struct bio *bio) bio_io_error(bio); return; } - if (mddev->ro == 1 && unlikely(rw == WRITE)) { - bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS); - return; - } smp_rmb(); /* Ensure implications of 'active' are visible */ rcu_read_lock(); if (mddev->suspended) { @@ -2998,9 +2994,6 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) } else if (!sectors) sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - rdev->data_offset; - if (!my_mddev->pers->resize) - /* Cannot change size for RAID0 or Linear etc */ - return -EINVAL; } if (sectors < my_mddev->dev_sectors) return -EINVAL; /* component must fit device */ @@ -6532,17 +6525,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, mddev->ro = 0; sysfs_notify_dirent_safe(mddev->sysfs_state); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - /* mddev_unlock will wake thread */ - /* If a device failed while we were read-only, we - * need to make sure the metadata is updated now. - */ - if (test_bit(MD_CHANGE_DEVS, &mddev->flags)) { - mddev_unlock(mddev); - wait_event(mddev->sb_wait, - !test_bit(MD_CHANGE_DEVS, &mddev->flags) && - !test_bit(MD_CHANGE_PENDING, &mddev->flags)); - mddev_lock(mddev); - } + md_wakeup_thread(mddev->thread); } else { err = -EROFS; goto abort_unlock; diff --git a/trunk/drivers/md/raid0.c b/trunk/drivers/md/raid0.c index 0505452de8d6..24b359717a7e 100644 --- a/trunk/drivers/md/raid0.c +++ b/trunk/drivers/md/raid0.c @@ -175,13 +175,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) rdev1->new_raid_disk = j; } - if (j < 0) { - printk(KERN_ERR - "md/raid0:%s: remove inactive devices before converting to RAID0\n", - mdname(mddev)); - goto abort; - } - if (j >= mddev->raid_disks) { + if (j < 0 || j >= mddev->raid_disks) { printk(KERN_ERR "md/raid0:%s: bad disk number %d - " "aborting!\n", mdname(mddev), j); goto abort; @@ -295,7 +289,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) kfree(conf->strip_zone); kfree(conf->devlist); kfree(conf); - *private_conf = ERR_PTR(err); + *private_conf = NULL; return err; } @@ -417,8 +411,7 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks "%s does not support generic reshape\n", __func__); rdev_for_each(rdev, mddev) - array_sectors += (rdev->sectors & - ~(sector_t)(mddev->chunk_sectors-1)); + array_sectors += rdev->sectors; return array_sectors; } diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index fd86b372692d..d5bddfc4010e 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -967,7 +967,6 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) bio_list_merge(&conf->pending_bio_list, &plug->pending); conf->pending_count += plug->pending_cnt; spin_unlock_irq(&conf->device_lock); - wake_up(&conf->wait_barrier); md_wakeup_thread(mddev->thread); kfree(plug); return; @@ -1001,7 +1000,6 @@ static void make_request(struct mddev *mddev, struct bio * bio) const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); const unsigned long do_discard = (bio->bi_rw & (REQ_DISCARD | REQ_SECURE)); - const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); struct md_rdev *blocked_rdev; struct blk_plug_cb *cb; struct raid1_plug_cb *plug = NULL; @@ -1303,8 +1301,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) conf->mirrors[i].rdev->data_offset); mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; - mbio->bi_rw = - WRITE | do_flush_fua | do_sync | do_discard | do_same; + mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard; mbio->bi_private = r1_bio; atomic_inc(&r1_bio->remaining); @@ -2821,9 +2818,6 @@ static int run(struct mddev *mddev) if (IS_ERR(conf)) return PTR_ERR(conf); - if (mddev->queue) - blk_queue_max_write_same_sectors(mddev->queue, - mddev->chunk_sectors); rdev_for_each(rdev, mddev) { if (!mddev->gendisk) continue; diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 77b562d18a90..64d48249c03b 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -38,36 +38,21 @@ * near_copies (stored in low byte of layout) * far_copies (stored in second byte of layout) * far_offset (stored in bit 16 of layout ) - * use_far_sets (stored in bit 17 of layout ) * - * The data to be stored is divided into chunks using chunksize. Each device - * is divided into far_copies sections. In each section, chunks are laid out - * in a style similar to raid0, but near_copies copies of each chunk is stored - * (each on a different drive). The starting device for each section is offset - * near_copies from the starting device of the previous section. Thus there - * are (near_copies * far_copies) of each chunk, and each is on a different - * drive. near_copies and far_copies must be at least one, and their product - * is at most raid_disks. + * The data to be stored is divided into chunks using chunksize. + * Each device is divided into far_copies sections. + * In each section, chunks are laid out in a style similar to raid0, but + * near_copies copies of each chunk is stored (each on a different drive). + * The starting device for each section is offset near_copies from the starting + * device of the previous section. + * Thus they are (near_copies*far_copies) of each chunk, and each is on a different + * drive. + * near_copies and far_copies must be at least one, and their product is at most + * raid_disks. * * If far_offset is true, then the far_copies are handled a bit differently. - * The copies are still in different stripes, but instead of being very far - * apart on disk, there are adjacent stripes. - * - * The far and offset algorithms are handled slightly differently if - * 'use_far_sets' is true. In this case, the array's devices are grouped into - * sets that are (near_copies * far_copies) in size. The far copied stripes - * are still shifted by 'near_copies' devices, but this shifting stays confined - * to the set rather than the entire array. This is done to improve the number - * of device combinations that can fail without causing the array to fail. - * Example 'far' algorithm w/o 'use_far_sets' (each letter represents a chunk - * on a device): - * A B C D A B C D E - * ... ... - * D A B C E A B C D - * Example 'far' algorithm w/ 'use_far_sets' enabled (sets illustrated w/ []'s): - * [A B] [C D] [A B] [C D E] - * |...| |...| |...| | ... | - * [B A] [D C] [B A] [E C D] + * The copies are still in different stripes, but instead of be very far apart + * on disk, there are adjacent stripes. */ /* @@ -550,13 +535,6 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) sector_t stripe; int dev; int slot = 0; - int last_far_set_start, last_far_set_size; - - last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; - last_far_set_start *= geo->far_set_size; - - last_far_set_size = geo->far_set_size; - last_far_set_size += (geo->raid_disks % geo->far_set_size); /* now calculate first sector/dev */ chunk = r10bio->sector >> geo->chunk_shift; @@ -573,25 +551,15 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) /* and calculate all the others */ for (n = 0; n < geo->near_copies; n++) { int d = dev; - int set; sector_t s = sector; + r10bio->devs[slot].addr = sector; r10bio->devs[slot].devnum = d; - r10bio->devs[slot].addr = s; slot++; for (f = 1; f < geo->far_copies; f++) { - set = d / geo->far_set_size; d += geo->near_copies; - - if ((geo->raid_disks % geo->far_set_size) && - (d > last_far_set_start)) { - d -= last_far_set_start; - d %= last_far_set_size; - d += last_far_set_start; - } else { - d %= geo->far_set_size; - d += geo->far_set_size * set; - } + if (d >= geo->raid_disks) + d -= geo->raid_disks; s += geo->stride; r10bio->devs[slot].devnum = d; r10bio->devs[slot].addr = s; @@ -627,20 +595,6 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) * or recovery, so reshape isn't happening */ struct geom *geo = &conf->geo; - int far_set_start = (dev / geo->far_set_size) * geo->far_set_size; - int far_set_size = geo->far_set_size; - int last_far_set_start; - - if (geo->raid_disks % geo->far_set_size) { - last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; - last_far_set_start *= geo->far_set_size; - - if (dev >= last_far_set_start) { - far_set_size = geo->far_set_size; - far_set_size += (geo->raid_disks % geo->far_set_size); - far_set_start = last_far_set_start; - } - } offset = sector & geo->chunk_mask; if (geo->far_offset) { @@ -648,13 +602,13 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) chunk = sector >> geo->chunk_shift; fc = sector_div(chunk, geo->far_copies); dev -= fc * geo->near_copies; - if (dev < far_set_start) - dev += far_set_size; + if (dev < 0) + dev += geo->raid_disks; } else { while (sector >= geo->stride) { sector -= geo->stride; - if (dev < (geo->near_copies + far_set_start)) - dev += far_set_size - geo->near_copies; + if (dev < geo->near_copies) + dev += geo->raid_disks - geo->near_copies; else dev -= geo->near_copies; } @@ -1119,7 +1073,6 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) bio_list_merge(&conf->pending_bio_list, &plug->pending); conf->pending_count += plug->pending_cnt; spin_unlock_irq(&conf->device_lock); - wake_up(&conf->wait_barrier); md_wakeup_thread(mddev->thread); kfree(plug); return; @@ -1152,7 +1105,6 @@ static void make_request(struct mddev *mddev, struct bio * bio) const unsigned long do_fua = (bio->bi_rw & REQ_FUA); const unsigned long do_discard = (bio->bi_rw & (REQ_DISCARD | REQ_SECURE)); - const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); unsigned long flags; struct md_rdev *blocked_rdev; struct blk_plug_cb *cb; @@ -1508,8 +1460,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) rdev)); mbio->bi_bdev = rdev->bdev; mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = - WRITE | do_sync | do_fua | do_discard | do_same; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); @@ -1551,8 +1502,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) r10_bio, rdev)); mbio->bi_bdev = rdev->bdev; mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = - WRITE | do_sync | do_fua | do_discard | do_same; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); @@ -3486,7 +3436,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) disks = mddev->raid_disks + mddev->delta_disks; break; } - if (layout >> 18) + if (layout >> 17) return -1; if (chunk < (PAGE_SIZE >> 9) || !is_power_of_2(chunk)) @@ -3498,7 +3448,6 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) geo->near_copies = nc; geo->far_copies = fc; geo->far_offset = fo; - geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks; geo->chunk_mask = chunk - 1; geo->chunk_shift = ffz(~chunk); return nc*fc; @@ -3620,8 +3569,6 @@ static int run(struct mddev *mddev) if (mddev->queue) { blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors); - blk_queue_max_write_same_sectors(mddev->queue, - mddev->chunk_sectors); blk_queue_io_min(mddev->queue, chunk_size); if (conf->geo.raid_disks % conf->geo.near_copies) blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); diff --git a/trunk/drivers/md/raid10.h b/trunk/drivers/md/raid10.h index 157d69e83ff4..1054cf602345 100644 --- a/trunk/drivers/md/raid10.h +++ b/trunk/drivers/md/raid10.h @@ -33,11 +33,6 @@ struct r10conf { * far_offset, in which case it is * 1 stripe. */ - int far_set_size; /* The number of devices in a set, - * where a 'set' are devices that - * contain far/offset copies of - * each other. - */ int chunk_shift; /* shift from chunks to sectors */ sector_t chunk_mask; } prev, geo; diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 3ee2912889e7..5af2d2709081 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -1403,7 +1403,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu &sh->ops.zero_sum_result, percpu->spare_page, &submit); } -static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) +static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request) { int overlap_clear = 0, i, disks = sh->disks; struct dma_async_tx_descriptor *tx = NULL; @@ -1468,6 +1468,36 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) put_cpu(); } +#ifdef CONFIG_MULTICORE_RAID456 +static void async_run_ops(void *param, async_cookie_t cookie) +{ + struct stripe_head *sh = param; + unsigned long ops_request = sh->ops.request; + + clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state); + wake_up(&sh->ops.wait_for_ops); + + __raid_run_ops(sh, ops_request); + release_stripe(sh); +} + +static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) +{ + /* since handle_stripe can be called outside of raid5d context + * we need to ensure sh->ops.request is de-staged before another + * request arrives + */ + wait_event(sh->ops.wait_for_ops, + !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state)); + sh->ops.request = ops_request; + + atomic_inc(&sh->count); + async_schedule(async_run_ops, sh); +} +#else +#define raid_run_ops __raid_run_ops +#endif + static int grow_one_stripe(struct r5conf *conf) { struct stripe_head *sh; @@ -1476,6 +1506,9 @@ static int grow_one_stripe(struct r5conf *conf) return 0; sh->raid_conf = conf; + #ifdef CONFIG_MULTICORE_RAID456 + init_waitqueue_head(&sh->ops.wait_for_ops); + #endif spin_lock_init(&sh->stripe_lock); @@ -1594,6 +1627,9 @@ static int resize_stripes(struct r5conf *conf, int newsize) break; nsh->raid_conf = conf; + #ifdef CONFIG_MULTICORE_RAID456 + init_waitqueue_head(&nsh->ops.wait_for_ops); + #endif spin_lock_init(&nsh->stripe_lock); list_add(&nsh->lru, &newstripes); diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 7bd068a6056a..11d01d67b3f5 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -1629,7 +1629,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* If this is the first slave, then we need to set the master's hardware * address to be the same as the slave's. */ - if (bond->slave_cnt == 0 && bond->dev_addr_from_first) + if (bond->dev_addr_from_first) bond_set_dev_addr(bond->dev, slave_dev); new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); diff --git a/trunk/drivers/net/ethernet/broadcom/bgmac.c b/trunk/drivers/net/ethernet/broadcom/bgmac.c index da5f4397f87c..639049d7e92d 100644 --- a/trunk/drivers/net/ethernet/broadcom/bgmac.c +++ b/trunk/drivers/net/ethernet/broadcom/bgmac.c @@ -301,16 +301,12 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", ring->start); } else { - /* Omit CRC. */ - len -= ETH_FCS_LEN; - new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len); if (new_skb) { skb_put(new_skb, len); skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET, new_skb->data, len); - skb_checksum_none_assert(skb); new_skb->protocol = eth_type_trans(new_skb, bgmac->net_dev); netif_receive_skb(new_skb); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index a923bc4d5a1f..ecac04a3687c 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3142,7 +3142,7 @@ static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix) tsum = ~csum_fold(csum_add((__force __wsum) csum, csum_partial(t_header, -fix, 0))); - return bswab16(tsum); + return bswab16(csum); } static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index edfa67adf2f9..9a674b14b403 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -281,8 +281,6 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->lp_advertising |= ADVERTISED_2500baseX_Full; if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE) cmd->lp_advertising |= ADVERTISED_10000baseT_Full; - if (status & LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE) - cmd->lp_advertising |= ADVERTISED_20000baseKR2_Full; } cmd->maxtxpkt = 0; @@ -465,10 +463,6 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ADVERTISED_10000baseKR_Full)) bp->link_params.speed_cap_mask[cfg_idx] |= PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; - - if (cmd->advertising & ADVERTISED_20000baseKR2_Full) - bp->link_params.speed_cap_mask[cfg_idx] |= - PORT_HW_CFG_SPEED_CAPABILITY_D0_20G; } } else { /* forced speed */ /* advertise the requested speed and duplex if supported */ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 31c5787970db..1663e0b6b5a0 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -10422,28 +10422,6 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); - if (phy->type == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { - /* Disable MI_INT interrupt before setting LED4 - * source to constant off. - */ - if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + - params->port*4) & - NIG_MASK_MI_INT) { - params->link_flags |= - LINK_FLAGS_INT_DISABLED; - - bnx2x_bits_dis( - bp, - NIG_REG_MASK_INTERRUPT_PORT0 + - params->port*4, - NIG_MASK_MI_INT); - } - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_SIGNAL_MASK, - 0x0); - } } break; case LED_MODE_ON: @@ -10490,28 +10468,6 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x20); - if (phy->type == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { - /* Disable MI_INT interrupt before setting LED4 - * source to constant on. - */ - if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + - params->port*4) & - NIG_MASK_MI_INT) { - params->link_flags |= - LINK_FLAGS_INT_DISABLED; - - bnx2x_bits_dis( - bp, - NIG_REG_MASK_INTERRUPT_PORT0 + - params->port*4, - NIG_MASK_MI_INT); - } - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_SIGNAL_MASK, - 0x20); - } } break; @@ -10576,22 +10532,6 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val); - if (phy->type == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { - /* Restore LED4 source to external link, - * and re-enable interrupts. - */ - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_SIGNAL_MASK, - 0x40); - if (params->link_flags & - LINK_FLAGS_INT_DISABLED) { - bnx2x_link_int_enable(params); - params->link_flags &= - ~LINK_FLAGS_INT_DISABLED; - } - } } break; } @@ -11851,8 +11791,6 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, phy->media_type = ETH_PHY_KR; phy->flags |= FLAGS_WC_DUAL_MODE; phy->supported &= (SUPPORTED_20000baseKR2_Full | - SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE | SUPPORTED_Pause | @@ -13499,7 +13437,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; bnx2x_set_aer_mmd(params, phy); if ((phy->supported & SUPPORTED_20000baseKR2_Full) && - (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) + (phy->speed_cap_mask & SPEED_20000)) bnx2x_check_kr2_wa(params, vars, phy); bnx2x_check_over_curr(params, vars); if (vars->rx_tx_asic_rst) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index be5c195d03dd..d25c7d79787a 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -307,8 +307,7 @@ struct link_params { struct bnx2x *bp; u16 req_fc_auto_adv; /* Should be set to TX / BOTH when req_flow_ctrl is set to AUTO */ - u16 link_flags; -#define LINK_FLAGS_INT_DISABLED (1<<0) + u16 rsrv1; u32 lfa_base; }; diff --git a/trunk/drivers/net/ethernet/freescale/fec.c b/trunk/drivers/net/ethernet/freescale/fec.c index 069a155d16ed..fccc3bf2141d 100644 --- a/trunk/drivers/net/ethernet/freescale/fec.c +++ b/trunk/drivers/net/ethernet/freescale/fec.c @@ -246,13 +246,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct bufdesc *bdp; void *bufaddr; unsigned short status; - unsigned int index; + unsigned long flags; if (!fep->link) { /* Link is down or autonegotiation is in progress. */ return NETDEV_TX_BUSY; } + spin_lock_irqsave(&fep->hw_lock, flags); /* Fill in a Tx ring entry */ bdp = fep->cur_tx; @@ -263,6 +264,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) * This should not happen, since ndev->tbusy should be set. */ printk("%s: tx queue full!.\n", ndev->name); + spin_unlock_irqrestore(&fep->hw_lock, flags); return NETDEV_TX_BUSY; } @@ -278,13 +280,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ - if (fep->bufdesc_ex) - index = (struct bufdesc_ex *)bdp - - (struct bufdesc_ex *)fep->tx_bd_base; - else - index = bdp - fep->tx_bd_base; - if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { + unsigned int index; + if (fep->bufdesc_ex) + index = (struct bufdesc_ex *)bdp - + (struct bufdesc_ex *)fep->tx_bd_base; + else + index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], skb->data, skb->len); bufaddr = fep->tx_bounce[index]; } @@ -298,7 +300,10 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) swap_buffer(bufaddr, skb->len); /* Save skb pointer */ - fep->tx_skbuff[index] = skb; + fep->tx_skbuff[fep->skb_cur] = skb; + + ndev->stats.tx_bytes += skb->len; + fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; /* Push the data cache so the CPM does not get stale memory * data. @@ -326,22 +331,26 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) ebdp->cbd_esc = BD_ENET_TX_INT; } } + /* Trigger transmission start */ + writel(0, fep->hwp + FEC_X_DES_ACTIVE); + /* If this was the last BD in the ring, start at the beginning again. */ if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; else bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); - fep->cur_tx = bdp; - - if (fep->cur_tx == fep->dirty_tx) + if (bdp == fep->dirty_tx) { + fep->tx_full = 1; netif_stop_queue(ndev); + } - /* Trigger transmission start */ - writel(0, fep->hwp + FEC_X_DES_ACTIVE); + fep->cur_tx = bdp; skb_tx_timestamp(skb); + spin_unlock_irqrestore(&fep->hw_lock, flags); + return NETDEV_TX_OK; } @@ -397,8 +406,11 @@ fec_restart(struct net_device *ndev, int duplex) writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); + fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->cur_rx = fep->rx_bd_base; + /* Reset SKB transmit buffers. */ + fep->skb_cur = fep->skb_dirty = 0; for (i = 0; i <= TX_RING_MOD_MASK; i++) { if (fep->tx_skbuff[i]) { dev_kfree_skb_any(fep->tx_skbuff[i]); @@ -561,35 +573,20 @@ fec_enet_tx(struct net_device *ndev) struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; - int index = 0; fep = netdev_priv(ndev); + spin_lock(&fep->hw_lock); bdp = fep->dirty_tx; - /* get next bdp of dirty_tx */ - if (bdp->cbd_sc & BD_ENET_TX_WRAP) - bdp = fep->tx_bd_base; - else - bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); - while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { - - /* current queue is empty */ - if (bdp == fep->cur_tx) + if (bdp == fep->cur_tx && fep->tx_full == 0) break; - if (fep->bufdesc_ex) - index = (struct bufdesc_ex *)bdp - - (struct bufdesc_ex *)fep->tx_bd_base; - else - index = bdp - fep->tx_bd_base; - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); bdp->cbd_bufaddr = 0; - skb = fep->tx_skbuff[index]; - + skb = fep->tx_skbuff[fep->skb_dirty]; /* Check for errors. */ if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN | @@ -634,9 +631,8 @@ fec_enet_tx(struct net_device *ndev) /* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any(skb); - fep->tx_skbuff[index] = NULL; - - fep->dirty_tx = bdp; + fep->tx_skbuff[fep->skb_dirty] = NULL; + fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; /* Update pointer to next buffer descriptor to be transmitted */ if (status & BD_ENET_TX_WRAP) @@ -646,12 +642,14 @@ fec_enet_tx(struct net_device *ndev) /* Since we have freed up a buffer, the ring is no longer full */ - if (fep->dirty_tx != fep->cur_tx) { + if (fep->tx_full) { + fep->tx_full = 0; if (netif_queue_stopped(ndev)) netif_wake_queue(ndev); } } - return; + fep->dirty_tx = bdp; + spin_unlock(&fep->hw_lock); } @@ -818,7 +816,7 @@ fec_enet_interrupt(int irq, void *dev_id) int_events = readl(fep->hwp + FEC_IEVENT); writel(int_events, fep->hwp + FEC_IEVENT); - if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) { + if (int_events & FEC_ENET_RXF) { ret = IRQ_HANDLED; /* Disable the RX interrupt */ @@ -829,6 +827,15 @@ fec_enet_interrupt(int irq, void *dev_id) } } + /* Transmit OK, or non-fatal error. Update the buffer + * descriptors. FEC handles all errors, we just discover + * them as part of the transmit process. + */ + if (int_events & FEC_ENET_TXF) { + ret = IRQ_HANDLED; + fec_enet_tx(ndev); + } + if (int_events & FEC_ENET_MII) { ret = IRQ_HANDLED; complete(&fep->mdio_done); @@ -844,8 +851,6 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget) int pkts = fec_enet_rx(ndev, budget); struct fec_enet_private *fep = netdev_priv(ndev); - fec_enet_tx(ndev); - if (pkts < budget) { napi_complete(napi); writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); @@ -1641,7 +1646,6 @@ static int fec_enet_init(struct net_device *ndev) /* ...and the same for transmit */ bdp = fep->tx_bd_base; - fep->cur_tx = bdp; for (i = 0; i < TX_RING_SIZE; i++) { /* Initialize the BD for every fragment in the page. */ @@ -1653,7 +1657,6 @@ static int fec_enet_init(struct net_device *ndev) /* Set the last buffer to wrap */ bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); bdp->cbd_sc |= BD_SC_WRAP; - fep->dirty_tx = bdp; fec_restart(ndev, 0); diff --git a/trunk/drivers/net/ethernet/freescale/fec.h b/trunk/drivers/net/ethernet/freescale/fec.h index f5390071efd0..01579b8e37c4 100644 --- a/trunk/drivers/net/ethernet/freescale/fec.h +++ b/trunk/drivers/net/ethernet/freescale/fec.h @@ -97,13 +97,6 @@ struct bufdesc { unsigned short cbd_sc; /* Control and status info */ unsigned long cbd_bufaddr; /* Buffer address */ }; -#else -struct bufdesc { - unsigned short cbd_sc; /* Control and status info */ - unsigned short cbd_datlen; /* Data length */ - unsigned long cbd_bufaddr; /* Buffer address */ -}; -#endif struct bufdesc_ex { struct bufdesc desc; @@ -114,6 +107,14 @@ struct bufdesc_ex { unsigned short res0[4]; }; +#else +struct bufdesc { + unsigned short cbd_sc; /* Control and status info */ + unsigned short cbd_datlen; /* Data length */ + unsigned long cbd_bufaddr; /* Buffer address */ +}; +#endif + /* * The following definitions courtesy of commproc.h, which where * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). @@ -213,6 +214,8 @@ struct fec_enet_private { unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff *tx_skbuff[TX_RING_SIZE]; struct sk_buff *rx_skbuff[RX_RING_SIZE]; + ushort skb_cur; + ushort skb_dirty; /* CPM dual port RAM relative addresses */ dma_addr_t bd_dma; @@ -224,6 +227,7 @@ struct fec_enet_private { /* The ring entries to be free()ed */ struct bufdesc *dirty_tx; + uint tx_full; /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ spinlock_t hw_lock; diff --git a/trunk/drivers/net/ethernet/realtek/r8169.c b/trunk/drivers/net/ethernet/realtek/r8169.c index 28fb50a1e9c3..8900398ba103 100644 --- a/trunk/drivers/net/ethernet/realtek/r8169.c +++ b/trunk/drivers/net/ethernet/realtek/r8169.c @@ -4765,10 +4765,8 @@ static void rtl_hw_start_8168bb(struct rtl8169_private *tp) RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - if (tp->dev->mtu <= ETH_DATA_LEN) { - rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) | - PCI_EXP_DEVCTL_NOSNOOP_EN); - } + rtl_tx_performance_tweak(pdev, + (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } static void rtl_hw_start_8168bef(struct rtl8169_private *tp) @@ -4791,8 +4789,7 @@ static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); rtl_disable_clock_request(pdev); @@ -4825,8 +4822,7 @@ static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } @@ -4845,8 +4841,7 @@ static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) RTL_W8(MaxTxPacketSize, TxPacketMax); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } @@ -4906,8 +4901,7 @@ static void rtl_hw_start_8168d(struct rtl8169_private *tp) RTL_W8(MaxTxPacketSize, TxPacketMax); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); } @@ -4919,8 +4913,7 @@ static void rtl_hw_start_8168dp(struct rtl8169_private *tp) rtl_csi_access_enable_1(tp); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W8(MaxTxPacketSize, TxPacketMax); @@ -4979,8 +4972,7 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); RTL_W8(MaxTxPacketSize, TxPacketMax); @@ -5006,8 +4998,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); + rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); diff --git a/trunk/drivers/net/ethernet/sfc/efx.c b/trunk/drivers/net/ethernet/sfc/efx.c index 0bc00991d310..bf57b3cb16ab 100644 --- a/trunk/drivers/net/ethernet/sfc/efx.c +++ b/trunk/drivers/net/ethernet/sfc/efx.c @@ -779,7 +779,6 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) tx_queue->txd.entries); } - efx_device_detach_sync(efx); efx_stop_all(efx); efx_stop_interrupts(efx, true); @@ -833,7 +832,6 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) efx_start_interrupts(efx, true); efx_start_all(efx); - netif_device_attach(efx->net_dev); return rc; rollback: @@ -1643,12 +1641,8 @@ static void efx_stop_all(struct efx_nic *efx) /* Flush efx_mac_work(), refill_workqueue, monitor_work */ efx_flush_all(efx); - /* Stop the kernel transmit interface. This is only valid if - * the device is stopped or detached; otherwise the watchdog - * may fire immediately. - */ - WARN_ON(netif_running(efx->net_dev) && - netif_device_present(efx->net_dev)); + /* Stop the kernel transmit interface late, so the watchdog + * timer isn't ticking over the flush */ netif_tx_disable(efx->net_dev); efx_stop_datapath(efx); @@ -1969,18 +1963,16 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) if (new_mtu > EFX_MAX_MTU) return -EINVAL; - netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); - - efx_device_detach_sync(efx); efx_stop_all(efx); + netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); + mutex_lock(&efx->mac_lock); net_dev->mtu = new_mtu; efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); efx_start_all(efx); - netif_device_attach(efx->net_dev); return 0; } diff --git a/trunk/drivers/net/ethernet/sfc/net_driver.h b/trunk/drivers/net/ethernet/sfc/net_driver.h index 0a90abd2421b..2d756c1d7142 100644 --- a/trunk/drivers/net/ethernet/sfc/net_driver.h +++ b/trunk/drivers/net/ethernet/sfc/net_driver.h @@ -210,7 +210,6 @@ struct efx_tx_queue { * Will be %NULL if the buffer slot is currently free. * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. * Will be %NULL if the buffer slot is currently free. - * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE. * @len: Buffer length, in bytes. * @flags: Flags for buffer and packet state. */ @@ -220,8 +219,7 @@ struct efx_rx_buffer { struct sk_buff *skb; struct page *page; } u; - u16 page_offset; - u16 len; + unsigned int len; u16 flags; }; #define EFX_RX_BUF_PAGE 0x0001 diff --git a/trunk/drivers/net/ethernet/sfc/rx.c b/trunk/drivers/net/ethernet/sfc/rx.c index 879ff5849bbd..d780a0d096b4 100644 --- a/trunk/drivers/net/ethernet/sfc/rx.c +++ b/trunk/drivers/net/ethernet/sfc/rx.c @@ -90,7 +90,11 @@ static unsigned int rx_refill_threshold; static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, struct efx_rx_buffer *buf) { - return buf->page_offset + efx->type->rx_buffer_hash_size; + /* Offset is always within one page, so we don't need to consider + * the page order. + */ + return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) + + efx->type->rx_buffer_hash_size; } static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) { @@ -183,7 +187,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) struct efx_nic *efx = rx_queue->efx; struct efx_rx_buffer *rx_buf; struct page *page; - unsigned int page_offset; struct efx_rx_page_state *state; dma_addr_t dma_addr; unsigned index, count; @@ -208,14 +211,12 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) state->dma_addr = dma_addr; dma_addr += sizeof(struct efx_rx_page_state); - page_offset = sizeof(struct efx_rx_page_state); split: index = rx_queue->added_count & rx_queue->ptr_mask; rx_buf = efx_rx_buffer(rx_queue, index); rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; rx_buf->u.page = page; - rx_buf->page_offset = page_offset; rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; rx_buf->flags = EFX_RX_BUF_PAGE; ++rx_queue->added_count; @@ -226,7 +227,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) /* Use the second half of the page */ get_page(page); dma_addr += (PAGE_SIZE >> 1); - page_offset += (PAGE_SIZE >> 1); ++count; goto split; } @@ -236,8 +236,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) } static void efx_unmap_rx_buffer(struct efx_nic *efx, - struct efx_rx_buffer *rx_buf, - unsigned int used_len) + struct efx_rx_buffer *rx_buf) { if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { struct efx_rx_page_state *state; @@ -248,10 +247,6 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, state->dma_addr, efx_rx_buf_size(efx), DMA_FROM_DEVICE); - } else if (used_len) { - dma_sync_single_for_cpu(&efx->pci_dev->dev, - rx_buf->dma_addr, used_len, - DMA_FROM_DEVICE); } } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr, @@ -274,7 +269,7 @@ static void efx_free_rx_buffer(struct efx_nic *efx, static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, struct efx_rx_buffer *rx_buf) { - efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0); + efx_unmap_rx_buffer(rx_queue->efx, rx_buf); efx_free_rx_buffer(rx_queue->efx, rx_buf); } @@ -540,10 +535,10 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, goto out; } - /* Release and/or sync DMA mapping - assumes all RX buffers - * consumed in-order per RX queue + /* Release card resources - assumes all RX buffers consumed in-order + * per RX queue */ - efx_unmap_rx_buffer(efx, rx_buf, len); + efx_unmap_rx_buffer(efx, rx_buf); /* Prefetch nice and early so data will (hopefully) be in cache by * the time we look at it. diff --git a/trunk/drivers/net/ethernet/ti/cpsw.c b/trunk/drivers/net/ethernet/ti/cpsw.c index 01ffbc486982..7e93df6585e7 100644 --- a/trunk/drivers/net/ethernet/ti/cpsw.c +++ b/trunk/drivers/net/ethernet/ti/cpsw.c @@ -731,7 +731,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) writel(vlan, &priv->host_port_regs->port_vlan); - for (i = 0; i < priv->data.slaves; i++) + for (i = 0; i < 2; i++) slave_write(priv->slaves + i, vlan, reg); cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, diff --git a/trunk/drivers/net/phy/micrel.c b/trunk/drivers/net/phy/micrel.c index abf7b6153d00..29934446436a 100644 --- a/trunk/drivers/net/phy/micrel.c +++ b/trunk/drivers/net/phy/micrel.c @@ -257,7 +257,8 @@ static struct phy_driver ksphy_driver[] = { .phy_id = PHY_ID_KSZ9021, .phy_id_mask = 0x000ffffe, .name = "Micrel KSZ9021 Gigabit PHY", - .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), + .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause + | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, diff --git a/trunk/drivers/net/phy/phy_device.c b/trunk/drivers/net/phy/phy_device.c index 3657b4a29124..9930f9999561 100644 --- a/trunk/drivers/net/phy/phy_device.c +++ b/trunk/drivers/net/phy/phy_device.c @@ -44,13 +44,13 @@ MODULE_LICENSE("GPL"); void phy_device_free(struct phy_device *phydev) { - put_device(&phydev->dev); + kfree(phydev); } EXPORT_SYMBOL(phy_device_free); static void phy_device_release(struct device *dev) { - kfree(to_phy_device(dev)); + phy_device_free(to_phy_device(dev)); } static struct phy_driver genphy_driver; @@ -201,8 +201,6 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, there's no driver _already_ loaded. */ request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); - device_initialize(&dev->dev); - return dev; } EXPORT_SYMBOL(phy_device_create); @@ -365,9 +363,9 @@ int phy_device_register(struct phy_device *phydev) /* Run all of the fixups for this PHY */ phy_scan_fixups(phydev); - err = device_add(&phydev->dev); + err = device_register(&phydev->dev); if (err) { - pr_err("PHY %d failed to add\n", phydev->addr); + pr_err("phy %d failed to register\n", phydev->addr); goto out; } diff --git a/trunk/drivers/net/usb/Kconfig b/trunk/drivers/net/usb/Kconfig index 3b6e9b83342d..da92ed3797aa 100644 --- a/trunk/drivers/net/usb/Kconfig +++ b/trunk/drivers/net/usb/Kconfig @@ -156,24 +156,6 @@ config USB_NET_AX8817X This driver creates an interface named "ethX", where X depends on what other networking devices you have in use. -config USB_NET_AX88179_178A - tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet" - depends on USB_USBNET - select CRC32 - select PHYLIB - default y - help - This option adds support for ASIX AX88179 based USB 3.0/2.0 - to Gigabit Ethernet adapters. - - This driver should work with at least the following devices: - * ASIX AX88179 - * ASIX AX88178A - * Sitcomm LN-032 - - This driver creates an interface named "ethX", where X depends on - what other networking devices you have in use. - config USB_NET_CDCETHER tristate "CDC Ethernet support (smart devices such as cable modems)" depends on USB_USBNET diff --git a/trunk/drivers/net/usb/Makefile b/trunk/drivers/net/usb/Makefile index 119b06c9aa16..478691326f37 100644 --- a/trunk/drivers/net/usb/Makefile +++ b/trunk/drivers/net/usb/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o asix-y := asix_devices.o asix_common.o ax88172a.o -obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o diff --git a/trunk/drivers/net/usb/asix_devices.c b/trunk/drivers/net/usb/asix_devices.c index 709753469099..2205dbc8d32f 100644 --- a/trunk/drivers/net/usb/asix_devices.c +++ b/trunk/drivers/net/usb/asix_devices.c @@ -924,29 +924,6 @@ static const struct driver_info ax88178_info = { .tx_fixup = asix_tx_fixup, }; -/* - * USBLINK 20F9 "USB 2.0 LAN" USB ethernet adapter, typically found in - * no-name packaging. - * USB device strings are: - * 1: Manufacturer: USBLINK - * 2: Product: HG20F9 USB2.0 - * 3: Serial: 000003 - * Appears to be compatible with Asix 88772B. - */ -static const struct driver_info hg20f9_info = { - .description = "HG20F9 USB 2.0 Ethernet", - .bind = ax88772_bind, - .unbind = ax88772_unbind, - .status = asix_status, - .link_reset = ax88772_link_reset, - .reset = ax88772_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | - FLAG_MULTI_PACKET, - .rx_fixup = asix_rx_fixup_common, - .tx_fixup = asix_tx_fixup, - .data = FLAG_EEPROM_MAC, -}; - extern const struct driver_info ax88172a_info; static const struct usb_device_id products [] = { @@ -1086,14 +1063,6 @@ static const struct usb_device_id products [] = { /* ASIX 88172a demo board */ USB_DEVICE(0x0b95, 0x172a), .driver_info = (unsigned long) &ax88172a_info, -}, { - /* - * USBLINK HG20F9 "USB 2.0 LAN" - * Appears to have gazumped Linksys's manufacturer ID but - * doesn't (yet) conflict with any known Linksys product. - */ - USB_DEVICE(0x066b, 0x20f9), - .driver_info = (unsigned long) &hg20f9_info, }, { }, // END }; diff --git a/trunk/drivers/net/usb/ax88179_178a.c b/trunk/drivers/net/usb/ax88179_178a.c deleted file mode 100644 index 71c27d8d214f..000000000000 --- a/trunk/drivers/net/usb/ax88179_178a.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* - * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices - * - * Copyright (C) 2011-2013 ASIX - * - * 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. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include - -#define AX88179_PHY_ID 0x03 -#define AX_EEPROM_LEN 0x100 -#define AX88179_EEPROM_MAGIC 0x17900b95 -#define AX_MCAST_FLTSIZE 8 -#define AX_MAX_MCAST 64 -#define AX_INT_PPLS_LINK ((u32)BIT(16)) -#define AX_RXHDR_L4_TYPE_MASK 0x1c -#define AX_RXHDR_L4_TYPE_UDP 4 -#define AX_RXHDR_L4_TYPE_TCP 16 -#define AX_RXHDR_L3CSUM_ERR 2 -#define AX_RXHDR_L4CSUM_ERR 1 -#define AX_RXHDR_CRC_ERR ((u32)BIT(31)) -#define AX_RXHDR_DROP_ERR ((u32)BIT(30)) -#define AX_ACCESS_MAC 0x01 -#define AX_ACCESS_PHY 0x02 -#define AX_ACCESS_EEPROM 0x04 -#define AX_ACCESS_EFUS 0x05 -#define AX_PAUSE_WATERLVL_HIGH 0x54 -#define AX_PAUSE_WATERLVL_LOW 0x55 - -#define PHYSICAL_LINK_STATUS 0x02 - #define AX_USB_SS 0x04 - #define AX_USB_HS 0x02 - -#define GENERAL_STATUS 0x03 -/* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */ - #define AX_SECLD 0x04 - -#define AX_SROM_ADDR 0x07 -#define AX_SROM_CMD 0x0a - #define EEP_RD 0x04 - #define EEP_BUSY 0x10 - -#define AX_SROM_DATA_LOW 0x08 -#define AX_SROM_DATA_HIGH 0x09 - -#define AX_RX_CTL 0x0b - #define AX_RX_CTL_DROPCRCERR 0x0100 - #define AX_RX_CTL_IPE 0x0200 - #define AX_RX_CTL_START 0x0080 - #define AX_RX_CTL_AP 0x0020 - #define AX_RX_CTL_AM 0x0010 - #define AX_RX_CTL_AB 0x0008 - #define AX_RX_CTL_AMALL 0x0002 - #define AX_RX_CTL_PRO 0x0001 - #define AX_RX_CTL_STOP 0x0000 - -#define AX_NODE_ID 0x10 -#define AX_MULFLTARY 0x16 - -#define AX_MEDIUM_STATUS_MODE 0x22 - #define AX_MEDIUM_GIGAMODE 0x01 - #define AX_MEDIUM_FULL_DUPLEX 0x02 - #define AX_MEDIUM_ALWAYS_ONE 0x04 - #define AX_MEDIUM_EN_125MHZ 0x08 - #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 - #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 - #define AX_MEDIUM_RECEIVE_EN 0x100 - #define AX_MEDIUM_PS 0x200 - #define AX_MEDIUM_JUMBO_EN 0x8040 - -#define AX_MONITOR_MOD 0x24 - #define AX_MONITOR_MODE_RWLC 0x02 - #define AX_MONITOR_MODE_RWMP 0x04 - #define AX_MONITOR_MODE_PMEPOL 0x20 - #define AX_MONITOR_MODE_PMETYPE 0x40 - -#define AX_GPIO_CTRL 0x25 - #define AX_GPIO_CTRL_GPIO3EN 0x80 - #define AX_GPIO_CTRL_GPIO2EN 0x40 - #define AX_GPIO_CTRL_GPIO1EN 0x20 - -#define AX_PHYPWR_RSTCTL 0x26 - #define AX_PHYPWR_RSTCTL_BZ 0x0010 - #define AX_PHYPWR_RSTCTL_IPRL 0x0020 - #define AX_PHYPWR_RSTCTL_AT 0x1000 - -#define AX_RX_BULKIN_QCTRL 0x2e -#define AX_CLK_SELECT 0x33 - #define AX_CLK_SELECT_BCS 0x01 - #define AX_CLK_SELECT_ACS 0x02 - #define AX_CLK_SELECT_ULR 0x08 - -#define AX_RXCOE_CTL 0x34 - #define AX_RXCOE_IP 0x01 - #define AX_RXCOE_TCP 0x02 - #define AX_RXCOE_UDP 0x04 - #define AX_RXCOE_TCPV6 0x20 - #define AX_RXCOE_UDPV6 0x40 - -#define AX_TXCOE_CTL 0x35 - #define AX_TXCOE_IP 0x01 - #define AX_TXCOE_TCP 0x02 - #define AX_TXCOE_UDP 0x04 - #define AX_TXCOE_TCPV6 0x20 - #define AX_TXCOE_UDPV6 0x40 - -#define AX_LEDCTRL 0x73 - -#define GMII_PHY_PHYSR 0x11 - #define GMII_PHY_PHYSR_SMASK 0xc000 - #define GMII_PHY_PHYSR_GIGA 0x8000 - #define GMII_PHY_PHYSR_100 0x4000 - #define GMII_PHY_PHYSR_FULL 0x2000 - #define GMII_PHY_PHYSR_LINK 0x400 - -#define GMII_LED_ACT 0x1a - #define GMII_LED_ACTIVE_MASK 0xff8f - #define GMII_LED0_ACTIVE BIT(4) - #define GMII_LED1_ACTIVE BIT(5) - #define GMII_LED2_ACTIVE BIT(6) - -#define GMII_LED_LINK 0x1c - #define GMII_LED_LINK_MASK 0xf888 - #define GMII_LED0_LINK_10 BIT(0) - #define GMII_LED0_LINK_100 BIT(1) - #define GMII_LED0_LINK_1000 BIT(2) - #define GMII_LED1_LINK_10 BIT(4) - #define GMII_LED1_LINK_100 BIT(5) - #define GMII_LED1_LINK_1000 BIT(6) - #define GMII_LED2_LINK_10 BIT(8) - #define GMII_LED2_LINK_100 BIT(9) - #define GMII_LED2_LINK_1000 BIT(10) - #define LED0_ACTIVE BIT(0) - #define LED0_LINK_10 BIT(1) - #define LED0_LINK_100 BIT(2) - #define LED0_LINK_1000 BIT(3) - #define LED0_FD BIT(4) - #define LED0_USB3_MASK 0x001f - #define LED1_ACTIVE BIT(5) - #define LED1_LINK_10 BIT(6) - #define LED1_LINK_100 BIT(7) - #define LED1_LINK_1000 BIT(8) - #define LED1_FD BIT(9) - #define LED1_USB3_MASK 0x03e0 - #define LED2_ACTIVE BIT(10) - #define LED2_LINK_1000 BIT(13) - #define LED2_LINK_100 BIT(12) - #define LED2_LINK_10 BIT(11) - #define LED2_FD BIT(14) - #define LED_VALID BIT(15) - #define LED2_USB3_MASK 0x7c00 - -#define GMII_PHYPAGE 0x1e -#define GMII_PHY_PAGE_SELECT 0x1f - #define GMII_PHY_PGSEL_EXT 0x0007 - #define GMII_PHY_PGSEL_PAGE0 0x0000 - -struct ax88179_data { - u16 rxctl; - u16 reserved; -}; - -struct ax88179_int_data { - __le32 intdata1; - __le32 intdata2; -}; - -static const struct { - unsigned char ctrl, timer_l, timer_h, size, ifg; -} AX88179_BULKIN_SIZE[] = { - {7, 0x4f, 0, 0x12, 0xff}, - {7, 0x20, 3, 0x16, 0xff}, - {7, 0xae, 7, 0x18, 0xff}, - {7, 0xcc, 0x4c, 0x18, 8}, -}; - -static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int in_pm) -{ - int ret; - int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); - - BUG_ON(!dev); - - if (!in_pm) - fn = usbnet_read_cmd; - else - fn = usbnet_read_cmd_nopm; - - ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, size); - - if (unlikely(ret < 0)) - netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", - index, ret); - - return ret; -} - -static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int in_pm) -{ - int ret; - int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); - - BUG_ON(!dev); - - if (!in_pm) - fn = usbnet_write_cmd; - else - fn = usbnet_write_cmd_nopm; - - ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, size); - - if (unlikely(ret < 0)) - netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", - index, ret); - - return ret; -} - -static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - u16 buf; - - if (2 == size) { - buf = *((u16 *)data); - cpu_to_le16s(&buf); - usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, &buf, - size); - } else { - usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, data, - size); - } -} - -static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); - le16_to_cpus(&buf); - *((u16 *)data) = buf; - } else if (4 == size) { - u32 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); - le32_to_cpus(&buf); - *((u32 *)data) = buf; - } else { - ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1); - } - - return ret; -} - -static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - buf = *((u16 *)data); - cpu_to_le16s(&buf); - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, &buf, 1); - } else { - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, data, 1); - } - - return ret; -} - -static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); - le16_to_cpus(&buf); - *((u16 *)data) = buf; - } else if (4 == size) { - u32 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); - le32_to_cpus(&buf); - *((u32 *)data) = buf; - } else { - ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0); - } - - return ret; -} - -static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - buf = *((u16 *)data); - cpu_to_le16s(&buf); - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, &buf, 0); - } else { - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, data, 0); - } - - return ret; -} - -static void ax88179_status(struct usbnet *dev, struct urb *urb) -{ - struct ax88179_int_data *event; - u32 link; - - if (urb->actual_length < 8) - return; - - event = urb->transfer_buffer; - le32_to_cpus((void *)&event->intdata1); - - link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; - - if (netif_carrier_ok(dev->net) != link) { - if (link) - usbnet_defer_kevent(dev, EVENT_LINK_RESET); - else - netif_carrier_off(dev->net); - - netdev_info(dev->net, "ax88179 - Link status is: %d\n", link); - } -} - -static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc) -{ - struct usbnet *dev = netdev_priv(netdev); - u16 res; - - ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); - return res; -} - -static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, - int val) -{ - struct usbnet *dev = netdev_priv(netdev); - u16 res = (u16) val; - - ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); -} - -static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usbnet *dev = usb_get_intfdata(intf); - u16 tmp16; - u8 tmp8; - - usbnet_suspend(intf, message); - - /* Disable RX path */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - - /* Force bulk-in zero length */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - - tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - - /* change clock */ - tmp8 = 0; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - - /* Configure RX control register => stop operation */ - tmp16 = AX_RX_CTL_STOP; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); - - return 0; -} - -/* This function is used to enable the autodetach function. */ -/* This function is determined by offset 0x43 of EEPROM */ -static int ax88179_auto_detach(struct usbnet *dev, int in_pm) -{ - u16 tmp16; - u8 tmp8; - int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); - int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); - - if (!in_pm) { - fnr = ax88179_read_cmd; - fnw = ax88179_write_cmd; - } else { - fnr = ax88179_read_cmd_nopm; - fnw = ax88179_write_cmd_nopm; - } - - if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) - return 0; - - if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) - return 0; - - /* Enable Auto Detach bit */ - tmp8 = 0; - fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - tmp8 |= AX_CLK_SELECT_ULR; - fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - - fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); - tmp16 |= AX_PHYPWR_RSTCTL_AT; - fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); - - return 0; -} - -static int ax88179_resume(struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - u16 tmp16; - u8 tmp8; - - netif_carrier_off(dev->net); - - /* Power up ethernet PHY */ - tmp16 = 0; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - udelay(1000); - - tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - msleep(200); - - /* Ethernet PHY Auto Detach*/ - ax88179_auto_detach(dev, 1); - - /* Enable clock */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - msleep(100); - - /* Configure RX control register => start operation */ - tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); - - return usbnet_resume(intf); -} - -static void -ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt; - - if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, - 1, 1, &opt) < 0) { - wolinfo->supported = 0; - wolinfo->wolopts = 0; - return; - } - - wolinfo->supported = WAKE_PHY | WAKE_MAGIC; - wolinfo->wolopts = 0; - if (opt & AX_MONITOR_MODE_RWLC) - wolinfo->wolopts |= WAKE_PHY; - if (opt & AX_MONITOR_MODE_RWMP) - wolinfo->wolopts |= WAKE_MAGIC; -} - -static int -ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt = 0; - - if (wolinfo->wolopts & WAKE_PHY) - opt |= AX_MONITOR_MODE_RWLC; - if (wolinfo->wolopts & WAKE_MAGIC) - opt |= AX_MONITOR_MODE_RWMP; - - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, - 1, 1, &opt) < 0) - return -EINVAL; - - return 0; -} - -static int ax88179_get_eeprom_len(struct net_device *net) -{ - return AX_EEPROM_LEN; -} - -static int -ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct usbnet *dev = netdev_priv(net); - u16 *eeprom_buff; - int first_word, last_word; - int i, ret; - - if (eeprom->len == 0) - return -EINVAL; - - eeprom->magic = AX88179_EEPROM_MAGIC; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - /* ax88179/178A returns 2 bytes from eeprom on read */ - for (i = first_word; i <= last_word; i++) { - ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word], - 0); - if (ret < 0) { - kfree(eeprom_buff); - return -EIO; - } - } - - memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); - kfree(eeprom_buff); - return 0; -} - -static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - struct usbnet *dev = netdev_priv(net); - return mii_ethtool_gset(&dev->mii, cmd); -} - -static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - struct usbnet *dev = netdev_priv(net); - return mii_ethtool_sset(&dev->mii, cmd); -} - - -static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - struct usbnet *dev = netdev_priv(net); - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); -} - -static const struct ethtool_ops ax88179_ethtool_ops = { - .get_link = ethtool_op_get_link, - .get_msglevel = usbnet_get_msglevel, - .set_msglevel = usbnet_set_msglevel, - .get_wol = ax88179_get_wol, - .set_wol = ax88179_set_wol, - .get_eeprom_len = ax88179_get_eeprom_len, - .get_eeprom = ax88179_get_eeprom, - .get_settings = ax88179_get_settings, - .set_settings = ax88179_set_settings, - .nway_reset = usbnet_nway_reset, -}; - -static void ax88179_set_multicast(struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - struct ax88179_data *data = (struct ax88179_data *)dev->data; - u8 *m_filter = ((u8 *)dev->data) + 12; - - data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); - - if (net->flags & IFF_PROMISC) { - data->rxctl |= AX_RX_CTL_PRO; - } else if (net->flags & IFF_ALLMULTI || - netdev_mc_count(net) > AX_MAX_MCAST) { - data->rxctl |= AX_RX_CTL_AMALL; - } else if (netdev_mc_empty(net)) { - /* just broadcast and directed */ - } else { - /* We use the 20 byte dev->data for our 8 byte filter buffer - * to avoid allocating memory that is tricky to free later - */ - u32 crc_bits; - struct netdev_hw_addr *ha; - - memset(m_filter, 0, AX_MCAST_FLTSIZE); - - netdev_for_each_mc_addr(ha, net) { - crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; - *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7)); - } - - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, - AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, - m_filter); - - data->rxctl |= AX_RX_CTL_AM; - } - - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL, - 2, 2, &data->rxctl); -} - -static int -ax88179_set_features(struct net_device *net, netdev_features_t features) -{ - u8 tmp; - struct usbnet *dev = netdev_priv(net); - netdev_features_t changed = net->features ^ features; - - if (changed & NETIF_F_IP_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - } - - if (changed & NETIF_F_IPV6_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - } - - if (changed & NETIF_F_RXCSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); - tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); - } - - return 0; -} - -static int ax88179_change_mtu(struct net_device *net, int new_mtu) -{ - struct usbnet *dev = netdev_priv(net); - u16 tmp16; - - if (new_mtu <= 0 || new_mtu > 4088) - return -EINVAL; - - net->mtu = new_mtu; - dev->hard_mtu = net->mtu + net->hard_header_len; - - if (net->mtu > 1500) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 |= AX_MEDIUM_JUMBO_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - } else { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &= ~AX_MEDIUM_JUMBO_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - } - - return 0; -} - -static int ax88179_set_mac_addr(struct net_device *net, void *p) -{ - struct usbnet *dev = netdev_priv(net); - struct sockaddr *addr = p; - - if (netif_running(net)) - return -EBUSY; - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); - - /* Set the MAC address */ - return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, net->dev_addr); -} - -static const struct net_device_ops ax88179_netdev_ops = { - .ndo_open = usbnet_open, - .ndo_stop = usbnet_stop, - .ndo_start_xmit = usbnet_start_xmit, - .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_change_mtu = ax88179_change_mtu, - .ndo_set_mac_address = ax88179_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = ax88179_ioctl, - .ndo_set_rx_mode = ax88179_set_multicast, - .ndo_set_features = ax88179_set_features, -}; - -static int ax88179_check_eeprom(struct usbnet *dev) -{ - u8 i, buf, eeprom[20]; - u16 csum, delay = HZ / 10; - unsigned long jtimeout; - - /* Read EEPROM content */ - for (i = 0; i < 6; i++) { - buf = i; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, - 1, 1, &buf) < 0) - return -EINVAL; - - buf = EEP_RD; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &buf) < 0) - return -EINVAL; - - jtimeout = jiffies + delay; - do { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &buf); - - if (time_after(jiffies, jtimeout)) - return -EINVAL; - - } while (buf & EEP_BUSY); - - __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 2, 2, &eeprom[i * 2], 0); - - if ((i == 0) && (eeprom[0] == 0xFF)) - return -EINVAL; - } - - csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9]; - csum = (csum >> 8) + (csum & 0xff); - if ((csum + eeprom[10]) != 0xff) - return -EINVAL; - - return 0; -} - -static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode) -{ - u8 i; - u8 efuse[64]; - u16 csum = 0; - - if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0) - return -EINVAL; - - if (*efuse == 0xFF) - return -EINVAL; - - for (i = 0; i < 64; i++) - csum = csum + efuse[i]; - - while (csum > 255) - csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF); - - if (csum != 0xFF) - return -EINVAL; - - *ledmode = (efuse[51] << 8) | efuse[52]; - - return 0; -} - -static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue) -{ - u16 led; - - /* Loaded the old eFuse LED Mode */ - if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0) - return -EINVAL; - - led >>= 8; - switch (led) { - case 0xFF: - led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | - LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | - LED2_LINK_100 | LED2_LINK_1000 | LED_VALID; - break; - case 0xFE: - led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | LED_VALID; - break; - case 0xFD: - led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | - LED2_LINK_10 | LED_VALID; - break; - case 0xFC: - led = LED0_ACTIVE | LED1_ACTIVE | LED1_LINK_1000 | LED2_ACTIVE | - LED2_LINK_100 | LED2_LINK_10 | LED_VALID; - break; - default: - led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | - LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | - LED2_LINK_100 | LED2_LINK_1000 | LED_VALID; - break; - } - - *ledvalue = led; - - return 0; -} - -static int ax88179_led_setting(struct usbnet *dev) -{ - u8 ledfd, value = 0; - u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10; - unsigned long jtimeout; - - /* Check AX88179 version. UA1 or UA2*/ - ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value); - - if (!(value & AX_SECLD)) { /* UA1 */ - value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN | - AX_GPIO_CTRL_GPIO1EN; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL, - 1, 1, &value) < 0) - return -EINVAL; - } - - /* Check EEPROM */ - if (!ax88179_check_eeprom(dev)) { - value = 0x42; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, - 1, 1, &value) < 0) - return -EINVAL; - - value = EEP_RD; - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &value) < 0) - return -EINVAL; - - jtimeout = jiffies + delay; - do { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &value); - - if (time_after(jiffies, jtimeout)) - return -EINVAL; - - } while (value & EEP_BUSY); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH, - 1, 1, &value); - ledvalue = (value << 8); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 1, 1, &value); - ledvalue |= value; - - /* load internal ROM for defaule setting */ - if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) - ax88179_convert_old_led(dev, &ledvalue); - - } else if (!ax88179_check_efuse(dev, &ledvalue)) { - if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) - ax88179_convert_old_led(dev, &ledvalue); - } else { - ax88179_convert_old_led(dev, &ledvalue); - } - - tmp = GMII_PHY_PGSEL_EXT; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp); - - tmp = 0x2c; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHYPAGE, 2, &tmp); - - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_ACT, 2, &ledact); - - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_LINK, 2, &ledlink); - - ledact &= GMII_LED_ACTIVE_MASK; - ledlink &= GMII_LED_LINK_MASK; - - if (ledvalue & LED0_ACTIVE) - ledact |= GMII_LED0_ACTIVE; - - if (ledvalue & LED1_ACTIVE) - ledact |= GMII_LED1_ACTIVE; - - if (ledvalue & LED2_ACTIVE) - ledact |= GMII_LED2_ACTIVE; - - if (ledvalue & LED0_LINK_10) - ledlink |= GMII_LED0_LINK_10; - - if (ledvalue & LED1_LINK_10) - ledlink |= GMII_LED1_LINK_10; - - if (ledvalue & LED2_LINK_10) - ledlink |= GMII_LED2_LINK_10; - - if (ledvalue & LED0_LINK_100) - ledlink |= GMII_LED0_LINK_100; - - if (ledvalue & LED1_LINK_100) - ledlink |= GMII_LED1_LINK_100; - - if (ledvalue & LED2_LINK_100) - ledlink |= GMII_LED2_LINK_100; - - if (ledvalue & LED0_LINK_1000) - ledlink |= GMII_LED0_LINK_1000; - - if (ledvalue & LED1_LINK_1000) - ledlink |= GMII_LED1_LINK_1000; - - if (ledvalue & LED2_LINK_1000) - ledlink |= GMII_LED2_LINK_1000; - - tmp = ledact; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_ACT, 2, &tmp); - - tmp = ledlink; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_LINK, 2, &tmp); - - tmp = GMII_PHY_PGSEL_PAGE0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &tmp); - - /* LED full duplex setting */ - ledfd = 0; - if (ledvalue & LED0_FD) - ledfd |= 0x01; - else if ((ledvalue & LED0_USB3_MASK) == 0) - ledfd |= 0x02; - - if (ledvalue & LED1_FD) - ledfd |= 0x04; - else if ((ledvalue & LED1_USB3_MASK) == 0) - ledfd |= 0x08; - - if (ledvalue & LED2_FD) - ledfd |= 0x10; - else if ((ledvalue & LED2_USB3_MASK) == 0) - ledfd |= 0x20; - - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd); - - return 0; -} - -static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) -{ - u8 buf[5]; - u16 *tmp16; - u8 *tmp; - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - - usbnet_get_endpoints(dev, intf); - - tmp16 = (u16 *)buf; - tmp = (u8 *)buf; - - memset(ax179_data, 0, sizeof(*ax179_data)); - - /* Power up ethernet PHY */ - *tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); - *tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); - msleep(200); - - *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); - msleep(100); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, dev->net->dev_addr); - memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); - - /* RX bulk configuration */ - memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - - dev->rx_urb_size = 1024 * 20; - - *tmp = 0x34; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); - - *tmp = 0x52; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, - 1, 1, tmp); - - dev->net->netdev_ops = &ax88179_netdev_ops; - dev->net->ethtool_ops = &ax88179_ethtool_ops; - dev->net->needed_headroom = 8; - - /* Initialize MII structure */ - dev->mii.dev = dev->net; - dev->mii.mdio_read = ax88179_mdio_read; - dev->mii.mdio_write = ax88179_mdio_write; - dev->mii.phy_id_mask = 0xff; - dev->mii.reg_num_mask = 0xff; - dev->mii.phy_id = 0x03; - dev->mii.supports_gmii = 1; - - dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; - - dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; - - /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); - - *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | - AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); - - /* Configure RX control register => start operation */ - *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); - - *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); - - /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE | - AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, tmp16); - - ax88179_led_setting(dev); - - /* Restart autoneg */ - mii_nway_restart(&dev->mii); - - netif_carrier_off(dev->net); - - return 0; -} - -static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf) -{ - u16 tmp16; - - /* Configure RX control register => stop operation */ - tmp16 = AX_RX_CTL_STOP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); - - tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16); - - /* Power down ethernet PHY */ - tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); -} - -static void -ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr) -{ - skb->ip_summed = CHECKSUM_NONE; - - /* checksum error bit is set */ - if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) || - (*pkt_hdr & AX_RXHDR_L4CSUM_ERR)) - return; - - /* It must be a TCP or UDP packet with a valid checksum */ - if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) || - ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP)) - skb->ip_summed = CHECKSUM_UNNECESSARY; -} - -static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - struct sk_buff *ax_skb; - int pkt_cnt; - u32 rx_hdr; - u16 hdr_off; - u32 *pkt_hdr; - - skb_trim(skb, skb->len - 4); - memcpy(&rx_hdr, skb_tail_pointer(skb), 4); - le32_to_cpus(&rx_hdr); - - pkt_cnt = (u16)rx_hdr; - hdr_off = (u16)(rx_hdr >> 16); - pkt_hdr = (u32 *)(skb->data + hdr_off); - - while (pkt_cnt--) { - u16 pkt_len; - - le32_to_cpus(pkt_hdr); - pkt_len = (*pkt_hdr >> 16) & 0x1fff; - - /* Check CRC or runt packet */ - if ((*pkt_hdr & AX_RXHDR_CRC_ERR) || - (*pkt_hdr & AX_RXHDR_DROP_ERR)) { - skb_pull(skb, (pkt_len + 7) & 0xFFF8); - pkt_hdr++; - continue; - } - - if (pkt_cnt == 0) { - /* Skip IP alignment psudo header */ - skb_pull(skb, 2); - skb->len = pkt_len; - skb_set_tail_pointer(skb, pkt_len); - skb->truesize = pkt_len + sizeof(struct sk_buff); - ax88179_rx_checksum(skb, pkt_hdr); - return 1; - } - - ax_skb = skb_clone(skb, GFP_ATOMIC); - if (ax_skb) { - ax_skb->len = pkt_len; - ax_skb->data = skb->data + 2; - skb_set_tail_pointer(ax_skb, pkt_len); - ax_skb->truesize = pkt_len + sizeof(struct sk_buff); - ax88179_rx_checksum(ax_skb, pkt_hdr); - usbnet_skb_return(dev, ax_skb); - } else { - return 0; - } - - skb_pull(skb, (pkt_len + 7) & 0xFFF8); - pkt_hdr++; - } - return 1; -} - -static struct sk_buff * -ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - u32 tx_hdr1, tx_hdr2; - int frame_size = dev->maxpacket; - int mss = skb_shinfo(skb)->gso_size; - int headroom; - int tailroom; - - tx_hdr1 = skb->len; - tx_hdr2 = mss; - if (((skb->len + 8) % frame_size) == 0) - tx_hdr2 |= 0x80008000; /* Enable padding */ - - skb_linearize(skb); - headroom = skb_headroom(skb); - tailroom = skb_tailroom(skb); - - if (!skb_header_cloned(skb) && - !skb_cloned(skb) && - (headroom + tailroom) >= 8) { - if (headroom < 8) { - skb->data = memmove(skb->head + 8, skb->data, skb->len); - skb_set_tail_pointer(skb, skb->len); - } - } else { - struct sk_buff *skb2; - - skb2 = skb_copy_expand(skb, 8, 0, flags); - dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; - } - - skb_push(skb, 4); - cpu_to_le32s(&tx_hdr2); - skb_copy_to_linear_data(skb, &tx_hdr2, 4); - - skb_push(skb, 4); - cpu_to_le32s(&tx_hdr1); - skb_copy_to_linear_data(skb, &tx_hdr1, 4); - - return skb; -} - -static int ax88179_link_reset(struct usbnet *dev) -{ - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - u8 tmp[5], link_sts; - u16 mode, tmp16, delay = HZ / 10; - u32 tmp32 = 0x40000000; - unsigned long jtimeout; - - jtimeout = jiffies + delay; - while (tmp32 & 0x40000000) { - mode = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, - &ax179_data->rxctl); - - /*link up, check the usb device control TX FIFO full or empty*/ - ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32); - - if (time_after(jiffies, jtimeout)) - return 0; - } - - mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE; - - ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, - 1, 1, &link_sts); - - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PHYSR, 2, &tmp16); - - if (!(tmp16 & GMII_PHY_PHYSR_LINK)) { - return 0; - } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) { - mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ; - if (dev->net->mtu > 1500) - mode |= AX_MEDIUM_JUMBO_EN; - - if (link_sts & AX_USB_SS) - memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - else if (link_sts & AX_USB_HS) - memcpy(tmp, &AX88179_BULKIN_SIZE[1], 5); - else - memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) { - mode |= AX_MEDIUM_PS; - - if (link_sts & (AX_USB_SS | AX_USB_HS)) - memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5); - else - memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } else { - memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } - - /* RX bulk configuration */ - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - - dev->rx_urb_size = (1024 * (tmp[3] + 2)); - - if (tmp16 & GMII_PHY_PHYSR_FULL) - mode |= AX_MEDIUM_FULL_DUPLEX; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &mode); - - netif_carrier_on(dev->net); - - return 0; -} - -static int ax88179_reset(struct usbnet *dev) -{ - u8 buf[5]; - u16 *tmp16; - u8 *tmp; - - tmp16 = (u16 *)buf; - tmp = (u8 *)buf; - - /* Power up ethernet PHY */ - *tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); - - *tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); - msleep(200); - - *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); - msleep(100); - - /* Ethernet PHY Auto Detach*/ - ax88179_auto_detach(dev, 0); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, - dev->net->dev_addr); - memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); - - /* RX bulk configuration */ - memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - - dev->rx_urb_size = 1024 * 20; - - *tmp = 0x34; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); - - *tmp = 0x52; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, - 1, 1, tmp); - - dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; - - dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; - - /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); - - *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | - AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); - - /* Configure RX control register => start operation */ - *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); - - *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); - - /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE | - AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, tmp16); - - ax88179_led_setting(dev); - - /* Restart autoneg */ - mii_nway_restart(&dev->mii); - - netif_carrier_off(dev->net); - - return 0; -} - -static int ax88179_stop(struct usbnet *dev) -{ - u16 tmp16; - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - - return 0; -} - -static const struct driver_info ax88179_info = { - .description = "ASIX AX88179 USB 3.0 Gigibit Ethernet", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info ax88178a_info = { - .description = "ASIX AX88178A USB 2.0 Gigibit Ethernet", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct driver_info sitecom_info = { - .description = "Sitecom USB 3.0 to Gigabit Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, - .reset = ax88179_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, - .tx_fixup = ax88179_tx_fixup, -}; - -static const struct usb_device_id products[] = { -{ - /* ASIX AX88179 10/100/1000 */ - USB_DEVICE(0x0b95, 0x1790), - .driver_info = (unsigned long)&ax88179_info, -}, { - /* ASIX AX88178A 10/100/1000 */ - USB_DEVICE(0x0b95, 0x178a), - .driver_info = (unsigned long)&ax88178a_info, -}, { - /* Sitecom USB 3.0 to Gigabit Adapter */ - USB_DEVICE(0x0df6, 0x0072), - .driver_info = (unsigned long) &sitecom_info, -}, - { }, -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver ax88179_178a_driver = { - .name = "ax88179_178a", - .id_table = products, - .probe = usbnet_probe, - .suspend = ax88179_suspend, - .resume = ax88179_resume, - .disconnect = usbnet_disconnect, - .supports_autosuspend = 1, - .disable_hub_initiated_lpm = 1, -}; - -module_usb_driver(ax88179_178a_driver); - -MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/usb/cdc_ncm.c b/trunk/drivers/net/usb/cdc_ncm.c index 61b74a2b89ac..4a8c25a22294 100644 --- a/trunk/drivers/net/usb/cdc_ncm.c +++ b/trunk/drivers/net/usb/cdc_ncm.c @@ -1213,14 +1213,6 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, - /* tag Huawei devices as wwan */ - { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, - USB_CLASS_COMM, - USB_CDC_SUBCLASS_NCM, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&wwan_info, - }, - /* Huawei NCM devices disguised as vendor specific */ { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), .driver_info = (unsigned long)&wwan_info, diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.h b/trunk/drivers/net/wireless/ath/ath9k/common.h index 050ca4a4850d..5f845beeb18b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.h +++ b/trunk/drivers/net/wireless/ath/ath9k/common.h @@ -27,7 +27,7 @@ #define WME_MAX_BA WME_BA_BMP_SIZE #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) -#define ATH_RSSI_DUMMY_MARKER 127 +#define ATH_RSSI_DUMMY_MARKER 0x127 #define ATH_RSSI_LPF_LEN 10 #define RSSI_LPF_THRESHOLD -20 #define ATH_RSSI_EP_MULTIPLIER (1<<7) diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc.h b/trunk/drivers/net/wireless/ath/ath9k/htc.h index d3b099d7898b..96bfb18078fa 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc.h +++ b/trunk/drivers/net/wireless/ath/ath9k/htc.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index bd8251c1c749..3ad1fd05c5e7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -1067,19 +1067,15 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, last_rssi = priv->rx.last_rssi; - if (ieee80211_is_beacon(hdr->frame_control) && - !is_zero_ether_addr(common->curbssid) && - ether_addr_equal(hdr->addr3, common->curbssid)) { - s8 rssi = rxbuf->rxstatus.rs_rssi; + if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) + rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, + ATH_RSSI_EP_MULTIPLIER); - if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) - rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); + if (rxbuf->rxstatus.rs_rssi < 0) + rxbuf->rxstatus.rs_rssi = 0; - if (rssi < 0) - rssi = 0; - - priv->ah->stats.avgbrssi = rssi; - } + if (ieee80211_is_beacon(fc)) + priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); rx_status->band = hw->conf.channel->band; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 07e25260c31d..2a2ae403e0e5 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -1463,9 +1463,7 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, reset_type = ATH9K_RESET_POWER_ON; else reset_type = ATH9K_RESET_COLD; - } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || - (REG_READ(ah, AR_CR) & AR_CR_RXE)) - reset_type = ATH9K_RESET_COLD; + } if (!ath9k_hw_set_reset_reg(ah, reset_type)) return false; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 10f01793d7a6..9a0f45ec9e01 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -349,23 +349,25 @@ TRACE_EVENT(iwlwifi_dev_rx_data, TRACE_EVENT(iwlwifi_dev_hcmd, TP_PROTO(const struct device *dev, struct iwl_host_cmd *cmd, u16 total_size, - struct iwl_cmd_header *hdr), - TP_ARGS(dev, cmd, total_size, hdr), + const void *hdr, size_t hdr_len), + TP_ARGS(dev, cmd, total_size, hdr, hdr_len), TP_STRUCT__entry( DEV_ENTRY __dynamic_array(u8, hcmd, total_size) __field(u32, flags) ), TP_fast_assign( - int i, offset = sizeof(*hdr); + int i, offset = hdr_len; DEV_ASSIGN; __entry->flags = cmd->flags; - memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr)); + memcpy(__get_dynamic_array(hcmd), hdr, hdr_len); for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { if (!cmd->len[i]) continue; + if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) + continue; memcpy((u8 *)__get_dynamic_array(hcmd) + offset, cmd->data[i], cmd->len[i]); offset += cmd->len[i]; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 3392011a8768..14fc8d39fc28 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c @@ -136,6 +136,12 @@ struct iwl_calib_res_notif_phy_db { u8 data[]; } __packed; +#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587) +static inline void iwl_phy_db_test_pic(__le32 pic) +{ + WARN_ON(IWL_PHY_DB_STATIC_PIC != pic); +} + struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) { struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), @@ -254,6 +260,11 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; } + /* Test PIC */ + if (type != IWL_PHY_DB_CFG) + iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) + + (size / sizeof(__le32)) - 1)); + IWL_DEBUG_INFO(phy_db->trans, "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", __func__, __LINE__, type, size); @@ -361,6 +372,11 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, *size = entry->size; } + /* Test PIC */ + if (type != IWL_PHY_DB_CFG) + iwl_phy_db_test_pic(*(((__le32 *)*data) + + (*size / sizeof(__le32)) - 1)); + IWL_DEBUG_INFO(phy_db->trans, "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", __func__, __LINE__, type, *size); diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c b/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c index 994c8c263dc0..c64d864799cd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -61,7 +61,6 @@ * *****************************************************************************/ -#include #include #include #include "iwl-modparams.h" @@ -193,11 +192,6 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, sizeof(wkc), &wkc); data->error = ret != 0; - mvm->ptk_ivlen = key->iv_len; - mvm->ptk_icvlen = key->icv_len; - mvm->gtk_ivlen = key->iv_len; - mvm->gtk_icvlen = key->icv_len; - /* don't upload key again */ goto out_unlock; } @@ -310,13 +304,9 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, */ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { key->hw_key_idx = 0; - mvm->ptk_ivlen = key->iv_len; - mvm->ptk_icvlen = key->icv_len; } else { data->gtk_key_idx++; key->hw_key_idx = data->gtk_key_idx; - mvm->gtk_ivlen = key->iv_len; - mvm->gtk_icvlen = key->icv_len; } ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); @@ -659,11 +649,6 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) /* We reprogram keys and shouldn't allocate new key indices */ memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); - mvm->ptk_ivlen = 0; - mvm->ptk_icvlen = 0; - mvm->ptk_ivlen = 0; - mvm->ptk_icvlen = 0; - /* * The D3 firmware still hardcodes the AP station ID for the * BSS we're associated with as 0. As a result, we have to move @@ -798,6 +783,7 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct iwl_wowlan_status *status; u32 reasons; int ret, len; + bool pkt8023 = false; struct sk_buff *pkt = NULL; iwl_trans_read_mem_bytes(mvm->trans, base, @@ -838,8 +824,7 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, status = (void *)cmd.resp_pkt->data; if (len - sizeof(struct iwl_cmd_header) != - sizeof(*status) + - ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { + sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) { IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); goto out; } @@ -851,96 +836,61 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, goto report; } - if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) + if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) { wakeup.magic_pkt = true; + pkt8023 = true; + } - if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) + if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) { wakeup.pattern_idx = le16_to_cpu(status->pattern_number); + pkt8023 = true; + } if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) wakeup.disconnect = true; - if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) + if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) { wakeup.gtk_rekey_failure = true; + pkt8023 = true; + } - if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) + if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) { wakeup.rfkill_release = true; + pkt8023 = true; + } - if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) + if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) { wakeup.eap_identity_req = true; + pkt8023 = true; + } - if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) + if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) { wakeup.four_way_handshake = true; + pkt8023 = true; + } if (status->wake_packet_bufsize) { - int pktsize = le32_to_cpu(status->wake_packet_bufsize); - int pktlen = le32_to_cpu(status->wake_packet_length); - const u8 *pktdata = status->wake_packet; - struct ieee80211_hdr *hdr = (void *)pktdata; - int truncated = pktlen - pktsize; - - /* this would be a firmware bug */ - if (WARN_ON_ONCE(truncated < 0)) - truncated = 0; - - if (ieee80211_is_data(hdr->frame_control)) { - int hdrlen = ieee80211_hdrlen(hdr->frame_control); - int ivlen = 0, icvlen = 4; /* also FCS */ + u32 pktsize = le32_to_cpu(status->wake_packet_bufsize); + u32 pktlen = le32_to_cpu(status->wake_packet_length); + if (pkt8023) { pkt = alloc_skb(pktsize, GFP_KERNEL); if (!pkt) goto report; - - memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen); - pktdata += hdrlen; - pktsize -= hdrlen; - - if (ieee80211_has_protected(hdr->frame_control)) { - if (is_multicast_ether_addr(hdr->addr1)) { - ivlen = mvm->gtk_ivlen; - icvlen += mvm->gtk_icvlen; - } else { - ivlen = mvm->ptk_ivlen; - icvlen += mvm->ptk_icvlen; - } - } - - /* if truncated, FCS/ICV is (partially) gone */ - if (truncated >= icvlen) { - icvlen = 0; - truncated -= icvlen; - } else { - icvlen -= truncated; - truncated = 0; - } - - pktsize -= ivlen + icvlen; - pktdata += ivlen; - - memcpy(skb_put(pkt, pktsize), pktdata, pktsize); - + memcpy(skb_put(pkt, pktsize), status->wake_packet, + pktsize); if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) goto report; wakeup.packet = pkt->data; wakeup.packet_present_len = pkt->len; - wakeup.packet_len = pkt->len - truncated; + wakeup.packet_len = pkt->len - (pktlen - pktsize); wakeup.packet_80211 = false; } else { - int fcslen = 4; - - if (truncated >= 4) { - truncated -= 4; - fcslen = 0; - } else { - fcslen -= truncated; - truncated = 0; - } - pktsize -= fcslen; wakeup.packet = status->wake_packet; wakeup.packet_present_len = pktsize; - wakeup.packet_len = pktlen - truncated; + wakeup.packet_len = pktlen; wakeup.packet_80211 = true; } } diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7e169b085afe..e8264e11b12d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -557,9 +557,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, return ret; } -static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) +static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); u32 tfd_msk = 0, ac; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) @@ -592,21 +594,12 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, */ flush_work(&mvm->sta_drained_wk); } -} - -static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - - iwl_mvm_prepare_mac_removal(mvm, vif); mutex_lock(&mvm->mutex); /* * For AP/GO interface, the tear down of the resources allocated to the - * interface is be handled as part of the stop_ap flow. + * interface should be handled as part of the bss_info_changed flow. */ if (vif->type == NL80211_IFTYPE_AP) { iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); @@ -770,8 +763,6 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - iwl_mvm_prepare_mac_removal(mvm, vif); - mutex_lock(&mvm->mutex); mvmvif->ap_active = false; diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h b/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h index 537711b10478..4e339ccfa800 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -327,10 +327,6 @@ struct iwl_mvm { struct led_classdev led; struct ieee80211_vif *p2p_device_vif; - -#ifdef CONFIG_PM_SLEEP - int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; -#endif }; /* Extract MVM priv from op_mode and _hw */ diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h index 3d62e8055352..aa2a39a637dd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -182,15 +182,6 @@ struct iwl_queue { #define TFD_TX_CMD_SLOTS 256 #define TFD_CMD_SLOTS 32 -/* - * The FH will write back to the first TB only, so we need - * to copy some data into the buffer regardless of whether - * it should be mapped or not. This indicates how much to - * copy, even for HCMDs it must be big enough to fit the - * DRAM scratch from the TX cmd, at least 16 bytes. - */ -#define IWL_HCMD_MIN_COPY_SIZE 16 - struct iwl_pcie_txq_entry { struct iwl_device_cmd *cmd; struct iwl_device_cmd *copy_cmd; diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c index 8b625a7f5685..8e9e3212fe78 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1152,12 +1152,10 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, void *dup_buf = NULL; dma_addr_t phys_addr; int idx; - u16 copy_size, cmd_size, dma_size; + u16 copy_size, cmd_size; bool had_nocopy = false; int i; u32 cmd_pos; - const u8 *cmddata[IWL_MAX_CMD_TFDS]; - u16 cmdlen[IWL_MAX_CMD_TFDS]; copy_size = sizeof(out_cmd->hdr); cmd_size = sizeof(out_cmd->hdr); @@ -1166,23 +1164,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { - cmddata[i] = cmd->data[i]; - cmdlen[i] = cmd->len[i]; - if (!cmd->len[i]) continue; - - /* need at least IWL_HCMD_MIN_COPY_SIZE copied */ - if (copy_size < IWL_HCMD_MIN_COPY_SIZE) { - int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size; - - if (copy > cmdlen[i]) - copy = cmdlen[i]; - cmdlen[i] -= copy; - cmddata[i] += copy; - copy_size += copy; - } - if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { had_nocopy = true; if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { @@ -1202,7 +1185,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, goto free_dup_buf; } - dup_buf = kmemdup(cmddata[i], cmdlen[i], + dup_buf = kmemdup(cmd->data[i], cmd->len[i], GFP_ATOMIC); if (!dup_buf) return -ENOMEM; @@ -1212,7 +1195,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, idx = -EINVAL; goto free_dup_buf; } - copy_size += cmdlen[i]; + copy_size += cmd->len[i]; } cmd_size += cmd->len[i]; } @@ -1259,31 +1242,14 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, /* and copy the data that needs to be copied */ cmd_pos = offsetof(struct iwl_device_cmd, payload); - copy_size = sizeof(out_cmd->hdr); for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { - int copy = 0; - - if (!cmd->len) + if (!cmd->len[i]) continue; - - /* need at least IWL_HCMD_MIN_COPY_SIZE copied */ - if (copy_size < IWL_HCMD_MIN_COPY_SIZE) { - copy = IWL_HCMD_MIN_COPY_SIZE - copy_size; - - if (copy > cmd->len[i]) - copy = cmd->len[i]; - } - - /* copy everything if not nocopy/dup */ - if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | - IWL_HCMD_DFL_DUP))) - copy = cmd->len[i]; - - if (copy) { - memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); - cmd_pos += copy; - copy_size += copy; - } + if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | + IWL_HCMD_DFL_DUP)) + break; + memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); + cmd_pos += cmd->len[i]; } WARN_ON_ONCE(txq->entries[idx].copy_cmd); @@ -1309,14 +1275,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); - /* - * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must - * still map at least that many bytes for the hardware to write back to. - * We have enough space, so that's not a problem. - */ - dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE); - - phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size, + phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { idx = -ENOMEM; @@ -1324,15 +1283,14 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, } dma_unmap_addr_set(out_meta, mapping, phys_addr); - dma_unmap_len_set(out_meta, len, dma_size); + dma_unmap_len_set(out_meta, len, copy_size); iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); - /* map the remaining (adjusted) nocopy/dup fragments */ for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { - const void *data = cmddata[i]; + const void *data = cmd->data[i]; - if (!cmdlen[i]) + if (!cmd->len[i]) continue; if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | IWL_HCMD_DFL_DUP))) @@ -1340,7 +1298,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) data = dup_buf; phys_addr = dma_map_single(trans->dev, (void *)data, - cmdlen[i], DMA_BIDIRECTIONAL); + cmd->len[i], DMA_BIDIRECTIONAL); if (dma_mapping_error(trans->dev, phys_addr)) { iwl_pcie_tfd_unmap(trans, out_meta, &txq->tfds[q->write_ptr], @@ -1349,7 +1307,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, goto out; } - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0); + iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0); } out_meta->flags = cmd->flags; @@ -1359,7 +1317,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, txq->need_update = 1; - trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); + trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, + &out_cmd->hdr, copy_size); /* start timer if queue currently empty */ if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) diff --git a/trunk/drivers/net/wireless/libertas/if_sdio.c b/trunk/drivers/net/wireless/libertas/if_sdio.c index 45578335e420..739309e70d8b 100644 --- a/trunk/drivers/net/wireless/libertas/if_sdio.c +++ b/trunk/drivers/net/wireless/libertas/if_sdio.c @@ -825,11 +825,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) sdio_release_host(func); - /* Set fw_ready before queuing any commands so that - * lbs_thread won't block from sending them to firmware. - */ - priv->fw_ready = 1; - /* * FUNC_INIT is required for SD8688 WLAN/BT multiple functions */ @@ -844,6 +839,7 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); } + priv->fw_ready = 1; wake_up(&card->pwron_waitq); if (!card->started) { diff --git a/trunk/drivers/net/wireless/mwifiex/pcie.c b/trunk/drivers/net/wireless/mwifiex/pcie.c index 5c395e2e6a2b..35c79722c361 100644 --- a/trunk/drivers/net/wireless/mwifiex/pcie.c +++ b/trunk/drivers/net/wireless/mwifiex/pcie.c @@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) i++; usleep_range(10, 20); /* 50ms max wait */ - if (i == 5000) + if (i == 50000) break; } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index 189744db65e0..1031db66474a 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1236,10 +1236,8 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) */ if_limit = &rt2x00dev->if_limits_ap; if_limit->max = rt2x00dev->ops->max_ap_intf; - if_limit->types = BIT(NL80211_IFTYPE_AP); -#ifdef CONFIG_MAC80211_MESH - if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); -#endif + if_limit->types = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT); /* * Build up AP interface combinations structure. @@ -1311,9 +1309,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH BIT(NL80211_IFTYPE_MESH_POINT) | -#endif BIT(NL80211_IFTYPE_WDS); rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; diff --git a/trunk/include/linux/hardirq.h b/trunk/include/linux/hardirq.h index c1d6555d2567..29eb805ea4a6 100644 --- a/trunk/include/linux/hardirq.h +++ b/trunk/include/linux/hardirq.h @@ -118,8 +118,10 @@ #ifdef CONFIG_PREEMPT_COUNT # define preemptible() (preempt_count() == 0 && !irqs_disabled()) +# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) #else # define preemptible() 0 +# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET #endif #if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS) diff --git a/trunk/include/linux/netfilter/ipset/ip_set_ahash.h b/trunk/include/linux/netfilter/ipset/ip_set_ahash.h index 01d25e6fc792..ef9acd3c8450 100644 --- a/trunk/include/linux/netfilter/ipset/ip_set_ahash.h +++ b/trunk/include/linux/netfilter/ipset/ip_set_ahash.h @@ -854,8 +854,6 @@ type_pf_tresize(struct ip_set *set, bool retried) retry: ret = 0; htable_bits++; - pr_debug("attempt to resize set %s from %u to %u, t %p\n", - set->name, orig->htable_bits, htable_bits, orig); if (!htable_bits) { /* In case we have plenty of memory :-) */ pr_warning("Cannot increase the hashsize of set %s further\n", @@ -875,7 +873,7 @@ type_pf_tresize(struct ip_set *set, bool retried) data = ahash_tdata(n, j); m = hbucket(t, HKEY(data, h->initval, htable_bits)); ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, - ip_set_timeout_get(type_pf_data_timeout(data))); + type_pf_data_timeout(data)); if (ret < 0) { read_unlock_bh(&set->lock); ahash_destroy(t); diff --git a/trunk/include/linux/smpboot.h b/trunk/include/linux/smpboot.h index 13e929679550..c65dee059913 100644 --- a/trunk/include/linux/smpboot.h +++ b/trunk/include/linux/smpboot.h @@ -24,9 +24,6 @@ struct smpboot_thread_data; * parked (cpu offline) * @unpark: Optional unpark function, called when the thread is * unparked (cpu online) - * @pre_unpark: Optional unpark function, called before the thread is - * unparked (cpu online). This is not guaranteed to be - * called on the target cpu of the thread. Careful! * @selfparking: Thread is not parked by the park function. * @thread_comm: The base name of the thread */ @@ -40,7 +37,6 @@ struct smp_hotplug_thread { void (*cleanup)(unsigned int cpu, bool online); void (*park)(unsigned int cpu); void (*unpark)(unsigned int cpu); - void (*pre_unpark)(unsigned int cpu); bool selfparking; const char *thread_comm; }; diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index cf0694d4ad60..23f2e98d4b65 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -1045,10 +1045,6 @@ static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) if (sysctl_tcp_low_latency || !tp->ucopy.task) return false; - if (skb->len <= tcp_hdrlen(skb) && - skb_queue_len(&tp->ucopy.prequeue) == 0) - return false; - __skb_queue_tail(&tp->ucopy.prequeue, skb); tp->ucopy.memory += skb->truesize; if (tp->ucopy.memory > sk->sk_rcvbuf) { diff --git a/trunk/kernel/smpboot.c b/trunk/kernel/smpboot.c index 25d3d8b6e4e1..b9bde5727829 100644 --- a/trunk/kernel/smpboot.c +++ b/trunk/kernel/smpboot.c @@ -209,8 +209,6 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp { struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); - if (ht->pre_unpark) - ht->pre_unpark(cpu); kthread_unpark(tsk); } diff --git a/trunk/kernel/softirq.c b/trunk/kernel/softirq.c index 14d7758074aa..b4d252fd195b 100644 --- a/trunk/kernel/softirq.c +++ b/trunk/kernel/softirq.c @@ -323,10 +323,18 @@ void irq_enter(void) static inline void invoke_softirq(void) { - if (!force_irqthreads) + if (!force_irqthreads) { +#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED __do_softirq(); - else +#else + do_softirq(); +#endif + } else { + __local_bh_disable((unsigned long)__builtin_return_address(0), + SOFTIRQ_OFFSET); wakeup_softirqd(); + __local_bh_enable(SOFTIRQ_OFFSET); + } } /* @@ -334,15 +342,9 @@ static inline void invoke_softirq(void) */ void irq_exit(void) { -#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED - local_irq_disable(); -#else - WARN_ON_ONCE(!irqs_disabled()); -#endif - account_irq_exit_time(current); trace_hardirq_exit(); - sub_preempt_count(HARDIRQ_OFFSET); + sub_preempt_count(IRQ_EXIT_OFFSET); if (!in_interrupt() && local_softirq_pending()) invoke_softirq(); @@ -352,6 +354,7 @@ void irq_exit(void) tick_nohz_irq_exit(); #endif rcu_irq_exit(); + sched_preempt_enable_no_resched(); } /* diff --git a/trunk/kernel/stop_machine.c b/trunk/kernel/stop_machine.c index c09f2955ae30..95d178c62d5a 100644 --- a/trunk/kernel/stop_machine.c +++ b/trunk/kernel/stop_machine.c @@ -336,7 +336,7 @@ static struct smp_hotplug_thread cpu_stop_threads = { .create = cpu_stop_create, .setup = cpu_stop_unpark, .park = cpu_stop_park, - .pre_unpark = cpu_stop_unpark, + .unpark = cpu_stop_unpark, .selfparking = true, }; diff --git a/trunk/net/caif/caif_dev.c b/trunk/net/caif/caif_dev.c index 21760f008974..1ae1d9cb278d 100644 --- a/trunk/net/caif/caif_dev.c +++ b/trunk/net/caif/caif_dev.c @@ -118,7 +118,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev) return NULL; } -static void caif_flow_cb(struct sk_buff *skb) +void caif_flow_cb(struct sk_buff *skb) { struct caif_device_entry *caifd; void (*dtor)(struct sk_buff *skb) = NULL; diff --git a/trunk/net/caif/caif_usb.c b/trunk/net/caif/caif_usb.c index ef8ebaa993cf..3ebc8cbc91ff 100644 --- a/trunk/net/caif/caif_usb.c +++ b/trunk/net/caif/caif_usb.c @@ -81,8 +81,8 @@ static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, layr->up->ctrlcmd(layr->up, ctrl, layr->id); } -static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], - u8 braddr[ETH_ALEN]) +struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], + u8 braddr[ETH_ALEN]) { struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC); diff --git a/trunk/net/ipv4/ip_input.c b/trunk/net/ipv4/ip_input.c index 2bdf802e28e2..87abd3e2bd32 100644 --- a/trunk/net/ipv4/ip_input.c +++ b/trunk/net/ipv4/ip_input.c @@ -228,11 +228,9 @@ static int ip_local_deliver_finish(struct sk_buff *skb) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); } - kfree_skb(skb); - } else { + } else IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); - consume_skb(skb); - } + kfree_skb(skb); } } out: diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 0d9bdacce99f..a759e19496d2 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -5485,9 +5485,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, if (tcp_checksum_complete_user(sk, skb)) goto csum_error; - if ((int)skb->truesize > sk->sk_forward_alloc) - goto step5; - /* Predicted packet is in window by definition. * seq == rcv_nxt and rcv_wup <= rcv_nxt. * Hence, check seq<=rcv_wup reduces to: @@ -5499,6 +5496,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, tcp_rcv_rtt_measure_ts(sk, skb); + if ((int)skb->truesize > sk->sk_forward_alloc) + goto step5; + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS); /* Bulk data transfer: receiver */ diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index b1876e52091e..5b10414e619e 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -241,11 +241,9 @@ static int ip6_input_finish(struct sk_buff *skb) icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_UNK_NEXTHDR, nhoff); } - kfree_skb(skb); - } else { + } else IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); - consume_skb(skb); - } + kfree_skb(skb); } rcu_read_unlock(); return 0; diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index e5fe0041adfa..928266569689 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -1915,8 +1915,7 @@ void rt6_purge_dflt_routers(struct net *net) restart: read_lock_bh(&table->tb6_lock); for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { - if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && - (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) { + if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); ip6_del_rt(rt); diff --git a/trunk/net/irda/iriap.c b/trunk/net/irda/iriap.c index 29340a9a6fb9..e71e85ba2bf1 100644 --- a/trunk/net/irda/iriap.c +++ b/trunk/net/irda/iriap.c @@ -495,11 +495,8 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self, /* case CS_ISO_8859_9: */ /* case CS_UNICODE: */ default: - IRDA_DEBUG(0, "%s(), charset [%d] %s, not supported\n", - __func__, charset, - charset < ARRAY_SIZE(ias_charset_types) ? - ias_charset_types[charset] : - "(unknown)"); + IRDA_DEBUG(0, "%s(), charset %s, not supported\n", + __func__, ias_charset_types[charset]); /* Aborting, close connection! */ iriap_disconnect_request(self); diff --git a/trunk/net/l2tp/l2tp_ppp.c b/trunk/net/l2tp/l2tp_ppp.c index 6a53371dba1f..3f4e3afc191a 100644 --- a/trunk/net/l2tp/l2tp_ppp.c +++ b/trunk/net/l2tp/l2tp_ppp.c @@ -355,7 +355,6 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh l2tp_xmit_skb(session, skb, session->hdr_len); sock_put(ps->tunnel_sock); - sock_put(sk); return error; diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 808f5fcd1ced..09d96a8f6c2c 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -3285,19 +3285,13 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef) { struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_chanctx_conf *chanctx_conf; int ret = -ENODATA; rcu_read_lock(); - if (local->use_chanctx) { - chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (chanctx_conf) { - *chandef = chanctx_conf->def; - ret = 0; - } - } else if (local->open_count == local->monitors) { - *chandef = local->monitor_chandef; + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); + if (chanctx_conf) { + *chandef = chanctx_conf->def; ret = 0; } rcu_read_unlock(); diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 640afab304d7..2c059e54e885 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) lockdep_assert_held(&local->mtx); - active = !list_empty(&local->chanctx_list) || local->monitors; + active = !list_empty(&local->chanctx_list); if (!local->ops->remain_on_channel) { list_for_each_entry(roc, &local->roc_list, list) { diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index ce78d1149f1d..de8548bf0a7f 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1231,40 +1231,34 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, if (local->queue_stop_reasons[q] || (!txpending && !skb_queue_empty(&local->pending[q]))) { if (unlikely(info->flags & - IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { - if (local->queue_stop_reasons[q] & - ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { - /* - * Drop off-channel frames if queues - * are stopped for any reason other - * than off-channel operation. Never - * queue them. - */ - spin_unlock_irqrestore( - &local->queue_stop_reason_lock, - flags); - ieee80211_purge_tx_queue(&local->hw, - skbs); - return true; - } - } else { - + IEEE80211_TX_INTFL_OFFCHAN_TX_OK && + local->queue_stop_reasons[q] & + ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { /* - * Since queue is stopped, queue up frames for - * later transmission from the tx-pending - * tasklet when the queue is woken again. + * Drop off-channel frames if queues are stopped + * for any reason other than off-channel + * operation. Never queue them. */ - if (txpending) - skb_queue_splice_init(skbs, - &local->pending[q]); - else - skb_queue_splice_tail_init(skbs, - &local->pending[q]); - - spin_unlock_irqrestore(&local->queue_stop_reason_lock, - flags); - return false; + spin_unlock_irqrestore( + &local->queue_stop_reason_lock, flags); + ieee80211_purge_tx_queue(&local->hw, skbs); + return true; } + + /* + * Since queue is stopped, queue up frames for later + * transmission from the tx-pending tasklet when the + * queue is woken again. + */ + if (txpending) + skb_queue_splice_init(skbs, &local->pending[q]); + else + skb_queue_splice_tail_init(skbs, + &local->pending[q]); + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); + return false; } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); @@ -1850,24 +1844,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, } if (!is_multicast_ether_addr(skb->data)) { - struct sta_info *next_hop; - bool mpp_lookup = true; - mpath = mesh_path_lookup(sdata, skb->data); - if (mpath) { - mpp_lookup = false; - next_hop = rcu_dereference(mpath->next_hop); - if (!next_hop || - !(mpath->flags & (MESH_PATH_ACTIVE | - MESH_PATH_RESOLVING))) - mpp_lookup = true; - } - - if (mpp_lookup) + if (!mpath) mppath = mpp_path_lookup(sdata, skb->data); - - if (mppath && mpath) - mesh_path_del(mpath->sdata, mpath->dst); } /* @@ -2371,9 +2350,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, if (local->tim_in_locked_section) { __ieee80211_beacon_add_tim(sdata, ps, skb); } else { - spin_lock_bh(&local->tim_lock); + spin_lock(&local->tim_lock); __ieee80211_beacon_add_tim(sdata, ps, skb); - spin_unlock_bh(&local->tim_lock); + spin_unlock(&local->tim_lock); } return 0; diff --git a/trunk/net/netfilter/ipset/ip_set_core.c b/trunk/net/netfilter/ipset/ip_set_core.c index 1ba9dbc0e107..f82b2e606cfd 100644 --- a/trunk/net/netfilter/ipset/ip_set_core.c +++ b/trunk/net/netfilter/ipset/ip_set_core.c @@ -1470,8 +1470,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb, if (ret == -EAGAIN) ret = 1; - return (ret < 0 && ret != -ENOTEMPTY) ? ret : - ret > 0 ? 0 : -IPSET_ERR_EXIST; + return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST; } /* Get headed data of a set */ diff --git a/trunk/net/rds/message.c b/trunk/net/rds/message.c index aba232f9f308..f0a4658f3273 100644 --- a/trunk/net/rds/message.c +++ b/trunk/net/rds/message.c @@ -82,7 +82,10 @@ static void rds_message_purge(struct rds_message *rm) void rds_message_put(struct rds_message *rm) { rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount)); - WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm); + if (atomic_read(&rm->m_refcount) == 0) { +printk(KERN_CRIT "danger refcount zero on %p\n", rm); +WARN_ON(1); + } if (atomic_dec_and_test(&rm->m_refcount)) { BUG_ON(!list_empty(&rm->m_sock_item)); BUG_ON(!list_empty(&rm->m_conn_item)); @@ -194,9 +197,6 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp) { struct rds_message *rm; - if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message)) - return NULL; - rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp); if (!rm) goto out; diff --git a/trunk/net/sctp/endpointola.c b/trunk/net/sctp/endpointola.c index 12ed45dbe75d..2b3ef03c6098 100644 --- a/trunk/net/sctp/endpointola.c +++ b/trunk/net/sctp/endpointola.c @@ -155,7 +155,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, /* SCTP-AUTH extensions*/ INIT_LIST_HEAD(&ep->endpoint_shared_keys); - null_key = sctp_auth_shkey_create(0, gfp); + null_key = sctp_auth_shkey_create(0, GFP_KERNEL); if (!null_key) goto nomem; diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index b9070736b8d9..c99458df3f3f 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -5653,9 +5653,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, if (len < sizeof(sctp_assoc_t)) return -EINVAL; - /* Allow the struct to grow and fill in as much as possible */ - len = min_t(size_t, len, sizeof(sas)); - if (copy_from_user(&sas, optval, len)) return -EFAULT; @@ -5689,6 +5686,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, /* Mark beginning of a new observation period */ asoc->stats.max_obs_rto = asoc->rto_min; + /* Allow the struct to grow and fill in as much as possible */ + len = min_t(size_t, len, sizeof(sas)); + if (put_user(len, optlen)) return -EFAULT; diff --git a/trunk/net/sctp/ssnmap.c b/trunk/net/sctp/ssnmap.c index 825ea94415b3..442ad4ed6315 100644 --- a/trunk/net/sctp/ssnmap.c +++ b/trunk/net/sctp/ssnmap.c @@ -41,6 +41,8 @@ #include #include +#define MAX_KMALLOC_SIZE 131072 + static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, __u16 out); @@ -63,7 +65,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int size; size = sctp_ssnmap_size(in, out); - if (size <= KMALLOC_MAX_SIZE) + if (size <= MAX_KMALLOC_SIZE) retval = kmalloc(size, gfp); else retval = (struct sctp_ssnmap *) @@ -80,7 +82,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, return retval; fail_map: - if (size <= KMALLOC_MAX_SIZE) + if (size <= MAX_KMALLOC_SIZE) kfree(retval); else free_pages((unsigned long)retval, get_order(size)); @@ -122,7 +124,7 @@ void sctp_ssnmap_free(struct sctp_ssnmap *map) int size; size = sctp_ssnmap_size(map->in.len, map->out.len); - if (size <= KMALLOC_MAX_SIZE) + if (size <= MAX_KMALLOC_SIZE) kfree(map); else free_pages((unsigned long)map, get_order(size)); diff --git a/trunk/net/sctp/tsnmap.c b/trunk/net/sctp/tsnmap.c index 396c45174e5b..5f25e0c92c31 100644 --- a/trunk/net/sctp/tsnmap.c +++ b/trunk/net/sctp/tsnmap.c @@ -51,7 +51,7 @@ static void sctp_tsnmap_update(struct sctp_tsnmap *map); static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off, __u16 len, __u16 *start, __u16 *end); -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size); +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap); /* Initialize a block of memory as a tsnmap. */ struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, @@ -124,7 +124,7 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, gap = tsn - map->base_tsn; - if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1)) + if (gap >= map->len && !sctp_tsnmap_grow(map, gap)) return -ENOMEM; if (!sctp_tsnmap_has_gap(map) && gap == 0) { @@ -360,24 +360,23 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map, return ngaps; } -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size) +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap) { unsigned long *new; unsigned long inc; u16 len; - if (size > SCTP_TSN_MAP_SIZE) + if (gap >= SCTP_TSN_MAP_SIZE) return 0; - inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; + inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE); new = kzalloc(len>>3, GFP_ATOMIC); if (!new) return 0; - bitmap_copy(new, map->tsn_map, - map->max_tsn_seen - map->cumulative_tsn_ack_point); + bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn); kfree(map->tsn_map); map->tsn_map = new; map->len = len; diff --git a/trunk/net/sctp/ulpqueue.c b/trunk/net/sctp/ulpqueue.c index 0fd5b3d2df03..ada17464b65b 100644 --- a/trunk/net/sctp/ulpqueue.c +++ b/trunk/net/sctp/ulpqueue.c @@ -106,7 +106,6 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, { struct sk_buff_head temp; struct sctp_ulpevent *event; - int event_eor = 0; /* Create an event from the incoming chunk. */ event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp); @@ -128,12 +127,10 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, /* Send event to the ULP. 'event' is the sctp_ulpevent for * very first SKB on the 'temp' list. */ - if (event) { - event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0; + if (event) sctp_ulpq_tail_event(ulpq, event); - } - return event_eor; + return 0; } /* Add a new event for propagation to the ULP. */ @@ -543,19 +540,14 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq) ctsn = cevent->tsn; switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { - case SCTP_DATA_FIRST_FRAG: - if (!first_frag) - return NULL; - goto done; case SCTP_DATA_MIDDLE_FRAG: if (!first_frag) { first_frag = pos; next_tsn = ctsn + 1; last_frag = pos; - } else if (next_tsn == ctsn) { + } else if (next_tsn == ctsn) next_tsn++; - last_frag = pos; - } else + else goto done; break; case SCTP_DATA_LAST_FRAG: @@ -659,14 +651,6 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq) } else goto done; break; - - case SCTP_DATA_LAST_FRAG: - if (!first_frag) - return NULL; - else - goto done; - break; - default: return NULL; } @@ -978,43 +962,20 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq, struct sk_buff_head *list, __u16 needed) { __u16 freed = 0; - __u32 tsn, last_tsn; - struct sk_buff *skb, *flist, *last; + __u32 tsn; + struct sk_buff *skb; struct sctp_ulpevent *event; struct sctp_tsnmap *tsnmap; tsnmap = &ulpq->asoc->peer.tsn_map; - while ((skb = skb_peek_tail(list)) != NULL) { + while ((skb = __skb_dequeue_tail(list)) != NULL) { + freed += skb_headlen(skb); event = sctp_skb2event(skb); tsn = event->tsn; - /* Don't renege below the Cumulative TSN ACK Point. */ - if (TSN_lte(tsn, sctp_tsnmap_get_ctsn(tsnmap))) - break; - - /* Events in ordering queue may have multiple fragments - * corresponding to additional TSNs. Sum the total - * freed space; find the last TSN. - */ - freed += skb_headlen(skb); - flist = skb_shinfo(skb)->frag_list; - for (last = flist; flist; flist = flist->next) { - last = flist; - freed += skb_headlen(last); - } - if (last) - last_tsn = sctp_skb2event(last)->tsn; - else - last_tsn = tsn; - - /* Unlink the event, then renege all applicable TSNs. */ - __skb_unlink(skb, list); sctp_ulpevent_free(event); - while (TSN_lte(tsn, last_tsn)) { - sctp_tsnmap_renege(tsnmap, tsn); - tsn++; - } + sctp_tsnmap_renege(tsnmap, tsn); if (freed >= needed) return freed; } @@ -1041,28 +1002,16 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event; struct sctp_association *asoc; struct sctp_sock *sp; - __u32 ctsn; - struct sk_buff *skb; asoc = ulpq->asoc; sp = sctp_sk(asoc->base.sk); /* If the association is already in Partial Delivery mode - * we have nothing to do. + * we have noting to do. */ if (ulpq->pd_mode) return; - /* Data must be at or below the Cumulative TSN ACK Point to - * start partial delivery. - */ - skb = skb_peek(&asoc->ulpq.reasm); - if (skb != NULL) { - ctsn = sctp_skb2event(skb)->tsn; - if (!TSN_lte(ctsn, sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map))) - return; - } - /* If the user enabled fragment interleave socket option, * multiple associations can enter partial delivery. * Otherwise, we can only enter partial delivery if the @@ -1105,16 +1054,12 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, } /* If able to free enough room, accept this chunk. */ if (chunk && (freed >= needed)) { - int retval; - retval = sctp_ulpq_tail_data(ulpq, chunk, gfp); - /* - * Enter partial delivery if chunk has not been - * delivered; otherwise, drain the reassembly queue. - */ - if (retval <= 0) - sctp_ulpq_partial_delivery(ulpq, gfp); - else if (retval == 1) - sctp_ulpq_reasm_drain(ulpq); + __u32 tsn; + tsn = ntohl(chunk->subh.data_hdr->tsn); + sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport); + sctp_ulpq_tail_data(ulpq, chunk, gfp); + + sctp_ulpq_partial_delivery(ulpq, gfp); } sk_mem_reclaim(asoc->base.sk); diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index e652d05ff712..35545ccc30fd 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -554,9 +554,16 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_RADAR) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) - goto nla_put_failure; + if (chan->flags & IEEE80211_CHAN_RADAR) { + u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered); + if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) + goto nla_put_failure; + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, + chan->dfs_state)) + goto nla_put_failure; + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time)) + goto nla_put_failure; + } if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) goto nla_put_failure; @@ -893,6 +900,9 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, c->max_interfaces)) goto nla_put_failure; + if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + c->radar_detect_widths)) + goto nla_put_failure; nla_nest_end(msg, nl_combi); } @@ -904,6 +914,48 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, return -ENOBUFS; } +#ifdef CONFIG_PM +static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, + struct sk_buff *msg) +{ + const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; + struct nlattr *nl_tcp; + + if (!tcp) + return 0; + + nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION); + if (!nl_tcp) + return -ENOBUFS; + + if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, + tcp->data_payload_max)) + return -ENOBUFS; + + if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, + tcp->data_payload_max)) + return -ENOBUFS; + + if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ)) + return -ENOBUFS; + + if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, + sizeof(*tcp->tok), tcp->tok)) + return -ENOBUFS; + + if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL, + tcp->data_interval_max)) + return -ENOBUFS; + + if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD, + tcp->wake_payload_max)) + return -ENOBUFS; + + nla_nest_end(msg, nl_tcp); + return 0; +} +#endif + static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, struct cfg80211_registered_device *dev) { @@ -1278,6 +1330,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag goto nla_put_failure; } + if (nl80211_send_wowlan_tcp_caps(dev, msg)) + goto nla_put_failure; + nla_nest_end(msg, nl_wowlan); } #endif