mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 06:25:52 +02:00
Merge tag 'v3.10.73' into linux-linaro-lsk
This is the 3.10.73 stable release
This commit is contained in:
commit
88720d8b84
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 10
|
||||
SUBLEVEL = 72
|
||||
SUBLEVEL = 73
|
||||
EXTRAVERSION =
|
||||
NAME = TOSSUG Baby Fish
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ static inline void at91rm9200_standby(void)
|
|||
" mcr p15, 0, %0, c7, c0, 4\n\t"
|
||||
" str %5, [%1, %2]"
|
||||
:
|
||||
: "r" (0), "r" (AT91_BASE_SYS), "r" (AT91RM9200_SDRAMC_LPR),
|
||||
: "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR),
|
||||
"r" (1), "r" (AT91RM9200_SDRAMC_SRR),
|
||||
"r" (lpr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -544,8 +544,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
|||
if (smp_ops->give_timebase)
|
||||
smp_ops->give_timebase();
|
||||
|
||||
/* Wait until cpu puts itself in the online map */
|
||||
while (!cpu_online(cpu))
|
||||
/* Wait until cpu puts itself in the online & active maps */
|
||||
while (!cpu_online(cpu) || !cpu_active(cpu))
|
||||
cpu_relax();
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -960,6 +960,8 @@ static void calculate_single_pcr(struct cpu_hw_events *cpuc)
|
|||
cpuc->pcr[0] |= cpuc->event[0]->hw.config_base;
|
||||
}
|
||||
|
||||
static void sparc_pmu_start(struct perf_event *event, int flags);
|
||||
|
||||
/* On this PMU each PIC has it's own PCR control register. */
|
||||
static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
|
||||
{
|
||||
|
|
@ -972,20 +974,13 @@ static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
|
|||
struct perf_event *cp = cpuc->event[i];
|
||||
struct hw_perf_event *hwc = &cp->hw;
|
||||
int idx = hwc->idx;
|
||||
u64 enc;
|
||||
|
||||
if (cpuc->current_idx[i] != PIC_NO_INDEX)
|
||||
continue;
|
||||
|
||||
sparc_perf_event_set_period(cp, hwc, idx);
|
||||
cpuc->current_idx[i] = idx;
|
||||
|
||||
enc = perf_event_get_enc(cpuc->events[i]);
|
||||
cpuc->pcr[idx] &= ~mask_for_index(idx);
|
||||
if (hwc->state & PERF_HES_STOPPED)
|
||||
cpuc->pcr[idx] |= nop_for_index(idx);
|
||||
else
|
||||
cpuc->pcr[idx] |= event_encoding(enc, idx);
|
||||
sparc_pmu_start(cp, PERF_EF_RELOAD);
|
||||
}
|
||||
out:
|
||||
for (i = 0; i < cpuc->n_events; i++) {
|
||||
|
|
@ -1101,7 +1096,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags)
|
|||
int i;
|
||||
|
||||
local_irq_save(flags);
|
||||
perf_pmu_disable(event->pmu);
|
||||
|
||||
for (i = 0; i < cpuc->n_events; i++) {
|
||||
if (event == cpuc->event[i]) {
|
||||
|
|
@ -1127,7 +1121,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags)
|
|||
}
|
||||
}
|
||||
|
||||
perf_pmu_enable(event->pmu);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
|
@ -1361,7 +1354,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags)
|
|||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
perf_pmu_disable(event->pmu);
|
||||
|
||||
n0 = cpuc->n_events;
|
||||
if (n0 >= sparc_pmu->max_hw_events)
|
||||
|
|
@ -1394,7 +1386,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags)
|
|||
|
||||
ret = 0;
|
||||
out:
|
||||
perf_pmu_enable(event->pmu);
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,6 +280,8 @@ void arch_trigger_all_cpu_backtrace(void)
|
|||
printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
|
||||
gp->tpc, gp->o7, gp->i7, gp->rpc);
|
||||
}
|
||||
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
|
||||
memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
|
||||
|
|
@ -352,6 +354,8 @@ static void pmu_snapshot_all_cpus(void)
|
|||
(cpu == this_cpu ? '*' : ' '), cpu,
|
||||
pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
|
||||
pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
|
||||
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
|
||||
memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
|
|||
long err;
|
||||
|
||||
/* No need for backward compatibility. We can start fresh... */
|
||||
if (call <= SEMCTL) {
|
||||
if (call <= SEMTIMEDOP) {
|
||||
switch (call) {
|
||||
case SEMOP:
|
||||
err = sys_semtimedop(first, ptr,
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
.text
|
||||
ENTRY(memmove) /* o0=dst o1=src o2=len */
|
||||
mov %o0, %g1
|
||||
brz,pn %o2, 99f
|
||||
mov %o0, %g1
|
||||
|
||||
cmp %o0, %o1
|
||||
bleu,pt %xcc, memcpy
|
||||
bleu,pt %xcc, 2f
|
||||
add %o1, %o2, %g7
|
||||
cmp %g7, %o0
|
||||
bleu,pt %xcc, memcpy
|
||||
|
|
@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */
|
|||
stb %g7, [%o0]
|
||||
bne,pt %icc, 1b
|
||||
sub %o0, 1, %o0
|
||||
|
||||
99:
|
||||
retl
|
||||
mov %g1, %o0
|
||||
|
||||
/* We can't just call memcpy for these memmove cases. On some
|
||||
* chips the memcpy uses cache initializing stores and when dst
|
||||
* and src are close enough, those can clobber the source data
|
||||
* before we've loaded it in.
|
||||
*/
|
||||
2: or %o0, %o1, %g7
|
||||
or %o2, %g7, %g7
|
||||
andcc %g7, 0x7, %g0
|
||||
bne,pn %xcc, 4f
|
||||
nop
|
||||
|
||||
3: ldx [%o1], %g7
|
||||
add %o1, 8, %o1
|
||||
subcc %o2, 8, %o2
|
||||
add %o0, 8, %o0
|
||||
bne,pt %icc, 3b
|
||||
stx %g7, [%o0 - 0x8]
|
||||
ba,a,pt %xcc, 99b
|
||||
|
||||
4: ldub [%o1], %g7
|
||||
add %o1, 1, %o1
|
||||
subcc %o2, 1, %o2
|
||||
add %o0, 1, %o0
|
||||
bne,pt %icc, 4b
|
||||
stb %g7, [%o0 - 0x1]
|
||||
ba,a,pt %xcc, 99b
|
||||
ENDPROC(memmove)
|
||||
|
|
|
|||
|
|
@ -455,10 +455,12 @@ static void __init sparc_context_init(int numctx)
|
|||
void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (mm->context == NO_CONTEXT) {
|
||||
spin_lock(&srmmu_context_spinlock);
|
||||
spin_lock_irqsave(&srmmu_context_spinlock, flags);
|
||||
alloc_context(old_mm, mm);
|
||||
spin_unlock(&srmmu_context_spinlock);
|
||||
spin_unlock_irqrestore(&srmmu_context_spinlock, flags);
|
||||
srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd);
|
||||
}
|
||||
|
||||
|
|
@ -983,14 +985,15 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
|||
|
||||
void destroy_context(struct mm_struct *mm)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (mm->context != NO_CONTEXT) {
|
||||
flush_cache_mm(mm);
|
||||
srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir);
|
||||
flush_tlb_mm(mm);
|
||||
spin_lock(&srmmu_context_spinlock);
|
||||
spin_lock_irqsave(&srmmu_context_spinlock, flags);
|
||||
free_context(mm->context);
|
||||
spin_unlock(&srmmu_context_spinlock);
|
||||
spin_unlock_irqrestore(&srmmu_context_spinlock, flags);
|
||||
mm->context = NO_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -989,7 +989,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
|
|||
src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC);
|
||||
if (!src)
|
||||
return -ENOMEM;
|
||||
assoc = (src + req->cryptlen + auth_tag_len);
|
||||
assoc = (src + req->cryptlen);
|
||||
scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0);
|
||||
scatterwalk_map_and_copy(assoc, req->assoc, 0,
|
||||
req->assoclen, 0);
|
||||
|
|
@ -1014,7 +1014,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
|
|||
scatterwalk_done(&src_sg_walk, 0, 0);
|
||||
scatterwalk_done(&assoc_sg_walk, 0, 0);
|
||||
} else {
|
||||
scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1);
|
||||
scatterwalk_map_and_copy(dst, req->dst, 0, tempCipherLen, 1);
|
||||
kfree(src);
|
||||
}
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ static inline void drop_fpu(struct task_struct *tsk)
|
|||
preempt_disable();
|
||||
tsk->fpu_counter = 0;
|
||||
__drop_fpu(tsk);
|
||||
clear_used_math();
|
||||
clear_stopped_child_used_math(tsk);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
|
|||
* thread's fpu state, reconstruct fxstate from the fsave
|
||||
* header. Sanitize the copied state etc.
|
||||
*/
|
||||
struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
|
||||
struct fpu *fpu = &tsk->thread.fpu;
|
||||
struct user_i387_ia32_struct env;
|
||||
int err = 0;
|
||||
|
||||
|
|
@ -390,14 +390,15 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
|
|||
*/
|
||||
drop_fpu(tsk);
|
||||
|
||||
if (__copy_from_user(xsave, buf_fx, state_size) ||
|
||||
if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) ||
|
||||
__copy_from_user(&env, buf, sizeof(env))) {
|
||||
fpu_finit(fpu);
|
||||
err = -1;
|
||||
} else {
|
||||
sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only);
|
||||
set_used_math();
|
||||
}
|
||||
|
||||
set_used_math();
|
||||
if (use_eager_fpu()) {
|
||||
preempt_disable();
|
||||
math_state_restore();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
.text
|
||||
.globl __kernel_sigreturn
|
||||
.type __kernel_sigreturn,@function
|
||||
nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */
|
||||
ALIGN
|
||||
__kernel_sigreturn:
|
||||
.LSTART_sigreturn:
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
|
|||
{
|
||||
struct ibmvtpm_dev *ibmvtpm;
|
||||
struct ibmvtpm_crq crq;
|
||||
u64 *word = (u64 *) &crq;
|
||||
__be64 *word = (__be64 *)&crq;
|
||||
int rc;
|
||||
|
||||
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
|
||||
|
|
@ -145,11 +145,11 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
|
|||
memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
|
||||
crq.valid = (u8)IBMVTPM_VALID_CMD;
|
||||
crq.msg = (u8)VTPM_TPM_COMMAND;
|
||||
crq.len = (u16)count;
|
||||
crq.data = ibmvtpm->rtce_dma_handle;
|
||||
crq.len = cpu_to_be16(count);
|
||||
crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);
|
||||
|
||||
rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]),
|
||||
cpu_to_be64(word[1]));
|
||||
rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
|
||||
be64_to_cpu(word[1]));
|
||||
if (rc != H_SUCCESS) {
|
||||
dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
|
||||
rc = 0;
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@
|
|||
struct ibmvtpm_crq {
|
||||
u8 valid;
|
||||
u8 msg;
|
||||
u16 len;
|
||||
u32 data;
|
||||
u64 reserved;
|
||||
__be16 len;
|
||||
__be32 data;
|
||||
__be64 reserved;
|
||||
} __attribute__((packed, aligned(8)));
|
||||
|
||||
struct ibmvtpm_crq_queue {
|
||||
|
|
|
|||
|
|
@ -2023,12 +2023,13 @@ static int virtcons_probe(struct virtio_device *vdev)
|
|||
spin_lock_init(&portdev->ports_lock);
|
||||
INIT_LIST_HEAD(&portdev->ports);
|
||||
|
||||
INIT_WORK(&portdev->control_work, &control_work_handler);
|
||||
|
||||
if (multiport) {
|
||||
unsigned int nr_added_bufs;
|
||||
|
||||
spin_lock_init(&portdev->c_ivq_lock);
|
||||
spin_lock_init(&portdev->c_ovq_lock);
|
||||
INIT_WORK(&portdev->control_work, &control_work_handler);
|
||||
|
||||
nr_added_bufs = fill_queue(portdev->c_ivq,
|
||||
&portdev->c_ivq_lock);
|
||||
|
|
|
|||
|
|
@ -4016,6 +4016,9 @@ int evergreen_irq_set(struct radeon_device *rdev)
|
|||
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5);
|
||||
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6);
|
||||
|
||||
/* posting read */
|
||||
RREG32(SRBM_STATUS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -743,6 +743,10 @@ int r100_irq_set(struct radeon_device *rdev)
|
|||
tmp |= RADEON_FP2_DETECT_MASK;
|
||||
}
|
||||
WREG32(RADEON_GEN_INT_CNTL, tmp);
|
||||
|
||||
/* read back to post the write */
|
||||
RREG32(RADEON_GEN_INT_CNTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3459,6 +3459,9 @@ int r600_init(struct radeon_device *rdev)
|
|||
rdev->accel_working = false;
|
||||
}
|
||||
|
||||
/* posting read */
|
||||
RREG32(R_000E50_SRBM_STATUS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -177,11 +177,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
|
|||
u32 ring = RADEON_CS_RING_GFX;
|
||||
s32 priority = 0;
|
||||
|
||||
INIT_LIST_HEAD(&p->validated);
|
||||
|
||||
if (!cs->num_chunks) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get chunks */
|
||||
INIT_LIST_HEAD(&p->validated);
|
||||
p->idx = 0;
|
||||
p->ib.sa_bo = NULL;
|
||||
p->ib.semaphore = NULL;
|
||||
|
|
|
|||
|
|
@ -636,6 +636,10 @@ int rs600_irq_set(struct radeon_device *rdev)
|
|||
WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
|
||||
if (ASIC_IS_DCE2(rdev))
|
||||
WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
|
||||
|
||||
/* posting read */
|
||||
RREG32(R_000040_GEN_INT_CNTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5704,8 +5704,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
|
|||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
|
||||
|
||||
if (!vclk || !dclk) {
|
||||
/* keep the Bypass mode, put PLL to sleep */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
|
||||
/* keep the Bypass mode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -5721,8 +5720,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
|
|||
/* set VCO_MODE to 1 */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK);
|
||||
|
||||
/* toggle UPLL_SLEEP to 1 then back to 0 */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
|
||||
/* disable sleep mode */
|
||||
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK);
|
||||
|
||||
/* deassert UPLL_RESET */
|
||||
|
|
@ -5778,5 +5776,8 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
|
|||
|
||||
mdelay(100);
|
||||
|
||||
/* posting read */
|
||||
RREG32(SRBM_STATUS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,6 +503,14 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
|
|||
skb->pkt_type = PACKET_BROADCAST;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
can_skb_reserve(skb);
|
||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||
|
||||
|
|
|
|||
|
|
@ -302,9 +302,18 @@ static const struct driver_info cx82310_info = {
|
|||
.tx_fixup = cx82310_tx_fixup,
|
||||
};
|
||||
|
||||
#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
|
||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
|
||||
USB_DEVICE_ID_MATCH_DEV_INFO, \
|
||||
.idVendor = (vend), \
|
||||
.idProduct = (prod), \
|
||||
.bDeviceClass = (cl), \
|
||||
.bDeviceSubClass = (sc), \
|
||||
.bDeviceProtocol = (pr)
|
||||
|
||||
static const struct usb_device_id products[] = {
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0),
|
||||
USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
|
||||
.driver_info = (unsigned long) &cx82310_info
|
||||
},
|
||||
{ },
|
||||
|
|
|
|||
|
|
@ -1596,10 +1596,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
|
|||
trace_regulator_enable(rdev_get_name(rdev));
|
||||
|
||||
if (rdev->ena_pin) {
|
||||
ret = regulator_ena_gpio_ctrl(rdev, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rdev->ena_gpio_state = 1;
|
||||
if (!rdev->ena_gpio_state) {
|
||||
ret = regulator_ena_gpio_ctrl(rdev, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rdev->ena_gpio_state = 1;
|
||||
}
|
||||
} else if (rdev->desc->ops->enable) {
|
||||
ret = rdev->desc->ops->enable(rdev);
|
||||
if (ret < 0)
|
||||
|
|
@ -1701,10 +1703,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
|
|||
trace_regulator_disable(rdev_get_name(rdev));
|
||||
|
||||
if (rdev->ena_pin) {
|
||||
ret = regulator_ena_gpio_ctrl(rdev, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rdev->ena_gpio_state = 0;
|
||||
if (rdev->ena_gpio_state) {
|
||||
ret = regulator_ena_gpio_ctrl(rdev, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rdev->ena_gpio_state = 0;
|
||||
}
|
||||
|
||||
} else if (rdev->desc->ops->disable) {
|
||||
ret = rdev->desc->ops->disable(rdev);
|
||||
|
|
@ -3615,12 +3619,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
|
|||
config->ena_gpio, ret);
|
||||
goto wash;
|
||||
}
|
||||
|
||||
if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
|
||||
rdev->ena_gpio_state = 1;
|
||||
|
||||
if (config->ena_gpio_invert)
|
||||
rdev->ena_gpio_state = !rdev->ena_gpio_state;
|
||||
}
|
||||
|
||||
/* set regulator constraints */
|
||||
|
|
@ -3789,9 +3787,11 @@ int regulator_suspend_finish(void)
|
|||
list_for_each_entry(rdev, ®ulator_list, list) {
|
||||
mutex_lock(&rdev->mutex);
|
||||
if (rdev->use_count > 0 || rdev->constraints->always_on) {
|
||||
error = _regulator_do_enable(rdev);
|
||||
if (error)
|
||||
ret = error;
|
||||
if (!_regulator_is_enabled(rdev)) {
|
||||
error = _regulator_do_enable(rdev);
|
||||
if (error)
|
||||
ret = error;
|
||||
}
|
||||
} else {
|
||||
if (!has_full_constraints)
|
||||
goto unlock;
|
||||
|
|
|
|||
|
|
@ -500,6 +500,7 @@ static void sas_revalidate_domain(struct work_struct *work)
|
|||
struct sas_discovery_event *ev = to_sas_discovery_event(work);
|
||||
struct asd_sas_port *port = ev->port;
|
||||
struct sas_ha_struct *ha = port->ha;
|
||||
struct domain_device *ddev = port->port_dev;
|
||||
|
||||
/* prevent revalidation from finding sata links in recovery */
|
||||
mutex_lock(&ha->disco_mutex);
|
||||
|
|
@ -514,8 +515,9 @@ static void sas_revalidate_domain(struct work_struct *work)
|
|||
SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
|
||||
task_pid_nr(current));
|
||||
|
||||
if (port->port_dev)
|
||||
res = sas_ex_revalidate_domain(port->port_dev);
|
||||
if (ddev && (ddev->dev_type == SAS_FANOUT_EXPANDER_DEVICE ||
|
||||
ddev->dev_type == SAS_EDGE_EXPANDER_DEVICE))
|
||||
res = sas_ex_revalidate_domain(ddev);
|
||||
|
||||
SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
|
||||
port->id, task_pid_nr(current), res);
|
||||
|
|
|
|||
|
|
@ -508,12 +508,12 @@ static void giveback(struct pl022 *pl022)
|
|||
pl022->cur_msg = NULL;
|
||||
pl022->cur_transfer = NULL;
|
||||
pl022->cur_chip = NULL;
|
||||
spi_finalize_current_message(pl022->master);
|
||||
|
||||
/* disable the SPI/SSP operation */
|
||||
writew((readw(SSP_CR1(pl022->virtbase)) &
|
||||
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
|
||||
|
||||
spi_finalize_current_message(pl022->master);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4136,11 +4136,17 @@ int iscsit_close_connection(
|
|||
pr_debug("Closing iSCSI connection CID %hu on SID:"
|
||||
" %u\n", conn->cid, sess->sid);
|
||||
/*
|
||||
* Always up conn_logout_comp just in case the RX Thread is sleeping
|
||||
* and the logout response never got sent because the connection
|
||||
* failed.
|
||||
* Always up conn_logout_comp for the traditional TCP case just in case
|
||||
* the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout
|
||||
* response never got sent because the connection failed.
|
||||
*
|
||||
* However for iser-target, isert_wait4logout() is using conn_logout_comp
|
||||
* to signal logout response TX interrupt completion. Go ahead and skip
|
||||
* this for iser since isert_rx_opcode() does not wait on logout failure,
|
||||
* and to avoid iscsi_conn pointer dereference in iser-target code.
|
||||
*/
|
||||
complete(&conn->conn_logout_comp);
|
||||
if (conn->conn_transport->transport_type == ISCSI_TCP)
|
||||
complete(&conn->conn_logout_comp);
|
||||
|
||||
iscsi_release_thread_set(conn);
|
||||
|
||||
|
|
|
|||
|
|
@ -518,6 +518,18 @@ static int core_scsi3_pr_seq_non_holder(
|
|||
|
||||
return 0;
|
||||
}
|
||||
} else if (we && registered_nexus) {
|
||||
/*
|
||||
* Reads are allowed for Write Exclusive locks
|
||||
* from all registrants.
|
||||
*/
|
||||
if (cmd->data_direction == DMA_FROM_DEVICE) {
|
||||
pr_debug("Allowing READ CDB: 0x%02x for %s"
|
||||
" reservation\n", cdb[0],
|
||||
core_scsi3_pr_dump_type(pr_reg_type));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pr_debug("%s Conflict for %sregistered nexus %s CDB: 0x%2x"
|
||||
" for %s reservation\n", transport_dump_cmd_direction(cmd),
|
||||
|
|
@ -2397,6 +2409,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
|
|||
spin_lock(&dev->dev_reservation_lock);
|
||||
pr_res_holder = dev->dev_pr_res_holder;
|
||||
if (pr_res_holder) {
|
||||
int pr_res_type = pr_res_holder->pr_res_type;
|
||||
/*
|
||||
* From spc4r17 Section 5.7.9: Reserving:
|
||||
*
|
||||
|
|
@ -2407,7 +2420,9 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
|
|||
* the logical unit, then the command shall be completed with
|
||||
* RESERVATION CONFLICT status.
|
||||
*/
|
||||
if (pr_res_holder != pr_reg) {
|
||||
if ((pr_res_holder != pr_reg) &&
|
||||
(pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) &&
|
||||
(pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
|
||||
struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
|
||||
pr_err("SPC-3 PR: Attempted RESERVE from"
|
||||
" [%s]: %s while reservation already held by"
|
||||
|
|
@ -4012,7 +4027,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|||
unsigned char *buf;
|
||||
u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
|
||||
u32 off = 8; /* off into first Full Status descriptor */
|
||||
int format_code = 0;
|
||||
int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
|
||||
bool all_reg = false;
|
||||
|
||||
if (cmd->data_length < 8) {
|
||||
pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
|
||||
|
|
@ -4029,6 +4045,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|||
buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
|
||||
buf[3] = (dev->t10_pr.pr_generation & 0xff);
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
if (dev->dev_pr_res_holder) {
|
||||
struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder;
|
||||
|
||||
if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
|
||||
pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) {
|
||||
all_reg = true;
|
||||
pr_res_type = pr_holder->pr_res_type;
|
||||
pr_res_scope = pr_holder->pr_res_scope;
|
||||
}
|
||||
}
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
spin_lock(&pr_tmpl->registration_lock);
|
||||
list_for_each_entry_safe(pr_reg, pr_reg_tmp,
|
||||
&pr_tmpl->registration_list, pr_reg_list) {
|
||||
|
|
@ -4078,14 +4107,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|||
* reservation holder for PR_HOLDER bit.
|
||||
*
|
||||
* Also, if this registration is the reservation
|
||||
* holder, fill in SCOPE and TYPE in the next byte.
|
||||
* holder or there is an All Registrants reservation
|
||||
* active, fill in SCOPE and TYPE in the next byte.
|
||||
*/
|
||||
if (pr_reg->pr_res_holder) {
|
||||
buf[off++] |= 0x01;
|
||||
buf[off++] = (pr_reg->pr_res_scope & 0xf0) |
|
||||
(pr_reg->pr_res_type & 0x0f);
|
||||
} else
|
||||
} else if (all_reg) {
|
||||
buf[off++] |= 0x01;
|
||||
buf[off++] = (pr_res_scope & 0xf0) |
|
||||
(pr_res_type & 0x0f);
|
||||
} else {
|
||||
off += 2;
|
||||
}
|
||||
|
||||
off += 4; /* Skip over reserved area */
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1112,7 +1112,7 @@ static u32 pscsi_get_device_type(struct se_device *dev)
|
|||
struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
|
||||
struct scsi_device *sd = pdv->pdv_sd;
|
||||
|
||||
return sd->type;
|
||||
return (sd) ? sd->type : TYPE_NO_LUN;
|
||||
}
|
||||
|
||||
static sector_t pscsi_get_blocks(struct se_device *dev)
|
||||
|
|
|
|||
|
|
@ -2222,6 +2222,10 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
|
|||
|
||||
out:
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
if (ret && ack_kref)
|
||||
target_put_sess_cmd(se_sess, se_cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(target_get_sess_cmd);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
|
|||
"Please send the output of lspci -vv, this\n"
|
||||
"message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
|
||||
"manufacturer and name of serial board or\n"
|
||||
"modem board to rmk+serial@arm.linux.org.uk.\n",
|
||||
"modem board to <linux-serial@vger.kernel.org>.\n",
|
||||
pci_name(dev), str, dev->vendor, dev->device,
|
||||
dev->subsystem_vendor, dev->subsystem_device);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "conf_space.h"
|
||||
#include "conf_space_quirks.h"
|
||||
|
||||
static bool permissive;
|
||||
bool permissive;
|
||||
module_param(permissive, bool, 0644);
|
||||
|
||||
/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ struct config_field_entry {
|
|||
void *data;
|
||||
};
|
||||
|
||||
extern bool permissive;
|
||||
|
||||
#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
|
||||
|
||||
/* Add fields to a device - the add_fields macro expects to get a pointer to
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
#include "pciback.h"
|
||||
#include "conf_space.h"
|
||||
|
||||
struct pci_cmd_info {
|
||||
u16 val;
|
||||
};
|
||||
|
||||
struct pci_bar_info {
|
||||
u32 val;
|
||||
u32 len_val;
|
||||
|
|
@ -18,21 +22,35 @@ struct pci_bar_info {
|
|||
#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
|
||||
#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
|
||||
|
||||
/* Bits guests are allowed to control in permissive mode. */
|
||||
#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \
|
||||
PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \
|
||||
PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK)
|
||||
|
||||
static void *command_init(struct pci_dev *dev, int offset)
|
||||
{
|
||||
struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
int err;
|
||||
|
||||
if (!cmd)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
|
||||
if (err) {
|
||||
kfree(cmd);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int ret = pci_read_config_word(dev, offset, value);
|
||||
const struct pci_cmd_info *cmd = data;
|
||||
|
||||
ret = xen_pcibk_read_config_word(dev, offset, value, data);
|
||||
if (!pci_is_enabled(dev))
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < PCI_ROM_RESOURCE; i++) {
|
||||
if (dev->resource[i].flags & IORESOURCE_IO)
|
||||
*value |= PCI_COMMAND_IO;
|
||||
if (dev->resource[i].flags & IORESOURCE_MEM)
|
||||
*value |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
*value &= PCI_COMMAND_GUEST;
|
||||
*value |= cmd->val & ~PCI_COMMAND_GUEST;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -41,6 +59,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
|
|||
{
|
||||
struct xen_pcibk_dev_data *dev_data;
|
||||
int err;
|
||||
u16 val;
|
||||
struct pci_cmd_info *cmd = data;
|
||||
|
||||
dev_data = pci_get_drvdata(dev);
|
||||
if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
|
||||
|
|
@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
cmd->val = value;
|
||||
|
||||
if (!permissive && (!dev_data || !dev_data->permissive))
|
||||
return 0;
|
||||
|
||||
/* Only allow the guest to control certain bits. */
|
||||
err = pci_read_config_word(dev, offset, &val);
|
||||
if (err || val == value)
|
||||
return err;
|
||||
|
||||
value &= PCI_COMMAND_GUEST;
|
||||
value |= val & ~PCI_COMMAND_GUEST;
|
||||
|
||||
return pci_write_config_word(dev, offset, value);
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +315,8 @@ static const struct config_field header_common[] = {
|
|||
{
|
||||
.offset = PCI_COMMAND,
|
||||
.size = 2,
|
||||
.init = command_init,
|
||||
.release = bar_release,
|
||||
.u.w.read = command_read,
|
||||
.u.w.write = command_write,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -819,8 +819,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
|||
|
||||
newpage = buf->page;
|
||||
|
||||
if (WARN_ON(!PageUptodate(newpage)))
|
||||
return -EIO;
|
||||
if (!PageUptodate(newpage))
|
||||
SetPageUptodate(newpage);
|
||||
|
||||
ClearPageMappedToDisk(newpage);
|
||||
|
||||
|
|
@ -1725,6 +1725,9 @@ static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
|
|||
static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
|
||||
unsigned int size, struct fuse_copy_state *cs)
|
||||
{
|
||||
/* Don't try to move pages (yet) */
|
||||
cs->move_pages = 0;
|
||||
|
||||
switch (code) {
|
||||
case FUSE_NOTIFY_POLL:
|
||||
return fuse_notify_poll(fc, size, cs);
|
||||
|
|
|
|||
|
|
@ -1906,6 +1906,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
|
|||
struct the_nilfs *nilfs)
|
||||
{
|
||||
struct nilfs_inode_info *ii, *n;
|
||||
int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE);
|
||||
int defer_iput = false;
|
||||
|
||||
spin_lock(&nilfs->ns_inode_lock);
|
||||
|
|
@ -1918,10 +1919,10 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
|
|||
brelse(ii->i_bh);
|
||||
ii->i_bh = NULL;
|
||||
list_del_init(&ii->i_dirty);
|
||||
if (!ii->vfs_inode.i_nlink) {
|
||||
if (!ii->vfs_inode.i_nlink || during_mount) {
|
||||
/*
|
||||
* Defer calling iput() to avoid a deadlock
|
||||
* over I_SYNC flag for inodes with i_nlink == 0
|
||||
* Defer calling iput() to avoid deadlocks if
|
||||
* i_nlink == 0 or mount is not yet finished.
|
||||
*/
|
||||
list_add_tail(&ii->i_dirty, &sci->sc_iput_queue);
|
||||
defer_iput = true;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ enum {
|
|||
/* data contains off-queue information when !WORK_STRUCT_PWQ */
|
||||
WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT,
|
||||
|
||||
WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE),
|
||||
__WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE,
|
||||
WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING),
|
||||
|
||||
/*
|
||||
* When a work item is off queue, its high bits point to the last
|
||||
|
|
|
|||
|
|
@ -2874,19 +2874,57 @@ bool flush_work(struct work_struct *work)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(flush_work);
|
||||
|
||||
struct cwt_wait {
|
||||
wait_queue_t wait;
|
||||
struct work_struct *work;
|
||||
};
|
||||
|
||||
static int cwt_wakefn(wait_queue_t *wait, unsigned mode, int sync, void *key)
|
||||
{
|
||||
struct cwt_wait *cwait = container_of(wait, struct cwt_wait, wait);
|
||||
|
||||
if (cwait->work != key)
|
||||
return 0;
|
||||
return autoremove_wake_function(wait, mode, sync, key);
|
||||
}
|
||||
|
||||
static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
|
||||
{
|
||||
static DECLARE_WAIT_QUEUE_HEAD(cancel_waitq);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = try_to_grab_pending(work, is_dwork, &flags);
|
||||
/*
|
||||
* If someone else is canceling, wait for the same event it
|
||||
* would be waiting for before retrying.
|
||||
* If someone else is already canceling, wait for it to
|
||||
* finish. flush_work() doesn't work for PREEMPT_NONE
|
||||
* because we may get scheduled between @work's completion
|
||||
* and the other canceling task resuming and clearing
|
||||
* CANCELING - flush_work() will return false immediately
|
||||
* as @work is no longer busy, try_to_grab_pending() will
|
||||
* return -ENOENT as @work is still being canceled and the
|
||||
* other canceling task won't be able to clear CANCELING as
|
||||
* we're hogging the CPU.
|
||||
*
|
||||
* Let's wait for completion using a waitqueue. As this
|
||||
* may lead to the thundering herd problem, use a custom
|
||||
* wake function which matches @work along with exclusive
|
||||
* wait and wakeup.
|
||||
*/
|
||||
if (unlikely(ret == -ENOENT))
|
||||
flush_work(work);
|
||||
if (unlikely(ret == -ENOENT)) {
|
||||
struct cwt_wait cwait;
|
||||
|
||||
init_wait(&cwait.wait);
|
||||
cwait.wait.func = cwt_wakefn;
|
||||
cwait.work = work;
|
||||
|
||||
prepare_to_wait_exclusive(&cancel_waitq, &cwait.wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
if (work_is_canceling(work))
|
||||
schedule();
|
||||
finish_wait(&cancel_waitq, &cwait.wait);
|
||||
}
|
||||
} while (unlikely(ret < 0));
|
||||
|
||||
/* tell other tasks trying to grab @work to back off */
|
||||
|
|
@ -2895,6 +2933,16 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
|
|||
|
||||
flush_work(work);
|
||||
clear_work_data(work);
|
||||
|
||||
/*
|
||||
* Paired with prepare_to_wait() above so that either
|
||||
* waitqueue_active() is visible here or !work_is_canceling() is
|
||||
* visible there.
|
||||
*/
|
||||
smp_mb();
|
||||
if (waitqueue_active(&cancel_waitq))
|
||||
__wake_up(&cancel_waitq, TASK_NORMAL, 1, work);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||
int copylen;
|
||||
|
||||
ret = -EOPNOTSUPP;
|
||||
if (m->msg_flags&MSG_OOB)
|
||||
if (flags & MSG_OOB)
|
||||
goto read_error;
|
||||
|
||||
skb = skb_recv_datagram(sk, flags, 0 , &ret);
|
||||
|
|
|
|||
|
|
@ -262,6 +262,9 @@ int can_send(struct sk_buff *skb, int loop)
|
|||
goto inval_skb;
|
||||
}
|
||||
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
|
|||
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
|
||||
__get_user(kmsg->msg_flags, &umsg->msg_flags))
|
||||
return -EFAULT;
|
||||
|
||||
if (!tmp1)
|
||||
kmsg->msg_namelen = 0;
|
||||
|
||||
if (kmsg->msg_namelen < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
|
||||
kmsg->msg_namelen = sizeof(struct sockaddr_storage);
|
||||
kmsg->msg_name = compat_ptr(tmp1);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
static int zero = 0;
|
||||
static int one = 1;
|
||||
static int ushort_max = USHRT_MAX;
|
||||
static int min_sndbuf = SOCK_MIN_SNDBUF;
|
||||
static int min_rcvbuf = SOCK_MIN_RCVBUF;
|
||||
|
||||
#ifdef CONFIG_RPS
|
||||
static int rps_sock_flow_sysctl(ctl_table *table, int write,
|
||||
|
|
@ -97,7 +99,7 @@ static struct ctl_table net_core_table[] = {
|
|||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &one,
|
||||
.extra1 = &min_sndbuf,
|
||||
},
|
||||
{
|
||||
.procname = "rmem_max",
|
||||
|
|
@ -105,7 +107,7 @@ static struct ctl_table net_core_table[] = {
|
|||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &one,
|
||||
.extra1 = &min_rcvbuf,
|
||||
},
|
||||
{
|
||||
.procname = "wmem_default",
|
||||
|
|
@ -113,7 +115,7 @@ static struct ctl_table net_core_table[] = {
|
|||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &one,
|
||||
.extra1 = &min_sndbuf,
|
||||
},
|
||||
{
|
||||
.procname = "rmem_default",
|
||||
|
|
@ -121,7 +123,7 @@ static struct ctl_table net_core_table[] = {
|
|||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &one,
|
||||
.extra1 = &min_rcvbuf,
|
||||
},
|
||||
{
|
||||
.procname = "dev_weight",
|
||||
|
|
|
|||
|
|
@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler(
|
|||
mutex_unlock(&inet_diag_table_mutex);
|
||||
}
|
||||
|
||||
static size_t inet_sk_attr_size(void)
|
||||
{
|
||||
return nla_total_size(sizeof(struct tcp_info))
|
||||
+ nla_total_size(1) /* INET_DIAG_SHUTDOWN */
|
||||
+ nla_total_size(1) /* INET_DIAG_TOS */
|
||||
+ nla_total_size(1) /* INET_DIAG_TCLASS */
|
||||
+ nla_total_size(sizeof(struct inet_diag_meminfo))
|
||||
+ nla_total_size(sizeof(struct inet_diag_msg))
|
||||
+ nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
|
||||
+ nla_total_size(TCP_CA_NAME_MAX)
|
||||
+ nla_total_size(sizeof(struct tcpvegas_info))
|
||||
+ 64;
|
||||
}
|
||||
|
||||
int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||
struct sk_buff *skb, struct inet_diag_req_v2 *req,
|
||||
struct user_namespace *user_ns,
|
||||
|
|
@ -326,9 +340,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
rep = nlmsg_new(sizeof(struct inet_diag_msg) +
|
||||
sizeof(struct inet_diag_meminfo) +
|
||||
sizeof(struct tcp_info) + 64, GFP_KERNEL);
|
||||
rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL);
|
||||
if (!rep) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -2593,15 +2593,11 @@ void tcp_send_fin(struct sock *sk)
|
|||
} else {
|
||||
/* Socket is locked, keep trying until memory is available. */
|
||||
for (;;) {
|
||||
skb = alloc_skb_fclone(MAX_TCP_HEADER,
|
||||
sk->sk_allocation);
|
||||
skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
|
||||
if (skb)
|
||||
break;
|
||||
yield();
|
||||
}
|
||||
|
||||
/* Reserve space for headers and prepare control bits. */
|
||||
skb_reserve(skb, MAX_TCP_HEADER);
|
||||
/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
|
||||
tcp_init_nondata_skb(skb, tp->write_seq,
|
||||
TCPHDR_ACK | TCPHDR_FIN);
|
||||
|
|
@ -2875,9 +2871,9 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
|
|||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct tcp_fastopen_request *fo = tp->fastopen_req;
|
||||
int syn_loss = 0, space, i, err = 0, iovlen = fo->data->msg_iovlen;
|
||||
struct sk_buff *syn_data = NULL, *data;
|
||||
int syn_loss = 0, space, err = 0;
|
||||
unsigned long last_syn_loss = 0;
|
||||
struct sk_buff *syn_data;
|
||||
|
||||
tp->rx_opt.mss_clamp = tp->advmss; /* If MSS is not cached */
|
||||
tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie,
|
||||
|
|
@ -2908,42 +2904,38 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
|
|||
/* limit to order-0 allocations */
|
||||
space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER));
|
||||
|
||||
syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space,
|
||||
sk->sk_allocation);
|
||||
if (syn_data == NULL)
|
||||
syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation);
|
||||
if (!syn_data)
|
||||
goto fallback;
|
||||
syn_data->ip_summed = CHECKSUM_PARTIAL;
|
||||
memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
|
||||
if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
|
||||
fo->data->msg_iov, 0, space))) {
|
||||
kfree_skb(syn_data);
|
||||
goto fallback;
|
||||
|
||||
for (i = 0; i < iovlen && syn_data->len < space; ++i) {
|
||||
struct iovec *iov = &fo->data->msg_iov[i];
|
||||
unsigned char __user *from = iov->iov_base;
|
||||
int len = iov->iov_len;
|
||||
|
||||
if (syn_data->len + len > space)
|
||||
len = space - syn_data->len;
|
||||
else if (i + 1 == iovlen)
|
||||
/* No more data pending in inet_wait_for_connect() */
|
||||
fo->data = NULL;
|
||||
|
||||
if (skb_add_data(syn_data, from, len))
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Queue a data-only packet after the regular SYN for retransmission */
|
||||
data = pskb_copy(syn_data, sk->sk_allocation);
|
||||
if (data == NULL)
|
||||
goto fallback;
|
||||
TCP_SKB_CB(data)->seq++;
|
||||
TCP_SKB_CB(data)->tcp_flags &= ~TCPHDR_SYN;
|
||||
TCP_SKB_CB(data)->tcp_flags = (TCPHDR_ACK|TCPHDR_PSH);
|
||||
tcp_connect_queue_skb(sk, data);
|
||||
fo->copied = data->len;
|
||||
/* No more data pending in inet_wait_for_connect() */
|
||||
if (space == fo->size)
|
||||
fo->data = NULL;
|
||||
fo->copied = space;
|
||||
|
||||
if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) {
|
||||
tcp_connect_queue_skb(sk, syn_data);
|
||||
|
||||
err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation);
|
||||
|
||||
/* Now full SYN+DATA was cloned and sent (or not),
|
||||
* remove the SYN from the original skb (syn_data)
|
||||
* we keep in write queue in case of a retransmit, as we
|
||||
* also have the SYN packet (with no data) in the same queue.
|
||||
*/
|
||||
TCP_SKB_CB(syn_data)->seq++;
|
||||
TCP_SKB_CB(syn_data)->tcp_flags = TCPHDR_ACK | TCPHDR_PSH;
|
||||
if (!err) {
|
||||
tp->syn_data = (fo->copied > 0);
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
|
||||
goto done;
|
||||
}
|
||||
syn_data = NULL;
|
||||
|
||||
fallback:
|
||||
/* Send a regular SYN with Fast Open cookie request option */
|
||||
|
|
@ -2952,7 +2944,6 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
|
|||
err = tcp_transmit_skb(sk, syn, 1, sk->sk_allocation);
|
||||
if (err)
|
||||
tp->syn_fastopen = 0;
|
||||
kfree_skb(syn_data);
|
||||
done:
|
||||
fo->cookie.len = -1; /* Exclude Fast Open option for SYN retries */
|
||||
return err;
|
||||
|
|
@ -2972,13 +2963,10 @@ int tcp_connect(struct sock *sk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation);
|
||||
if (unlikely(buff == NULL))
|
||||
buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
|
||||
if (unlikely(!buff))
|
||||
return -ENOBUFS;
|
||||
|
||||
/* Reserve space for headers. */
|
||||
skb_reserve(buff, MAX_TCP_HEADER);
|
||||
|
||||
tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
|
||||
tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp;
|
||||
tcp_connect_queue_skb(sk, buff);
|
||||
|
|
|
|||
|
|
@ -650,16 +650,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
|
||||
static int ip_vs_route_me_harder(int af, struct sk_buff *skb,
|
||||
unsigned int hooknum)
|
||||
{
|
||||
if (!sysctl_snat_reroute(skb))
|
||||
return 0;
|
||||
/* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */
|
||||
if (NF_INET_LOCAL_IN == hooknum)
|
||||
return 0;
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6) {
|
||||
if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0)
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
|
||||
if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) &&
|
||||
ip6_route_me_harder(skb) != 0)
|
||||
return 1;
|
||||
} else
|
||||
#endif
|
||||
if ((sysctl_snat_reroute(skb) ||
|
||||
skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
|
||||
if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
|
||||
ip_route_me_harder(skb, RTN_LOCAL) != 0)
|
||||
return 1;
|
||||
|
||||
|
|
@ -782,7 +790,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
|
|||
union nf_inet_addr *snet,
|
||||
__u8 protocol, struct ip_vs_conn *cp,
|
||||
struct ip_vs_protocol *pp,
|
||||
unsigned int offset, unsigned int ihl)
|
||||
unsigned int offset, unsigned int ihl,
|
||||
unsigned int hooknum)
|
||||
{
|
||||
unsigned int verdict = NF_DROP;
|
||||
|
||||
|
|
@ -812,7 +821,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
|
|||
#endif
|
||||
ip_vs_nat_icmp(skb, pp, cp, 1);
|
||||
|
||||
if (ip_vs_route_me_harder(af, skb))
|
||||
if (ip_vs_route_me_harder(af, skb, hooknum))
|
||||
goto out;
|
||||
|
||||
/* do the statistics and put it back */
|
||||
|
|
@ -907,7 +916,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
|
|||
|
||||
snet.ip = iph->saddr;
|
||||
return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
|
||||
pp, ciph.len, ihl);
|
||||
pp, ciph.len, ihl, hooknum);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
|
|
@ -972,7 +981,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
|
|||
snet.in6 = ciph.saddr.in6;
|
||||
writable = ciph.len;
|
||||
return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
|
||||
pp, writable, sizeof(struct ipv6hdr));
|
||||
pp, writable, sizeof(struct ipv6hdr),
|
||||
hooknum);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1031,7 +1041,8 @@ static inline bool is_new_conn(const struct sk_buff *skb,
|
|||
*/
|
||||
static unsigned int
|
||||
handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
|
||||
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
|
||||
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph,
|
||||
unsigned int hooknum)
|
||||
{
|
||||
struct ip_vs_protocol *pp = pd->pp;
|
||||
|
||||
|
|
@ -1069,7 +1080,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
|
|||
* if it came from this machine itself. So re-compute
|
||||
* the routing information.
|
||||
*/
|
||||
if (ip_vs_route_me_harder(af, skb))
|
||||
if (ip_vs_route_me_harder(af, skb, hooknum))
|
||||
goto drop;
|
||||
|
||||
IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
|
||||
|
|
@ -1172,7 +1183,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
|
|||
cp = pp->conn_out_get(af, skb, &iph, 0);
|
||||
|
||||
if (likely(cp))
|
||||
return handle_response(af, skb, pd, cp, &iph);
|
||||
return handle_response(af, skb, pd, cp, &iph, hooknum);
|
||||
if (sysctl_nat_icmp_send(net) &&
|
||||
(pp->protocol == IPPROTO_TCP ||
|
||||
pp->protocol == IPPROTO_UDP ||
|
||||
|
|
|
|||
|
|
@ -878,6 +878,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
|
|||
IP_VS_DBG(2, "BACKUP, add new conn. failed\n");
|
||||
return;
|
||||
}
|
||||
if (!(flags & IP_VS_CONN_F_TEMPLATE))
|
||||
kfree(param->pe_data);
|
||||
}
|
||||
|
||||
if (opt)
|
||||
|
|
@ -1151,6 +1153,7 @@ static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end)
|
|||
(opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL)
|
||||
);
|
||||
#endif
|
||||
ip_vs_pe_put(param.pe);
|
||||
return 0;
|
||||
/* Error exit */
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg_list(struct rds_iw_mr_pool *pool,
|
|||
int *unpinned);
|
||||
static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr);
|
||||
|
||||
static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id)
|
||||
static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst,
|
||||
struct rds_iw_device **rds_iwdev,
|
||||
struct rdma_cm_id **cm_id)
|
||||
{
|
||||
struct rds_iw_device *iwdev;
|
||||
struct rds_iw_cm_id *i_cm_id;
|
||||
|
|
@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd
|
|||
src_addr->sin_port,
|
||||
dst_addr->sin_addr.s_addr,
|
||||
dst_addr->sin_port,
|
||||
rs->rs_bound_addr,
|
||||
rs->rs_bound_port,
|
||||
rs->rs_conn_addr,
|
||||
rs->rs_conn_port);
|
||||
src->sin_addr.s_addr,
|
||||
src->sin_port,
|
||||
dst->sin_addr.s_addr,
|
||||
dst->sin_port);
|
||||
#ifdef WORKING_TUPLE_DETECTION
|
||||
if (src_addr->sin_addr.s_addr == rs->rs_bound_addr &&
|
||||
src_addr->sin_port == rs->rs_bound_port &&
|
||||
dst_addr->sin_addr.s_addr == rs->rs_conn_addr &&
|
||||
dst_addr->sin_port == rs->rs_conn_port) {
|
||||
if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr &&
|
||||
src_addr->sin_port == src->sin_port &&
|
||||
dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr &&
|
||||
dst_addr->sin_port == dst->sin_port) {
|
||||
#else
|
||||
/* FIXME - needs to compare the local and remote
|
||||
* ipaddr/port tuple, but the ipaddr is the only
|
||||
|
|
@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd
|
|||
* zero'ed. It doesn't appear to be properly populated
|
||||
* during connection setup...
|
||||
*/
|
||||
if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) {
|
||||
if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) {
|
||||
#endif
|
||||
spin_unlock_irq(&iwdev->spinlock);
|
||||
*rds_iwdev = iwdev;
|
||||
|
|
@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_i
|
|||
{
|
||||
struct sockaddr_in *src_addr, *dst_addr;
|
||||
struct rds_iw_device *rds_iwdev_old;
|
||||
struct rds_sock rs;
|
||||
struct rdma_cm_id *pcm_id;
|
||||
int rc;
|
||||
|
||||
src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr;
|
||||
dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr;
|
||||
|
||||
rs.rs_bound_addr = src_addr->sin_addr.s_addr;
|
||||
rs.rs_bound_port = src_addr->sin_port;
|
||||
rs.rs_conn_addr = dst_addr->sin_addr.s_addr;
|
||||
rs.rs_conn_port = dst_addr->sin_port;
|
||||
|
||||
rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id);
|
||||
rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id);
|
||||
if (rc)
|
||||
rds_iw_remove_cm_id(rds_iwdev, cm_id);
|
||||
|
||||
|
|
@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist *sg, unsigned long nents,
|
|||
struct rds_iw_device *rds_iwdev;
|
||||
struct rds_iw_mr *ibmr = NULL;
|
||||
struct rdma_cm_id *cm_id;
|
||||
struct sockaddr_in src = {
|
||||
.sin_addr.s_addr = rs->rs_bound_addr,
|
||||
.sin_port = rs->rs_bound_port,
|
||||
};
|
||||
struct sockaddr_in dst = {
|
||||
.sin_addr.s_addr = rs->rs_conn_addr,
|
||||
.sin_port = rs->rs_conn_port,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id);
|
||||
ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id);
|
||||
if (ret || !cm_id) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||
if (!skb) {
|
||||
/* nothing remains on the queue */
|
||||
if (copied &&
|
||||
(msg->msg_flags & MSG_PEEK || timeo == 0))
|
||||
(flags & MSG_PEEK || timeo == 0))
|
||||
goto out;
|
||||
|
||||
/* wait for a message to turn up */
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
|||
|
||||
if (info->count < 1)
|
||||
return -EINVAL;
|
||||
if (!*info->id.name)
|
||||
return -EINVAL;
|
||||
if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name))
|
||||
return -EINVAL;
|
||||
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
|
||||
(info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
|
||||
SNDRV_CTL_ELEM_ACCESS_INACTIVE|
|
||||
|
|
|
|||
|
|
@ -642,12 +642,45 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
|
|||
return val;
|
||||
}
|
||||
|
||||
/* is this a stereo widget or a stereo-to-mono mix? */
|
||||
static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
|
||||
{
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
hda_nid_t conn;
|
||||
|
||||
if (wcaps & AC_WCAP_STEREO)
|
||||
return true;
|
||||
if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
|
||||
return false;
|
||||
if (snd_hda_get_num_conns(codec, nid) != 1)
|
||||
return false;
|
||||
if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
|
||||
return false;
|
||||
return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
|
||||
}
|
||||
|
||||
/* initialize the amp value (only at the first time) */
|
||||
static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
|
||||
{
|
||||
unsigned int caps = query_amp_caps(codec, nid, dir);
|
||||
int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
|
||||
snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
|
||||
|
||||
if (is_stereo_amps(codec, nid, dir))
|
||||
snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
|
||||
else
|
||||
snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
|
||||
}
|
||||
|
||||
/* update the amp, doing in stereo or mono depending on NID */
|
||||
static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
if (is_stereo_amps(codec, nid, dir))
|
||||
return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
|
||||
mask, val);
|
||||
else
|
||||
return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
|
||||
mask, val);
|
||||
}
|
||||
|
||||
/* calculate amp value mask we can modify;
|
||||
|
|
@ -687,7 +720,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
|
|||
return;
|
||||
|
||||
val &= mask;
|
||||
snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
|
||||
update_amp(codec, nid, dir, idx, mask, val);
|
||||
}
|
||||
|
||||
static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
|
||||
|
|
@ -4235,13 +4268,11 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
|
|||
has_amp = nid_has_mute(codec, mix, HDA_INPUT);
|
||||
for (i = 0; i < nums; i++) {
|
||||
if (has_amp)
|
||||
snd_hda_codec_amp_stereo(codec, mix,
|
||||
HDA_INPUT, i,
|
||||
0xff, HDA_AMP_MUTE);
|
||||
update_amp(codec, mix, HDA_INPUT, i,
|
||||
0xff, HDA_AMP_MUTE);
|
||||
else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
|
||||
snd_hda_codec_amp_stereo(codec, conn[i],
|
||||
HDA_OUTPUT, 0,
|
||||
0xff, HDA_AMP_MUTE);
|
||||
update_amp(codec, conn[i], HDA_OUTPUT, 0,
|
||||
0xff, HDA_AMP_MUTE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,13 +129,38 @@ static void print_amp_caps(struct snd_info_buffer *buffer,
|
|||
(caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
|
||||
}
|
||||
|
||||
/* is this a stereo widget or a stereo-to-mono mix? */
|
||||
static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
|
||||
int dir, unsigned int wcaps, int indices)
|
||||
{
|
||||
hda_nid_t conn;
|
||||
|
||||
if (wcaps & AC_WCAP_STEREO)
|
||||
return true;
|
||||
/* check for a stereo-to-mono mix; it must be:
|
||||
* only a single connection, only for input, and only a mixer widget
|
||||
*/
|
||||
if (indices != 1 || dir != HDA_INPUT ||
|
||||
get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
|
||||
return false;
|
||||
|
||||
if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
|
||||
return false;
|
||||
/* the connection source is a stereo? */
|
||||
wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
|
||||
return !!(wcaps & AC_WCAP_STEREO);
|
||||
}
|
||||
|
||||
static void print_amp_vals(struct snd_info_buffer *buffer,
|
||||
struct hda_codec *codec, hda_nid_t nid,
|
||||
int dir, int stereo, int indices)
|
||||
int dir, unsigned int wcaps, int indices)
|
||||
{
|
||||
unsigned int val;
|
||||
bool stereo;
|
||||
int i;
|
||||
|
||||
stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
|
||||
|
||||
dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
|
||||
for (i = 0; i < indices; i++) {
|
||||
snd_iprintf(buffer, " [");
|
||||
|
|
@ -682,12 +707,10 @@ static void print_codec_info(struct snd_info_entry *entry,
|
|||
(codec->single_adc_amp &&
|
||||
wid_type == AC_WID_AUD_IN))
|
||||
print_amp_vals(buffer, codec, nid, HDA_INPUT,
|
||||
wid_caps & AC_WCAP_STEREO,
|
||||
1);
|
||||
wid_caps, 1);
|
||||
else
|
||||
print_amp_vals(buffer, codec, nid, HDA_INPUT,
|
||||
wid_caps & AC_WCAP_STEREO,
|
||||
conn_len);
|
||||
wid_caps, conn_len);
|
||||
}
|
||||
if (wid_caps & AC_WCAP_OUT_AMP) {
|
||||
snd_iprintf(buffer, " Amp-Out caps: ");
|
||||
|
|
@ -696,11 +719,10 @@ static void print_codec_info(struct snd_info_entry *entry,
|
|||
if (wid_type == AC_WID_PIN &&
|
||||
codec->pin_amp_workaround)
|
||||
print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
|
||||
wid_caps & AC_WCAP_STEREO,
|
||||
conn_len);
|
||||
wid_caps, conn_len);
|
||||
else
|
||||
print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
|
||||
wid_caps & AC_WCAP_STEREO, 1);
|
||||
wid_caps, 1);
|
||||
}
|
||||
|
||||
switch (wid_type) {
|
||||
|
|
|
|||
|
|
@ -363,6 +363,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
|
||||
SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
|
||||
SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
|
||||
SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81),
|
||||
SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42),
|
||||
SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
|
||||
{} /* terminator */
|
||||
|
|
@ -531,6 +532,7 @@ static int patch_cs420x(struct hda_codec *codec)
|
|||
return -ENOMEM;
|
||||
|
||||
spec->gen.automute_hook = cs_automute;
|
||||
codec->single_adc_amp = 1;
|
||||
|
||||
snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
|
||||
cs420x_fixups);
|
||||
|
|
|
|||
|
|
@ -3223,6 +3223,7 @@ enum {
|
|||
CXT_PINCFG_LENOVO_TP410,
|
||||
CXT_PINCFG_LEMOTE_A1004,
|
||||
CXT_PINCFG_LEMOTE_A1205,
|
||||
CXT_PINCFG_COMPAQ_CQ60,
|
||||
CXT_FIXUP_STEREO_DMIC,
|
||||
CXT_FIXUP_INC_MIC_BOOST,
|
||||
CXT_FIXUP_GPIO1,
|
||||
|
|
@ -3296,6 +3297,15 @@ static const struct hda_fixup cxt_fixups[] = {
|
|||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cxt_pincfg_lemote,
|
||||
},
|
||||
[CXT_PINCFG_COMPAQ_CQ60] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
/* 0x17 was falsely set up as a mic, it should 0x1d */
|
||||
{ 0x17, 0x400001f0 },
|
||||
{ 0x1d, 0x97a70120 },
|
||||
{ }
|
||||
}
|
||||
},
|
||||
[CXT_FIXUP_STEREO_DMIC] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = cxt_fixup_stereo_dmic,
|
||||
|
|
@ -3316,6 +3326,7 @@ static const struct hda_fixup cxt_fixups[] = {
|
|||
};
|
||||
|
||||
static const struct snd_pci_quirk cxt5051_fixups[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60),
|
||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
|
||||
{}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user