Commit 87135d92 authored by Ingo Molnar's avatar Ingo Molnar

Merge commit 'v2.6.28-rc4' into x86/cleanups

parents 4fcc50ab f7160c75
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 28 SUBLEVEL = 28
EXTRAVERSION = -rc3 EXTRAVERSION = -rc4
NAME = Killer Bat of Doom NAME = Killer Bat of Doom
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -65,12 +65,14 @@ static void cpuidle_idle_call(void) ...@@ -65,12 +65,14 @@ static void cpuidle_idle_call(void)
return; return;
} }
#if 0
/* shows regressions, re-enable for 2.6.29 */
/* /*
* run any timers that can be run now, at this point * run any timers that can be run now, at this point
* before calculating the idle duration etc. * before calculating the idle duration etc.
*/ */
hrtimer_peek_ahead_timers(); hrtimer_peek_ahead_timers();
#endif
/* ask the governor for the next state */ /* ask the governor for the next state */
next_state = cpuidle_curr_governor->select(dev); next_state = cpuidle_curr_governor->select(dev);
if (need_resched()) if (need_resched())
......
...@@ -216,8 +216,7 @@ int mmc_add_card(struct mmc_card *card) ...@@ -216,8 +216,7 @@ int mmc_add_card(struct mmc_card *card)
int ret; int ret;
const char *type; const char *type;
snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
"%s:%04x", mmc_hostname(card->host), card->rca);
switch (card->type) { switch (card->type) {
case MMC_TYPE_MMC: case MMC_TYPE_MMC:
......
...@@ -280,7 +280,11 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) ...@@ -280,7 +280,11 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
(card->host->ios.clock / 1000); (card->host->ios.clock / 1000);
if (data->flags & MMC_DATA_WRITE) if (data->flags & MMC_DATA_WRITE)
limit_us = 250000; /*
* The limit is really 250 ms, but that is
* insufficient for some crappy cards.
*/
limit_us = 300000;
else else
limit_us = 100000; limit_us = 100000;
......
...@@ -73,8 +73,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -73,8 +73,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
if (err) if (err)
goto free; goto free;
snprintf(host->class_dev.bus_id, BUS_ID_SIZE, dev_set_name(&host->class_dev, "mmc%d", host->index);
"mmc%d", host->index);
host->parent = dev; host->parent = dev;
host->class_dev.parent = dev; host->class_dev.parent = dev;
...@@ -121,7 +120,7 @@ int mmc_add_host(struct mmc_host *host) ...@@ -121,7 +120,7 @@ int mmc_add_host(struct mmc_host *host)
WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
!host->ops->enable_sdio_irq); !host->ops->enable_sdio_irq);
led_trigger_register_simple(host->class_dev.bus_id, &host->led); led_trigger_register_simple(dev_name(&host->class_dev), &host->led);
err = device_add(&host->class_dev); err = device_add(&host->class_dev);
if (err) if (err)
......
...@@ -239,8 +239,7 @@ int sdio_add_func(struct sdio_func *func) ...@@ -239,8 +239,7 @@ int sdio_add_func(struct sdio_func *func)
{ {
int ret; int ret;
snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
"%s:%d", mmc_card_id(func->card), func->num);
ret = device_add(&func->dev); ret = device_add(&func->dev);
if (ret == 0) if (ret == 0)
......
...@@ -1348,7 +1348,7 @@ static int mmc_spi_probe(struct spi_device *spi) ...@@ -1348,7 +1348,7 @@ static int mmc_spi_probe(struct spi_device *spi)
goto fail_add_host; goto fail_add_host;
dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
mmc->class_dev.bus_id, dev_name(&mmc->class_dev),
host->dma_dev ? "" : ", no DMA", host->dma_dev ? "" : ", no DMA",
(host->pdata && host->pdata->get_ro) (host->pdata && host->pdata->get_ro)
? "" : ", no WP", ? "" : ", no WP",
......
...@@ -1733,7 +1733,7 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -1733,7 +1733,7 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_add_host(mmc); mmc_add_host(mmc);
printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n", printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n",
mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->bus_id, mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
(host->flags & SDHCI_USE_ADMA)?"A":"", (host->flags & SDHCI_USE_ADMA)?"A":"",
(host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
......
...@@ -632,7 +632,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -632,7 +632,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
if (host->req) { if (host->req) {
printk(KERN_ERR "%s : unfinished request detected\n", printk(KERN_ERR "%s : unfinished request detected\n",
sock->dev.bus_id); dev_name(&sock->dev));
mrq->cmd->error = -ETIMEDOUT; mrq->cmd->error = -ETIMEDOUT;
goto err_out; goto err_out;
} }
...@@ -672,7 +672,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -672,7 +672,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
? PCI_DMA_TODEVICE ? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE)) { : PCI_DMA_FROMDEVICE)) {
printk(KERN_ERR "%s : scatterlist map failed\n", printk(KERN_ERR "%s : scatterlist map failed\n",
sock->dev.bus_id); dev_name(&sock->dev));
mrq->cmd->error = -ENOMEM; mrq->cmd->error = -ENOMEM;
goto err_out; goto err_out;
} }
...@@ -684,7 +684,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -684,7 +684,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
: PCI_DMA_FROMDEVICE); : PCI_DMA_FROMDEVICE);
if (host->sg_len < 1) { if (host->sg_len < 1) {
printk(KERN_ERR "%s : scatterlist map failed\n", printk(KERN_ERR "%s : scatterlist map failed\n",
sock->dev.bus_id); dev_name(&sock->dev));
tifm_unmap_sg(sock, &host->bounce_buf, 1, tifm_unmap_sg(sock, &host->bounce_buf, 1,
r_data->flags & MMC_DATA_WRITE r_data->flags & MMC_DATA_WRITE
? PCI_DMA_TODEVICE ? PCI_DMA_TODEVICE
...@@ -748,7 +748,7 @@ static void tifm_sd_end_cmd(unsigned long data) ...@@ -748,7 +748,7 @@ static void tifm_sd_end_cmd(unsigned long data)
if (!mrq) { if (!mrq) {
printk(KERN_ERR " %s : no request to complete?\n", printk(KERN_ERR " %s : no request to complete?\n",
sock->dev.bus_id); dev_name(&sock->dev));
spin_unlock_irqrestore(&sock->lock, flags); spin_unlock_irqrestore(&sock->lock, flags);
return; return;
} }
...@@ -789,7 +789,7 @@ static void tifm_sd_abort(unsigned long data) ...@@ -789,7 +789,7 @@ static void tifm_sd_abort(unsigned long data)
printk(KERN_ERR printk(KERN_ERR
"%s : card failed to respond for a long period of time " "%s : card failed to respond for a long period of time "
"(%x, %x)\n", "(%x, %x)\n",
host->dev->dev.bus_id, host->req->cmd->opcode, host->cmd_flags); dev_name(&host->dev->dev), host->req->cmd->opcode, host->cmd_flags);
tifm_eject(host->dev); tifm_eject(host->dev);
} }
...@@ -906,7 +906,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host) ...@@ -906,7 +906,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host)
if (rc) { if (rc) {
printk(KERN_ERR "%s : controller failed to reset\n", printk(KERN_ERR "%s : controller failed to reset\n",
sock->dev.bus_id); dev_name(&sock->dev));
return -ENODEV; return -ENODEV;
} }
...@@ -933,7 +933,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host) ...@@ -933,7 +933,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host)
if (rc) { if (rc) {
printk(KERN_ERR printk(KERN_ERR
"%s : card not ready - probe failed on initialization\n", "%s : card not ready - probe failed on initialization\n",
sock->dev.bus_id); dev_name(&sock->dev));
return -ENODEV; return -ENODEV;
} }
...@@ -954,7 +954,7 @@ static int tifm_sd_probe(struct tifm_dev *sock) ...@@ -954,7 +954,7 @@ static int tifm_sd_probe(struct tifm_dev *sock)
if (!(TIFM_SOCK_STATE_OCCUPIED if (!(TIFM_SOCK_STATE_OCCUPIED
& readl(sock->addr + SOCK_PRESENT_STATE))) { & readl(sock->addr + SOCK_PRESENT_STATE))) {
printk(KERN_WARNING "%s : card gone, unexpectedly\n", printk(KERN_WARNING "%s : card gone, unexpectedly\n",
sock->dev.bus_id); dev_name(&sock->dev));
return rc; return rc;
} }
......
menu "Voltage and Current regulators" menuconfig REGULATOR
config REGULATOR
bool "Voltage and Current Regulator Support" bool "Voltage and Current Regulator Support"
default n default n
help help
...@@ -23,21 +21,20 @@ config REGULATOR ...@@ -23,21 +21,20 @@ config REGULATOR
If unsure, say no. If unsure, say no.
if REGULATOR
config REGULATOR_DEBUG config REGULATOR_DEBUG
bool "Regulator debug support" bool "Regulator debug support"
depends on REGULATOR
help help
Say yes here to enable debugging support. Say yes here to enable debugging support.
config REGULATOR_FIXED_VOLTAGE config REGULATOR_FIXED_VOLTAGE
tristate tristate
default n default n
select REGULATOR
config REGULATOR_VIRTUAL_CONSUMER config REGULATOR_VIRTUAL_CONSUMER
tristate "Virtual regulator consumer support" tristate "Virtual regulator consumer support"
default n default n
select REGULATOR
help help
This driver provides a virtual consumer for the voltage and This driver provides a virtual consumer for the voltage and
current regulator API which provides sysfs controls for current regulator API which provides sysfs controls for
...@@ -49,7 +46,6 @@ config REGULATOR_VIRTUAL_CONSUMER ...@@ -49,7 +46,6 @@ config REGULATOR_VIRTUAL_CONSUMER
config REGULATOR_BQ24022 config REGULATOR_BQ24022
tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC"
default n default n
select REGULATOR
help help
This driver controls a TI bq24022 Charger attached via This driver controls a TI bq24022 Charger attached via
GPIOs. The provided current regulator can enable/disable GPIOs. The provided current regulator can enable/disable
...@@ -59,7 +55,6 @@ config REGULATOR_BQ24022 ...@@ -59,7 +55,6 @@ config REGULATOR_BQ24022
config REGULATOR_WM8350 config REGULATOR_WM8350
tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC" tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
depends on MFD_WM8350 depends on MFD_WM8350
select REGULATOR
help help
This driver provides support for the voltage and current regulators This driver provides support for the voltage and current regulators
of the WM8350 AudioPlus PMIC. of the WM8350 AudioPlus PMIC.
...@@ -67,7 +62,6 @@ config REGULATOR_WM8350 ...@@ -67,7 +62,6 @@ config REGULATOR_WM8350
config REGULATOR_WM8400 config REGULATOR_WM8400
tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC" tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC"
depends on MFD_WM8400 depends on MFD_WM8400
select REGULATOR
help help
This driver provides support for the voltage regulators of the This driver provides support for the voltage regulators of the
WM8400 AudioPlus PMIC. WM8400 AudioPlus PMIC.
...@@ -75,9 +69,8 @@ config REGULATOR_WM8400 ...@@ -75,9 +69,8 @@ config REGULATOR_WM8400
config REGULATOR_DA903X config REGULATOR_DA903X
tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC" tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
depends on PMIC_DA903X depends on PMIC_DA903X
select REGULATOR
help help
Say y here to support the BUCKs and LDOs regulators found on Say y here to support the BUCKs and LDOs regulators found on
Dialog Semiconductor DA9030/DA9034 PMIC. Dialog Semiconductor DA9030/DA9034 PMIC.
endmenu endif
...@@ -23,7 +23,7 @@ menuconfig STAGING ...@@ -23,7 +23,7 @@ menuconfig STAGING
config STAGING_EXCLUDE_BUILD config STAGING_EXCLUDE_BUILD
bool "Exclude Staging drivers from being built" bool "Exclude Staging drivers from being built" if STAGING
default y default y
---help--- ---help---
Are you sure you really want to build the staging drivers? Are you sure you really want to build the staging drivers?
......
...@@ -1875,11 +1875,11 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, ...@@ -1875,11 +1875,11 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
return -ENOMEM; return -ENOMEM;
offset = *offsetp; offset = *offsetp;
cdp->err = nfserr_eof; /* will be cleared on successful read */
while (1) { while (1) {
unsigned int reclen; unsigned int reclen;
cdp->err = nfserr_eof; /* will be cleared on successful read */
buf.used = 0; buf.used = 0;
buf.full = 0; buf.full = 0;
...@@ -1912,9 +1912,6 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, ...@@ -1912,9 +1912,6 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
de = (struct buffered_dirent *)((char *)de + reclen); de = (struct buffered_dirent *)((char *)de + reclen);
} }
offset = vfs_llseek(file, 0, SEEK_CUR); offset = vfs_llseek(file, 0, SEEK_CUR);
cdp->err = nfserr_eof;
if (!buf.full)
break;
} }
done: done:
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/system.h>
/* this is used only to give gcc a clue about good code generation */ /* this is used only to give gcc a clue about good code generation */
union cnt32_to_63 { union cnt32_to_63 {
...@@ -53,11 +54,19 @@ union cnt32_to_63 { ...@@ -53,11 +54,19 @@ union cnt32_to_63 {
* needed increment. And any race in updating the value in memory is harmless * needed increment. And any race in updating the value in memory is harmless
* as the same value would simply be stored more than once. * as the same value would simply be stored more than once.
* *
* The only restriction for the algorithm to work properly is that this * The restrictions for the algorithm to work properly are:
* code must be executed at least once per each half period of the 32-bit *
* counter to properly update the state bit in memory. This is usually not a * 1) this code must be called at least once per each half period of the
* problem in practice, but if it is then a kernel timer could be scheduled * 32-bit counter;
* to manage for this code to be executed often enough. *
* 2) this code must not be preempted for a duration longer than the
* 32-bit counter half period minus the longest period between two
* calls to this code.
*
* Those requirements ensure proper update to the state bit in memory.
* This is usually not a problem in practice, but if it is then a kernel
* timer should be scheduled to manage for this code to be executed often
* enough.
* *
* Note that the top bit (bit 63) in the returned value should be considered * Note that the top bit (bit 63) in the returned value should be considered
* as garbage. It is not cleared here because callers are likely to use a * as garbage. It is not cleared here because callers are likely to use a
...@@ -68,9 +77,10 @@ union cnt32_to_63 { ...@@ -68,9 +77,10 @@ union cnt32_to_63 {
*/ */
#define cnt32_to_63(cnt_lo) \ #define cnt32_to_63(cnt_lo) \
({ \ ({ \
static volatile u32 __m_cnt_hi; \ static u32 __m_cnt_hi; \
union cnt32_to_63 __x; \ union cnt32_to_63 __x; \
__x.hi = __m_cnt_hi; \ __x.hi = __m_cnt_hi; \
smp_rmb(); \
__x.lo = (cnt_lo); \ __x.lo = (cnt_lo); \
if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \
__m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
* Cpumasks provide a bitmap suitable for representing the * Cpumasks provide a bitmap suitable for representing the
* set of CPU's in a system, one bit position per CPU number. * set of CPU's in a system, one bit position per CPU number.
* *
* The new cpumask_ ops take a "struct cpumask *"; the old ones
* use cpumask_t.
*
* See detailed comments in the file linux/bitmap.h describing the * See detailed comments in the file linux/bitmap.h describing the
* data type on which these cpumasks are based. * data type on which these cpumasks are based.
* *
...@@ -31,7 +34,7 @@ ...@@ -31,7 +34,7 @@
* will span the entire range of NR_CPUS. * will span the entire range of NR_CPUS.
* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
* *
* The available cpumask operations are: * The obsolescent cpumask operations are:
* *
* void cpu_set(cpu, mask) turn on bit 'cpu' in mask * void cpu_set(cpu, mask) turn on bit 'cpu' in mask
* void cpu_clear(cpu, mask) turn off bit 'cpu' in mask * void cpu_clear(cpu, mask) turn off bit 'cpu' in mask
...@@ -138,7 +141,7 @@ ...@@ -138,7 +141,7 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
typedef struct { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t; typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
extern cpumask_t _unused_cpumask_arg_; extern cpumask_t _unused_cpumask_arg_;
#define cpu_set(cpu, dst) __cpu_set((cpu), &(dst)) #define cpu_set(cpu, dst) __cpu_set((cpu), &(dst))
...@@ -527,4 +530,556 @@ extern cpumask_t cpu_active_map; ...@@ -527,4 +530,556 @@ extern cpumask_t cpu_active_map;
#define for_each_online_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_online_map) #define for_each_online_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_online_map)
#define for_each_present_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_present_map) #define for_each_present_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_present_map)
/* These are the new versions of the cpumask operators: passed by pointer.
* The older versions will be implemented in terms of these, then deleted. */
#define cpumask_bits(maskp) ((maskp)->bits)
#if NR_CPUS <= BITS_PER_LONG
#define CPU_BITS_ALL \
{ \
[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
}
/* This produces more efficient code. */
#define nr_cpumask_bits NR_CPUS
#else /* NR_CPUS > BITS_PER_LONG */
#define CPU_BITS_ALL \
{ \
[0 ... BITS_TO_LONGS(NR_CPUS)-2] = ~0UL, \
[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
}
#define nr_cpumask_bits nr_cpu_ids
#endif /* NR_CPUS > BITS_PER_LONG */
/* verify cpu argument to cpumask_* operators */
static inline unsigned int cpumask_check(unsigned int cpu)
{
#ifdef CONFIG_DEBUG_PER_CPU_MAPS
WARN_ON_ONCE(cpu >= nr_cpumask_bits);
#endif /* CONFIG_DEBUG_PER_CPU_MAPS */
return cpu;
}
#if NR_CPUS == 1
/* Uniprocessor. Assume all masks are "1". */
static inline unsigned int cpumask_first(const struct cpumask *srcp)
{
return 0;
}
/* Valid inputs for n are -1 and 0. */
static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
{
return n+1;
}
static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp)
{
return n+1;
}
static inline unsigned int cpumask_next_and(int n,
const struct cpumask *srcp,
const struct cpumask *andp)
{
return n+1;
}
/* cpu must be a valid cpu, ie 0, so there's no other choice. */
static inline unsigned int cpumask_any_but(const struct cpumask *mask,
unsigned int cpu)
{
return 1;
}
#define for_each_cpu(cpu, mask) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
#define for_each_cpu_and(cpu, mask, and) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)and)
#else
/**
* cpumask_first - get the first cpu in a cpumask
* @srcp: the cpumask pointer
*
* Returns >= nr_cpu_ids if no cpus set.
*/
static inline unsigned int cpumask_first(const struct cpumask *srcp)
{
return find_first_bit(cpumask_bits(srcp), nr_cpumask_bits);
}
/**
* cpumask_next - get the next cpu in a cpumask
* @n: the cpu prior to the place to search (ie. return will be > @n)
* @srcp: the cpumask pointer
*
* Returns >= nr_cpu_ids if no further cpus set.
*/
static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
{
/* -1 is a legal arg here. */
if (n != -1)
cpumask_check(n);
return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1);
}
/**
* cpumask_next_zero - get the next unset cpu in a cpumask
* @n: the cpu prior to the place to search (ie. return will be > @n)
* @srcp: the cpumask pointer
*
* Returns >= nr_cpu_ids if no further cpus unset.
*/
static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp)
{
/* -1 is a legal arg here. */
if (n != -1)
cpumask_check(n);
return find_next_zero_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1);
}
int cpumask_next_and(int n, const struct cpumask *, const struct cpumask *);
int cpumask_any_but(const struct cpumask *mask, unsigned int cpu);
/**
* for_each_cpu - iterate over every cpu in a mask
* @cpu: the (optionally unsigned) integer iterator
* @mask: the cpumask pointer
*
* After the loop, cpu is >= nr_cpu_ids.
*/
#define for_each_cpu(cpu, mask) \
for ((cpu) = -1; \
(cpu) = cpumask_next((cpu), (mask)), \
(cpu) < nr_cpu_ids;)
/**
* for_each_cpu_and - iterate over every cpu in both masks
* @cpu: the (optionally unsigned) integer iterator
* @mask: the first cpumask pointer
* @and: the second cpumask pointer
*
* This saves a temporary CPU mask in many places. It is equivalent to:
* struct cpumask tmp;
* cpumask_and(&tmp, &mask, &and);
* for_each_cpu(cpu, &tmp)
* ...
*
* After the loop, cpu is >= nr_cpu_ids.
*/
#define for_each_cpu_and(cpu, mask, and) \
for ((cpu) = -1; \
(cpu) = cpumask_next_and((cpu), (mask), (and)), \
(cpu) < nr_cpu_ids;)
#endif /* SMP */
#define CPU_BITS_NONE \
{ \
[0 ... BITS_TO_LONGS(NR_CPUS)-1] = 0UL \
}
#define CPU_BITS_CPU0 \
{ \
[0] = 1UL \
}
/**
* cpumask_set_cpu - set a cpu in a cpumask
* @cpu: cpu number (< nr_cpu_ids)
* @dstp: the cpumask pointer
*/
static inline void cpumask_set_cpu(unsigned int cpu, struct cpumask *dstp)
{
set_bit(cpumask_check(cpu), cpumask_bits(dstp));
}
/**
* cpumask_clear_cpu - clear a cpu in a cpumask
* @cpu: cpu number (< nr_cpu_ids)
* @dstp: the cpumask pointer
*/
static inline void cpumask_clear_cpu(int cpu, struct cpumask *dstp)
{
clear_bit(cpumask_check(cpu), cpumask_bits(dstp));
}
/**
* cpumask_test_cpu - test for a cpu in a cpumask
* @cpu: cpu number (< nr_cpu_ids)
* @cpumask: the cpumask pointer
*
* No static inline type checking - see Subtlety (1) above.
*/
#define cpumask_test_cpu(cpu, cpumask) \
test_bit(cpumask_check(cpu), (cpumask)->bits)
/**
* cpumask_test_and_set_cpu - atomically test and set a cpu in a cpumask
* @cpu: cpu number (< nr_cpu_ids)
* @cpumask: the cpumask pointer
*
* test_and_set_bit wrapper for cpumasks.
*/
static inline int cpumask_test_and_set_cpu(int cpu, struct cpumask *cpumask)
{
return test_and_set_bit(cpumask_check(cpu), cpumask_bits(cpumask));
}
/**
* cpumask_setall - set all cpus (< nr_cpu_ids) in a cpumask
* @dstp: the cpumask pointer
*/
static inline void cpumask_setall(struct cpumask *dstp)
{
bitmap_fill(cpumask_bits(dstp), nr_cpumask_bits);
}
/**
* cpumask_clear - clear all cpus (< nr_cpu_ids) in a cpumask
* @dstp: the cpumask pointer
*/
static inline void cpumask_clear(struct cpumask *dstp)
{
bitmap_zero(cpumask_bits(dstp), nr_cpumask_bits);
}
/**
* cpumask_and - *dstp = *src1p & *src2p
* @dstp: the cpumask result
* @src1p: the first input
* @src2p: the second input
*/
static inline void cpumask_and(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}
/**
* cpumask_or - *dstp = *src1p | *src2p
* @dstp: the cpumask result
* @src1p: the first input
* @src2p: the second input
*/
static inline void cpumask_or(struct cpumask *dstp, const struct cpumask *src1p,
const struct cpumask *src2p)
{
bitmap_or(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}
/**
* cpumask_xor - *dstp = *src1p ^ *src2p
* @dstp: the cpumask result
* @src1p: the first input
* @src2p: the second input
*/
static inline void cpumask_xor(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
bitmap_xor(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}
/**
* cpumask_andnot - *dstp = *src1p & ~*src2p
* @dstp: the cpumask result
* @src1p: the first input
* @src2p: the second input
*/
static inline void cpumask_andnot(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}
/**
* cpumask_complement - *dstp = ~*srcp
* @dstp: the cpumask result
* @srcp: the input to invert
*/
static inline void cpumask_complement(struct cpumask *dstp,
const struct cpumask *srcp)
{
bitmap_complement(cpumask_bits(dstp), cpumask_bits(srcp),
nr_cpumask_bits);
}
/**
* cpumask_equal - *src1p == *src2p
* @src1p: the first input
* @src2p: the second input
*/
static inline bool cpumask_equal(const struct cpumask *src1p,
const struct cpumask *src2p)
{
return bitmap_equal(cpumask_bits(src1p), cpumask_bits(src2p),
nr_cpumask_bits);
}
/**
* cpumask_intersects - (*src1p & *src2p) != 0
* @src1p: the first input
* @src2p: the second input
*/
static inline bool cpumask_intersects(const struct cpumask *src1p,
const struct cpumask *src2p)
{
return bitmap_intersects(cpumask_bits(src1p), cpumask_bits(src2p),
nr_cpumask_bits);
}
/**
* cpumask_subset - (*src1p & ~*src2p) == 0
* @src1p: the first input
* @src2p: the second input
*/
static inline int cpumask_subset(const struct cpumask *src1p,
const struct cpumask *src2p)
{
return bitmap_subset(cpumask_bits(src1p), cpumask_bits(src2p),
nr_cpumask_bits);
}
/**
* cpumask_empty - *srcp == 0
* @srcp: the cpumask to that all cpus < nr_cpu_ids are clear.
*/
static inline bool cpumask_empty(const struct cpumask *srcp)
{
return bitmap_empty(cpumask_bits(srcp), nr_cpumask_bits);
}
/**
* cpumask_full - *srcp == 0xFFFFFFFF...
* @srcp: the cpumask to that all cpus < nr_cpu_ids are set.
*/
static inline bool cpumask_full(const struct cpumask *srcp)
{
return bitmap_full(cpumask_bits(srcp), nr_cpumask_bits);
}
/**
* cpumask_weight - Count of bits in *srcp
* @srcp: the cpumask to count bits (< nr_cpu_ids) in.
*/
static inline unsigned int cpumask_weight(const struct cpumask *srcp)
{
return bitmap_weight(cpumask_bits(srcp), nr_cpumask_bits);
}
/**
* cpumask_shift_right - *dstp = *srcp >> n
* @dstp: the cpumask result
* @srcp: the input to shift
* @n: the number of bits to shift by
*/
static inline void cpumask_shift_right(struct cpumask *dstp,
const struct cpumask *srcp, int n)
{
bitmap_shift_right(cpumask_bits(dstp), cpumask_bits(srcp), n,
nr_cpumask_bits);
}
/**
* cpumask_shift_left - *dstp = *srcp << n
* @dstp: the cpumask result
* @srcp: the input to shift
* @n: the number of bits to shift by
*/
static inline void cpumask_shift_left(struct cpumask *dstp,
const struct cpumask *srcp, int n)
{
bitmap_shift_left(cpumask_bits(dstp), cpumask_bits(srcp), n,
nr_cpumask_bits);
}
/**
* cpumask_copy - *dstp = *srcp
* @dstp: the result
* @srcp: the input cpumask
*/
static inline void cpumask_copy(struct cpumask *dstp,
const struct cpumask *srcp)
{
bitmap_copy(cpumask_bits(dstp), cpumask_bits(srcp), nr_cpumask_bits);
}
/**
* cpumask_any - pick a "random" cpu from *srcp
* @srcp: the input cpumask
*
* Returns >= nr_cpu_ids if no cpus set.
*/
#define cpumask_any(srcp) cpumask_first(srcp)
/**
* cpumask_first_and - return the first cpu from *srcp1 & *srcp2
* @src1p: the first input
* @src2p: the second input
*
* Returns >= nr_cpu_ids if no cpus set in both. See also cpumask_next_and().
*/
#define cpumask_first_and(src1p, src2p) cpumask_next_and(-1, (src1p), (src2p))
/**
* cpumask_any_and - pick a "random" cpu from *mask1 & *mask2
* @mask1: the first input cpumask
* @mask2: the second input cpumask
*
* Returns >= nr_cpu_ids if no cpus set.
*/
#define cpumask_any_and(mask1, mask2) cpumask_first_and((mask1), (mask2))
/**
* cpumask_of - the cpumask containing just a given cpu
* @cpu: the cpu (<= nr_cpu_ids)
*/
#define cpumask_of(cpu) (get_cpu_mask(cpu))
/**
* to_cpumask - convert an NR_CPUS bitmap to a struct cpumask *
* @bitmap: the bitmap
*
* There are a few places where cpumask_var_t isn't appropriate and
* static cpumasks must be used (eg. very early boot), yet we don't
* expose the definition of 'struct cpumask'.
*
* This does the conversion, and can be used as a constant initializer.
*/
#define to_cpumask(bitmap) \
((struct cpumask *)(1 ? (bitmap) \
: (void *)sizeof(__check_is_bitmap(bitmap))))
static inline int __check_is_bitmap(const unsigned long *bitmap)
{
return 1;
}
/**
* cpumask_size - size to allocate for a 'struct cpumask' in bytes
*
* This will eventually be a runtime variable, depending on nr_cpu_ids.
*/
static inline size_t cpumask_size(void)
{
/* FIXME: Once all cpumask assignments are eliminated, this
* can be nr_cpumask_bits */
return BITS_TO_LONGS(NR_CPUS) * sizeof(long);
}
/*
* cpumask_var_t: struct cpumask for stack usage.
*
* Oh, the wicked games we play! In order to make kernel coding a
* little more difficult, we typedef cpumask_var_t to an array or a
* pointer: doing &mask on an array is a noop, so it still works.
*
* ie.
* cpumask_var_t tmpmask;
* if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL))
* return -ENOMEM;
*
* ... use 'tmpmask' like a normal struct cpumask * ...
*
* free_cpumask_var(tmpmask);
*/
#ifdef CONFIG_CPUMASK_OFFSTACK
typedef struct cpumask *cpumask_var_t;
bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags);
void alloc_bootmem_cpumask_var(cpumask_var_t *mask);
void free_cpumask_var(cpumask_var_t mask);
void free_bootmem_cpumask_var(cpumask_var_t mask);
#else
typedef struct cpumask cpumask_var_t[1];
static inline bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
{
return true;
}
static inline void alloc_bootmem_cpumask_var(cpumask_var_t *mask)
{
}
static inline void free_cpumask_var(cpumask_var_t mask)
{
}
static inline void free_bootmem_cpumask_var(cpumask_var_t mask)
{
}
#endif /* CONFIG_CPUMASK_OFFSTACK */
/* The pointer versions of the maps, these will become the primary versions. */
#define cpu_possible_mask ((const struct cpumask *)&cpu_possible_map)
#define cpu_online_mask ((const struct cpumask *)&cpu_online_map)
#define cpu_present_mask ((const struct cpumask *)&cpu_present_map)
#define cpu_active_mask ((const struct cpumask *)&cpu_active_map)
/* It's common to want to use cpu_all_mask in struct member initializers,
* so it has to refer to an address rather than a pointer. */
extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS);
#define cpu_all_mask to_cpumask(cpu_all_bits)
/* First bits of cpu_bit_bitmap are in fact unset. */
#define cpu_none_mask to_cpumask(cpu_bit_bitmap[0])
/* Wrappers for arch boot code to manipulate normally-constant masks */
static inline void set_cpu_possible(unsigned int cpu, bool possible)
{
if (possible)
cpumask_set_cpu(cpu, &cpu_possible_map);
else
cpumask_clear_cpu(cpu, &cpu_possible_map);
}
static inline void set_cpu_present(unsigned int cpu, bool present)
{
if (present)
cpumask_set_cpu(cpu, &cpu_present_map);
else
cpumask_clear_cpu(cpu, &cpu_present_map);
}
static inline void set_cpu_online(unsigned int cpu, bool online)
{
if (online)
cpumask_set_cpu(cpu, &cpu_online_map);
else
cpumask_clear_cpu(cpu, &cpu_online_map);
}
static inline void set_cpu_active(unsigned int cpu, bool active)
{
if (active)
cpumask_set_cpu(cpu, &cpu_active_map);
else
cpumask_clear_cpu(cpu, &cpu_active_map);
}
static inline void init_cpu_present(const struct cpumask *src)
{
cpumask_copy(&cpu_present_map, src);
}
static inline void init_cpu_possible(const struct cpumask *src)
{
cpumask_copy(&cpu_possible_map, src);
}
static inline void init_cpu_online(const struct cpumask *src)
{
cpumask_copy(&cpu_online_map, src);
}
#endif /* __LINUX_CPUMASK_H */ #endif /* __LINUX_CPUMASK_H */
...@@ -130,7 +130,7 @@ struct mmc_card { ...@@ -130,7 +130,7 @@ struct mmc_card {
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) ((c)->dev.bus_id) #define mmc_card_id(c) (dev_name(&(c)->dev))
#define mmc_list_to_card(l) container_of(l, struct mmc_card, node) #define mmc_list_to_card(l) container_of(l, struct mmc_card, node)
#define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) #define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev)
......
...@@ -176,7 +176,7 @@ static inline void *mmc_priv(struct mmc_host *host) ...@@ -176,7 +176,7 @@ static inline void *mmc_priv(struct mmc_host *host)
#define mmc_dev(x) ((x)->parent) #define mmc_dev(x) ((x)->parent)
#define mmc_classdev(x) (&(x)->class_dev) #define mmc_classdev(x) (&(x)->class_dev)
#define mmc_hostname(x) ((x)->class_dev.bus_id) #define mmc_hostname(x) (dev_name(&(x)->class_dev))
extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
extern int mmc_resume_host(struct mmc_host *); extern int mmc_resume_host(struct mmc_host *);
......
...@@ -63,7 +63,7 @@ struct sdio_func { ...@@ -63,7 +63,7 @@ struct sdio_func {
#define sdio_func_set_present(f) ((f)->state |= SDIO_STATE_PRESENT) #define sdio_func_set_present(f) ((f)->state |= SDIO_STATE_PRESENT)
#define sdio_func_id(f) ((f)->dev.bus_id) #define sdio_func_id(f) (dev_name(&(f)->dev))
#define sdio_get_drvdata(f) dev_get_drvdata(&(f)->dev) #define sdio_get_drvdata(f) dev_get_drvdata(&(f)->dev)
#define sdio_set_drvdata(f,d) dev_set_drvdata(&(f)->dev, d) #define sdio_set_drvdata(f,d) dev_set_drvdata(&(f)->dev, d)
......
...@@ -64,8 +64,17 @@ extern void smp_cpus_done(unsigned int max_cpus); ...@@ -64,8 +64,17 @@ extern void smp_cpus_done(unsigned int max_cpus);
* Call a function on all other processors * Call a function on all other processors
*/ */
int smp_call_function(void(*func)(void *info), void *info, int wait); int smp_call_function(void(*func)(void *info), void *info, int wait);
/* Deprecated: use smp_call_function_many() which uses a cpumask ptr. */
int smp_call_function_mask(cpumask_t mask, void(*func)(void *info), void *info, int smp_call_function_mask(cpumask_t mask, void(*func)(void *info), void *info,
int wait); int wait);
static inline void smp_call_function_many(const struct cpumask *mask,
void (*func)(void *info), void *info,
int wait)
{
smp_call_function_mask(*mask, func, info, wait);
}
int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
int wait); int wait);
void __smp_call_function_single(int cpuid, struct call_single_data *data); void __smp_call_function_single(int cpuid, struct call_single_data *data);
......
...@@ -240,4 +240,12 @@ void cancel_rearming_delayed_work(struct delayed_work *work) ...@@ -240,4 +240,12 @@ void cancel_rearming_delayed_work(struct delayed_work *work)
cancel_delayed_work_sync(work); cancel_delayed_work_sync(work);
} }
#ifndef CONFIG_SMP
static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
{
return fn(arg);
}
#else
long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg);
#endif /* CONFIG_SMP */
#endif #endif
...@@ -54,6 +54,7 @@ struct unix_sock { ...@@ -54,6 +54,7 @@ struct unix_sock {
atomic_long_t inflight; atomic_long_t inflight;
spinlock_t lock; spinlock_t lock;
unsigned int gc_candidate : 1; unsigned int gc_candidate : 1;
unsigned int gc_maybe_cycle : 1;
wait_queue_head_t peer_wait; wait_queue_head_t peer_wait;
}; };
#define unix_sk(__sk) ((struct unix_sock *)__sk) #define unix_sk(__sk) ((struct unix_sock *)__sk)
......
...@@ -499,3 +499,6 @@ const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = { ...@@ -499,3 +499,6 @@ const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
#endif #endif
}; };
EXPORT_SYMBOL_GPL(cpu_bit_bitmap); EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
EXPORT_SYMBOL(cpu_all_bits);
...@@ -970,6 +970,51 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, ...@@ -970,6 +970,51 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
return ret; return ret;
} }
#ifdef CONFIG_SMP
struct work_for_cpu {
struct work_struct work;
long (*fn)(void *);
void *arg;
long ret;
};
static void do_work_for_cpu(struct work_struct *w)
{
struct work_for_cpu *wfc = container_of(w, struct work_for_cpu, work);
wfc->ret = wfc->fn(wfc->arg);
}
/**
* work_on_cpu - run a function in user context on a particular cpu
* @cpu: the cpu to run on
* @fn: the function to run
* @arg: the function arg
*
* This will return -EINVAL in the cpu is not online, or the return value
* of @fn otherwise.
*/
long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
{
struct work_for_cpu wfc;
INIT_WORK(&wfc.work, do_work_for_cpu);
wfc.fn = fn;
wfc.arg = arg;
get_online_cpus();
if (unlikely(!cpu_online(cpu)))
wfc.ret = -EINVAL;
else {
schedule_work_on(cpu, &wfc.work);
flush_work(&wfc.work);
}
put_online_cpus();
return wfc.ret;
}
EXPORT_SYMBOL_GPL(work_on_cpu);
#endif /* CONFIG_SMP */
void __init init_workqueues(void) void __init init_workqueues(void)
{ {
cpu_populated_map = cpu_online_map; cpu_populated_map = cpu_online_map;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/bootmem.h>
int __first_cpu(const cpumask_t *srcp) int __first_cpu(const cpumask_t *srcp)
{ {
...@@ -35,3 +36,81 @@ int __any_online_cpu(const cpumask_t *mask) ...@@ -35,3 +36,81 @@ int __any_online_cpu(const cpumask_t *mask)
return cpu; return cpu;
} }
EXPORT_SYMBOL(__any_online_cpu); EXPORT_SYMBOL(__any_online_cpu);
/**
* cpumask_next_and - get the next cpu in *src1p & *src2p
* @n: the cpu prior to the place to search (ie. return will be > @n)
* @src1p: the first cpumask pointer
* @src2p: the second cpumask pointer
*
* Returns >= nr_cpu_ids if no further cpus set in both.
*/
int cpumask_next_and(int n, const struct cpumask *src1p,
const struct cpumask *src2p)
{
while ((n = cpumask_next(n, src1p)) < nr_cpu_ids)
if (cpumask_test_cpu(n, src2p))
break;
return n;
}
EXPORT_SYMBOL(cpumask_next_and);
/**
* cpumask_any_but - return a "random" in a cpumask, but not this one.
* @mask: the cpumask to search
* @cpu: the cpu to ignore.
*
* Often used to find any cpu but smp_processor_id() in a mask.
* Returns >= nr_cpu_ids if no cpus set.
*/
int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
{
unsigned int i;
cpumask_check(cpu);
for_each_cpu(i, mask)
if (i != cpu)
break;
return i;
}
/* These are not inline because of header tangles. */
#ifdef CONFIG_CPUMASK_OFFSTACK
bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
{
if (likely(slab_is_available()))
*mask = kmalloc(cpumask_size(), flags);
else {
#ifdef CONFIG_DEBUG_PER_CPU_MAPS
printk(KERN_ERR
"=> alloc_cpumask_var: kmalloc not available!\n");
dump_stack();
#endif
*mask = NULL;
}
#ifdef CONFIG_DEBUG_PER_CPU_MAPS
if (!*mask) {
printk(KERN_ERR "=> alloc_cpumask_var: failed!\n");
dump_stack();
}
#endif
return *mask != NULL;
}
EXPORT_SYMBOL(alloc_cpumask_var);
void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)
{
*mask = alloc_bootmem(cpumask_size());
}
void free_cpumask_var(cpumask_var_t mask)
{
kfree(mask);
}
EXPORT_SYMBOL(free_cpumask_var);
void __init free_bootmem_cpumask_var(cpumask_var_t mask)
{
free_bootmem((unsigned long)mask, cpumask_size());
}
#endif
...@@ -1302,14 +1302,23 @@ static void unix_destruct_fds(struct sk_buff *skb) ...@@ -1302,14 +1302,23 @@ static void unix_destruct_fds(struct sk_buff *skb)
sock_wfree(skb); sock_wfree(skb);
} }
static void unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
{ {
int i; int i;
/*
* Need to duplicate file references for the sake of garbage
* collection. Otherwise a socket in the fps might become a
* candidate for GC while the skb is not yet queued.
*/
UNIXCB(skb).fp = scm_fp_dup(scm->fp);
if (!UNIXCB(skb).fp)
return -ENOMEM;
for (i=scm->fp->count-1; i>=0; i--) for (i=scm->fp->count-1; i>=0; i--)
unix_inflight(scm->fp->fp[i]); unix_inflight(scm->fp->fp[i]);
UNIXCB(skb).fp = scm->fp;
skb->destructor = unix_destruct_fds; skb->destructor = unix_destruct_fds;
scm->fp = NULL; return 0;
} }
/* /*
...@@ -1368,8 +1377,11 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1368,8 +1377,11 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out; goto out;
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
if (siocb->scm->fp) if (siocb->scm->fp) {
unix_attach_fds(siocb->scm, skb); err = unix_attach_fds(siocb->scm, skb);
if (err)
goto out_free;
}
unix_get_secdata(siocb->scm, skb); unix_get_secdata(siocb->scm, skb);
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
...@@ -1538,8 +1550,13 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1538,8 +1550,13 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
size = min_t(int, size, skb_tailroom(skb)); size = min_t(int, size, skb_tailroom(skb));
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
if (siocb->scm->fp) if (siocb->scm->fp) {
unix_attach_fds(siocb->scm, skb); err = unix_attach_fds(siocb->scm, skb);
if (err) {
kfree_skb(skb);
goto out_err;
}
}
if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) { if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) {
kfree_skb(skb); kfree_skb(skb);
......
...@@ -186,8 +186,17 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), ...@@ -186,8 +186,17 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
*/ */
struct sock *sk = unix_get_socket(*fp++); struct sock *sk = unix_get_socket(*fp++);
if (sk) { if (sk) {
struct unix_sock *u = unix_sk(sk);
/*
* Ignore non-candidates, they could
* have been added to the queues after
* starting the garbage collection
*/
if (u->gc_candidate) {
hit = true; hit = true;
func(unix_sk(sk)); func(u);
}
} }
} }
if (hit && hitlist != NULL) { if (hit && hitlist != NULL) {
...@@ -249,11 +258,11 @@ static void inc_inflight_move_tail(struct unix_sock *u) ...@@ -249,11 +258,11 @@ static void inc_inflight_move_tail(struct unix_sock *u)
{ {
atomic_long_inc(&u->inflight); atomic_long_inc(&u->inflight);
/* /*
* If this is still a candidate, move it to the end of the * If this still might be part of a cycle, move it to the end
* list, so that it's checked even if it was already passed * of the list, so that it's checked even if it was already
* over * passed over
*/ */
if (u->gc_candidate) if (u->gc_maybe_cycle)
list_move_tail(&u->link, &gc_candidates); list_move_tail(&u->link, &gc_candidates);
} }
...@@ -267,6 +276,7 @@ void unix_gc(void) ...@@ -267,6 +276,7 @@ void unix_gc(void)
struct unix_sock *next; struct unix_sock *next;
struct sk_buff_head hitlist; struct sk_buff_head hitlist;
struct list_head cursor; struct list_head cursor;
LIST_HEAD(not_cycle_list);
spin_lock(&unix_gc_lock); spin_lock(&unix_gc_lock);
...@@ -282,10 +292,14 @@ void unix_gc(void) ...@@ -282,10 +292,14 @@ void unix_gc(void)
* *
* Holding unix_gc_lock will protect these candidates from * Holding unix_gc_lock will protect these candidates from
* being detached, and hence from gaining an external * being detached, and hence from gaining an external
* reference. This also means, that since there are no * reference. Since there are no possible receivers, all
* possible receivers, the receive queues of these sockets are * buffers currently on the candidates' queues stay there
* static during the GC, even though the dequeue is done * during the garbage collection.
* before the detach without atomicity guarantees. *
* We also know that no new candidate can be added onto the
* receive queues. Other, non candidate sockets _can_ be
* added to queue, so we must make sure only to touch
* candidates.
*/ */
list_for_each_entry_safe(u, next, &gc_inflight_list, link) { list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
long total_refs; long total_refs;
...@@ -299,6 +313,7 @@ void unix_gc(void) ...@@ -299,6 +313,7 @@ void unix_gc(void)
if (total_refs == inflight_refs) { if (total_refs == inflight_refs) {
list_move_tail(&u->link, &gc_candidates); list_move_tail(&u->link, &gc_candidates);
u->gc_candidate = 1; u->gc_candidate = 1;
u->gc_maybe_cycle = 1;
} }
} }
...@@ -325,13 +340,23 @@ void unix_gc(void) ...@@ -325,13 +340,23 @@ void unix_gc(void)
list_move(&cursor, &u->link); list_move(&cursor, &u->link);
if (atomic_long_read(&u->inflight) > 0) { if (atomic_long_read(&u->inflight) > 0) {
list_move_tail(&u->link, &gc_inflight_list); list_move_tail(&u->link, &not_cycle_list);
u->gc_candidate = 0; u->gc_maybe_cycle = 0;
scan_children(&u->sk, inc_inflight_move_tail, NULL); scan_children(&u->sk, inc_inflight_move_tail, NULL);
} }
} }
list_del(&cursor); list_del(&cursor);
/*
* not_cycle_list contains those sockets which do not make up a
* cycle. Restore these to the inflight list.
*/
while (!list_empty(&not_cycle_list)) {
u = list_entry(not_cycle_list.next, struct unix_sock, link);
u->gc_candidate = 0;
list_move_tail(&u->link, &gc_inflight_list);
}
/* /*
* Now gc_candidates contains only garbage. Restore original * Now gc_candidates contains only garbage. Restore original
* inflight counters for these as well, and remove the skbuffs * inflight counters for these as well, and remove the skbuffs
......
...@@ -15,15 +15,18 @@ set -e ...@@ -15,15 +15,18 @@ set -e
version=$KERNELRELEASE version=$KERNELRELEASE
revision=`cat .version` revision=`cat .version`
tmpdir="$objtree/debian/tmp" tmpdir="$objtree/debian/tmp"
fwdir="$objtree/debian/fwtmp"
packagename=linux-$version packagename=linux-$version
fwpackagename=linux-firmware-image
if [ "$ARCH" == "um" ] ; then if [ "$ARCH" == "um" ] ; then
packagename=user-mode-linux-$version packagename=user-mode-linux-$version
fi fi
# Setup the directory structure # Setup the directory structure
rm -rf "$tmpdir" rm -rf "$tmpdir" "$fwdir"
mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot" mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot"
mkdir -p "$fwdir/DEBIAN" "$fwdir/lib"
if [ "$ARCH" == "um" ] ; then if [ "$ARCH" == "um" ] ; then
mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/share/doc/$packagename" "$tmpdir/usr/bin" mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/share/doc/$packagename" "$tmpdir/usr/bin"
fi fi
...@@ -107,6 +110,7 @@ Standards-Version: 3.6.1 ...@@ -107,6 +110,7 @@ Standards-Version: 3.6.1
Package: $packagename Package: $packagename
Provides: kernel-image-$version, linux-image-$version Provides: kernel-image-$version, linux-image-$version
Suggests: $fwpackagename
Architecture: any Architecture: any
Description: Linux kernel, version $version Description: Linux kernel, version $version
This package contains the Linux kernel, modules and corresponding other This package contains the Linux kernel, modules and corresponding other
...@@ -118,8 +122,24 @@ fi ...@@ -118,8 +122,24 @@ fi
chown -R root:root "$tmpdir" chown -R root:root "$tmpdir"
chmod -R go-w "$tmpdir" chmod -R go-w "$tmpdir"
# Do we have firmware? Move it out of the way and build it into a package.
if [ -e "$tmpdir/lib/firmware" ]; then
mv "$tmpdir/lib/firmware" "$fwdir/lib/"
cat <<EOF >> debian/control
Package: $fwpackagename
Architecture: all
Description: Linux kernel firmware, version $version
This package contains firmware from the Linux kernel, version $version
EOF
dpkg-gencontrol -isp -p$fwpackagename -P"$fwdir"
dpkg --build "$fwdir" ..
fi
# Perform the final magic # Perform the final magic
dpkg-gencontrol -isp dpkg-gencontrol -isp -p$packagename
dpkg --build "$tmpdir" .. dpkg --build "$tmpdir" ..
exit 0 exit 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment