From: Greg Kroah-Hartman Date: Thu, 20 Feb 2014 22:13:14 +0000 (-0800) Subject: 3.12-stable patches X-Git-Tag: v3.4.82~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d914b886c384080b43586603f0ecd543852dc76c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.12-stable patches added patches: hwmon-ntc_thermistor-avoid-math-overflow.patch lockd-send-correct-lock-when-granting-a-delayed-lock.patch of-fix-pci-bus-match-for-pcie-slots.patch raw-test-against-runtime-value-of-max_raw_minors.patch serial-sirf-fix-kernel-panic-caused-by-unpaired-spinlock.patch spi-nuc900-set-spi_lsb_first-for-master-mode_bits-if-hw-pdata-lsb-is-true.patch tty-n_gsm-fix-for-modems-with-brk-in-modem-status-control.patch tty-set-correct-tty-name-in-active-sysfs-attribute.patch --- diff --git a/queue-3.12/hwmon-ntc_thermistor-avoid-math-overflow.patch b/queue-3.12/hwmon-ntc_thermistor-avoid-math-overflow.patch new file mode 100644 index 00000000000..76ad44434b1 --- /dev/null +++ b/queue-3.12/hwmon-ntc_thermistor-avoid-math-overflow.patch @@ -0,0 +1,49 @@ +From d3d89c468ceebbcf9423d1a3d66c5bf91f569570 Mon Sep 17 00:00:00 2001 +From: Doug Anderson +Date: Thu, 13 Feb 2014 14:39:34 -0800 +Subject: hwmon: (ntc_thermistor) Avoid math overflow + +From: Doug Anderson + +commit d3d89c468ceebbcf9423d1a3d66c5bf91f569570 upstream. + +The ntc thermistor code was doing math whose temporary result might +have overflowed 32-bits. We need some casts in there to make it safe. + +In one example I found: +- pullup_uV: 1800000 +- result of iio_read_channel_raw: 3226 +- 1800000 * 3226 => 0x15a1cbc80 + +Signed-off-by: Doug Anderson +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/ntc_thermistor.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/hwmon/ntc_thermistor.c ++++ b/drivers/hwmon/ntc_thermistor.c +@@ -145,7 +145,7 @@ struct ntc_data { + static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata) + { + struct iio_channel *channel = pdata->chan; +- unsigned int result; ++ s64 result; + int val, ret; + + ret = iio_read_channel_raw(channel, &val); +@@ -155,10 +155,10 @@ static int ntc_adc_iio_read(struct ntc_t + } + + /* unit: mV */ +- result = pdata->pullup_uv * val; ++ result = pdata->pullup_uv * (s64) val; + result >>= 12; + +- return result; ++ return (int)result; + } + + static const struct of_device_id ntc_match[] = { diff --git a/queue-3.12/lockd-send-correct-lock-when-granting-a-delayed-lock.patch b/queue-3.12/lockd-send-correct-lock-when-granting-a-delayed-lock.patch new file mode 100644 index 00000000000..27dc2cfff5f --- /dev/null +++ b/queue-3.12/lockd-send-correct-lock-when-granting-a-delayed-lock.patch @@ -0,0 +1,70 @@ +From 2ec197db1a56c9269d75e965f14c344b58b2a4f6 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 7 Feb 2014 17:10:26 +1100 +Subject: lockd: send correct lock when granting a delayed lock. + +From: NeilBrown + +commit 2ec197db1a56c9269d75e965f14c344b58b2a4f6 upstream. + +If an NFS client attempts to get a lock (using NLM) and the lock is +not available, the server will remember the request and when the lock +becomes available it will send a GRANT request to the client to +provide the lock. + +If the client already held an adjacent lock, the GRANT callback will +report the union of the existing and new locks, which can confuse the +client. + +This happens because __posix_lock_file (called by vfs_lock_file) +updates the passed-in file_lock structure when adjacent or +over-lapping locks are found. + +To avoid this problem we take a copy of the two fields that can +be changed (fl_start and fl_end) before the call and restore them +afterwards. +An alternate would be to allocate a 'struct file_lock', initialise it, +use locks_copy_lock() to take a copy, then locks_release_private() +after the vfs_lock_file() call. But that is a lot more work. + +Reported-by: Olaf Kirch +Signed-off-by: NeilBrown +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +-- +v1 had a couple of issues (large on-stack struct and didn't really work properly). +This version is much better tested. +Signed-off-by: J. Bruce Fields + +--- + fs/lockd/svclock.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/lockd/svclock.c ++++ b/fs/lockd/svclock.c +@@ -779,6 +779,7 @@ nlmsvc_grant_blocked(struct nlm_block *b + struct nlm_file *file = block->b_file; + struct nlm_lock *lock = &block->b_call->a_args.lock; + int error; ++ loff_t fl_start, fl_end; + + dprintk("lockd: grant blocked lock %p\n", block); + +@@ -796,9 +797,16 @@ nlmsvc_grant_blocked(struct nlm_block *b + } + + /* Try the lock operation again */ ++ /* vfs_lock_file() can mangle fl_start and fl_end, but we need ++ * them unchanged for the GRANT_MSG ++ */ + lock->fl.fl_flags |= FL_SLEEP; ++ fl_start = lock->fl.fl_start; ++ fl_end = lock->fl.fl_end; + error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); + lock->fl.fl_flags &= ~FL_SLEEP; ++ lock->fl.fl_start = fl_start; ++ lock->fl.fl_end = fl_end; + + switch (error) { + case 0: diff --git a/queue-3.12/of-fix-pci-bus-match-for-pcie-slots.patch b/queue-3.12/of-fix-pci-bus-match-for-pcie-slots.patch new file mode 100644 index 00000000000..baf9014d07c --- /dev/null +++ b/queue-3.12/of-fix-pci-bus-match-for-pcie-slots.patch @@ -0,0 +1,45 @@ +From 14e2abb732e485ee57d9d5b2cb8884652238e5c1 Mon Sep 17 00:00:00 2001 +From: Kleber Sacilotto de Souza +Date: Mon, 3 Feb 2014 13:31:03 -0200 +Subject: of: fix PCI bus match for PCIe slots + +From: Kleber Sacilotto de Souza + +commit 14e2abb732e485ee57d9d5b2cb8884652238e5c1 upstream. + +On IBM pseries systems the device_type device-tree property of a PCIe +bridge contains the string "pciex". The of_bus_pci_match() function was +looking only for "pci" on this property, so in such cases the bus +matching code was falling back to the default bus, causing problems on +functions that should be using "assigned-addresses" for region address +translation. This patch fixes the problem by also looking for "pciex" on +the PCI bus match function. + +v2: added comment + +Signed-off-by: Kleber Sacilotto de Souza +Acked-by: Grant Likely +Signed-off-by: Rob Herring +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/of/address.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -99,11 +99,12 @@ static unsigned int of_bus_default_get_f + static int of_bus_pci_match(struct device_node *np) + { + /* ++ * "pciex" is PCI Express + * "vci" is for the /chaos bridge on 1st-gen PCI powermacs + * "ht" is hypertransport + */ +- return !strcmp(np->type, "pci") || !strcmp(np->type, "vci") || +- !strcmp(np->type, "ht"); ++ return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") || ++ !strcmp(np->type, "vci") || !strcmp(np->type, "ht"); + } + + static void of_bus_pci_count_cells(struct device_node *np, diff --git a/queue-3.12/raw-test-against-runtime-value-of-max_raw_minors.patch b/queue-3.12/raw-test-against-runtime-value-of-max_raw_minors.patch new file mode 100644 index 00000000000..0e8828ea536 --- /dev/null +++ b/queue-3.12/raw-test-against-runtime-value-of-max_raw_minors.patch @@ -0,0 +1,37 @@ +From 5bbb2ae3d6f896f8d2082d1eceb6131c2420b7cf Mon Sep 17 00:00:00 2001 +From: Paul Bolle +Date: Tue, 4 Feb 2014 23:23:12 +0100 +Subject: raw: test against runtime value of max_raw_minors + +From: Paul Bolle + +commit 5bbb2ae3d6f896f8d2082d1eceb6131c2420b7cf upstream. + +bind_get() checks the device number it is called with. It uses +MAX_RAW_MINORS for the upper bound. But MAX_RAW_MINORS is set at compile +time while the actual number of raw devices can be set at runtime. This +means the test can either be too strict or too lenient. And if the test +ends up being too lenient bind_get() might try to access memory beyond +what was allocated for "raw_devices". + +So check against the runtime value (max_raw_minors) in this function. + +Signed-off-by: Paul Bolle +Acked-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/char/raw.c ++++ b/drivers/char/raw.c +@@ -190,7 +190,7 @@ static int bind_get(int number, dev_t *d + struct raw_device_data *rawdev; + struct block_device *bdev; + +- if (number <= 0 || number >= MAX_RAW_MINORS) ++ if (number <= 0 || number >= max_raw_minors) + return -EINVAL; + + rawdev = &raw_devices[number]; diff --git a/queue-3.12/serial-sirf-fix-kernel-panic-caused-by-unpaired-spinlock.patch b/queue-3.12/serial-sirf-fix-kernel-panic-caused-by-unpaired-spinlock.patch new file mode 100644 index 00000000000..1cfde1c8bfa --- /dev/null +++ b/queue-3.12/serial-sirf-fix-kernel-panic-caused-by-unpaired-spinlock.patch @@ -0,0 +1,90 @@ +From fb78b811422cd2d8c8605949cc4cc13618347ad5 Mon Sep 17 00:00:00 2001 +From: Qipan Li +Date: Mon, 27 Jan 2014 14:23:39 +0800 +Subject: serial: sirf: fix kernel panic caused by unpaired spinlock + +From: Qipan Li + +commit fb78b811422cd2d8c8605949cc4cc13618347ad5 upstream. + +commit 8b9ade9f74f8a279 coming from Viresh Kumar "tty: serial: sirfsoc: drop +uart_port->lock before calling tty_flip_buffer_push()" broke sirfsoc uart +driver by knic: + + [ 5.129122] BUG: spinlock already unlocked on CPU#0, ip6tables/1331 + [ 5.132554] lock: sirfsoc_uart_ports+0x4/0x8a0, .magic: dead4ead, + .owner: /-1, .owner_cpu: -1 + [ 5.141651] CPU: 0 PID: 1331 Comm: ip6tables Tainted: G + W O 3.10.16 #3 + [ 5.148866] [] (unwind_backtrace+0x0/0xe0) from + [] (show_stack+0x10/0x14) + [ 5.157362] [] (show_stack+0x10/0x14) from + [] (do_raw_spin_unlock+0x40/0xc8) + [ 5.166125] [] (do_raw_spin_unlock+0x40/0xc8) from + [] (_raw_spin_unlock+0x8/0x40) + [ 5.175322] [] (_raw_spin_unlock+0x8/0x40) from + [] (sirfsoc_uart_pio_rx_chars+0xa4/0xc0) + [ 5.185120] [] + (sirfsoc_uart_pio_rx_chars+0xa4/0xc0) from [] + (sirfsoc_rx_tmo_process_tl+0xdc/0x1e0) + [ 5.195875] [] + (sirfsoc_rx_tmo_process_tl+0xdc/0x1e0) from [] + (tasklet_action+0x8c/0xec) + [ 5.205673] [] (tasklet_action+0x8c/0xec) from + [] (__do_softirq+0xec/0x1d4) + [ 5.214347] [] (__do_softirq+0xec/0x1d4) from + [] (do_softirq+0x48/0x54) + [ 5.222674] [] (do_softirq+0x48/0x54) from + [] (irq_exit+0x74/0xc0) + [ 5.230573] [] (irq_exit+0x74/0xc0) from + [] (handle_IRQ+0x6c/0x90) + [ 5.238465] [] (handle_IRQ+0x6c/0x90) from + [] (__irq_svc+0x40/0x70) + [ 5.246446] [] (__irq_svc+0x40/0x70) from + [] (mark_page_accessed+0xc/0x68) + [ 5.255034] [] (mark_page_accessed+0xc/0x68) from + [] (unmap_single_vma+0x3bc/0x550) + [ 5.264402] [] (unmap_single_vma+0x3bc/0x550) from + [] (unmap_vmas+0x44/0x54) + [ 5.273164] [] (unmap_vmas+0x44/0x54) from + [] (exit_mmap+0xc4/0x1e0) + [ 5.281233] [] (exit_mmap+0xc4/0x1e0) from + [] (mmput+0x3c/0xdc) + [ 5.288868] [] (mmput+0x3c/0xdc) from [] + (do_exit+0x30c/0x828) + [ 5.296413] [] (do_exit+0x30c/0x828) from + [] (do_group_exit+0x4c/0xb0) + [ 5.304653] [] (do_group_exit+0x4c/0xb0) from + [] (__wake_up_parent+0x0/0x18) + +Root cause: +the commit dropped uart_port->lock before calling tty_flip_buffer_push(), but in sirfsoc-uart, +sirfsoc_uart_pio_rx_chars() can be called by sirfsoc_rx_tmo_process_tl(). here uart_port->lock +has not been taken yet. so that caused unpaired lock/unlock. + +Solution: +This patch is doing a quick fix for that, it adds spin_lock/unlock(&port->lock) protect to +sirfsoc_uart_pio_rx_chars() in sirfsoc_rx_tmo_process_tl() to keep spin_lock/unlock in pair. + +Signed-off-by: Qipan Li +Signed-off-by: Barry Song +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/sirfsoc_uart.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/tty/serial/sirfsoc_uart.c ++++ b/drivers/tty/serial/sirfsoc_uart.c +@@ -540,8 +540,10 @@ static void sirfsoc_rx_tmo_process_tl(un + wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, + rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | + SIRFUART_IO_MODE); +- sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); + spin_unlock_irqrestore(&sirfport->rx_lock, flags); ++ spin_lock(&port->lock); ++ sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); ++ spin_unlock(&port->lock); + if (sirfport->rx_io_count == 4) { + spin_lock_irqsave(&sirfport->rx_lock, flags); + sirfport->rx_io_count = 0; diff --git a/queue-3.12/series b/queue-3.12/series index 24c6fab8763..37a4a6f3da9 100644 --- a/queue-3.12/series +++ b/queue-3.12/series @@ -20,3 +20,11 @@ spi-fix-crash-with-double-message-finalisation-on-error-handling.patch iwlwifi-mvm-don-t-allow-a-band-if-sku-forbids-it.patch iwlwifi-mvm-print-the-version-of-the-firmware-when-it-asserts.patch iwlwifi-mvm-bt-coex-disable-bt-when-txing-probe-request-in-scan.patch +of-fix-pci-bus-match-for-pcie-slots.patch +spi-nuc900-set-spi_lsb_first-for-master-mode_bits-if-hw-pdata-lsb-is-true.patch +serial-sirf-fix-kernel-panic-caused-by-unpaired-spinlock.patch +raw-test-against-runtime-value-of-max_raw_minors.patch +hwmon-ntc_thermistor-avoid-math-overflow.patch +lockd-send-correct-lock-when-granting-a-delayed-lock.patch +tty-n_gsm-fix-for-modems-with-brk-in-modem-status-control.patch +tty-set-correct-tty-name-in-active-sysfs-attribute.patch diff --git a/queue-3.12/spi-nuc900-set-spi_lsb_first-for-master-mode_bits-if-hw-pdata-lsb-is-true.patch b/queue-3.12/spi-nuc900-set-spi_lsb_first-for-master-mode_bits-if-hw-pdata-lsb-is-true.patch new file mode 100644 index 00000000000..431af485808 --- /dev/null +++ b/queue-3.12/spi-nuc900-set-spi_lsb_first-for-master-mode_bits-if-hw-pdata-lsb-is-true.patch @@ -0,0 +1,30 @@ +From f7db1588d6028c97c098bb6445eaabc56a25fed8 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Mon, 20 Jan 2014 23:22:07 +0800 +Subject: spi: nuc900: Set SPI_LSB_FIRST for master->mode_bits if hw->pdata->lsb is true + +From: Axel Lin + +commit f7db1588d6028c97c098bb6445eaabc56a25fed8 upstream. + +Otherwise, spi_setup() fails with unsupported mode bits message. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/spi/spi-nuc900.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/spi/spi-nuc900.c ++++ b/drivers/spi/spi-nuc900.c +@@ -363,6 +363,8 @@ static int nuc900_spi_probe(struct platf + init_completion(&hw->done); + + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; ++ if (hw->pdata->lsb) ++ master->mode_bits |= SPI_LSB_FIRST; + master->num_chipselect = hw->pdata->num_cs; + master->bus_num = hw->pdata->bus_num; + hw->bitbang.master = hw->master; diff --git a/queue-3.12/tty-n_gsm-fix-for-modems-with-brk-in-modem-status-control.patch b/queue-3.12/tty-n_gsm-fix-for-modems-with-brk-in-modem-status-control.patch new file mode 100644 index 00000000000..273a40aa821 --- /dev/null +++ b/queue-3.12/tty-n_gsm-fix-for-modems-with-brk-in-modem-status-control.patch @@ -0,0 +1,59 @@ +From 3ac06b905655b3ef2fd2196bab36e4587e1e4e4f Mon Sep 17 00:00:00 2001 +From: Lars Poeschel +Date: Tue, 7 Jan 2014 13:34:37 +0100 +Subject: tty: n_gsm: Fix for modems with brk in modem status control + +From: Lars Poeschel + +commit 3ac06b905655b3ef2fd2196bab36e4587e1e4e4f upstream. + +3GPP TS 07.10 states in section 5.4.6.3.7: +"The length byte contains the value 2 or 3 ... depending on the break +signal." The break byte is optional and if it is sent, the length is +3. In fact the driver was not able to work with modems that send this +break byte in their modem status control message. If the modem just +sends the break byte if it is really set, then weird things might +happen. +The code for deconding the modem status to the internal linux +presentation in gsm_process_modem has already a big comment about +this 2 or 3 byte length thing and it is already able to decode the +brk, but the code calling the gsm_process_modem function in +gsm_control_modem does not encode it and hand it over the right way. +This patch fixes this. +Without this fix if the modem sends the brk byte in it's modem status +control message the driver will hang when opening a muxed channel. + +Signed-off-by: Lars Poeschel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/n_gsm.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -1089,6 +1089,7 @@ static void gsm_control_modem(struct gsm + { + unsigned int addr = 0; + unsigned int modem = 0; ++ unsigned int brk = 0; + struct gsm_dlci *dlci; + int len = clen; + u8 *dp = data; +@@ -1115,6 +1116,16 @@ static void gsm_control_modem(struct gsm + if (len == 0) + return; + } ++ len--; ++ if (len > 0) { ++ while (gsm_read_ea(&brk, *dp++) == 0) { ++ len--; ++ if (len == 0) ++ return; ++ } ++ modem <<= 7; ++ modem |= (brk & 0x7f); ++ } + tty = tty_port_tty_get(&dlci->port); + gsm_process_modem(tty, dlci, modem, clen); + if (tty) { diff --git a/queue-3.12/tty-set-correct-tty-name-in-active-sysfs-attribute.patch b/queue-3.12/tty-set-correct-tty-name-in-active-sysfs-attribute.patch new file mode 100644 index 00000000000..54582fa8b48 --- /dev/null +++ b/queue-3.12/tty-set-correct-tty-name-in-active-sysfs-attribute.patch @@ -0,0 +1,91 @@ +From d8a5dc3033af2fd6d16030d2ee4fbd073460fe54 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 7 Feb 2014 11:38:30 +0100 +Subject: tty: Set correct tty name in 'active' sysfs attribute + +From: Hannes Reinecke + +commit d8a5dc3033af2fd6d16030d2ee4fbd073460fe54 upstream. + +The 'active' sysfs attribute should refer to the currently active tty +devices the console is running on, not the currently active console. + +The console structure doesn't refer to any device in sysfs, only the tty +the console is running on has. So we need to print out the tty names in +'active', not the console names. + +This resolves an issue on s390 platforms in determining the correct +console device to use. + +Cc: Lennart Poettering +Cc: Kay Sievers +Cc: Jiri Slaby +Cc: David Herrmann +Signed-off-by: Werner Fink +Signed-off-by: Hannes Reinecke +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/ABI/testing/sysfs-tty | 3 ++- + drivers/tty/tty_io.c | 25 ++++++++++++++++++------- + 2 files changed, 20 insertions(+), 8 deletions(-) + +--- a/Documentation/ABI/testing/sysfs-tty ++++ b/Documentation/ABI/testing/sysfs-tty +@@ -3,7 +3,8 @@ Date: Nov 2010 + Contact: Kay Sievers + Description: + Shows the list of currently configured +- console devices, like 'tty1 ttyS0'. ++ tty devices used for the console, ++ like 'tty1 ttyS0'. + The last entry in the file is the active + device connected to /dev/console. + The file supports poll() to detect virtual +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -1267,16 +1267,17 @@ static void pty_line_name(struct tty_dri + * @p: output buffer of at least 7 bytes + * + * Generate a name from a driver reference and write it to the output +- * buffer. ++ * buffer. Return the number of bytes written. + * + * Locking: None + */ +-static void tty_line_name(struct tty_driver *driver, int index, char *p) ++static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) + { + if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) +- strcpy(p, driver->name); ++ return sprintf(p, "%s", driver->name); + else +- sprintf(p, "%s%d", driver->name, index + driver->name_base); ++ return sprintf(p, "%s%d", driver->name, ++ index + driver->name_base); + } + + /** +@@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct d + if (i >= ARRAY_SIZE(cs)) + break; + } +- while (i--) +- count += sprintf(buf + count, "%s%d%c", +- cs[i]->name, cs[i]->index, i ? ' ':'\n'); ++ while (i--) { ++ struct tty_driver *driver; ++ const char *name = cs[i]->name; ++ int index = cs[i]->index; ++ ++ driver = cs[i]->device(cs[i], &index); ++ if (driver) { ++ count += tty_line_name(driver, index, buf + count); ++ count += sprintf(buf + count, "%c", i ? ' ':'\n'); ++ } else ++ count += sprintf(buf + count, "%s%d%c", ++ name, index, i ? ' ':'\n'); ++ } + console_unlock(); + + return count;