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); \
......
This diff is collapsed.
...@@ -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) {
hit = true; struct unix_sock *u = unix_sk(sk);
func(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;
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