Merge branch 'for_2.6.40/pm-cleanup' of ssh://master.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-linus

This commit is contained in:
Tony Lindgren 2011-05-24 00:45:06 -07:00
commit 9b28b11e2a
192 changed files with 1651 additions and 1104 deletions

View file

@ -1,7 +1,7 @@
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 39 SUBLEVEL = 39
EXTRAVERSION = -rc7 EXTRAVERSION =
NAME = Flesh-Eating Bats with Fangs NAME = Flesh-Eating Bats with Fangs
# *DOCUMENTATION* # *DOCUMENTATION*

View file

@ -452,10 +452,14 @@
#define __NR_fanotify_init 494 #define __NR_fanotify_init 494
#define __NR_fanotify_mark 495 #define __NR_fanotify_mark 495
#define __NR_prlimit64 496 #define __NR_prlimit64 496
#define __NR_name_to_handle_at 497
#define __NR_open_by_handle_at 498
#define __NR_clock_adjtime 499
#define __NR_syncfs 500
#ifdef __KERNEL__ #ifdef __KERNEL__
#define NR_SYSCALLS 497 #define NR_SYSCALLS 501
#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_READDIR

View file

@ -498,23 +498,27 @@ sys_call_table:
.quad sys_ni_syscall /* sys_timerfd */ .quad sys_ni_syscall /* sys_timerfd */
.quad sys_eventfd .quad sys_eventfd
.quad sys_recvmmsg .quad sys_recvmmsg
.quad sys_fallocate /* 480 */ .quad sys_fallocate /* 480 */
.quad sys_timerfd_create .quad sys_timerfd_create
.quad sys_timerfd_settime .quad sys_timerfd_settime
.quad sys_timerfd_gettime .quad sys_timerfd_gettime
.quad sys_signalfd4 .quad sys_signalfd4
.quad sys_eventfd2 /* 485 */ .quad sys_eventfd2 /* 485 */
.quad sys_epoll_create1 .quad sys_epoll_create1
.quad sys_dup3 .quad sys_dup3
.quad sys_pipe2 .quad sys_pipe2
.quad sys_inotify_init1 .quad sys_inotify_init1
.quad sys_preadv /* 490 */ .quad sys_preadv /* 490 */
.quad sys_pwritev .quad sys_pwritev
.quad sys_rt_tgsigqueueinfo .quad sys_rt_tgsigqueueinfo
.quad sys_perf_event_open .quad sys_perf_event_open
.quad sys_fanotify_init .quad sys_fanotify_init
.quad sys_fanotify_mark /* 495 */ .quad sys_fanotify_mark /* 495 */
.quad sys_prlimit64 .quad sys_prlimit64
.quad sys_name_to_handle_at
.quad sys_open_by_handle_at
.quad sys_clock_adjtime
.quad sys_syncfs /* 500 */
.size sys_call_table, . - sys_call_table .size sys_call_table, . - sys_call_table
.type sys_call_table, @object .type sys_call_table, @object

View file

@ -375,8 +375,7 @@ static struct clocksource clocksource_rpcc = {
static inline void register_rpcc_clocksource(long cycle_freq) static inline void register_rpcc_clocksource(long cycle_freq)
{ {
clocksource_calc_mult_shift(&clocksource_rpcc, cycle_freq, 4); clocksource_register_hz(&clocksource_rpcc, cycle_freq);
clocksource_register(&clocksource_rpcc);
} }
#else /* !CONFIG_SMP */ #else /* !CONFIG_SMP */
static inline void register_rpcc_clocksource(long cycle_freq) static inline void register_rpcc_clocksource(long cycle_freq)

View file

@ -59,24 +59,6 @@
#define TWL4030_MSECURE_GPIO 22 #define TWL4030_MSECURE_GPIO 22
/* FIXME: These values need to be updated based on more profiling on 3430sdp*/
static struct cpuidle_params omap3_cpuidle_params_table[] = {
/* C1 */
{1, 2, 2, 5},
/* C2 */
{1, 10, 10, 30},
/* C3 */
{1, 50, 50, 300},
/* C4 */
{1, 1500, 1800, 4000},
/* C5 */
{1, 2500, 7500, 12000},
/* C6 */
{1, 3000, 8500, 15000},
/* C7 */
{1, 10000, 30000, 300000},
};
static uint32_t board_keymap[] = { static uint32_t board_keymap[] = {
KEY(0, 0, KEY_LEFT), KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT), KEY(0, 1, KEY_RIGHT),
@ -800,7 +782,6 @@ static void __init omap_3430sdp_init(void)
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap_board_config = sdp3430_config; omap_board_config = sdp3430_config;
omap_board_config_size = ARRAY_SIZE(sdp3430_config); omap_board_config_size = ARRAY_SIZE(sdp3430_config);
omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
omap3430_i2c_init(); omap3430_i2c_init();
omap_display_init(&sdp3430_dss_data); omap_display_init(&sdp3430_dss_data);
if (omap_rev() > OMAP3430_REV_ES1_0) if (omap_rev() > OMAP3430_REV_ES1_0)

View file

@ -58,21 +58,25 @@ static struct platform_device leds_gpio = {
}, },
}; };
/*
* cpuidle C-states definition override from the default values.
* The 'exit_latency' field is the sum of sleep and wake-up latencies.
*/
static struct cpuidle_params rx51_cpuidle_params[] = { static struct cpuidle_params rx51_cpuidle_params[] = {
/* C1 */ /* C1 */
{1, 110, 162, 5}, {110 + 162, 5 , 1},
/* C2 */ /* C2 */
{1, 106, 180, 309}, {106 + 180, 309, 1},
/* C3 */ /* C3 */
{0, 107, 410, 46057}, {107 + 410, 46057, 0},
/* C4 */ /* C4 */
{0, 121, 3374, 46057}, {121 + 3374, 46057, 0},
/* C5 */ /* C5 */
{1, 855, 1146, 46057}, {855 + 1146, 46057, 1},
/* C6 */ /* C6 */
{0, 7580, 4134, 484329}, {7580 + 4134, 484329, 0},
/* C7 */ /* C7 */
{1, 7505, 15274, 484329}, {7505 + 15274, 484329, 1},
}; };
static struct omap_lcd_config rx51_lcd_config = { static struct omap_lcd_config rx51_lcd_config = {

View file

@ -36,36 +36,6 @@
#ifdef CONFIG_CPU_IDLE #ifdef CONFIG_CPU_IDLE
#define OMAP3_MAX_STATES 7
#define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */
#define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */
#define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */
#define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */
#define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */
#define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */
#define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */
#define OMAP3_STATE_MAX OMAP3_STATE_C7
#define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap3_enter_idle_bm() */
struct omap3_processor_cx {
u8 valid;
u8 type;
u32 sleep_latency;
u32 wakeup_latency;
u32 mpu_state;
u32 core_state;
u32 threshold;
u32 flags;
const char *desc;
};
struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
struct omap3_processor_cx current_cx_state;
struct powerdomain *mpu_pd, *core_pd, *per_pd;
struct powerdomain *cam_pd;
/* /*
* The latencies/thresholds for various C states have * The latencies/thresholds for various C states have
* to be configured from the respective board files. * to be configured from the respective board files.
@ -75,27 +45,31 @@ struct powerdomain *cam_pd;
*/ */
static struct cpuidle_params cpuidle_params_table[] = { static struct cpuidle_params cpuidle_params_table[] = {
/* C1 */ /* C1 */
{1, 2, 2, 5}, {2 + 2, 5, 1},
/* C2 */ /* C2 */
{1, 10, 10, 30}, {10 + 10, 30, 1},
/* C3 */ /* C3 */
{1, 50, 50, 300}, {50 + 50, 300, 1},
/* C4 */ /* C4 */
{1, 1500, 1800, 4000}, {1500 + 1800, 4000, 1},
/* C5 */ /* C5 */
{1, 2500, 7500, 12000}, {2500 + 7500, 12000, 1},
/* C6 */ /* C6 */
{1, 3000, 8500, 15000}, {3000 + 8500, 15000, 1},
/* C7 */ /* C7 */
{1, 10000, 30000, 300000}, {10000 + 30000, 300000, 1},
}; };
#define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
static int omap3_idle_bm_check(void) /* Mach specific information to be recorded in the C-state driver_data */
{ struct omap3_idle_statedata {
if (!omap3_can_sleep()) u32 mpu_state;
return 1; u32 core_state;
return 0; u8 valid;
} };
struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES];
struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
static int _cpuidle_allow_idle(struct powerdomain *pwrdm, static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
struct clockdomain *clkdm) struct clockdomain *clkdm)
@ -122,12 +96,10 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
static int omap3_enter_idle(struct cpuidle_device *dev, static int omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state) struct cpuidle_state *state)
{ {
struct omap3_processor_cx *cx = cpuidle_get_statedata(state); struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
struct timespec ts_preidle, ts_postidle, ts_idle; struct timespec ts_preidle, ts_postidle, ts_idle;
u32 mpu_state = cx->mpu_state, core_state = cx->core_state; u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
current_cx_state = *cx;
/* Used to keep track of the total time in idle */ /* Used to keep track of the total time in idle */
getnstimeofday(&ts_preidle); getnstimeofday(&ts_preidle);
@ -140,7 +112,8 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
if (omap_irq_pending() || need_resched()) if (omap_irq_pending() || need_resched())
goto return_sleep_time; goto return_sleep_time;
if (cx->type == OMAP3_STATE_C1) { /* Deny idle for C1 */
if (state == &dev->states[0]) {
pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
} }
@ -148,7 +121,8 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
/* Execute ARM wfi */ /* Execute ARM wfi */
omap_sram_idle(); omap_sram_idle();
if (cx->type == OMAP3_STATE_C1) { /* Re-allow idle for C1 */
if (state == &dev->states[0]) {
pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
} }
@ -164,41 +138,53 @@ return_sleep_time:
} }
/** /**
* next_valid_state - Find next valid c-state * next_valid_state - Find next valid C-state
* @dev: cpuidle device * @dev: cpuidle device
* @state: Currently selected c-state * @state: Currently selected C-state
* *
* If the current state is valid, it is returned back to the caller. * If the current state is valid, it is returned back to the caller.
* Else, this function searches for a lower c-state which is still * Else, this function searches for a lower c-state which is still
* valid (as defined in omap3_power_states[]). * valid.
*
* A state is valid if the 'valid' field is enabled and
* if it satisfies the enable_off_mode condition.
*/ */
static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
struct cpuidle_state *curr) struct cpuidle_state *curr)
{ {
struct cpuidle_state *next = NULL; struct cpuidle_state *next = NULL;
struct omap3_processor_cx *cx; struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
u32 mpu_deepest_state = PWRDM_POWER_RET;
u32 core_deepest_state = PWRDM_POWER_RET;
cx = (struct omap3_processor_cx *)cpuidle_get_statedata(curr); if (enable_off_mode) {
mpu_deepest_state = PWRDM_POWER_OFF;
/*
* Erratum i583: valable for ES rev < Es1.2 on 3630.
* CORE OFF mode is not supported in a stable form, restrict
* instead the CORE state to RET.
*/
if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
core_deepest_state = PWRDM_POWER_OFF;
}
/* Check if current state is valid */ /* Check if current state is valid */
if (cx->valid) { if ((cx->valid) &&
(cx->mpu_state >= mpu_deepest_state) &&
(cx->core_state >= core_deepest_state)) {
return curr; return curr;
} else { } else {
u8 idx = OMAP3_STATE_MAX; int idx = OMAP3_NUM_STATES - 1;
/* /* Reach the current state starting at highest C-state */
* Reach the current state starting at highest C-state for (; idx >= 0; idx--) {
*/
for (; idx >= OMAP3_STATE_C1; idx--) {
if (&dev->states[idx] == curr) { if (&dev->states[idx] == curr) {
next = &dev->states[idx]; next = &dev->states[idx];
break; break;
} }
} }
/* /* Should never hit this condition */
* Should never hit this condition.
*/
WARN_ON(next == NULL); WARN_ON(next == NULL);
/* /*
@ -206,17 +192,17 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
* Start search from the next (lower) state. * Start search from the next (lower) state.
*/ */
idx--; idx--;
for (; idx >= OMAP3_STATE_C1; idx--) { for (; idx >= 0; idx--) {
struct omap3_processor_cx *cx;
cx = cpuidle_get_statedata(&dev->states[idx]); cx = cpuidle_get_statedata(&dev->states[idx]);
if (cx->valid) { if ((cx->valid) &&
(cx->mpu_state >= mpu_deepest_state) &&
(cx->core_state >= core_deepest_state)) {
next = &dev->states[idx]; next = &dev->states[idx];
break; break;
} }
} }
/* /*
* C1 and C2 are always valid. * C1 is always valid.
* So, no need to check for 'next==NULL' outside this loop. * So, no need to check for 'next==NULL' outside this loop.
*/ */
} }
@ -229,36 +215,22 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
* @dev: cpuidle device * @dev: cpuidle device
* @state: The target state to be programmed * @state: The target state to be programmed
* *
* Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This * This function checks for any pending activity and then programs
* function checks for any pending activity and then programs the * the device to the specified or a safer state.
* device to the specified or a safer state.
*/ */
static int omap3_enter_idle_bm(struct cpuidle_device *dev, static int omap3_enter_idle_bm(struct cpuidle_device *dev,
struct cpuidle_state *state) struct cpuidle_state *state)
{ {
struct cpuidle_state *new_state = next_valid_state(dev, state); struct cpuidle_state *new_state;
u32 core_next_state, per_next_state = 0, per_saved_state = 0; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
u32 cam_state; struct omap3_idle_statedata *cx;
struct omap3_processor_cx *cx;
int ret; int ret;
if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) { if (!omap3_can_sleep()) {
BUG_ON(!dev->safe_state);
new_state = dev->safe_state; new_state = dev->safe_state;
goto select_state; goto select_state;
} }
cx = cpuidle_get_statedata(state);
core_next_state = cx->core_state;
/*
* FIXME: we currently manage device-specific idle states
* for PER and CORE in combination with CPU-specific
* idle states. This is wrong, and device-specific
* idle management needs to be separated out into
* its own code.
*/
/* /*
* Prevent idle completely if CAM is active. * Prevent idle completely if CAM is active.
* CAM does not have wakeup capability in OMAP3. * CAM does not have wakeup capability in OMAP3.
@ -269,10 +241,20 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
goto select_state; goto select_state;
} }
/*
* FIXME: we currently manage device-specific idle states
* for PER and CORE in combination with CPU-specific
* idle states. This is wrong, and device-specific
* idle management needs to be separated out into
* its own code.
*/
/* /*
* Prevent PER off if CORE is not in retention or off as this * Prevent PER off if CORE is not in retention or off as this
* would disable PER wakeups completely. * would disable PER wakeups completely.
*/ */
cx = cpuidle_get_statedata(state);
core_next_state = cx->core_state;
per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
if ((per_next_state == PWRDM_POWER_OFF) && if ((per_next_state == PWRDM_POWER_OFF) &&
(core_next_state > PWRDM_POWER_RET)) (core_next_state > PWRDM_POWER_RET))
@ -282,6 +264,8 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
if (per_next_state != per_saved_state) if (per_next_state != per_saved_state)
pwrdm_set_next_pwrst(per_pd, per_next_state); pwrdm_set_next_pwrst(per_pd, per_next_state);
new_state = next_valid_state(dev, state);
select_state: select_state:
dev->last_state = new_state; dev->last_state = new_state;
ret = omap3_enter_idle(dev, new_state); ret = omap3_enter_idle(dev, new_state);
@ -295,31 +279,6 @@ select_state:
DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
/**
* omap3_cpuidle_update_states() - Update the cpuidle states
* @mpu_deepest_state: Enable states up to and including this for mpu domain
* @core_deepest_state: Enable states up to and including this for core domain
*
* This goes through the list of states available and enables and disables the
* validity of C states based on deepest state that can be achieved for the
* variable domain
*/
void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
{
int i;
for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {
struct omap3_processor_cx *cx = &omap3_power_states[i];
if ((cx->mpu_state >= mpu_deepest_state) &&
(cx->core_state >= core_deepest_state)) {
cx->valid = 1;
} else {
cx->valid = 0;
}
}
}
void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
{ {
int i; int i;
@ -327,212 +286,109 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
if (!cpuidle_board_params) if (!cpuidle_board_params)
return; return;
for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { for (i = 0; i < OMAP3_NUM_STATES; i++) {
cpuidle_params_table[i].valid = cpuidle_params_table[i].valid = cpuidle_board_params[i].valid;
cpuidle_board_params[i].valid; cpuidle_params_table[i].exit_latency =
cpuidle_params_table[i].sleep_latency = cpuidle_board_params[i].exit_latency;
cpuidle_board_params[i].sleep_latency; cpuidle_params_table[i].target_residency =
cpuidle_params_table[i].wake_latency = cpuidle_board_params[i].target_residency;
cpuidle_board_params[i].wake_latency;
cpuidle_params_table[i].threshold =
cpuidle_board_params[i].threshold;
} }
return; return;
} }
/* omap3_init_power_states - Initialises the OMAP3 specific C states.
*
* Below is the desciption of each C state.
* C1 . MPU WFI + Core active
* C2 . MPU WFI + Core inactive
* C3 . MPU CSWR + Core inactive
* C4 . MPU OFF + Core inactive
* C5 . MPU CSWR + Core CSWR
* C6 . MPU OFF + Core CSWR
* C7 . MPU OFF + Core OFF
*/
void omap_init_power_states(void)
{
/* C1 . MPU WFI + Core active */
omap3_power_states[OMAP3_STATE_C1].valid =
cpuidle_params_table[OMAP3_STATE_C1].valid;
omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1;
omap3_power_states[OMAP3_STATE_C1].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C1].sleep_latency;
omap3_power_states[OMAP3_STATE_C1].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C1].wake_latency;
omap3_power_states[OMAP3_STATE_C1].threshold =
cpuidle_params_table[OMAP3_STATE_C1].threshold;
omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
omap3_power_states[OMAP3_STATE_C1].desc = "MPU ON + CORE ON";
/* C2 . MPU WFI + Core inactive */
omap3_power_states[OMAP3_STATE_C2].valid =
cpuidle_params_table[OMAP3_STATE_C2].valid;
omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2;
omap3_power_states[OMAP3_STATE_C2].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C2].sleep_latency;
omap3_power_states[OMAP3_STATE_C2].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
omap3_power_states[OMAP3_STATE_C2].desc = "MPU ON + CORE ON";
/* C3 . MPU CSWR + Core inactive */
omap3_power_states[OMAP3_STATE_C3].valid =
cpuidle_params_table[OMAP3_STATE_C3].valid;
omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3;
omap3_power_states[OMAP3_STATE_C3].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C3].sleep_latency;
omap3_power_states[OMAP3_STATE_C3].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C3].wake_latency;
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
omap3_power_states[OMAP3_STATE_C3].desc = "MPU RET + CORE ON";
/* C4 . MPU OFF + Core inactive */
omap3_power_states[OMAP3_STATE_C4].valid =
cpuidle_params_table[OMAP3_STATE_C4].valid;
omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4;
omap3_power_states[OMAP3_STATE_C4].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C4].sleep_latency;
omap3_power_states[OMAP3_STATE_C4].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C4].wake_latency;
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
omap3_power_states[OMAP3_STATE_C4].desc = "MPU OFF + CORE ON";
/* C5 . MPU CSWR + Core CSWR*/
omap3_power_states[OMAP3_STATE_C5].valid =
cpuidle_params_table[OMAP3_STATE_C5].valid;
omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5;
omap3_power_states[OMAP3_STATE_C5].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C5].sleep_latency;
omap3_power_states[OMAP3_STATE_C5].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C5].wake_latency;
omap3_power_states[OMAP3_STATE_C5].threshold =
cpuidle_params_table[OMAP3_STATE_C5].threshold;
omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET;
omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
omap3_power_states[OMAP3_STATE_C5].desc = "MPU RET + CORE RET";
/* C6 . MPU OFF + Core CSWR */
omap3_power_states[OMAP3_STATE_C6].valid =
cpuidle_params_table[OMAP3_STATE_C6].valid;
omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6;
omap3_power_states[OMAP3_STATE_C6].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C6].sleep_latency;
omap3_power_states[OMAP3_STATE_C6].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C6].wake_latency;
omap3_power_states[OMAP3_STATE_C6].threshold =
cpuidle_params_table[OMAP3_STATE_C6].threshold;
omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF;
omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET;
omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
omap3_power_states[OMAP3_STATE_C6].desc = "MPU OFF + CORE RET";
/* C7 . MPU OFF + Core OFF */
omap3_power_states[OMAP3_STATE_C7].valid =
cpuidle_params_table[OMAP3_STATE_C7].valid;
omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7;
omap3_power_states[OMAP3_STATE_C7].sleep_latency =
cpuidle_params_table[OMAP3_STATE_C7].sleep_latency;
omap3_power_states[OMAP3_STATE_C7].wakeup_latency =
cpuidle_params_table[OMAP3_STATE_C7].wake_latency;
omap3_power_states[OMAP3_STATE_C7].threshold =
cpuidle_params_table[OMAP3_STATE_C7].threshold;
omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF;
omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
omap3_power_states[OMAP3_STATE_C7].desc = "MPU OFF + CORE OFF";
/*
* Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
* enable OFF mode in a stable form for previous revisions.
* we disable C7 state as a result.
*/
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
omap3_power_states[OMAP3_STATE_C7].valid = 0;
cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
pr_warn("%s: core off state C7 disabled due to i583\n",
__func__);
}
}
struct cpuidle_driver omap3_idle_driver = { struct cpuidle_driver omap3_idle_driver = {
.name = "omap3_idle", .name = "omap3_idle",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
/* Helper to fill the C-state common data and register the driver_data */
static inline struct omap3_idle_statedata *_fill_cstate(
struct cpuidle_device *dev,
int idx, const char *descr)
{
struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
struct cpuidle_state *state = &dev->states[idx];
state->exit_latency = cpuidle_params_table[idx].exit_latency;
state->target_residency = cpuidle_params_table[idx].target_residency;
state->flags = CPUIDLE_FLAG_TIME_VALID;
state->enter = omap3_enter_idle_bm;
cx->valid = cpuidle_params_table[idx].valid;
sprintf(state->name, "C%d", idx + 1);
strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
cpuidle_set_statedata(state, cx);
return cx;
}
/** /**
* omap3_idle_init - Init routine for OMAP3 idle * omap3_idle_init - Init routine for OMAP3 idle
* *
* Registers the OMAP3 specific cpuidle driver with the cpuidle * Registers the OMAP3 specific cpuidle driver to the cpuidle
* framework with the valid set of states. * framework with the valid set of states.
*/ */
int __init omap3_idle_init(void) int __init omap3_idle_init(void)
{ {
int i, count = 0;
struct omap3_processor_cx *cx;
struct cpuidle_state *state;
struct cpuidle_device *dev; struct cpuidle_device *dev;
struct omap3_idle_statedata *cx;
mpu_pd = pwrdm_lookup("mpu_pwrdm"); mpu_pd = pwrdm_lookup("mpu_pwrdm");
core_pd = pwrdm_lookup("core_pwrdm"); core_pd = pwrdm_lookup("core_pwrdm");
per_pd = pwrdm_lookup("per_pwrdm"); per_pd = pwrdm_lookup("per_pwrdm");
cam_pd = pwrdm_lookup("cam_pwrdm"); cam_pd = pwrdm_lookup("cam_pwrdm");
omap_init_power_states();
cpuidle_register_driver(&omap3_idle_driver); cpuidle_register_driver(&omap3_idle_driver);
dev = &per_cpu(omap3_idle_dev, smp_processor_id()); dev = &per_cpu(omap3_idle_dev, smp_processor_id());
for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { /* C1 . MPU WFI + Core active */
cx = &omap3_power_states[i]; cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
state = &dev->states[count]; (&dev->states[0])->enter = omap3_enter_idle;
dev->safe_state = &dev->states[0];
cx->valid = 1; /* C1 is always valid */
cx->mpu_state = PWRDM_POWER_ON;
cx->core_state = PWRDM_POWER_ON;
if (!cx->valid) /* C2 . MPU WFI + Core inactive */
continue; cx = _fill_cstate(dev, 1, "MPU ON + CORE ON");
cpuidle_set_statedata(state, cx); cx->mpu_state = PWRDM_POWER_ON;
state->exit_latency = cx->sleep_latency + cx->wakeup_latency; cx->core_state = PWRDM_POWER_ON;
state->target_residency = cx->threshold;
state->flags = cx->flags; /* C3 . MPU CSWR + Core inactive */
state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ? cx = _fill_cstate(dev, 2, "MPU RET + CORE ON");
omap3_enter_idle_bm : omap3_enter_idle; cx->mpu_state = PWRDM_POWER_RET;
if (cx->type == OMAP3_STATE_C1) cx->core_state = PWRDM_POWER_ON;
dev->safe_state = state;
sprintf(state->name, "C%d", count+1); /* C4 . MPU OFF + Core inactive */
strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON");
count++; cx->mpu_state = PWRDM_POWER_OFF;
cx->core_state = PWRDM_POWER_ON;
/* C5 . MPU RET + Core RET */
cx = _fill_cstate(dev, 4, "MPU RET + CORE RET");
cx->mpu_state = PWRDM_POWER_RET;
cx->core_state = PWRDM_POWER_RET;
/* C6 . MPU OFF + Core RET */
cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET");
cx->mpu_state = PWRDM_POWER_OFF;
cx->core_state = PWRDM_POWER_RET;
/* C7 . MPU OFF + Core OFF */
cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF");
/*
* Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
* enable OFF mode in a stable form for previous revisions.
* We disable C7 state as a result.
*/
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
cx->valid = 0;
pr_warn("%s: core off state C7 disabled due to i583\n",
__func__);
} }
cx->mpu_state = PWRDM_POWER_OFF;
cx->core_state = PWRDM_POWER_OFF;
if (!count) dev->state_count = OMAP3_NUM_STATES;
return -EINVAL;
dev->state_count = count;
if (enable_off_mode)
omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
else
omap3_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
if (cpuidle_register_device(dev)) { if (cpuidle_register_device(dev)) {
printk(KERN_ERR "%s: CPUidle register device failed\n", printk(KERN_ERR "%s: CPUidle register device failed\n",
__func__); __func__);

View file

@ -36,11 +36,16 @@ static inline int omap4_opp_init(void)
} }
#endif #endif
/*
* cpuidle mach specific parameters
*
* The board code can override the default C-states definition using
* omap3_pm_init_cpuidle
*/
struct cpuidle_params { struct cpuidle_params {
u8 valid; u32 exit_latency; /* exit_latency = sleep + wake-up latencies */
u32 sleep_latency; u32 target_residency;
u32 wake_latency; u8 valid; /* validates the C-state */
u32 threshold;
}; };
#if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE) #if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE)
@ -73,10 +78,6 @@ extern u32 sleep_while_idle;
#define sleep_while_idle 0 #define sleep_while_idle 0
#endif #endif
#if defined(CONFIG_CPU_IDLE)
extern void omap3_cpuidle_update_states(u32, u32);
#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
extern int pm_dbg_regset_save(int reg_set); extern int pm_dbg_regset_save(int reg_set);

View file

@ -779,18 +779,6 @@ void omap3_pm_off_mode_enable(int enable)
else else
state = PWRDM_POWER_RET; state = PWRDM_POWER_RET;
#ifdef CONFIG_CPU_IDLE
/*
* Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
* enable OFF mode in a stable form for previous revisions, restrict
* instead to RET
*/
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
omap3_cpuidle_update_states(state, PWRDM_POWER_RET);
else
omap3_cpuidle_update_states(state, state);
#endif
list_for_each_entry(pwrst, &pwrst_list, node) { list_for_each_entry(pwrst, &pwrst_list, node) {
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) && if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
pwrst->pwrdm == core_pwrdm && pwrst->pwrdm == core_pwrdm &&
@ -895,8 +883,6 @@ static int __init omap3_pm_init(void)
pm_errata_configure(); pm_errata_configure();
printk(KERN_ERR "Power Management for TI OMAP3.\n");
/* XXX prcm_setup_regs needs to be before enabling hw /* XXX prcm_setup_regs needs to be before enabling hw
* supervised mode for powerdomains */ * supervised mode for powerdomains */
prcm_setup_regs(); prcm_setup_regs();

View file

@ -325,9 +325,7 @@ int __init ar7_gpio_init(void)
size = 0x1f; size = 0x1f;
} }
gpch->regs = ioremap_nocache(AR7_REGS_GPIO, gpch->regs = ioremap_nocache(AR7_REGS_GPIO, size);
AR7_REGS_GPIO + 0x10);
if (!gpch->regs) { if (!gpch->regs) {
printk(KERN_ERR "%s: failed to ioremap regs\n", printk(KERN_ERR "%s: failed to ioremap regs\n",
gpch->chip.label); gpch->chip.label);

View file

@ -5,7 +5,9 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm-generic/dma-coherent.h> #include <asm-generic/dma-coherent.h>
#ifndef CONFIG_SGI_IP27 /* Kludge to fix 2.6.39 build for IP27 */
#include <dma-coherence.h> #include <dma-coherence.h>
#endif
extern struct dma_map_ops *mips_dma_map_ops; extern struct dma_map_ops *mips_dma_map_ops;

View file

@ -374,7 +374,8 @@ void __noreturn die(const char *str, struct pt_regs *regs)
unsigned long dvpret = dvpe(); unsigned long dvpret = dvpe();
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV); if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
sig = 0;
console_verbose(); console_verbose();
spin_lock_irq(&die_lock); spin_lock_irq(&die_lock);
@ -383,9 +384,6 @@ void __noreturn die(const char *str, struct pt_regs *regs)
mips_mt_regdump(dvpret); mips_mt_regdump(dvpret);
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
sig = 0;
printk("%s[#%d]:\n", str, ++die_counter); printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs); show_registers(regs);
add_taint(TAINT_DIE); add_taint(TAINT_DIE);

View file

@ -185,7 +185,7 @@ int __init rb532_gpio_init(void)
struct resource *r; struct resource *r;
r = rb532_gpio_reg0_res; r = rb532_gpio_reg0_res;
rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start); rb532_gpio_chip->regbase = ioremap_nocache(r->start, resource_size(r));
if (!rb532_gpio_chip->regbase) { if (!rb532_gpio_chip->regbase) {
printk(KERN_ERR "rb532: cannot remap GPIO register 0\n"); printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");

View file

@ -318,17 +318,20 @@ static const struct platform_suspend_ops mpc83xx_suspend_ops = {
.end = mpc83xx_suspend_end, .end = mpc83xx_suspend_end,
}; };
static struct of_device_id pmc_match[];
static int pmc_probe(struct platform_device *ofdev) static int pmc_probe(struct platform_device *ofdev)
{ {
const struct of_device_id *match;
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
struct resource res; struct resource res;
struct pmc_type *type; struct pmc_type *type;
int ret = 0; int ret = 0;
if (!ofdev->dev.of_match) match = of_match_device(pmc_match, &ofdev->dev);
if (!match)
return -EINVAL; return -EINVAL;
type = ofdev->dev.of_match->data; type = match->data;
if (!of_device_is_available(np)) if (!of_device_is_available(np))
return -ENODEV; return -ENODEV;

View file

@ -304,8 +304,10 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
return 0; return 0;
} }
static const struct of_device_id fsl_of_msi_ids[];
static int __devinit fsl_of_msi_probe(struct platform_device *dev) static int __devinit fsl_of_msi_probe(struct platform_device *dev)
{ {
const struct of_device_id *match;
struct fsl_msi *msi; struct fsl_msi *msi;
struct resource res; struct resource res;
int err, i, j, irq_index, count; int err, i, j, irq_index, count;
@ -316,9 +318,10 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
u32 offset; u32 offset;
static const u32 all_avail[] = { 0, NR_MSI_IRQS }; static const u32 all_avail[] = { 0, NR_MSI_IRQS };
if (!dev->dev.of_match) match = of_match_device(fsl_of_msi_ids, &dev->dev);
if (!match)
return -EINVAL; return -EINVAL;
features = dev->dev.of_match->data; features = match->data;
printk(KERN_DEBUG "Setting up Freescale MSI support\n"); printk(KERN_DEBUG "Setting up Freescale MSI support\n");

View file

@ -165,7 +165,7 @@ static int __devinit apc_probe(struct platform_device *op)
return 0; return 0;
} }
static struct of_device_id __initdata apc_match[] = { static struct of_device_id apc_match[] = {
{ {
.name = APC_OBPNAME, .name = APC_OBPNAME,
}, },

View file

@ -452,8 +452,10 @@ static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm,
sabre_scan_bus(pbm, &op->dev); sabre_scan_bus(pbm, &op->dev);
} }
static const struct of_device_id sabre_match[];
static int __devinit sabre_probe(struct platform_device *op) static int __devinit sabre_probe(struct platform_device *op)
{ {
const struct of_device_id *match;
const struct linux_prom64_registers *pr_regs; const struct linux_prom64_registers *pr_regs;
struct device_node *dp = op->dev.of_node; struct device_node *dp = op->dev.of_node;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
@ -463,7 +465,8 @@ static int __devinit sabre_probe(struct platform_device *op)
const u32 *vdma; const u32 *vdma;
u64 clear_irq; u64 clear_irq;
hummingbird_p = op->dev.of_match && (op->dev.of_match->data != NULL); match = of_match_device(sabre_match, &op->dev);
hummingbird_p = match && (match->data != NULL);
if (!hummingbird_p) { if (!hummingbird_p) {
struct device_node *cpu_dp; struct device_node *cpu_dp;

View file

@ -1458,11 +1458,15 @@ out_err:
return err; return err;
} }
static const struct of_device_id schizo_match[];
static int __devinit schizo_probe(struct platform_device *op) static int __devinit schizo_probe(struct platform_device *op)
{ {
if (!op->dev.of_match) const struct of_device_id *match;
match = of_match_device(schizo_match, &op->dev);
if (!match)
return -EINVAL; return -EINVAL;
return __schizo_init(op, (unsigned long) op->dev.of_match->data); return __schizo_init(op, (unsigned long)match->data);
} }
/* The ordering of this table is very important. Some Tomatillo /* The ordering of this table is very important. Some Tomatillo

View file

@ -69,7 +69,7 @@ static int __devinit pmc_probe(struct platform_device *op)
return 0; return 0;
} }
static struct of_device_id __initdata pmc_match[] = { static struct of_device_id pmc_match[] = {
{ {
.name = PMC_OBPNAME, .name = PMC_OBPNAME,
}, },

View file

@ -53,6 +53,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_NONE;
void __cpuinit smp_store_cpu_info(int id) void __cpuinit smp_store_cpu_info(int id)
{ {
int cpu_node; int cpu_node;
int mid;
cpu_data(id).udelay_val = loops_per_jiffy; cpu_data(id).udelay_val = loops_per_jiffy;
@ -60,10 +61,13 @@ void __cpuinit smp_store_cpu_info(int id)
cpu_data(id).clock_tick = prom_getintdefault(cpu_node, cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
"clock-frequency", 0); "clock-frequency", 0);
cpu_data(id).prom_node = cpu_node; cpu_data(id).prom_node = cpu_node;
cpu_data(id).mid = cpu_get_hwmid(cpu_node); mid = cpu_get_hwmid(cpu_node);
if (cpu_data(id).mid < 0) if (mid < 0) {
panic("No MID found for CPU%d at node 0x%08d", id, cpu_node); printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08d", id, cpu_node);
mid = 0;
}
cpu_data(id).mid = mid;
} }
void __init smp_cpus_done(unsigned int max_cpus) void __init smp_cpus_done(unsigned int max_cpus)

View file

@ -168,7 +168,7 @@ static int __devinit clock_probe(struct platform_device *op)
return 0; return 0;
} }
static struct of_device_id __initdata clock_match[] = { static struct of_device_id clock_match[] = {
{ {
.name = "eeprom", .name = "eeprom",
}, },

View file

@ -289,10 +289,16 @@ cc_end_cruft:
/* Also, handle the alignment code out of band. */ /* Also, handle the alignment code out of band. */
cc_dword_align: cc_dword_align:
cmp %g1, 6 cmp %g1, 16
bl,a ccte bge 1f
srl %g1, 1, %o3
2: cmp %o3, 0
be,a ccte
andcc %g1, 0xf, %o3 andcc %g1, 0xf, %o3
andcc %o0, 0x1, %g0 andcc %o3, %o0, %g0 ! Check %o0 only (%o1 has the same last 2 bits)
be,a 2b
srl %o3, 1, %o3
1: andcc %o0, 0x1, %g0
bne ccslow bne ccslow
andcc %o0, 0x2, %g0 andcc %o0, 0x2, %g0
be 1f be 1f

View file

@ -5,6 +5,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
@ -75,6 +76,26 @@ void setup_hostinfo(char *buf, int len)
host.release, host.version, host.machine); host.release, host.version, host.machine);
} }
/*
* We cannot use glibc's abort(). It makes use of tgkill() which
* has no effect within UML's kernel threads.
* After that glibc would execute an invalid instruction to kill
* the calling process and UML crashes with SIGSEGV.
*/
static inline void __attribute__ ((noreturn)) uml_abort(void)
{
sigset_t sig;
fflush(NULL);
if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
sigprocmask(SIG_UNBLOCK, &sig, 0);
for (;;)
if (kill(getpid(), SIGABRT) < 0)
exit(127);
}
void os_dump_core(void) void os_dump_core(void)
{ {
int pid; int pid;
@ -116,5 +137,5 @@ void os_dump_core(void)
while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
os_kill_ptraced_process(pid, 0); os_kill_ptraced_process(pid, 0);
abort(); uml_abort();
} }

View file

@ -78,6 +78,7 @@
#define APIC_DEST_LOGICAL 0x00800 #define APIC_DEST_LOGICAL 0x00800
#define APIC_DEST_PHYSICAL 0x00000 #define APIC_DEST_PHYSICAL 0x00000
#define APIC_DM_FIXED 0x00000 #define APIC_DM_FIXED 0x00000
#define APIC_DM_FIXED_MASK 0x00700
#define APIC_DM_LOWEST 0x00100 #define APIC_DM_LOWEST 0x00100
#define APIC_DM_SMI 0x00200 #define APIC_DM_SMI 0x00200
#define APIC_DM_REMRD 0x00300 #define APIC_DM_REMRD 0x00300

View file

@ -299,6 +299,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
/* Install a pte for a particular vaddr in kernel space. */ /* Install a pte for a particular vaddr in kernel space. */
void set_pte_vaddr(unsigned long vaddr, pte_t pte); void set_pte_vaddr(unsigned long vaddr, pte_t pte);
extern void native_pagetable_reserve(u64 start, u64 end);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
extern void native_pagetable_setup_start(pgd_t *base); extern void native_pagetable_setup_start(pgd_t *base);
extern void native_pagetable_setup_done(pgd_t *base); extern void native_pagetable_setup_done(pgd_t *base);

View file

@ -94,6 +94,8 @@
/* after this # consecutive successes, bump up the throttle if it was lowered */ /* after this # consecutive successes, bump up the throttle if it was lowered */
#define COMPLETE_THRESHOLD 5 #define COMPLETE_THRESHOLD 5
#define UV_LB_SUBNODEID 0x10
/* /*
* number of entries in the destination side payload queue * number of entries in the destination side payload queue
*/ */
@ -124,7 +126,7 @@
* The distribution specification (32 bytes) is interpreted as a 256-bit * The distribution specification (32 bytes) is interpreted as a 256-bit
* distribution vector. Adjacent bits correspond to consecutive even numbered * distribution vector. Adjacent bits correspond to consecutive even numbered
* nodeIDs. The result of adding the index of a given bit to the 15-bit * nodeIDs. The result of adding the index of a given bit to the 15-bit
* 'base_dest_nodeid' field of the header corresponds to the * 'base_dest_nasid' field of the header corresponds to the
* destination nodeID associated with that specified bit. * destination nodeID associated with that specified bit.
*/ */
struct bau_target_uvhubmask { struct bau_target_uvhubmask {
@ -176,7 +178,7 @@ struct bau_msg_payload {
struct bau_msg_header { struct bau_msg_header {
unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */ unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */
/* bits 5:0 */ /* bits 5:0 */
unsigned int base_dest_nodeid:15; /* nasid of the */ unsigned int base_dest_nasid:15; /* nasid of the */
/* bits 20:6 */ /* first bit in uvhub map */ /* bits 20:6 */ /* first bit in uvhub map */
unsigned int command:8; /* message type */ unsigned int command:8; /* message type */
/* bits 28:21 */ /* bits 28:21 */
@ -378,6 +380,10 @@ struct ptc_stats {
unsigned long d_rcanceled; /* number of messages canceled by resets */ unsigned long d_rcanceled; /* number of messages canceled by resets */
}; };
struct hub_and_pnode {
short uvhub;
short pnode;
};
/* /*
* one per-cpu; to locate the software tables * one per-cpu; to locate the software tables
*/ */
@ -399,10 +405,12 @@ struct bau_control {
int baudisabled; int baudisabled;
int set_bau_off; int set_bau_off;
short cpu; short cpu;
short osnode;
short uvhub_cpu; short uvhub_cpu;
short uvhub; short uvhub;
short cpus_in_socket; short cpus_in_socket;
short cpus_in_uvhub; short cpus_in_uvhub;
short partition_base_pnode;
unsigned short message_number; unsigned short message_number;
unsigned short uvhub_quiesce; unsigned short uvhub_quiesce;
short socket_acknowledge_count[DEST_Q_SIZE]; short socket_acknowledge_count[DEST_Q_SIZE];
@ -422,15 +430,16 @@ struct bau_control {
int congested_period; int congested_period;
cycles_t period_time; cycles_t period_time;
long period_requests; long period_requests;
struct hub_and_pnode *target_hub_and_pnode;
}; };
static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp) static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp)
{ {
return constant_test_bit(uvhub, &dstp->bits[0]); return constant_test_bit(uvhub, &dstp->bits[0]);
} }
static inline void bau_uvhub_set(int uvhub, struct bau_target_uvhubmask *dstp) static inline void bau_uvhub_set(int pnode, struct bau_target_uvhubmask *dstp)
{ {
__set_bit(uvhub, &dstp->bits[0]); __set_bit(pnode, &dstp->bits[0]);
} }
static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp, static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp,
int nbits) int nbits)

View file

@ -398,6 +398,8 @@ struct uv_blade_info {
unsigned short nr_online_cpus; unsigned short nr_online_cpus;
unsigned short pnode; unsigned short pnode;
short memory_nid; short memory_nid;
spinlock_t nmi_lock;
unsigned long nmi_count;
}; };
extern struct uv_blade_info *uv_blade_info; extern struct uv_blade_info *uv_blade_info;
extern short *uv_node_to_blade; extern short *uv_node_to_blade;

View file

@ -5,7 +5,7 @@
* *
* SGI UV MMR definitions * SGI UV MMR definitions
* *
* Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved. * Copyright (C) 2007-2011 Silicon Graphics, Inc. All rights reserved.
*/ */
#ifndef _ASM_X86_UV_UV_MMRS_H #ifndef _ASM_X86_UV_UV_MMRS_H
@ -1099,5 +1099,19 @@ union uvh_rtc1_int_config_u {
} s; } s;
}; };
/* ========================================================================= */
/* UVH_SCRATCH5 */
/* ========================================================================= */
#define UVH_SCRATCH5 0x2d0200UL
#define UVH_SCRATCH5_32 0x00778
#define UVH_SCRATCH5_SCRATCH5_SHFT 0
#define UVH_SCRATCH5_SCRATCH5_MASK 0xffffffffffffffffUL
union uvh_scratch5_u {
unsigned long v;
struct uvh_scratch5_s {
unsigned long scratch5 : 64; /* RW, W1CS */
} s;
};
#endif /* __ASM_UV_MMRS_X86_H__ */ #endif /* __ASM_UV_MMRS_X86_H__ */

View file

@ -67,6 +67,17 @@ struct x86_init_oem {
void (*banner)(void); void (*banner)(void);
}; };
/**
* struct x86_init_mapping - platform specific initial kernel pagetable setup
* @pagetable_reserve: reserve a range of addresses for kernel pagetable usage
*
* For more details on the purpose of this hook, look in
* init_memory_mapping and the commit that added it.
*/
struct x86_init_mapping {
void (*pagetable_reserve)(u64 start, u64 end);
};
/** /**
* struct x86_init_paging - platform specific paging functions * struct x86_init_paging - platform specific paging functions
* @pagetable_setup_start: platform specific pre paging_init() call * @pagetable_setup_start: platform specific pre paging_init() call
@ -123,6 +134,7 @@ struct x86_init_ops {
struct x86_init_mpparse mpparse; struct x86_init_mpparse mpparse;
struct x86_init_irqs irqs; struct x86_init_irqs irqs;
struct x86_init_oem oem; struct x86_init_oem oem;
struct x86_init_mapping mapping;
struct x86_init_paging paging; struct x86_init_paging paging;
struct x86_init_timers timers; struct x86_init_timers timers;
struct x86_init_iommu iommu; struct x86_init_iommu iommu;

View file

@ -37,6 +37,13 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
#include <asm/emergency-restart.h> #include <asm/emergency-restart.h>
#include <asm/nmi.h>
/* BMC sets a bit this MMR non-zero before sending an NMI */
#define UVH_NMI_MMR UVH_SCRATCH5
#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8)
#define UV_NMI_PENDING_MASK (1UL << 63)
DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
DEFINE_PER_CPU(int, x2apic_extra_bits); DEFINE_PER_CPU(int, x2apic_extra_bits);
@ -642,18 +649,46 @@ void __cpuinit uv_cpu_init(void)
*/ */
int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data) int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
{ {
unsigned long real_uv_nmi;
int bid;
if (reason != DIE_NMIUNKNOWN) if (reason != DIE_NMIUNKNOWN)
return NOTIFY_OK; return NOTIFY_OK;
if (in_crash_kexec) if (in_crash_kexec)
/* do nothing if entering the crash kernel */ /* do nothing if entering the crash kernel */
return NOTIFY_OK; return NOTIFY_OK;
/* /*
* Use a lock so only one cpu prints at a time * Each blade has an MMR that indicates when an NMI has been sent
* to prevent intermixed output. * to cpus on the blade. If an NMI is detected, atomically
* clear the MMR and update a per-blade NMI count used to
* cause each cpu on the blade to notice a new NMI.
*/
bid = uv_numa_blade_id();
real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
if (unlikely(real_uv_nmi)) {
spin_lock(&uv_blade_info[bid].nmi_lock);
real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
if (real_uv_nmi) {
uv_blade_info[bid].nmi_count++;
uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);
}
spin_unlock(&uv_blade_info[bid].nmi_lock);
}
if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
return NOTIFY_DONE;
__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
/*
* Use a lock so only one cpu prints at a time.
* This prevents intermixed output.
*/ */
spin_lock(&uv_nmi_lock); spin_lock(&uv_nmi_lock);
pr_info("NMI stack dump cpu %u:\n", smp_processor_id()); pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
dump_stack(); dump_stack();
spin_unlock(&uv_nmi_lock); spin_unlock(&uv_nmi_lock);
@ -661,7 +696,8 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
} }
static struct notifier_block uv_dump_stack_nmi_nb = { static struct notifier_block uv_dump_stack_nmi_nb = {
.notifier_call = uv_handle_nmi .notifier_call = uv_handle_nmi,
.priority = NMI_LOCAL_LOW_PRIOR - 1,
}; };
void uv_register_nmi_notifier(void) void uv_register_nmi_notifier(void)
@ -720,8 +756,9 @@ void __init uv_system_init(void)
printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades()); printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());
bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades(); bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
uv_blade_info = kmalloc(bytes, GFP_KERNEL); uv_blade_info = kzalloc(bytes, GFP_KERNEL);
BUG_ON(!uv_blade_info); BUG_ON(!uv_blade_info);
for (blade = 0; blade < uv_num_possible_blades(); blade++) for (blade = 0; blade < uv_num_possible_blades(); blade++)
uv_blade_info[blade].memory_nid = -1; uv_blade_info[blade].memory_nid = -1;
@ -747,6 +784,7 @@ void __init uv_system_init(void)
uv_blade_info[blade].pnode = pnode; uv_blade_info[blade].pnode = pnode;
uv_blade_info[blade].nr_possible_cpus = 0; uv_blade_info[blade].nr_possible_cpus = 0;
uv_blade_info[blade].nr_online_cpus = 0; uv_blade_info[blade].nr_online_cpus = 0;
spin_lock_init(&uv_blade_info[blade].nmi_lock);
max_pnode = max(pnode, max_pnode); max_pnode = max(pnode, max_pnode);
blade++; blade++;
} }

View file

@ -613,7 +613,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
#endif #endif
/* As a rule processors have APIC timer running in deep C states */ /* As a rule processors have APIC timer running in deep C states */
if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400)) if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400))
set_cpu_cap(c, X86_FEATURE_ARAT); set_cpu_cap(c, X86_FEATURE_ARAT);
/* /*
@ -698,7 +698,7 @@ cpu_dev_register(amd_cpu_dev);
*/ */
const int amd_erratum_400[] = const int amd_erratum_400[] =
AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0x0f, 0x4, 0x2, 0xff, 0xf), AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
EXPORT_SYMBOL_GPL(amd_erratum_400); EXPORT_SYMBOL_GPL(amd_erratum_400);

View file

@ -509,6 +509,7 @@ recurse:
out_free: out_free:
if (b) { if (b) {
kobject_put(&b->kobj); kobject_put(&b->kobj);
list_del(&b->miscj);
kfree(b); kfree(b);
} }
return err; return err;

View file

@ -446,18 +446,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
*/ */
rdmsr(MSR_IA32_MISC_ENABLE, l, h); rdmsr(MSR_IA32_MISC_ENABLE, l, h);
h = lvtthmr_init;
/* /*
* The initial value of thermal LVT entries on all APs always reads * The initial value of thermal LVT entries on all APs always reads
* 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
* sequence to them and LVT registers are reset to 0s except for * sequence to them and LVT registers are reset to 0s except for
* the mask bits which are set to 1s when APs receive INIT IPI. * the mask bits which are set to 1s when APs receive INIT IPI.
* Always restore the value that BIOS has programmed on AP based on * If BIOS takes over the thermal interrupt and sets its interrupt
* BSP's info we saved since BIOS is always setting the same value * delivery mode to SMI (not fixed), it restores the value that the
* for all threads/cores * BIOS has programmed on AP based on BSP's info we saved since BIOS
* is always setting the same value for all threads/cores.
*/ */
apic_write(APIC_LVTTHMR, lvtthmr_init); if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
apic_write(APIC_LVTTHMR, lvtthmr_init);
h = lvtthmr_init;
if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
printk(KERN_DEBUG printk(KERN_DEBUG

View file

@ -1183,12 +1183,13 @@ static void __kprobes optimized_callback(struct optimized_kprobe *op,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
unsigned long flags;
/* This is possible if op is under delayed unoptimizing */ /* This is possible if op is under delayed unoptimizing */
if (kprobe_disabled(&op->kp)) if (kprobe_disabled(&op->kp))
return; return;
preempt_disable(); local_irq_save(flags);
if (kprobe_running()) { if (kprobe_running()) {
kprobes_inc_nmissed_count(&op->kp); kprobes_inc_nmissed_count(&op->kp);
} else { } else {
@ -1207,7 +1208,7 @@ static void __kprobes optimized_callback(struct optimized_kprobe *op,
opt_pre_handler(&op->kp, regs); opt_pre_handler(&op->kp, regs);
__this_cpu_write(current_kprobe, NULL); __this_cpu_write(current_kprobe, NULL);
} }
preempt_enable_no_resched(); local_irq_restore(flags);
} }
static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src) static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)

View file

@ -61,6 +61,10 @@ struct x86_init_ops x86_init __initdata = {
.banner = default_banner, .banner = default_banner,
}, },
.mapping = {
.pagetable_reserve = native_pagetable_reserve,
},
.paging = { .paging = {
.pagetable_setup_start = native_pagetable_setup_start, .pagetable_setup_start = native_pagetable_setup_start,
.pagetable_setup_done = native_pagetable_setup_done, .pagetable_setup_done = native_pagetable_setup_done,

View file

@ -81,6 +81,11 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT); end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
} }
void __init native_pagetable_reserve(u64 start, u64 end)
{
memblock_x86_reserve_range(start, end, "PGTABLE");
}
struct map_range { struct map_range {
unsigned long start; unsigned long start;
unsigned long end; unsigned long end;
@ -272,9 +277,24 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
__flush_tlb_all(); __flush_tlb_all();
/*
* Reserve the kernel pagetable pages we used (pgt_buf_start -
* pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top)
* so that they can be reused for other purposes.
*
* On native it just means calling memblock_x86_reserve_range, on Xen it
* also means marking RW the pagetable pages that we allocated before
* but that haven't been used.
*
* In fact on xen we mark RO the whole range pgt_buf_start -
* pgt_buf_top, because we have to make sure that when
* init_memory_mapping reaches the pagetable pages area, it maps
* RO all the pagetable pages, including the ones that are beyond
* pgt_buf_end at that time.
*/
if (!after_bootmem && pgt_buf_end > pgt_buf_start) if (!after_bootmem && pgt_buf_end > pgt_buf_start)
memblock_x86_reserve_range(pgt_buf_start << PAGE_SHIFT, x86_init.mapping.pagetable_reserve(PFN_PHYS(pgt_buf_start),
pgt_buf_end << PAGE_SHIFT, "PGTABLE"); PFN_PHYS(pgt_buf_end));
if (!after_bootmem) if (!after_bootmem)
early_memtest(start, end); early_memtest(start, end);

View file

@ -699,16 +699,17 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct mm_struct *mm, struct mm_struct *mm,
unsigned long va, unsigned int cpu) unsigned long va, unsigned int cpu)
{ {
int tcpu;
int uvhub;
int locals = 0; int locals = 0;
int remotes = 0; int remotes = 0;
int hubs = 0; int hubs = 0;
int tcpu;
int tpnode;
struct bau_desc *bau_desc; struct bau_desc *bau_desc;
struct cpumask *flush_mask; struct cpumask *flush_mask;
struct ptc_stats *stat; struct ptc_stats *stat;
struct bau_control *bcp; struct bau_control *bcp;
struct bau_control *tbcp; struct bau_control *tbcp;
struct hub_and_pnode *hpp;
/* kernel was booted 'nobau' */ /* kernel was booted 'nobau' */
if (nobau) if (nobau)
@ -750,11 +751,18 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu; bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu;
bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
/* cpu statistics */
for_each_cpu(tcpu, flush_mask) { for_each_cpu(tcpu, flush_mask) {
uvhub = uv_cpu_to_blade_id(tcpu); /*
bau_uvhub_set(uvhub, &bau_desc->distribution); * The distribution vector is a bit map of pnodes, relative
if (uvhub == bcp->uvhub) * to the partition base pnode (and the partition base nasid
* in the header).
* Translate cpu to pnode and hub using an array stored
* in local memory.
*/
hpp = &bcp->socket_master->target_hub_and_pnode[tcpu];
tpnode = hpp->pnode - bcp->partition_base_pnode;
bau_uvhub_set(tpnode, &bau_desc->distribution);
if (hpp->uvhub == bcp->uvhub)
locals++; locals++;
else else
remotes++; remotes++;
@ -855,7 +863,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
* an interrupt, but causes an error message to be returned to * an interrupt, but causes an error message to be returned to
* the sender. * the sender.
*/ */
static void uv_enable_timeouts(void) static void __init uv_enable_timeouts(void)
{ {
int uvhub; int uvhub;
int nuvhubs; int nuvhubs;
@ -1326,10 +1334,10 @@ static int __init uv_ptc_init(void)
} }
/* /*
* initialize the sending side's sending buffers * Initialize the sending side's sending buffers.
*/ */
static void static void
uv_activation_descriptor_init(int node, int pnode) uv_activation_descriptor_init(int node, int pnode, int base_pnode)
{ {
int i; int i;
int cpu; int cpu;
@ -1352,11 +1360,11 @@ uv_activation_descriptor_init(int node, int pnode)
n = pa >> uv_nshift; n = pa >> uv_nshift;
m = pa & uv_mmask; m = pa & uv_mmask;
/* the 14-bit pnode */
uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
(n << UV_DESC_BASE_PNODE_SHIFT | m)); (n << UV_DESC_BASE_PNODE_SHIFT | m));
/* /*
* initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each * Initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
* cpu even though we only use the first one; one descriptor can * cpu even though we only use the first one; one descriptor can
* describe a broadcast to 256 uv hubs. * describe a broadcast to 256 uv hubs.
*/ */
@ -1365,12 +1373,13 @@ uv_activation_descriptor_init(int node, int pnode)
memset(bd2, 0, sizeof(struct bau_desc)); memset(bd2, 0, sizeof(struct bau_desc));
bd2->header.sw_ack_flag = 1; bd2->header.sw_ack_flag = 1;
/* /*
* base_dest_nodeid is the nasid of the first uvhub * The base_dest_nasid set in the message header is the nasid
* in the partition. The bit map will indicate uvhub numbers, * of the first uvhub in the partition. The bit map will
* which are 0-N in a partition. Pnodes are unique system-wide. * indicate destination pnode numbers relative to that base.
* They may not be consecutive if nasid striding is being used.
*/ */
bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode); bd2->header.base_dest_nasid = UV_PNODE_TO_NASID(base_pnode);
bd2->header.dest_subnodeid = 0x10; /* the LB */ bd2->header.dest_subnodeid = UV_LB_SUBNODEID;
bd2->header.command = UV_NET_ENDPOINT_INTD; bd2->header.command = UV_NET_ENDPOINT_INTD;
bd2->header.int_both = 1; bd2->header.int_both = 1;
/* /*
@ -1442,7 +1451,7 @@ uv_payload_queue_init(int node, int pnode)
/* /*
* Initialization of each UV hub's structures * Initialization of each UV hub's structures
*/ */
static void __init uv_init_uvhub(int uvhub, int vector) static void __init uv_init_uvhub(int uvhub, int vector, int base_pnode)
{ {
int node; int node;
int pnode; int pnode;
@ -1450,11 +1459,11 @@ static void __init uv_init_uvhub(int uvhub, int vector)
node = uvhub_to_first_node(uvhub); node = uvhub_to_first_node(uvhub);
pnode = uv_blade_to_pnode(uvhub); pnode = uv_blade_to_pnode(uvhub);
uv_activation_descriptor_init(node, pnode); uv_activation_descriptor_init(node, pnode, base_pnode);
uv_payload_queue_init(node, pnode); uv_payload_queue_init(node, pnode);
/* /*
* the below initialization can't be in firmware because the * The below initialization can't be in firmware because the
* messaging IRQ will be determined by the OS * messaging IRQ will be determined by the OS.
*/ */
apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits; apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits;
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
@ -1491,10 +1500,11 @@ calculate_destination_timeout(void)
/* /*
* initialize the bau_control structure for each cpu * initialize the bau_control structure for each cpu
*/ */
static int __init uv_init_per_cpu(int nuvhubs) static int __init uv_init_per_cpu(int nuvhubs, int base_part_pnode)
{ {
int i; int i;
int cpu; int cpu;
int tcpu;
int pnode; int pnode;
int uvhub; int uvhub;
int have_hmaster; int have_hmaster;
@ -1528,6 +1538,15 @@ static int __init uv_init_per_cpu(int nuvhubs)
bcp = &per_cpu(bau_control, cpu); bcp = &per_cpu(bau_control, cpu);
memset(bcp, 0, sizeof(struct bau_control)); memset(bcp, 0, sizeof(struct bau_control));
pnode = uv_cpu_hub_info(cpu)->pnode; pnode = uv_cpu_hub_info(cpu)->pnode;
if ((pnode - base_part_pnode) >= UV_DISTRIBUTION_SIZE) {
printk(KERN_EMERG
"cpu %d pnode %d-%d beyond %d; BAU disabled\n",
cpu, pnode, base_part_pnode,
UV_DISTRIBUTION_SIZE);
return 1;
}
bcp->osnode = cpu_to_node(cpu);
bcp->partition_base_pnode = uv_partition_base_pnode;
uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; uvhub = uv_cpu_hub_info(cpu)->numa_blade_id;
*(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8)); *(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8));
bdp = &uvhub_descs[uvhub]; bdp = &uvhub_descs[uvhub];
@ -1536,7 +1555,7 @@ static int __init uv_init_per_cpu(int nuvhubs)
bdp->pnode = pnode; bdp->pnode = pnode;
/* kludge: 'assuming' one node per socket, and assuming that /* kludge: 'assuming' one node per socket, and assuming that
disabling a socket just leaves a gap in node numbers */ disabling a socket just leaves a gap in node numbers */
socket = (cpu_to_node(cpu) & 1); socket = bcp->osnode & 1;
bdp->socket_mask |= (1 << socket); bdp->socket_mask |= (1 << socket);
sdp = &bdp->socket[socket]; sdp = &bdp->socket[socket];
sdp->cpu_number[sdp->num_cpus] = cpu; sdp->cpu_number[sdp->num_cpus] = cpu;
@ -1585,6 +1604,20 @@ static int __init uv_init_per_cpu(int nuvhubs)
nextsocket: nextsocket:
socket++; socket++;
socket_mask = (socket_mask >> 1); socket_mask = (socket_mask >> 1);
/* each socket gets a local array of pnodes/hubs */
bcp = smaster;
bcp->target_hub_and_pnode = kmalloc_node(
sizeof(struct hub_and_pnode) *
num_possible_cpus(), GFP_KERNEL, bcp->osnode);
memset(bcp->target_hub_and_pnode, 0,
sizeof(struct hub_and_pnode) *
num_possible_cpus());
for_each_present_cpu(tcpu) {
bcp->target_hub_and_pnode[tcpu].pnode =
uv_cpu_hub_info(tcpu)->pnode;
bcp->target_hub_and_pnode[tcpu].uvhub =
uv_cpu_hub_info(tcpu)->numa_blade_id;
}
} }
} }
kfree(uvhub_descs); kfree(uvhub_descs);
@ -1637,21 +1670,22 @@ static int __init uv_bau_init(void)
spin_lock_init(&disable_lock); spin_lock_init(&disable_lock);
congested_cycles = microsec_2_cycles(congested_response_us); congested_cycles = microsec_2_cycles(congested_response_us);
if (uv_init_per_cpu(nuvhubs)) { uv_partition_base_pnode = 0x7fffffff;
for (uvhub = 0; uvhub < nuvhubs; uvhub++) {
if (uv_blade_nr_possible_cpus(uvhub) &&
(uv_blade_to_pnode(uvhub) < uv_partition_base_pnode))
uv_partition_base_pnode = uv_blade_to_pnode(uvhub);
}
if (uv_init_per_cpu(nuvhubs, uv_partition_base_pnode)) {
nobau = 1; nobau = 1;
return 0; return 0;
} }
uv_partition_base_pnode = 0x7fffffff;
for (uvhub = 0; uvhub < nuvhubs; uvhub++)
if (uv_blade_nr_possible_cpus(uvhub) &&
(uv_blade_to_pnode(uvhub) < uv_partition_base_pnode))
uv_partition_base_pnode = uv_blade_to_pnode(uvhub);
vector = UV_BAU_MESSAGE; vector = UV_BAU_MESSAGE;
for_each_possible_blade(uvhub) for_each_possible_blade(uvhub)
if (uv_blade_nr_possible_cpus(uvhub)) if (uv_blade_nr_possible_cpus(uvhub))
uv_init_uvhub(uvhub, vector); uv_init_uvhub(uvhub, vector, uv_partition_base_pnode);
uv_enable_timeouts(); uv_enable_timeouts();
alloc_intr_gate(vector, uv_bau_message_intr1); alloc_intr_gate(vector, uv_bau_message_intr1);

View file

@ -1275,6 +1275,20 @@ static __init void xen_pagetable_setup_start(pgd_t *base)
{ {
} }
static __init void xen_mapping_pagetable_reserve(u64 start, u64 end)
{
/* reserve the range used */
native_pagetable_reserve(start, end);
/* set as RW the rest */
printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n", end,
PFN_PHYS(pgt_buf_top));
while (end < PFN_PHYS(pgt_buf_top)) {
make_lowmem_page_readwrite(__va(end));
end += PAGE_SIZE;
}
}
static void xen_post_allocator_init(void); static void xen_post_allocator_init(void);
static __init void xen_pagetable_setup_done(pgd_t *base) static __init void xen_pagetable_setup_done(pgd_t *base)
@ -1463,119 +1477,6 @@ static int xen_pgd_alloc(struct mm_struct *mm)
return ret; return ret;
} }
#ifdef CONFIG_X86_64
static __initdata u64 __last_pgt_set_rw = 0;
static __initdata u64 __pgt_buf_start = 0;
static __initdata u64 __pgt_buf_end = 0;
static __initdata u64 __pgt_buf_top = 0;
/*
* As a consequence of the commit:
*
* commit 4b239f458c229de044d6905c2b0f9fe16ed9e01e
* Author: Yinghai Lu <yinghai@kernel.org>
* Date: Fri Dec 17 16:58:28 2010 -0800
*
* x86-64, mm: Put early page table high
*
* at some point init_memory_mapping is going to reach the pagetable pages
* area and map those pages too (mapping them as normal memory that falls
* in the range of addresses passed to init_memory_mapping as argument).
* Some of those pages are already pagetable pages (they are in the range
* pgt_buf_start-pgt_buf_end) therefore they are going to be mapped RO and
* everything is fine.
* Some of these pages are not pagetable pages yet (they fall in the range
* pgt_buf_end-pgt_buf_top; for example the page at pgt_buf_end) so they
* are going to be mapped RW. When these pages become pagetable pages and
* are hooked into the pagetable, xen will find that the guest has already
* a RW mapping of them somewhere and fail the operation.
* The reason Xen requires pagetables to be RO is that the hypervisor needs
* to verify that the pagetables are valid before using them. The validation
* operations are called "pinning".
*
* In order to fix the issue we mark all the pages in the entire range
* pgt_buf_start-pgt_buf_top as RO, however when the pagetable allocation
* is completed only the range pgt_buf_start-pgt_buf_end is reserved by
* init_memory_mapping. Hence the kernel is going to crash as soon as one
* of the pages in the range pgt_buf_end-pgt_buf_top is reused (b/c those
* ranges are RO).
*
* For this reason, 'mark_rw_past_pgt' is introduced which is called _after_
* the init_memory_mapping has completed (in a perfect world we would
* call this function from init_memory_mapping, but lets ignore that).
*
* Because we are called _after_ init_memory_mapping the pgt_buf_[start,
* end,top] have all changed to new values (b/c init_memory_mapping
* is called and setting up another new page-table). Hence, the first time
* we enter this function, we save away the pgt_buf_start value and update
* the pgt_buf_[end,top].
*
* When we detect that the "old" pgt_buf_start through pgt_buf_end
* PFNs have been reserved (so memblock_x86_reserve_range has been called),
* we immediately set out to RW the "old" pgt_buf_end through pgt_buf_top.
*
* And then we update those "old" pgt_buf_[end|top] with the new ones
* so that we can redo this on the next pagetable.
*/
static __init void mark_rw_past_pgt(void) {
if (pgt_buf_end > pgt_buf_start) {
u64 addr, size;
/* Save it away. */
if (!__pgt_buf_start) {
__pgt_buf_start = pgt_buf_start;
__pgt_buf_end = pgt_buf_end;
__pgt_buf_top = pgt_buf_top;
return;
}
/* If we get the range that starts at __pgt_buf_end that means
* the range is reserved, and that in 'init_memory_mapping'
* the 'memblock_x86_reserve_range' has been called with the
* outdated __pgt_buf_start, __pgt_buf_end (the "new"
* pgt_buf_[start|end|top] refer now to a new pagetable.
* Note: we are called _after_ the pgt_buf_[..] have been
* updated.*/
addr = memblock_x86_find_in_range_size(PFN_PHYS(__pgt_buf_start),
&size, PAGE_SIZE);
/* Still not reserved, meaning 'memblock_x86_reserve_range'
* hasn't been called yet. Update the _end and _top.*/
if (addr == PFN_PHYS(__pgt_buf_start)) {
__pgt_buf_end = pgt_buf_end;
__pgt_buf_top = pgt_buf_top;
return;
}
/* OK, the area is reserved, meaning it is time for us to
* set RW for the old end->top PFNs. */
/* ..unless we had already done this. */
if (__pgt_buf_end == __last_pgt_set_rw)
return;
addr = PFN_PHYS(__pgt_buf_end);
/* set as RW the rest */
printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n",
PFN_PHYS(__pgt_buf_end), PFN_PHYS(__pgt_buf_top));
while (addr < PFN_PHYS(__pgt_buf_top)) {
make_lowmem_page_readwrite(__va(addr));
addr += PAGE_SIZE;
}
/* And update everything so that we are ready for the next
* pagetable (the one created for regions past 4GB) */
__last_pgt_set_rw = __pgt_buf_end;
__pgt_buf_start = pgt_buf_start;
__pgt_buf_end = pgt_buf_end;
__pgt_buf_top = pgt_buf_top;
}
return;
}
#else
static __init void mark_rw_past_pgt(void) { }
#endif
static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
{ {
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
@ -1601,14 +1502,6 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
{ {
unsigned long pfn = pte_pfn(pte); unsigned long pfn = pte_pfn(pte);
/*
* A bit of optimization. We do not need to call the workaround
* when xen_set_pte_init is called with a PTE with 0 as PFN.
* That is b/c the pagetable at that point are just being populated
* with empty values and we can save some cycles by not calling
* the 'memblock' code.*/
if (pfn)
mark_rw_past_pgt();
/* /*
* If the new pfn is within the range of the newly allocated * If the new pfn is within the range of the newly allocated
* kernel pagetable, and it isn't being mapped into an * kernel pagetable, and it isn't being mapped into an
@ -2118,8 +2011,6 @@ __init void xen_ident_map_ISA(void)
static __init void xen_post_allocator_init(void) static __init void xen_post_allocator_init(void)
{ {
mark_rw_past_pgt();
#ifdef CONFIG_XEN_DEBUG #ifdef CONFIG_XEN_DEBUG
pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
#endif #endif
@ -2228,6 +2119,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
void __init xen_init_mmu_ops(void) void __init xen_init_mmu_ops(void)
{ {
x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve;
x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start;
x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done;
pv_mmu_ops = xen_mmu_ops; pv_mmu_ops = xen_mmu_ops;

View file

@ -114,6 +114,13 @@ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
} }
EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup); EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk)
{
return container_of(task_subsys_state(tsk, blkio_subsys_id),
struct blkio_cgroup, css);
}
EXPORT_SYMBOL_GPL(task_blkio_cgroup);
static inline void static inline void
blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight) blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
{ {

View file

@ -291,6 +291,7 @@ static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
extern struct blkio_cgroup blkio_root_cgroup; extern struct blkio_cgroup blkio_root_cgroup;
extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
extern struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk);
extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
struct blkio_group *blkg, void *key, dev_t dev, struct blkio_group *blkg, void *key, dev_t dev,
enum blkio_policy_id plid); enum blkio_policy_id plid);
@ -314,6 +315,8 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg,
struct cgroup; struct cgroup;
static inline struct blkio_cgroup * static inline struct blkio_cgroup *
cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; } cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
static inline struct blkio_cgroup *
task_blkio_cgroup(struct task_struct *tsk) { return NULL; }
static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
struct blkio_group *blkg, void *key, dev_t dev, struct blkio_group *blkg, void *key, dev_t dev,

View file

@ -316,8 +316,10 @@ EXPORT_SYMBOL(__blk_run_queue);
*/ */
void blk_run_queue_async(struct request_queue *q) void blk_run_queue_async(struct request_queue *q)
{ {
if (likely(!blk_queue_stopped(q))) if (likely(!blk_queue_stopped(q))) {
__cancel_delayed_work(&q->delay_work);
queue_delayed_work(kblockd_workqueue, &q->delay_work, 0); queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
}
} }
EXPORT_SYMBOL(blk_run_queue_async); EXPORT_SYMBOL(blk_run_queue_async);

View file

@ -160,9 +160,8 @@ static void throtl_put_tg(struct throtl_grp *tg)
} }
static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
struct cgroup *cgroup) struct blkio_cgroup *blkcg)
{ {
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
struct throtl_grp *tg = NULL; struct throtl_grp *tg = NULL;
void *key = td; void *key = td;
struct backing_dev_info *bdi = &td->queue->backing_dev_info; struct backing_dev_info *bdi = &td->queue->backing_dev_info;
@ -229,12 +228,12 @@ done:
static struct throtl_grp * throtl_get_tg(struct throtl_data *td) static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
{ {
struct cgroup *cgroup;
struct throtl_grp *tg = NULL; struct throtl_grp *tg = NULL;
struct blkio_cgroup *blkcg;
rcu_read_lock(); rcu_read_lock();
cgroup = task_cgroup(current, blkio_subsys_id); blkcg = task_blkio_cgroup(current);
tg = throtl_find_alloc_tg(td, cgroup); tg = throtl_find_alloc_tg(td, blkcg);
if (!tg) if (!tg)
tg = &td->root_tg; tg = &td->root_tg;
rcu_read_unlock(); rcu_read_unlock();

View file

@ -1014,10 +1014,9 @@ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
cfqg->needs_update = true; cfqg->needs_update = true;
} }
static struct cfq_group * static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd,
cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) struct blkio_cgroup *blkcg, int create)
{ {
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
struct cfq_group *cfqg = NULL; struct cfq_group *cfqg = NULL;
void *key = cfqd; void *key = cfqd;
int i, j; int i, j;
@ -1079,12 +1078,12 @@ done:
*/ */
static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create) static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
{ {
struct cgroup *cgroup; struct blkio_cgroup *blkcg;
struct cfq_group *cfqg = NULL; struct cfq_group *cfqg = NULL;
rcu_read_lock(); rcu_read_lock();
cgroup = task_cgroup(current, blkio_subsys_id); blkcg = task_blkio_cgroup(current);
cfqg = cfq_find_alloc_cfqg(cfqd, cgroup, create); cfqg = cfq_find_alloc_cfqg(cfqd, blkcg, create);
if (!cfqg && create) if (!cfqg && create)
cfqg = &cfqd->root_group; cfqg = &cfqd->root_group;
rcu_read_unlock(); rcu_read_unlock();

View file

@ -561,27 +561,6 @@ void ahci_start_engine(struct ata_port *ap)
{ {
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp; u32 tmp;
u8 status;
status = readl(port_mmio + PORT_TFDATA) & 0xFF;
/*
* At end of section 10.1 of AHCI spec (rev 1.3), it states
* Software shall not set PxCMD.ST to 1 until it is determined
* that a functoinal device is present on the port as determined by
* PxTFD.STS.BSY=0, PxTFD.STS.DRQ=0 and PxSSTS.DET=3h
*
* Even though most AHCI host controllers work without this check,
* specific controller will fail under this condition
*/
if (status & (ATA_BUSY | ATA_DRQ))
return;
else {
ahci_scr_read(&ap->link, SCR_STATUS, &tmp);
if ((tmp & 0xf) != 0x3)
return;
}
/* start DMA */ /* start DMA */
tmp = readl(port_mmio + PORT_CMD); tmp = readl(port_mmio + PORT_CMD);

View file

@ -3316,7 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
struct ata_eh_context *ehc = &link->eh_context; struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
enum ata_lpm_policy old_policy = link->lpm_policy; enum ata_lpm_policy old_policy = link->lpm_policy;
bool no_dipm = ap->flags & ATA_FLAG_NO_DIPM; bool no_dipm = link->ap->flags & ATA_FLAG_NO_DIPM;
unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM; unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
unsigned int err_mask; unsigned int err_mask;
int rc; int rc;

View file

@ -2643,16 +2643,19 @@ fore200e_init(struct fore200e* fore200e, struct device *parent)
} }
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
static const struct of_device_id fore200e_sba_match[];
static int __devinit fore200e_sba_probe(struct platform_device *op) static int __devinit fore200e_sba_probe(struct platform_device *op)
{ {
const struct of_device_id *match;
const struct fore200e_bus *bus; const struct fore200e_bus *bus;
struct fore200e *fore200e; struct fore200e *fore200e;
static int index = 0; static int index = 0;
int err; int err;
if (!op->dev.of_match) match = of_match_device(fore200e_sba_match, &op->dev);
if (!match)
return -EINVAL; return -EINVAL;
bus = op->dev.of_match->data; bus = match->data;
fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
if (!fore200e) if (!fore200e)

View file

@ -2547,7 +2547,6 @@ static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
disk->major = MajorNumber; disk->major = MajorNumber;
disk->first_minor = n << DAC960_MaxPartitionsBits; disk->first_minor = n << DAC960_MaxPartitionsBits;
disk->fops = &DAC960_BlockDeviceOperations; disk->fops = &DAC960_BlockDeviceOperations;
disk->events = DISK_EVENT_MEDIA_CHANGE;
} }
/* /*
Indicate the Block Device Registration completed successfully, Indicate the Block Device Registration completed successfully,

View file

@ -1736,7 +1736,6 @@ static int __init fd_probe_drives(void)
disk->major = FLOPPY_MAJOR; disk->major = FLOPPY_MAJOR;
disk->first_minor = drive; disk->first_minor = drive;
disk->fops = &floppy_fops; disk->fops = &floppy_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disk->disk_name, "fd%d", drive); sprintf(disk->disk_name, "fd%d", drive);
disk->private_data = &unit[drive]; disk->private_data = &unit[drive];
set_capacity(disk, 880*2); set_capacity(disk, 880*2);

View file

@ -1964,7 +1964,6 @@ static int __init atari_floppy_init (void)
unit[i].disk->first_minor = i; unit[i].disk->first_minor = i;
sprintf(unit[i].disk->disk_name, "fd%d", i); sprintf(unit[i].disk->disk_name, "fd%d", i);
unit[i].disk->fops = &floppy_fops; unit[i].disk->fops = &floppy_fops;
unit[i].disk->events = DISK_EVENT_MEDIA_CHANGE;
unit[i].disk->private_data = &unit[i]; unit[i].disk->private_data = &unit[i];
unit[i].disk->queue = blk_init_queue(do_fd_request, unit[i].disk->queue = blk_init_queue(do_fd_request,
&ataflop_lock); &ataflop_lock);

View file

@ -4205,7 +4205,6 @@ static int __init floppy_init(void)
disks[dr]->major = FLOPPY_MAJOR; disks[dr]->major = FLOPPY_MAJOR;
disks[dr]->first_minor = TOMINOR(dr); disks[dr]->first_minor = TOMINOR(dr);
disks[dr]->fops = &floppy_fops; disks[dr]->fops = &floppy_fops;
disks[dr]->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disks[dr]->disk_name, "fd%d", dr); sprintf(disks[dr]->disk_name, "fd%d", dr);
init_timer(&motor_off_timer[dr]); init_timer(&motor_off_timer[dr]);

View file

@ -320,7 +320,6 @@ static void pcd_init_units(void)
disk->first_minor = unit; disk->first_minor = unit;
strcpy(disk->disk_name, cd->name); /* umm... */ strcpy(disk->disk_name, cd->name); /* umm... */
disk->fops = &pcd_bdops; disk->fops = &pcd_bdops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
} }
} }

View file

@ -837,7 +837,6 @@ static void pd_probe_drive(struct pd_unit *disk)
p->fops = &pd_fops; p->fops = &pd_fops;
p->major = major; p->major = major;
p->first_minor = (disk - pd) << PD_BITS; p->first_minor = (disk - pd) << PD_BITS;
p->events = DISK_EVENT_MEDIA_CHANGE;
disk->gd = p; disk->gd = p;
p->private_data = disk; p->private_data = disk;
p->queue = pd_queue; p->queue = pd_queue;

View file

@ -294,7 +294,6 @@ static void __init pf_init_units(void)
disk->first_minor = unit; disk->first_minor = unit;
strcpy(disk->disk_name, pf->name); strcpy(disk->disk_name, pf->name);
disk->fops = &pf_fops; disk->fops = &pf_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
if (!(*drives[unit])[D_PRT]) if (!(*drives[unit])[D_PRT])
pf_drive_count++; pf_drive_count++;
} }

View file

@ -92,6 +92,8 @@ struct rbd_client {
struct list_head node; struct list_head node;
}; };
struct rbd_req_coll;
/* /*
* a single io request * a single io request
*/ */
@ -100,6 +102,24 @@ struct rbd_request {
struct bio *bio; /* cloned bio */ struct bio *bio; /* cloned bio */
struct page **pages; /* list of used pages */ struct page **pages; /* list of used pages */
u64 len; u64 len;
int coll_index;
struct rbd_req_coll *coll;
};
struct rbd_req_status {
int done;
int rc;
u64 bytes;
};
/*
* a collection of requests
*/
struct rbd_req_coll {
int total;
int num_done;
struct kref kref;
struct rbd_req_status status[0];
}; };
struct rbd_snap { struct rbd_snap {
@ -416,6 +436,17 @@ static void rbd_put_client(struct rbd_device *rbd_dev)
rbd_dev->client = NULL; rbd_dev->client = NULL;
} }
/*
* Destroy requests collection
*/
static void rbd_coll_release(struct kref *kref)
{
struct rbd_req_coll *coll =
container_of(kref, struct rbd_req_coll, kref);
dout("rbd_coll_release %p\n", coll);
kfree(coll);
}
/* /*
* Create a new header structure, translate header format from the on-disk * Create a new header structure, translate header format from the on-disk
@ -590,6 +621,14 @@ static u64 rbd_get_segment(struct rbd_image_header *header,
return len; return len;
} }
static int rbd_get_num_segments(struct rbd_image_header *header,
u64 ofs, u64 len)
{
u64 start_seg = ofs >> header->obj_order;
u64 end_seg = (ofs + len - 1) >> header->obj_order;
return end_seg - start_seg + 1;
}
/* /*
* bio helpers * bio helpers
*/ */
@ -735,6 +774,50 @@ static void rbd_destroy_ops(struct ceph_osd_req_op *ops)
kfree(ops); kfree(ops);
} }
static void rbd_coll_end_req_index(struct request *rq,
struct rbd_req_coll *coll,
int index,
int ret, u64 len)
{
struct request_queue *q;
int min, max, i;
dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n",
coll, index, ret, len);
if (!rq)
return;
if (!coll) {
blk_end_request(rq, ret, len);
return;
}
q = rq->q;
spin_lock_irq(q->queue_lock);
coll->status[index].done = 1;
coll->status[index].rc = ret;
coll->status[index].bytes = len;
max = min = coll->num_done;
while (max < coll->total && coll->status[max].done)
max++;
for (i = min; i<max; i++) {
__blk_end_request(rq, coll->status[i].rc,
coll->status[i].bytes);
coll->num_done++;
kref_put(&coll->kref, rbd_coll_release);
}
spin_unlock_irq(q->queue_lock);
}
static void rbd_coll_end_req(struct rbd_request *req,
int ret, u64 len)
{
rbd_coll_end_req_index(req->rq, req->coll, req->coll_index, ret, len);
}
/* /*
* Send ceph osd request * Send ceph osd request
*/ */
@ -749,6 +832,8 @@ static int rbd_do_request(struct request *rq,
int flags, int flags,
struct ceph_osd_req_op *ops, struct ceph_osd_req_op *ops,
int num_reply, int num_reply,
struct rbd_req_coll *coll,
int coll_index,
void (*rbd_cb)(struct ceph_osd_request *req, void (*rbd_cb)(struct ceph_osd_request *req,
struct ceph_msg *msg), struct ceph_msg *msg),
struct ceph_osd_request **linger_req, struct ceph_osd_request **linger_req,
@ -763,12 +848,20 @@ static int rbd_do_request(struct request *rq,
struct ceph_osd_request_head *reqhead; struct ceph_osd_request_head *reqhead;
struct rbd_image_header *header = &dev->header; struct rbd_image_header *header = &dev->header;
ret = -ENOMEM;
req_data = kzalloc(sizeof(*req_data), GFP_NOIO); req_data = kzalloc(sizeof(*req_data), GFP_NOIO);
if (!req_data) if (!req_data) {
goto done; if (coll)
rbd_coll_end_req_index(rq, coll, coll_index,
-ENOMEM, len);
return -ENOMEM;
}
dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs); if (coll) {
req_data->coll = coll;
req_data->coll_index = coll_index;
}
dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs);
down_read(&header->snap_rwsem); down_read(&header->snap_rwsem);
@ -828,7 +921,8 @@ static int rbd_do_request(struct request *rq,
ret = ceph_osdc_wait_request(&dev->client->osdc, req); ret = ceph_osdc_wait_request(&dev->client->osdc, req);
if (ver) if (ver)
*ver = le64_to_cpu(req->r_reassert_version.version); *ver = le64_to_cpu(req->r_reassert_version.version);
dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version)); dout("reassert_ver=%lld\n",
le64_to_cpu(req->r_reassert_version.version));
ceph_osdc_put_request(req); ceph_osdc_put_request(req);
} }
return ret; return ret;
@ -837,10 +931,8 @@ done_err:
bio_chain_put(req_data->bio); bio_chain_put(req_data->bio);
ceph_osdc_put_request(req); ceph_osdc_put_request(req);
done_pages: done_pages:
rbd_coll_end_req(req_data, ret, len);
kfree(req_data); kfree(req_data);
done:
if (rq)
blk_end_request(rq, ret, len);
return ret; return ret;
} }
@ -874,7 +966,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
bytes = req_data->len; bytes = req_data->len;
} }
blk_end_request(req_data->rq, rc, bytes); rbd_coll_end_req(req_data, rc, bytes);
if (req_data->bio) if (req_data->bio)
bio_chain_put(req_data->bio); bio_chain_put(req_data->bio);
@ -934,6 +1026,7 @@ static int rbd_req_sync_op(struct rbd_device *dev,
flags, flags,
ops, ops,
2, 2,
NULL, 0,
NULL, NULL,
linger_req, ver); linger_req, ver);
if (ret < 0) if (ret < 0)
@ -959,7 +1052,9 @@ static int rbd_do_op(struct request *rq,
u64 snapid, u64 snapid,
int opcode, int flags, int num_reply, int opcode, int flags, int num_reply,
u64 ofs, u64 len, u64 ofs, u64 len,
struct bio *bio) struct bio *bio,
struct rbd_req_coll *coll,
int coll_index)
{ {
char *seg_name; char *seg_name;
u64 seg_ofs; u64 seg_ofs;
@ -995,7 +1090,10 @@ static int rbd_do_op(struct request *rq,
flags, flags,
ops, ops,
num_reply, num_reply,
coll, coll_index,
rbd_req_cb, 0, NULL); rbd_req_cb, 0, NULL);
rbd_destroy_ops(ops);
done: done:
kfree(seg_name); kfree(seg_name);
return ret; return ret;
@ -1008,13 +1106,15 @@ static int rbd_req_write(struct request *rq,
struct rbd_device *rbd_dev, struct rbd_device *rbd_dev,
struct ceph_snap_context *snapc, struct ceph_snap_context *snapc,
u64 ofs, u64 len, u64 ofs, u64 len,
struct bio *bio) struct bio *bio,
struct rbd_req_coll *coll,
int coll_index)
{ {
return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
CEPH_OSD_OP_WRITE, CEPH_OSD_OP_WRITE,
CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
2, 2,
ofs, len, bio); ofs, len, bio, coll, coll_index);
} }
/* /*
@ -1024,14 +1124,16 @@ static int rbd_req_read(struct request *rq,
struct rbd_device *rbd_dev, struct rbd_device *rbd_dev,
u64 snapid, u64 snapid,
u64 ofs, u64 len, u64 ofs, u64 len,
struct bio *bio) struct bio *bio,
struct rbd_req_coll *coll,
int coll_index)
{ {
return rbd_do_op(rq, rbd_dev, NULL, return rbd_do_op(rq, rbd_dev, NULL,
(snapid ? snapid : CEPH_NOSNAP), (snapid ? snapid : CEPH_NOSNAP),
CEPH_OSD_OP_READ, CEPH_OSD_OP_READ,
CEPH_OSD_FLAG_READ, CEPH_OSD_FLAG_READ,
2, 2,
ofs, len, bio); ofs, len, bio, coll, coll_index);
} }
/* /*
@ -1063,7 +1165,9 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev,
{ {
struct ceph_osd_req_op *ops; struct ceph_osd_req_op *ops;
struct page **pages = NULL; struct page **pages = NULL;
int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); int ret;
ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1077,6 +1181,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev,
CEPH_OSD_FLAG_READ, CEPH_OSD_FLAG_READ,
ops, ops,
1, 1,
NULL, 0,
rbd_simple_req_cb, 0, NULL); rbd_simple_req_cb, 0, NULL);
rbd_destroy_ops(ops); rbd_destroy_ops(ops);
@ -1274,6 +1379,20 @@ static int rbd_req_sync_exec(struct rbd_device *dev,
return ret; return ret;
} }
static struct rbd_req_coll *rbd_alloc_coll(int num_reqs)
{
struct rbd_req_coll *coll =
kzalloc(sizeof(struct rbd_req_coll) +
sizeof(struct rbd_req_status) * num_reqs,
GFP_ATOMIC);
if (!coll)
return NULL;
coll->total = num_reqs;
kref_init(&coll->kref);
return coll;
}
/* /*
* block device queue callback * block device queue callback
*/ */
@ -1291,6 +1410,8 @@ static void rbd_rq_fn(struct request_queue *q)
bool do_write; bool do_write;
int size, op_size = 0; int size, op_size = 0;
u64 ofs; u64 ofs;
int num_segs, cur_seg = 0;
struct rbd_req_coll *coll;
/* peek at request from block layer */ /* peek at request from block layer */
if (!rq) if (!rq)
@ -1321,6 +1442,14 @@ static void rbd_rq_fn(struct request_queue *q)
do_write ? "write" : "read", do_write ? "write" : "read",
size, blk_rq_pos(rq) * 512ULL); size, blk_rq_pos(rq) * 512ULL);
num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size);
coll = rbd_alloc_coll(num_segs);
if (!coll) {
spin_lock_irq(q->queue_lock);
__blk_end_request_all(rq, -ENOMEM);
goto next;
}
do { do {
/* a bio clone to be passed down to OSD req */ /* a bio clone to be passed down to OSD req */
dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt);
@ -1328,35 +1457,41 @@ static void rbd_rq_fn(struct request_queue *q)
rbd_dev->header.block_name, rbd_dev->header.block_name,
ofs, size, ofs, size,
NULL, NULL); NULL, NULL);
kref_get(&coll->kref);
bio = bio_chain_clone(&rq_bio, &next_bio, &bp, bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
op_size, GFP_ATOMIC); op_size, GFP_ATOMIC);
if (!bio) { if (!bio) {
spin_lock_irq(q->queue_lock); rbd_coll_end_req_index(rq, coll, cur_seg,
__blk_end_request_all(rq, -ENOMEM); -ENOMEM, op_size);
goto next; goto next_seg;
} }
/* init OSD command: write or read */ /* init OSD command: write or read */
if (do_write) if (do_write)
rbd_req_write(rq, rbd_dev, rbd_req_write(rq, rbd_dev,
rbd_dev->header.snapc, rbd_dev->header.snapc,
ofs, ofs,
op_size, bio); op_size, bio,
coll, cur_seg);
else else
rbd_req_read(rq, rbd_dev, rbd_req_read(rq, rbd_dev,
cur_snap_id(rbd_dev), cur_snap_id(rbd_dev),
ofs, ofs,
op_size, bio); op_size, bio,
coll, cur_seg);
next_seg:
size -= op_size; size -= op_size;
ofs += op_size; ofs += op_size;
cur_seg++;
rq_bio = next_bio; rq_bio = next_bio;
} while (size > 0); } while (size > 0);
kref_put(&coll->kref, rbd_coll_release);
if (bp) if (bp)
bio_pair_release(bp); bio_pair_release(bp);
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
next: next:
rq = blk_fetch_request(q); rq = blk_fetch_request(q);

View file

@ -858,7 +858,6 @@ static int __devinit swim_floppy_init(struct swim_priv *swd)
swd->unit[drive].disk->first_minor = drive; swd->unit[drive].disk->first_minor = drive;
sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive); sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
swd->unit[drive].disk->fops = &floppy_fops; swd->unit[drive].disk->fops = &floppy_fops;
swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE;
swd->unit[drive].disk->private_data = &swd->unit[drive]; swd->unit[drive].disk->private_data = &swd->unit[drive];
swd->unit[drive].disk->queue = swd->queue; swd->unit[drive].disk->queue = swd->queue;
set_capacity(swd->unit[drive].disk, 2880); set_capacity(swd->unit[drive].disk, 2880);

View file

@ -1163,7 +1163,6 @@ static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device
disk->major = FLOPPY_MAJOR; disk->major = FLOPPY_MAJOR;
disk->first_minor = i; disk->first_minor = i;
disk->fops = &floppy_fops; disk->fops = &floppy_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = &floppy_states[i]; disk->private_data = &floppy_states[i];
disk->queue = swim3_queue; disk->queue = swim3_queue;
disk->flags |= GENHD_FL_REMOVABLE; disk->flags |= GENHD_FL_REMOVABLE;

View file

@ -2334,7 +2334,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->major = UB_MAJOR; disk->major = UB_MAJOR;
disk->first_minor = lun->id * UB_PARTS_PER_LUN; disk->first_minor = lun->id * UB_PARTS_PER_LUN;
disk->fops = &ub_bd_fops; disk->fops = &ub_bd_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = lun; disk->private_data = lun;
disk->driverfs_dev = &sc->intf->dev; disk->driverfs_dev = &sc->intf->dev;

View file

@ -1005,7 +1005,6 @@ static int __devinit ace_setup(struct ace_device *ace)
ace->gd->major = ace_major; ace->gd->major = ace_major;
ace->gd->first_minor = ace->id * ACE_NUM_MINORS; ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
ace->gd->fops = &ace_fops; ace->gd->fops = &ace_fops;
ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
ace->gd->queue = ace->queue; ace->gd->queue = ace->queue;
ace->gd->private_data = ace; ace->gd->private_data = ace;
snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');

View file

@ -986,6 +986,9 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t
cdinfo(CD_OPEN, "entering cdrom_open\n"); cdinfo(CD_OPEN, "entering cdrom_open\n");
/* open is event synchronization point, check events first */
check_disk_change(bdev);
/* if this was a O_NONBLOCK open and we should honor the flags, /* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */ * do a quick open without drive/disc integrity checks. */
cdi->use_count++; cdi->use_count++;
@ -1012,9 +1015,6 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t
cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
cdi->name, cdi->use_count); cdi->name, cdi->use_count);
/* Do this on open. Don't wait for mount, because they might
not be mounting, but opening with O_NONBLOCK */
check_disk_change(bdev);
return 0; return 0;
err_release: err_release:
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {

View file

@ -803,7 +803,6 @@ static int __devinit probe_gdrom(struct platform_device *devptr)
goto probe_fail_cdrom_register; goto probe_fail_cdrom_register;
} }
gd.disk->fops = &gdrom_bdops; gd.disk->fops = &gdrom_bdops;
gd.disk->events = DISK_EVENT_MEDIA_CHANGE;
/* latch on to the interrupt */ /* latch on to the interrupt */
err = gdrom_set_interrupt_handlers(); err = gdrom_set_interrupt_handlers();
if (err) if (err)

View file

@ -626,7 +626,6 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
gendisk->queue = q; gendisk->queue = q;
gendisk->fops = &viocd_fops; gendisk->fops = &viocd_fops;
gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE; gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE;
gendisk->events = DISK_EVENT_MEDIA_CHANGE;
set_capacity(gendisk, 0); set_capacity(gendisk, 0);
gendisk->private_data = d; gendisk->private_data = d;
d->viocd_disk = gendisk; d->viocd_disk = gendisk;

View file

@ -619,15 +619,18 @@ static void __devinit n2rng_driver_version(void)
pr_info("%s", version); pr_info("%s", version);
} }
static const struct of_device_id n2rng_match[];
static int __devinit n2rng_probe(struct platform_device *op) static int __devinit n2rng_probe(struct platform_device *op)
{ {
const struct of_device_id *match;
int victoria_falls; int victoria_falls;
int err = -ENOMEM; int err = -ENOMEM;
struct n2rng *np; struct n2rng *np;
if (!op->dev.of_match) match = of_match_device(n2rng_match, &op->dev);
if (!match)
return -EINVAL; return -EINVAL;
victoria_falls = (op->dev.of_match->data != NULL); victoria_falls = (match->data != NULL);
n2rng_driver_version(); n2rng_driver_version();
np = kzalloc(sizeof(*np), GFP_KERNEL); np = kzalloc(sizeof(*np), GFP_KERNEL);

View file

@ -2554,9 +2554,11 @@ static struct pci_driver ipmi_pci_driver = {
}; };
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
static struct of_device_id ipmi_match[];
static int __devinit ipmi_probe(struct platform_device *dev) static int __devinit ipmi_probe(struct platform_device *dev)
{ {
#ifdef CONFIG_OF #ifdef CONFIG_OF
const struct of_device_id *match;
struct smi_info *info; struct smi_info *info;
struct resource resource; struct resource resource;
const __be32 *regsize, *regspacing, *regshift; const __be32 *regsize, *regspacing, *regshift;
@ -2566,7 +2568,8 @@ static int __devinit ipmi_probe(struct platform_device *dev)
dev_info(&dev->dev, "probing via device tree\n"); dev_info(&dev->dev, "probing via device tree\n");
if (!dev->dev.of_match) match = of_match_device(ipmi_match, &dev->dev);
if (!match)
return -EINVAL; return -EINVAL;
ret = of_address_to_resource(np, 0, &resource); ret = of_address_to_resource(np, 0, &resource);
@ -2601,7 +2604,7 @@ static int __devinit ipmi_probe(struct platform_device *dev)
return -ENOMEM; return -ENOMEM;
} }
info->si_type = (enum si_type) dev->dev.of_match->data; info->si_type = (enum si_type) match->data;
info->addr_source = SI_DEVICETREE; info->addr_source = SI_DEVICETREE;
info->irq_setup = std_irq_setup; info->irq_setup = std_irq_setup;

View file

@ -715,13 +715,13 @@ static int __devexit hwicap_remove(struct device *dev)
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int __devinit hwicap_of_probe(struct platform_device *op) static int __devinit hwicap_of_probe(struct platform_device *op,
const struct hwicap_driver_config *config)
{ {
struct resource res; struct resource res;
const unsigned int *id; const unsigned int *id;
const char *family; const char *family;
int rc; int rc;
const struct hwicap_driver_config *config = op->dev.of_match->data;
const struct config_registers *regs; const struct config_registers *regs;
@ -751,20 +751,24 @@ static int __devinit hwicap_of_probe(struct platform_device *op)
regs); regs);
} }
#else #else
static inline int hwicap_of_probe(struct platform_device *op) static inline int hwicap_of_probe(struct platform_device *op,
const struct hwicap_driver_config *config)
{ {
return -EINVAL; return -EINVAL;
} }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static const struct of_device_id __devinitconst hwicap_of_match[];
static int __devinit hwicap_drv_probe(struct platform_device *pdev) static int __devinit hwicap_drv_probe(struct platform_device *pdev)
{ {
const struct of_device_id *match;
struct resource *res; struct resource *res;
const struct config_registers *regs; const struct config_registers *regs;
const char *family; const char *family;
if (pdev->dev.of_match) match = of_match_device(hwicap_of_match, &pdev->dev);
return hwicap_of_probe(pdev); if (match)
return hwicap_of_probe(pdev, match->data);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) if (!res)

View file

@ -1019,7 +1019,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
struct ppc4xx_edac_pdata *pdata = NULL; struct ppc4xx_edac_pdata *pdata = NULL;
const struct device_node *np = op->dev.of_node; const struct device_node *np = op->dev.of_node;
if (op->dev.of_match == NULL) if (of_match_device(ppc4xx_edac_match, &op->dev) == NULL)
return -EINVAL; return -EINVAL;
/* Initial driver pointers and private data */ /* Initial driver pointers and private data */

View file

@ -1516,17 +1516,33 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
} }
EXPORT_SYMBOL(drm_fb_helper_initial_config); EXPORT_SYMBOL(drm_fb_helper_initial_config);
bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) /**
* drm_fb_helper_hotplug_event - respond to a hotplug notification by
* probing all the outputs attached to the fb.
* @fb_helper: the drm_fb_helper
*
* LOCKING:
* Called at runtime, must take mode config lock.
*
* Scan the connectors attached to the fb_helper and try to put together a
* setup after *notification of a change in output configuration.
*
* RETURNS:
* 0 on success and a non-zero error code otherwise.
*/
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
{ {
struct drm_device *dev = fb_helper->dev;
int count = 0; int count = 0;
u32 max_width, max_height, bpp_sel; u32 max_width, max_height, bpp_sel;
bool bound = false, crtcs_bound = false; bool bound = false, crtcs_bound = false;
struct drm_crtc *crtc; struct drm_crtc *crtc;
if (!fb_helper->fb) if (!fb_helper->fb)
return false; return 0;
list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) { mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (crtc->fb) if (crtc->fb)
crtcs_bound = true; crtcs_bound = true;
if (crtc->fb == fb_helper->fb) if (crtc->fb == fb_helper->fb)
@ -1535,7 +1551,8 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
if (!bound && crtcs_bound) { if (!bound && crtcs_bound) {
fb_helper->delayed_hotplug = true; fb_helper->delayed_hotplug = true;
return false; mutex_unlock(&dev->mode_config.mutex);
return 0;
} }
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
@ -1546,6 +1563,7 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
max_height); max_height);
drm_setup_crtcs(fb_helper); drm_setup_crtcs(fb_helper);
mutex_unlock(&dev->mode_config.mutex);
return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
} }

View file

@ -49,7 +49,7 @@ module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
unsigned int i915_powersave = 1; unsigned int i915_powersave = 1;
module_param_named(powersave, i915_powersave, int, 0600); module_param_named(powersave, i915_powersave, int, 0600);
unsigned int i915_semaphores = 1; unsigned int i915_semaphores = 0;
module_param_named(semaphores, i915_semaphores, int, 0600); module_param_named(semaphores, i915_semaphores, int, 0600);
unsigned int i915_enable_rc6 = 0; unsigned int i915_enable_rc6 = 0;

View file

@ -5154,6 +5154,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(DSPCNTR(plane), dspcntr); I915_WRITE(DSPCNTR(plane), dspcntr);
POSTING_READ(DSPCNTR(plane)); POSTING_READ(DSPCNTR(plane));
if (!HAS_PCH_SPLIT(dev))
intel_enable_plane(dev_priv, plane, pipe);
ret = intel_pipe_set_base(crtc, x, y, old_fb); ret = intel_pipe_set_base(crtc, x, y, old_fb);

View file

@ -1780,7 +1780,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
mc_shared_chmap = RREG32(MC_SHARED_CHMAP); mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); if (rdev->flags & RADEON_IS_IGP)
mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG);
else
mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
switch (rdev->config.evergreen.max_tile_pipes) { switch (rdev->config.evergreen.max_tile_pipes) {
case 1: case 1:

View file

@ -200,6 +200,7 @@
#define BURSTLENGTH_SHIFT 9 #define BURSTLENGTH_SHIFT 9
#define BURSTLENGTH_MASK 0x00000200 #define BURSTLENGTH_MASK 0x00000200
#define CHANSIZE_OVERRIDE (1 << 11) #define CHANSIZE_OVERRIDE (1 << 11)
#define FUS_MC_ARB_RAMCFG 0x2768
#define MC_VM_AGP_TOP 0x2028 #define MC_VM_AGP_TOP 0x2028
#define MC_VM_AGP_BOT 0x202C #define MC_VM_AGP_BOT 0x202C
#define MC_VM_AGP_BASE 0x2030 #define MC_VM_AGP_BASE 0x2030

View file

@ -1574,9 +1574,17 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record; ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
bool bad_record = false; bool bad_record = false;
u8 *record = (u8 *)(mode_info->atom_context->bios + u8 *record;
data_offset +
le16_to_cpu(lvds_info->info.usModePatchTableOffset)); if ((frev == 1) && (crev < 2))
/* absolute */
record = (u8 *)(mode_info->atom_context->bios +
le16_to_cpu(lvds_info->info.usModePatchTableOffset));
else
/* relative */
record = (u8 *)(mode_info->atom_context->bios +
data_offset +
le16_to_cpu(lvds_info->info.usModePatchTableOffset));
while (*record != ATOM_RECORD_END_TYPE) { while (*record != ATOM_RECORD_END_TYPE) {
switch (*record) { switch (*record) {
case LCD_MODE_PATCH_RECORD_MODE_TYPE: case LCD_MODE_PATCH_RECORD_MODE_TYPE:

View file

@ -33,6 +33,7 @@ cayman 0x9400
0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
0x00009100 SPI_CONFIG_CNTL 0x00009100 SPI_CONFIG_CNTL
0x0000913C SPI_CONFIG_CNTL_1 0x0000913C SPI_CONFIG_CNTL_1
0x00009508 TA_CNTL_AUX
0x00009830 DB_DEBUG 0x00009830 DB_DEBUG
0x00009834 DB_DEBUG2 0x00009834 DB_DEBUG2
0x00009838 DB_DEBUG3 0x00009838 DB_DEBUG3

View file

@ -46,6 +46,7 @@ evergreen 0x9400
0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
0x00009100 SPI_CONFIG_CNTL 0x00009100 SPI_CONFIG_CNTL
0x0000913C SPI_CONFIG_CNTL_1 0x0000913C SPI_CONFIG_CNTL_1
0x00009508 TA_CNTL_AUX
0x00009700 VC_CNTL 0x00009700 VC_CNTL
0x00009714 VC_ENHANCE 0x00009714 VC_ENHANCE
0x00009830 DB_DEBUG 0x00009830 DB_DEBUG

View file

@ -219,9 +219,6 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
int i; int i;
struct vga_switcheroo_client *active = NULL; struct vga_switcheroo_client *active = NULL;
if (new_client->active == true)
return 0;
for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
if (vgasr_priv.clients[i].active == true) { if (vgasr_priv.clients[i].active == true) {
active = &vgasr_priv.clients[i]; active = &vgasr_priv.clients[i];
@ -372,6 +369,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
goto out; goto out;
} }
if (client->active == true)
goto out;
/* okay we want a switch - test if devices are willing to switch */ /* okay we want a switch - test if devices are willing to switch */
can_switch = true; can_switch = true;
for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {

View file

@ -560,15 +560,18 @@ static struct i2c_adapter mpc_ops = {
.timeout = HZ, .timeout = HZ,
}; };
static const struct of_device_id mpc_i2c_of_match[];
static int __devinit fsl_i2c_probe(struct platform_device *op) static int __devinit fsl_i2c_probe(struct platform_device *op)
{ {
const struct of_device_id *match;
struct mpc_i2c *i2c; struct mpc_i2c *i2c;
const u32 *prop; const u32 *prop;
u32 clock = MPC_I2C_CLOCK_LEGACY; u32 clock = MPC_I2C_CLOCK_LEGACY;
int result = 0; int result = 0;
int plen; int plen;
if (!op->dev.of_match) match = of_match_device(mpc_i2c_of_match, &op->dev);
if (!match)
return -EINVAL; return -EINVAL;
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
@ -605,8 +608,8 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)
clock = *prop; clock = *prop;
} }
if (op->dev.of_match->data) { if (match->data) {
struct mpc_i2c_data *data = op->dev.of_match->data; struct mpc_i2c_data *data = match->data;
data->setup(op->dev.of_node, i2c, clock, data->prescaler); data->setup(op->dev.of_node, i2c, clock, data->prescaler);
} else { } else {
/* Backwards compatibility */ /* Backwards compatibility */

View file

@ -65,7 +65,7 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
jiffies, expires); jiffies, expires);
timer->expires = jiffies + expires; timer->expires = jiffies + expires;
timer->data = (unsigned long)&alg_data; timer->data = (unsigned long)alg_data;
add_timer(timer); add_timer(timer);
} }

View file

@ -281,17 +281,24 @@ struct ser_req {
u8 command; u8 command;
u8 ref_off; u8 ref_off;
u16 scratch; u16 scratch;
__be16 sample;
struct spi_message msg; struct spi_message msg;
struct spi_transfer xfer[6]; struct spi_transfer xfer[6];
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 sample ____cacheline_aligned;
}; };
struct ads7845_ser_req { struct ads7845_ser_req {
u8 command[3]; u8 command[3];
u8 pwrdown[3];
u8 sample[3];
struct spi_message msg; struct spi_message msg;
struct spi_transfer xfer[2]; struct spi_transfer xfer[2];
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
u8 sample[3] ____cacheline_aligned;
}; };
static int ads7846_read12_ser(struct device *dev, unsigned command) static int ads7846_read12_ser(struct device *dev, unsigned command)

View file

@ -349,6 +349,7 @@ static const struct i2c_device_id lm3530_id[] = {
{LM3530_NAME, 0}, {LM3530_NAME, 0},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, lm3530_id);
static struct i2c_driver lm3530_i2c_driver = { static struct i2c_driver lm3530_i2c_driver = {
.probe = lm3530_probe, .probe = lm3530_probe,

View file

@ -524,7 +524,7 @@ void cx88_ir_irq(struct cx88_core *core)
for (todo = 32; todo > 0; todo -= bits) { for (todo = 32; todo > 0; todo -= bits) {
ev.pulse = samples & 0x80000000 ? false : true; ev.pulse = samples & 0x80000000 ? false : true;
bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples)); bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate); ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
ir_raw_event_store_with_filter(ir->dev, &ev); ir_raw_event_store_with_filter(ir->dev, &ev);
samples <<= bits; samples <<= bits;
} }

View file

@ -136,11 +136,50 @@ unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
} }
EXPORT_SYMBOL(soc_camera_apply_sensor_flags); EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
((x) >> 24) & 0xff
static int soc_camera_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_pix_format *pix = &f->fmt.pix;
int ret;
dev_dbg(&icd->dev, "TRY_FMT(%c%c%c%c, %ux%u)\n",
pixfmtstr(pix->pixelformat), pix->width, pix->height);
pix->bytesperline = 0;
pix->sizeimage = 0;
ret = ici->ops->try_fmt(icd, f);
if (ret < 0)
return ret;
if (!pix->sizeimage) {
if (!pix->bytesperline) {
const struct soc_camera_format_xlate *xlate;
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate)
return -EINVAL;
ret = soc_mbus_bytes_per_line(pix->width,
xlate->host_fmt);
if (ret > 0)
pix->bytesperline = ret;
}
if (pix->bytesperline)
pix->sizeimage = pix->bytesperline * pix->height;
}
return 0;
}
static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct soc_camera_device *icd = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
@ -149,7 +188,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
/* limit format to hardware capabilities */ /* limit format to hardware capabilities */
return ici->ops->try_fmt(icd, f); return soc_camera_try_fmt(icd, f);
} }
static int soc_camera_enum_input(struct file *file, void *priv, static int soc_camera_enum_input(struct file *file, void *priv,
@ -362,9 +401,6 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
icd->user_formats = NULL; icd->user_formats = NULL;
} }
#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
((x) >> 24) & 0xff
/* Called with .vb_lock held, or from the first open(2), see comment there */ /* Called with .vb_lock held, or from the first open(2), see comment there */
static int soc_camera_set_fmt(struct soc_camera_device *icd, static int soc_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f) struct v4l2_format *f)
@ -377,7 +413,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
pixfmtstr(pix->pixelformat), pix->width, pix->height); pixfmtstr(pix->pixelformat), pix->width, pix->height);
/* We always call try_fmt() before set_fmt() or set_crop() */ /* We always call try_fmt() before set_fmt() or set_crop() */
ret = ici->ops->try_fmt(icd, f); ret = soc_camera_try_fmt(icd, f);
if (ret < 0) if (ret < 0)
return ret; return ret;

View file

@ -155,8 +155,10 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
sd->v4l2_dev = v4l2_dev; sd->v4l2_dev = v4l2_dev;
if (sd->internal_ops && sd->internal_ops->registered) { if (sd->internal_ops && sd->internal_ops->registered) {
err = sd->internal_ops->registered(sd); err = sd->internal_ops->registered(sd);
if (err) if (err) {
module_put(sd->owner);
return err; return err;
}
} }
/* This just returns 0 if either of the two args is NULL */ /* This just returns 0 if either of the two args is NULL */
@ -164,6 +166,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
if (err) { if (err) {
if (sd->internal_ops && sd->internal_ops->unregistered) if (sd->internal_ops && sd->internal_ops->unregistered)
sd->internal_ops->unregistered(sd); sd->internal_ops->unregistered(sd);
module_put(sd->owner);
return err; return err;
} }

View file

@ -155,25 +155,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
switch (cmd) { switch (cmd) {
case VIDIOC_QUERYCTRL: case VIDIOC_QUERYCTRL:
return v4l2_subdev_queryctrl(sd, arg); return v4l2_queryctrl(sd->ctrl_handler, arg);
case VIDIOC_QUERYMENU: case VIDIOC_QUERYMENU:
return v4l2_subdev_querymenu(sd, arg); return v4l2_querymenu(sd->ctrl_handler, arg);
case VIDIOC_G_CTRL: case VIDIOC_G_CTRL:
return v4l2_subdev_g_ctrl(sd, arg); return v4l2_g_ctrl(sd->ctrl_handler, arg);
case VIDIOC_S_CTRL: case VIDIOC_S_CTRL:
return v4l2_subdev_s_ctrl(sd, arg); return v4l2_s_ctrl(sd->ctrl_handler, arg);
case VIDIOC_G_EXT_CTRLS: case VIDIOC_G_EXT_CTRLS:
return v4l2_subdev_g_ext_ctrls(sd, arg); return v4l2_g_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_S_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS:
return v4l2_subdev_s_ext_ctrls(sd, arg); return v4l2_s_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_TRY_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS:
return v4l2_subdev_try_ext_ctrls(sd, arg); return v4l2_try_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_DQEVENT: case VIDIOC_DQEVENT:
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))

View file

@ -1000,7 +1000,6 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
gd->major = I2O_MAJOR; gd->major = I2O_MAJOR;
gd->queue = queue; gd->queue = queue;
gd->fops = &i2o_block_fops; gd->fops = &i2o_block_fops;
gd->events = DISK_EVENT_MEDIA_CHANGE;
gd->private_data = dev; gd->private_data = dev;
dev->gd = gd; dev->gd = gd;

View file

@ -94,7 +94,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
spin_unlock_irqrestore(&host->clk_lock, flags); spin_unlock_irqrestore(&host->clk_lock, flags);
return; return;
} }
mmc_claim_host(host); mutex_lock(&host->clk_gate_mutex);
spin_lock_irqsave(&host->clk_lock, flags); spin_lock_irqsave(&host->clk_lock, flags);
if (!host->clk_requests) { if (!host->clk_requests) {
spin_unlock_irqrestore(&host->clk_lock, flags); spin_unlock_irqrestore(&host->clk_lock, flags);
@ -104,7 +104,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
pr_debug("%s: gated MCI clock\n", mmc_hostname(host)); pr_debug("%s: gated MCI clock\n", mmc_hostname(host));
} }
spin_unlock_irqrestore(&host->clk_lock, flags); spin_unlock_irqrestore(&host->clk_lock, flags);
mmc_release_host(host); mutex_unlock(&host->clk_gate_mutex);
} }
/* /*
@ -130,7 +130,7 @@ void mmc_host_clk_ungate(struct mmc_host *host)
{ {
unsigned long flags; unsigned long flags;
mmc_claim_host(host); mutex_lock(&host->clk_gate_mutex);
spin_lock_irqsave(&host->clk_lock, flags); spin_lock_irqsave(&host->clk_lock, flags);
if (host->clk_gated) { if (host->clk_gated) {
spin_unlock_irqrestore(&host->clk_lock, flags); spin_unlock_irqrestore(&host->clk_lock, flags);
@ -140,7 +140,7 @@ void mmc_host_clk_ungate(struct mmc_host *host)
} }
host->clk_requests++; host->clk_requests++;
spin_unlock_irqrestore(&host->clk_lock, flags); spin_unlock_irqrestore(&host->clk_lock, flags);
mmc_release_host(host); mutex_unlock(&host->clk_gate_mutex);
} }
/** /**
@ -215,6 +215,7 @@ static inline void mmc_host_clk_init(struct mmc_host *host)
host->clk_gated = false; host->clk_gated = false;
INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
spin_lock_init(&host->clk_lock); spin_lock_init(&host->clk_lock);
mutex_init(&host->clk_gate_mutex);
} }
/** /**

View file

@ -124,8 +124,10 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
#endif #endif
} }
static const struct of_device_id sdhci_of_match[];
static int __devinit sdhci_of_probe(struct platform_device *ofdev) static int __devinit sdhci_of_probe(struct platform_device *ofdev)
{ {
const struct of_device_id *match;
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
struct sdhci_of_data *sdhci_of_data; struct sdhci_of_data *sdhci_of_data;
struct sdhci_host *host; struct sdhci_host *host;
@ -134,9 +136,10 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev)
int size; int size;
int ret; int ret;
if (!ofdev->dev.of_match) match = of_match_device(sdhci_of_match, &ofdev->dev);
if (!match)
return -EINVAL; return -EINVAL;
sdhci_of_data = ofdev->dev.of_match->data; sdhci_of_data = match->data;
if (!of_device_is_available(np)) if (!of_device_is_available(np))
return -ENODEV; return -ENODEV;

View file

@ -214,11 +214,13 @@ static void __devinit of_free_probes(const char **probes)
} }
#endif #endif
static struct of_device_id of_flash_match[];
static int __devinit of_flash_probe(struct platform_device *dev) static int __devinit of_flash_probe(struct platform_device *dev)
{ {
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
const char **part_probe_types; const char **part_probe_types;
#endif #endif
const struct of_device_id *match;
struct device_node *dp = dev->dev.of_node; struct device_node *dp = dev->dev.of_node;
struct resource res; struct resource res;
struct of_flash *info; struct of_flash *info;
@ -232,9 +234,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
struct mtd_info **mtd_list = NULL; struct mtd_info **mtd_list = NULL;
resource_size_t res_size; resource_size_t res_size;
if (!dev->dev.of_match) match = of_match_device(of_flash_match, &dev->dev);
if (!match)
return -EINVAL; return -EINVAL;
probe_type = dev->dev.of_match->data; probe_type = match->data;
reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32); reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);

View file

@ -144,7 +144,7 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o
obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_B44) += b44.o
obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_FORCEDETH) += forcedeth.o
obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o obj-$(CONFIG_NE_H8300) += ne-h8300.o
obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_AX88796) += ax88796.o
obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
obj-$(CONFIG_FTMAC100) += ftmac100.o obj-$(CONFIG_FTMAC100) += ftmac100.o
@ -219,7 +219,7 @@ obj-$(CONFIG_SC92031) += sc92031.o
obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_LP486E) += lp486e.o
obj-$(CONFIG_ETH16I) += eth16i.o obj-$(CONFIG_ETH16I) += eth16i.o
obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o obj-$(CONFIG_ZORRO8390) += zorro8390.o
obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
obj-$(CONFIG_EQUALIZER) += eql.o obj-$(CONFIG_EQUALIZER) += eql.o
@ -231,7 +231,7 @@ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_DECLANCE) += declance.o obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o obj-$(CONFIG_ATARILANCE) += atarilance.o
obj-$(CONFIG_A2065) += a2065.o obj-$(CONFIG_A2065) += a2065.o
obj-$(CONFIG_HYDRA) += hydra.o 8390.o obj-$(CONFIG_HYDRA) += hydra.o
obj-$(CONFIG_ARIADNE) += ariadne.o obj-$(CONFIG_ARIADNE) += ariadne.o
obj-$(CONFIG_CS89x0) += cs89x0.o obj-$(CONFIG_CS89x0) += cs89x0.o
obj-$(CONFIG_MACSONIC) += macsonic.o obj-$(CONFIG_MACSONIC) += macsonic.o

View file

@ -39,7 +39,7 @@
typedef struct mac_addr { typedef struct mac_addr {
u8 mac_addr_value[ETH_ALEN]; u8 mac_addr_value[ETH_ALEN];
} mac_addr_t; } __packed mac_addr_t;
enum { enum {
BOND_AD_STABLE = 0, BOND_AD_STABLE = 0,
@ -134,12 +134,12 @@ typedef struct lacpdu {
u8 tlv_type_terminator; // = terminator u8 tlv_type_terminator; // = terminator
u8 terminator_length; // = 0 u8 terminator_length; // = 0
u8 reserved_50[50]; // = 0 u8 reserved_50[50]; // = 0
} lacpdu_t; } __packed lacpdu_t;
typedef struct lacpdu_header { typedef struct lacpdu_header {
struct ethhdr hdr; struct ethhdr hdr;
struct lacpdu lacpdu; struct lacpdu lacpdu;
} lacpdu_header_t; } __packed lacpdu_header_t;
// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) // Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
typedef struct bond_marker { typedef struct bond_marker {
@ -155,12 +155,12 @@ typedef struct bond_marker {
u8 tlv_type_terminator; // = 0x00 u8 tlv_type_terminator; // = 0x00
u8 terminator_length; // = 0x00 u8 terminator_length; // = 0x00
u8 reserved_90[90]; // = 0 u8 reserved_90[90]; // = 0
} bond_marker_t; } __packed bond_marker_t;
typedef struct bond_marker_header { typedef struct bond_marker_header {
struct ethhdr hdr; struct ethhdr hdr;
struct bond_marker marker; struct bond_marker marker;
} bond_marker_header_t; } __packed bond_marker_header_t;
#pragma pack() #pragma pack()

View file

@ -247,8 +247,10 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
} }
#endif /* CONFIG_PPC_MPC512x */ #endif /* CONFIG_PPC_MPC512x */
static struct of_device_id mpc5xxx_can_table[];
static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev) static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
{ {
const struct of_device_id *match;
struct mpc5xxx_can_data *data; struct mpc5xxx_can_data *data;
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
struct net_device *dev; struct net_device *dev;
@ -258,9 +260,10 @@ static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
int irq, mscan_clksrc = 0; int irq, mscan_clksrc = 0;
int err = -ENOMEM; int err = -ENOMEM;
if (!ofdev->dev.of_match) match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
if (!match)
return -EINVAL; return -EINVAL;
data = (struct mpc5xxx_can_data *)ofdev->dev.of_match->data; data = match->data;
base = of_iomap(np, 0); base = of_iomap(np, 0);
if (!base) { if (!base) {

View file

@ -2688,9 +2688,6 @@ static int ehea_open(struct net_device *dev)
netif_start_queue(dev); netif_start_queue(dev);
} }
init_waitqueue_head(&port->swqe_avail_wq);
init_waitqueue_head(&port->restart_wq);
mutex_unlock(&port->port_lock); mutex_unlock(&port->port_lock);
return ret; return ret;
@ -3276,6 +3273,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
INIT_WORK(&port->reset_task, ehea_reset_port); INIT_WORK(&port->reset_task, ehea_reset_port);
init_waitqueue_head(&port->swqe_avail_wq);
init_waitqueue_head(&port->restart_wq);
ret = register_netdev(dev); ret = register_netdev(dev);
if (ret) { if (ret) {
pr_err("register_netdev failed. ret=%d\n", ret); pr_err("register_netdev failed. ret=%d\n", ret);

View file

@ -998,8 +998,10 @@ static const struct net_device_ops fs_enet_netdev_ops = {
#endif #endif
}; };
static struct of_device_id fs_enet_match[];
static int __devinit fs_enet_probe(struct platform_device *ofdev) static int __devinit fs_enet_probe(struct platform_device *ofdev)
{ {
const struct of_device_id *match;
struct net_device *ndev; struct net_device *ndev;
struct fs_enet_private *fep; struct fs_enet_private *fep;
struct fs_platform_info *fpi; struct fs_platform_info *fpi;
@ -1007,14 +1009,15 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev)
const u8 *mac_addr; const u8 *mac_addr;
int privsize, len, ret = -ENODEV; int privsize, len, ret = -ENODEV;
if (!ofdev->dev.of_match) match = of_match_device(fs_enet_match, &ofdev->dev);
if (!match)
return -EINVAL; return -EINVAL;
fpi = kzalloc(sizeof(*fpi), GFP_KERNEL); fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
if (!fpi) if (!fpi)
return -ENOMEM; return -ENOMEM;
if (!IS_FEC(ofdev->dev.of_match)) { if (!IS_FEC(match)) {
data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len); data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len);
if (!data || len != 4) if (!data || len != 4)
goto out_free_fpi; goto out_free_fpi;
@ -1049,7 +1052,7 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev)
fep->dev = &ofdev->dev; fep->dev = &ofdev->dev;
fep->ndev = ndev; fep->ndev = ndev;
fep->fpi = fpi; fep->fpi = fpi;
fep->ops = ofdev->dev.of_match->data; fep->ops = match->data;
ret = fep->ops->setup_data(ndev); ret = fep->ops->setup_data(ndev);
if (ret) if (ret)

View file

@ -101,17 +101,20 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
return 0; return 0;
} }
static struct of_device_id fs_enet_mdio_fec_match[];
static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
{ {
const struct of_device_id *match;
struct resource res; struct resource res;
struct mii_bus *new_bus; struct mii_bus *new_bus;
struct fec_info *fec; struct fec_info *fec;
int (*get_bus_freq)(struct device_node *); int (*get_bus_freq)(struct device_node *);
int ret = -ENOMEM, clock, speed; int ret = -ENOMEM, clock, speed;
if (!ofdev->dev.of_match) match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev);
if (!match)
return -EINVAL; return -EINVAL;
get_bus_freq = ofdev->dev.of_match->data; get_bus_freq = match->data;
new_bus = mdiobus_alloc(); new_bus = mdiobus_alloc();
if (!new_bus) if (!new_bus)

View file

@ -98,15 +98,15 @@ static const struct net_device_ops hydra_netdev_ops = {
.ndo_open = hydra_open, .ndo_open = hydra_open,
.ndo_stop = hydra_close, .ndo_stop = hydra_close,
.ndo_start_xmit = ei_start_xmit, .ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout, .ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = ei_get_stats, .ndo_get_stats = __ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list, .ndo_set_multicast_list = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu, .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll, .ndo_poll_controller = __ei_poll,
#endif #endif
}; };
@ -125,7 +125,7 @@ static int __devinit hydra_init(struct zorro_dev *z)
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
}; };
dev = alloc_ei_netdev(); dev = ____alloc_ei_netdev(0);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;

View file

@ -167,7 +167,7 @@ static void cleanup_card(struct net_device *dev)
#ifndef MODULE #ifndef MODULE
struct net_device * __init ne_probe(int unit) struct net_device * __init ne_probe(int unit)
{ {
struct net_device *dev = alloc_ei_netdev(); struct net_device *dev = ____alloc_ei_netdev(0);
int err; int err;
if (!dev) if (!dev)
@ -197,15 +197,15 @@ static const struct net_device_ops ne_netdev_ops = {
.ndo_open = ne_open, .ndo_open = ne_open,
.ndo_stop = ne_close, .ndo_stop = ne_close,
.ndo_start_xmit = ei_start_xmit, .ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout, .ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = ei_get_stats, .ndo_get_stats = __ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list, .ndo_set_multicast_list = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu, .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll, .ndo_poll_controller = __ei_poll,
#endif #endif
}; };
@ -637,7 +637,7 @@ int init_module(void)
int err; int err;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = alloc_ei_netdev(); struct net_device *dev = ____alloc_ei_netdev(0);
if (!dev) if (!dev)
break; break;
if (io[this_dev]) { if (io[this_dev]) {

View file

@ -50,6 +50,20 @@ static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
return &nic_data->mcdi; return &nic_data->mcdi;
} }
static inline void
efx_mcdi_readd(struct efx_nic *efx, efx_dword_t *value, unsigned reg)
{
struct siena_nic_data *nic_data = efx->nic_data;
value->u32[0] = (__force __le32)__raw_readl(nic_data->mcdi_smem + reg);
}
static inline void
efx_mcdi_writed(struct efx_nic *efx, const efx_dword_t *value, unsigned reg)
{
struct siena_nic_data *nic_data = efx->nic_data;
__raw_writel((__force u32)value->u32[0], nic_data->mcdi_smem + reg);
}
void efx_mcdi_init(struct efx_nic *efx) void efx_mcdi_init(struct efx_nic *efx)
{ {
struct efx_mcdi_iface *mcdi; struct efx_mcdi_iface *mcdi;
@ -70,8 +84,8 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
const u8 *inbuf, size_t inlen) const u8 *inbuf, size_t inlen)
{ {
struct efx_mcdi_iface *mcdi = efx_mcdi(efx); struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned pdu = MCDI_PDU(efx);
unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx); unsigned doorbell = MCDI_DOORBELL(efx);
unsigned int i; unsigned int i;
efx_dword_t hdr; efx_dword_t hdr;
u32 xflags, seqno; u32 xflags, seqno;
@ -92,30 +106,28 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
MCDI_HEADER_SEQ, seqno, MCDI_HEADER_SEQ, seqno,
MCDI_HEADER_XFLAGS, xflags); MCDI_HEADER_XFLAGS, xflags);
efx_writed(efx, &hdr, pdu); efx_mcdi_writed(efx, &hdr, pdu);
for (i = 0; i < inlen; i += 4) { for (i = 0; i < inlen; i += 4)
_efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i); efx_mcdi_writed(efx, (const efx_dword_t *)(inbuf + i),
/* use wmb() within loop to inhibit write combining */ pdu + 4 + i);
wmb();
}
/* ring the doorbell with a distinctive value */ /* ring the doorbell with a distinctive value */
_efx_writed(efx, (__force __le32) 0x45789abc, doorbell); EFX_POPULATE_DWORD_1(hdr, EFX_DWORD_0, 0x45789abc);
wmb(); efx_mcdi_writed(efx, &hdr, doorbell);
} }
static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
{ {
struct efx_mcdi_iface *mcdi = efx_mcdi(efx); struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned int pdu = MCDI_PDU(efx);
int i; int i;
BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
BUG_ON(outlen & 3 || outlen >= 0x100); BUG_ON(outlen & 3 || outlen >= 0x100);
for (i = 0; i < outlen; i += 4) for (i = 0; i < outlen; i += 4)
*((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i); efx_mcdi_readd(efx, (efx_dword_t *)(outbuf + i), pdu + 4 + i);
} }
static int efx_mcdi_poll(struct efx_nic *efx) static int efx_mcdi_poll(struct efx_nic *efx)
@ -123,7 +135,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
struct efx_mcdi_iface *mcdi = efx_mcdi(efx); struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
unsigned int time, finish; unsigned int time, finish;
unsigned int respseq, respcmd, error; unsigned int respseq, respcmd, error;
unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned int pdu = MCDI_PDU(efx);
unsigned int rc, spins; unsigned int rc, spins;
efx_dword_t reg; efx_dword_t reg;
@ -149,8 +161,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
time = get_seconds(); time = get_seconds();
rmb(); efx_mcdi_readd(efx, &reg, pdu);
efx_readd(efx, &reg, pdu);
/* All 1's indicates that shared memory is in reset (and is /* All 1's indicates that shared memory is in reset (and is
* not a valid header). Wait for it to come out reset before * not a valid header). Wait for it to come out reset before
@ -177,7 +188,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
respseq, mcdi->seqno); respseq, mcdi->seqno);
rc = EIO; rc = EIO;
} else if (error) { } else if (error) {
efx_readd(efx, &reg, pdu + 4); efx_mcdi_readd(efx, &reg, pdu + 4);
switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) { switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
#define TRANSLATE_ERROR(name) \ #define TRANSLATE_ERROR(name) \
case MC_CMD_ERR_ ## name: \ case MC_CMD_ERR_ ## name: \
@ -211,21 +222,21 @@ out:
/* Test and clear MC-rebooted flag for this port/function */ /* Test and clear MC-rebooted flag for this port/function */
int efx_mcdi_poll_reboot(struct efx_nic *efx) int efx_mcdi_poll_reboot(struct efx_nic *efx)
{ {
unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx); unsigned int addr = MCDI_REBOOT_FLAG(efx);
efx_dword_t reg; efx_dword_t reg;
uint32_t value; uint32_t value;
if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
return false; return false;
efx_readd(efx, &reg, addr); efx_mcdi_readd(efx, &reg, addr);
value = EFX_DWORD_FIELD(reg, EFX_DWORD_0); value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
if (value == 0) if (value == 0)
return 0; return 0;
EFX_ZERO_DWORD(reg); EFX_ZERO_DWORD(reg);
efx_writed(efx, &reg, addr); efx_mcdi_writed(efx, &reg, addr);
if (value == MC_STATUS_DWORD_ASSERT) if (value == MC_STATUS_DWORD_ASSERT)
return -EINTR; return -EINTR;

View file

@ -1937,6 +1937,13 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf)
size = min_t(size_t, table->step, 16); size = min_t(size_t, table->step, 16);
if (table->offset >= efx->type->mem_map_size) {
/* No longer mapped; return dummy data */
memcpy(buf, "\xde\xc0\xad\xde", 4);
buf += table->rows * size;
continue;
}
for (i = 0; i < table->rows; i++) { for (i = 0; i < table->rows; i++) {
switch (table->step) { switch (table->step) {
case 4: /* 32-bit register or SRAM */ case 4: /* 32-bit register or SRAM */

View file

@ -143,10 +143,12 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
/** /**
* struct siena_nic_data - Siena NIC state * struct siena_nic_data - Siena NIC state
* @mcdi: Management-Controller-to-Driver Interface * @mcdi: Management-Controller-to-Driver Interface
* @mcdi_smem: MCDI shared memory mapping. The mapping is always uncacheable.
* @wol_filter_id: Wake-on-LAN packet filter id * @wol_filter_id: Wake-on-LAN packet filter id
*/ */
struct siena_nic_data { struct siena_nic_data {
struct efx_mcdi_iface mcdi; struct efx_mcdi_iface mcdi;
void __iomem *mcdi_smem;
int wol_filter_id; int wol_filter_id;
}; };

View file

@ -220,12 +220,26 @@ static int siena_probe_nic(struct efx_nic *efx)
efx_reado(efx, &reg, FR_AZ_CS_DEBUG); efx_reado(efx, &reg, FR_AZ_CS_DEBUG);
efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1; efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
/* Initialise MCDI */
nic_data->mcdi_smem = ioremap_nocache(efx->membase_phys +
FR_CZ_MC_TREG_SMEM,
FR_CZ_MC_TREG_SMEM_STEP *
FR_CZ_MC_TREG_SMEM_ROWS);
if (!nic_data->mcdi_smem) {
netif_err(efx, probe, efx->net_dev,
"could not map MCDI at %llx+%x\n",
(unsigned long long)efx->membase_phys +
FR_CZ_MC_TREG_SMEM,
FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS);
rc = -ENOMEM;
goto fail1;
}
efx_mcdi_init(efx); efx_mcdi_init(efx);
/* Recover from a failed assertion before probing */ /* Recover from a failed assertion before probing */
rc = efx_mcdi_handle_assertion(efx); rc = efx_mcdi_handle_assertion(efx);
if (rc) if (rc)
goto fail1; goto fail2;
/* Let the BMC know that the driver is now in charge of link and /* Let the BMC know that the driver is now in charge of link and
* filter settings. We must do this before we reset the NIC */ * filter settings. We must do this before we reset the NIC */
@ -280,6 +294,7 @@ fail4:
fail3: fail3:
efx_mcdi_drv_attach(efx, false, NULL); efx_mcdi_drv_attach(efx, false, NULL);
fail2: fail2:
iounmap(nic_data->mcdi_smem);
fail1: fail1:
kfree(efx->nic_data); kfree(efx->nic_data);
return rc; return rc;
@ -359,6 +374,8 @@ static int siena_init_nic(struct efx_nic *efx)
static void siena_remove_nic(struct efx_nic *efx) static void siena_remove_nic(struct efx_nic *efx)
{ {
struct siena_nic_data *nic_data = efx->nic_data;
efx_nic_free_buffer(efx, &efx->irq_status); efx_nic_free_buffer(efx, &efx->irq_status);
siena_reset_hw(efx, RESET_TYPE_ALL); siena_reset_hw(efx, RESET_TYPE_ALL);
@ -368,7 +385,8 @@ static void siena_remove_nic(struct efx_nic *efx)
efx_mcdi_drv_attach(efx, false, NULL); efx_mcdi_drv_attach(efx, false, NULL);
/* Tear down the private nic state */ /* Tear down the private nic state */
kfree(efx->nic_data); iounmap(nic_data->mcdi_smem);
kfree(nic_data);
efx->nic_data = NULL; efx->nic_data = NULL;
} }
@ -606,8 +624,7 @@ struct efx_nic_type siena_a0_nic_type = {
.default_mac_ops = &efx_mcdi_mac_operations, .default_mac_ops = &efx_mcdi_mac_operations,
.revision = EFX_REV_SIENA_A0, .revision = EFX_REV_SIENA_A0,
.mem_map_size = (FR_CZ_MC_TREG_SMEM + .mem_map_size = FR_CZ_MC_TREG_SMEM, /* MC_TREG_SMEM mapped separately */
FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS),
.txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
.rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL, .rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL,
.buf_tbl_base = FR_BZ_BUF_FULL_TBL, .buf_tbl_base = FR_BZ_BUF_FULL_TBL,

View file

@ -3237,15 +3237,18 @@ static void happy_meal_pci_exit(void)
#endif #endif
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
static const struct of_device_id hme_sbus_match[];
static int __devinit hme_sbus_probe(struct platform_device *op) static int __devinit hme_sbus_probe(struct platform_device *op)
{ {
const struct of_device_id *match;
struct device_node *dp = op->dev.of_node; struct device_node *dp = op->dev.of_node;
const char *model = of_get_property(dp, "model", NULL); const char *model = of_get_property(dp, "model", NULL);
int is_qfe; int is_qfe;
if (!op->dev.of_match) match = of_match_device(hme_sbus_match, &op->dev);
if (!match)
return -EINVAL; return -EINVAL;
is_qfe = (op->dev.of_match->data != NULL); is_qfe = (match->data != NULL);
if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))
is_qfe = 1; is_qfe = 1;

View file

@ -311,6 +311,9 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
/* toggle the LRO feature*/ /* toggle the LRO feature*/
netdev->features ^= NETIF_F_LRO; netdev->features ^= NETIF_F_LRO;
/* Update private LRO flag */
adapter->lro = lro_requested;
/* update harware LRO capability accordingly */ /* update harware LRO capability accordingly */
if (lro_requested) if (lro_requested)
adapter->shared->devRead.misc.uptFeatures |= adapter->shared->devRead.misc.uptFeatures |=

Some files were not shown because too many files have changed in this diff Show more