Merge "Merge android-4.4.186 (aeb051d) into msm-4.4"

This commit is contained in:
Linux Build Service Account 2019-07-29 04:59:29 -07:00 committed by Gerrit - the friendly Code Review server
commit 6876dc0e13
49 changed files with 442 additions and 241 deletions

View file

@ -4,6 +4,7 @@ Required properties:
- compatible: Should be one of the following: - compatible: Should be one of the following:
- "microchip,mcp2510" for MCP2510. - "microchip,mcp2510" for MCP2510.
- "microchip,mcp2515" for MCP2515. - "microchip,mcp2515" for MCP2515.
- "microchip,mcp25625" for MCP25625.
- reg: SPI chip select. - reg: SPI chip select.
- clocks: The clock feeding the CAN controller. - clocks: The clock feeding the CAN controller.
- interrupt-parent: The parent interrupt controller. - interrupt-parent: The parent interrupt controller.

View file

@ -1,6 +1,6 @@
VERSION = 4 VERSION = 4
PATCHLEVEL = 4 PATCHLEVEL = 4
SUBLEVEL = 185 SUBLEVEL = 186
EXTRAVERSION = EXTRAVERSION =
NAME = Blurry Fish Butt NAME = Blurry Fish Butt

View file

@ -183,11 +183,6 @@ static void *__init unw_hdr_alloc_early(unsigned long sz)
MAX_DMA_ADDRESS); MAX_DMA_ADDRESS);
} }
static void *unw_hdr_alloc(unsigned long sz)
{
return kmalloc(sz, GFP_KERNEL);
}
static void init_unwind_table(struct unwind_table *table, const char *name, static void init_unwind_table(struct unwind_table *table, const char *name,
const void *core_start, unsigned long core_size, const void *core_start, unsigned long core_size,
const void *init_start, unsigned long init_size, const void *init_start, unsigned long init_size,
@ -368,6 +363,10 @@ ret_err:
} }
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
static void *unw_hdr_alloc(unsigned long sz)
{
return kmalloc(sz, GFP_KERNEL);
}
static struct unwind_table *last_table; static struct unwind_table *last_table;

View file

@ -1479,6 +1479,8 @@ static __init void da850_evm_init(void)
if (ret) if (ret)
pr_warn("%s: dsp/rproc registration failed: %d\n", pr_warn("%s: dsp/rproc registration failed: %d\n",
__func__, ret); __func__, ret);
regulator_has_full_constraints();
} }
#ifdef CONFIG_SERIAL_8250_CONSOLE #ifdef CONFIG_SERIAL_8250_CONSOLE

View file

@ -660,6 +660,9 @@ static struct platform_device da8xx_lcdc_device = {
.id = 0, .id = 0,
.num_resources = ARRAY_SIZE(da8xx_lcdc_resources), .num_resources = ARRAY_SIZE(da8xx_lcdc_resources),
.resource = da8xx_lcdc_resources, .resource = da8xx_lcdc_resources,
.dev = {
.coherent_dma_mask = DMA_BIT_MASK(32),
}
}; };
int __init da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata) int __init da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata)

View file

@ -430,7 +430,7 @@ static void omap3_prm_reconfigure_io_chain(void)
* registers, and omap3xxx_prm_reconfigure_io_chain() must be called. * registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
* No return value. * No return value.
*/ */
static void __init omap3xxx_prm_enable_io_wakeup(void) static void omap3xxx_prm_enable_io_wakeup(void)
{ {
if (prm_features & PRM_HAS_IO_WAKEUP) if (prm_features & PRM_HAS_IO_WAKEUP)
omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,

View file

@ -10,14 +10,6 @@
#ifndef __ASM_SGIDEFS_H #ifndef __ASM_SGIDEFS_H
#define __ASM_SGIDEFS_H #define __ASM_SGIDEFS_H
/*
* Using a Linux compiler for building Linux seems logic but not to
* everybody.
*/
#ifndef __linux__
#error Use a Linux compiler or give up.
#endif
/* /*
* Definitions for the ISA levels * Definitions for the ISA levels
* *

View file

@ -51,6 +51,18 @@ static inline int test_facility(unsigned long nr)
return __test_facility(nr, &S390_lowcore.stfle_fac_list); return __test_facility(nr, &S390_lowcore.stfle_fac_list);
} }
static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
{
register unsigned long reg0 asm("0") = size - 1;
asm volatile(
".insn s,0xb2b00000,0(%1)" /* stfle */
: "+d" (reg0)
: "a" (stfle_fac_list)
: "memory", "cc");
return reg0;
}
/** /**
* stfle - Store facility list extended * stfle - Store facility list extended
* @stfle_fac_list: array where facility list can be stored * @stfle_fac_list: array where facility list can be stored
@ -70,13 +82,8 @@ static inline void stfle(u64 *stfle_fac_list, int size)
memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
if (S390_lowcore.stfl_fac_list & 0x01000000) { if (S390_lowcore.stfl_fac_list & 0x01000000) {
/* More facility bits available with stfle */ /* More facility bits available with stfle */
register unsigned long reg0 asm("0") = size - 1; nr = __stfle_asm(stfle_fac_list, size);
nr = min_t(unsigned long, (nr + 1) * 8, size * 8);
asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
: "+d" (reg0)
: "a" (stfle_fac_list)
: "memory", "cc");
nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
} }
memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
preempt_enable(); preempt_enable();

View file

@ -23,6 +23,7 @@
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/context_tracking.h> #include <linux/context_tracking.h>
#include <linux/nospec.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
@ -697,9 +698,11 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)
{ {
struct thread_struct *thread = &tsk->thread; struct thread_struct *thread = &tsk->thread;
unsigned long val = 0; unsigned long val = 0;
int index = n;
if (n < HBP_NUM) { if (n < HBP_NUM) {
struct perf_event *bp = thread->ptrace_bps[n]; struct perf_event *bp = thread->ptrace_bps[index];
index = array_index_nospec(index, HBP_NUM);
if (bp) if (bp)
val = bp->hw.info.address; val = bp->hw.info.address;

View file

@ -4,6 +4,7 @@
#include <linux/user.h> #include <linux/user.h>
#include <linux/regset.h> #include <linux/regset.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/nospec.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/desc.h> #include <asm/desc.h>
@ -177,6 +178,7 @@ int do_get_thread_area(struct task_struct *p, int idx,
struct user_desc __user *u_info) struct user_desc __user *u_info)
{ {
struct user_desc info; struct user_desc info;
int index;
if (idx == -1 && get_user(idx, &u_info->entry_number)) if (idx == -1 && get_user(idx, &u_info->entry_number))
return -EFAULT; return -EFAULT;
@ -184,8 +186,11 @@ int do_get_thread_area(struct task_struct *p, int idx,
if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
return -EINVAL; return -EINVAL;
fill_user_desc(&info, idx, index = idx - GDT_ENTRY_TLS_MIN;
&p->thread.tls_array[idx - GDT_ENTRY_TLS_MIN]); index = array_index_nospec(index,
GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN + 1);
fill_user_desc(&info, idx, &p->thread.tls_array[index]);
if (copy_to_user(u_info, &info, sizeof(info))) if (copy_to_user(u_info, &info, sizeof(info)))
return -EFAULT; return -EFAULT;

View file

@ -678,7 +678,6 @@ static const struct kvm_io_device_ops speaker_dev_ops = {
.write = speaker_ioport_write, .write = speaker_ioport_write,
}; };
/* Caller must hold slots_lock */
struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
{ {
struct kvm_pit *pit; struct kvm_pit *pit;
@ -733,6 +732,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
pit->mask_notifier.func = pit_mask_notifer; pit->mask_notifier.func = pit_mask_notifer;
kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
mutex_lock(&kvm->slots_lock);
kvm_iodevice_init(&pit->dev, &pit_dev_ops); kvm_iodevice_init(&pit->dev, &pit_dev_ops);
ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS, ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS,
KVM_PIT_MEM_LENGTH, &pit->dev); KVM_PIT_MEM_LENGTH, &pit->dev);
@ -747,13 +747,14 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
if (ret < 0) if (ret < 0)
goto fail_unregister; goto fail_unregister;
} }
mutex_unlock(&kvm->slots_lock);
return pit; return pit;
fail_unregister: fail_unregister:
kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev); kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev);
fail: fail:
mutex_unlock(&kvm->slots_lock);
kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier); kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
kvm_unregister_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier); kvm_unregister_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
kvm_free_irq_source_id(kvm, pit->irq_source_id); kvm_free_irq_source_id(kvm, pit->irq_source_id);

View file

@ -3867,7 +3867,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
sizeof(struct kvm_pit_config))) sizeof(struct kvm_pit_config)))
goto out; goto out;
create_pit: create_pit:
mutex_lock(&kvm->slots_lock); mutex_lock(&kvm->lock);
r = -EEXIST; r = -EEXIST;
if (kvm->arch.vpit) if (kvm->arch.vpit)
goto create_pit_unlock; goto create_pit_unlock;
@ -3876,7 +3876,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
if (kvm->arch.vpit) if (kvm->arch.vpit)
r = 0; r = 0;
create_pit_unlock: create_pit_unlock:
mutex_unlock(&kvm->slots_lock); mutex_unlock(&kvm->lock);
break; break;
case KVM_GET_IRQCHIP: { case KVM_GET_IRQCHIP: {
/* 0: PIC master, 1: PIC slave, 2: IOAPIC */ /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
@ -7799,7 +7799,7 @@ int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
slot = id_to_memslot(slots, id); slot = id_to_memslot(slots, id);
if (size) { if (size) {
if (WARN_ON(slot->npages)) if (slot->npages)
return -EEXIST; return -EEXIST;
/* /*

View file

@ -530,11 +530,12 @@ static int imx_keypad_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int __maybe_unused imx_kbd_suspend(struct device *dev) static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev); struct imx_keypad *kbd = platform_get_drvdata(pdev);
struct input_dev *input_dev = kbd->input_dev; struct input_dev *input_dev = kbd->input_dev;
unsigned short reg_val = readw(kbd->mmio_base + KPSR);
/* imx kbd can wake up system even clock is disabled */ /* imx kbd can wake up system even clock is disabled */
mutex_lock(&input_dev->mutex); mutex_lock(&input_dev->mutex);
@ -544,13 +545,20 @@ static int __maybe_unused imx_kbd_suspend(struct device *dev)
mutex_unlock(&input_dev->mutex); mutex_unlock(&input_dev->mutex);
if (device_may_wakeup(&pdev->dev)) if (device_may_wakeup(&pdev->dev)) {
if (reg_val & KBD_STAT_KPKD)
reg_val |= KBD_STAT_KRIE;
if (reg_val & KBD_STAT_KPKR)
reg_val |= KBD_STAT_KDIE;
writew(reg_val, kbd->mmio_base + KPSR);
enable_irq_wake(kbd->irq); enable_irq_wake(kbd->irq);
}
return 0; return 0;
} }
static int __maybe_unused imx_kbd_resume(struct device *dev) static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev); struct imx_keypad *kbd = platform_get_drvdata(pdev);
@ -574,7 +582,9 @@ err_clk:
return ret; return ret;
} }
static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume); static const struct dev_pm_ops imx_kbd_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume)
};
static struct platform_driver imx_keypad_driver = { static struct platform_driver imx_keypad_driver = {
.driver = { .driver = {

View file

@ -1191,6 +1191,8 @@ static const char * const middle_button_pnp_ids[] = {
"LEN2132", /* ThinkPad P52 */ "LEN2132", /* ThinkPad P52 */
"LEN2133", /* ThinkPad P72 w/ NFC */ "LEN2133", /* ThinkPad P72 w/ NFC */
"LEN2134", /* ThinkPad P72 */ "LEN2134", /* ThinkPad P72 */
"LEN0407",
"LEN0408",
NULL NULL
}; };

View file

@ -220,8 +220,8 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
BUG(); BUG();
} }
DMERR("%s: %s block %llu is corrupted", v->data_dev->name, type_str, DMERR_LIMIT("%s: %s block %llu is corrupted", v->data_dev->name,
block); type_str, block);
if (v->corrupted_errs == DM_VERITY_MAX_CORRUPTED_ERRS) if (v->corrupted_errs == DM_VERITY_MAX_CORRUPTED_ERRS)
DMERR("%s: reached maximum errors", v->data_dev->name); DMERR("%s: reached maximum errors", v->data_dev->name);

View file

@ -7226,9 +7226,9 @@ static void status_unused(struct seq_file *seq)
static int status_resync(struct seq_file *seq, struct mddev *mddev) static int status_resync(struct seq_file *seq, struct mddev *mddev)
{ {
sector_t max_sectors, resync, res; sector_t max_sectors, resync, res;
unsigned long dt, db; unsigned long dt, db = 0;
sector_t rt; sector_t rt, curr_mark_cnt, resync_mark_cnt;
int scale; int scale, recovery_active;
unsigned int per_milli; unsigned int per_milli;
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) || if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
@ -7298,22 +7298,30 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
* db: blocks written from mark until now * db: blocks written from mark until now
* rt: remaining time * rt: remaining time
* *
* rt is a sector_t, so could be 32bit or 64bit. * rt is a sector_t, which is always 64bit now. We are keeping
* So we divide before multiply in case it is 32bit and close * the original algorithm, but it is not really necessary.
* to the limit. *
* We scale the divisor (db) by 32 to avoid losing precision * Original algorithm:
* near the end of resync when the number of remaining sectors * So we divide before multiply in case it is 32bit and close
* is close to 'db'. * to the limit.
* We then divide rt by 32 after multiplying by db to compensate. * We scale the divisor (db) by 32 to avoid losing precision
* The '+1' avoids division by zero if db is very small. * near the end of resync when the number of remaining sectors
* is close to 'db'.
* We then divide rt by 32 after multiplying by db to compensate.
* The '+1' avoids division by zero if db is very small.
*/ */
dt = ((jiffies - mddev->resync_mark) / HZ); dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++; if (!dt) dt++;
db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active))
- mddev->resync_mark_cnt; curr_mark_cnt = mddev->curr_mark_cnt;
recovery_active = atomic_read(&mddev->recovery_active);
resync_mark_cnt = mddev->resync_mark_cnt;
if (curr_mark_cnt >= (recovery_active + resync_mark_cnt))
db = curr_mark_cnt - (recovery_active + resync_mark_cnt);
rt = max_sectors - resync; /* number of remaining sectors */ rt = max_sectors - resync; /* number of remaining sectors */
sector_div(rt, db/32+1); rt = div64_u64(rt, db/32+1);
rt *= dt; rt *= dt;
rt >>= 5; rt >>= 5;

View file

@ -28,6 +28,9 @@
#include "vmci_driver.h" #include "vmci_driver.h"
#include "vmci_event.h" #include "vmci_event.h"
/* Use a wide upper bound for the maximum contexts. */
#define VMCI_MAX_CONTEXTS 2000
/* /*
* List of current VMCI contexts. Contexts can be added by * List of current VMCI contexts. Contexts can be added by
* vmci_ctx_create() and removed via vmci_ctx_destroy(). * vmci_ctx_create() and removed via vmci_ctx_destroy().
@ -124,19 +127,22 @@ struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
/* Initialize host-specific VMCI context. */ /* Initialize host-specific VMCI context. */
init_waitqueue_head(&context->host_context.wait_queue); init_waitqueue_head(&context->host_context.wait_queue);
context->queue_pair_array = vmci_handle_arr_create(0); context->queue_pair_array =
vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT);
if (!context->queue_pair_array) { if (!context->queue_pair_array) {
error = -ENOMEM; error = -ENOMEM;
goto err_free_ctx; goto err_free_ctx;
} }
context->doorbell_array = vmci_handle_arr_create(0); context->doorbell_array =
vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
if (!context->doorbell_array) { if (!context->doorbell_array) {
error = -ENOMEM; error = -ENOMEM;
goto err_free_qp_array; goto err_free_qp_array;
} }
context->pending_doorbell_array = vmci_handle_arr_create(0); context->pending_doorbell_array =
vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
if (!context->pending_doorbell_array) { if (!context->pending_doorbell_array) {
error = -ENOMEM; error = -ENOMEM;
goto err_free_db_array; goto err_free_db_array;
@ -211,7 +217,7 @@ static int ctx_fire_notification(u32 context_id, u32 priv_flags)
* We create an array to hold the subscribers we find when * We create an array to hold the subscribers we find when
* scanning through all contexts. * scanning through all contexts.
*/ */
subscriber_array = vmci_handle_arr_create(0); subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS);
if (subscriber_array == NULL) if (subscriber_array == NULL)
return VMCI_ERROR_NO_MEM; return VMCI_ERROR_NO_MEM;
@ -630,20 +636,26 @@ int vmci_ctx_add_notification(u32 context_id, u32 remote_cid)
spin_lock(&context->lock); spin_lock(&context->lock);
list_for_each_entry(n, &context->notifier_list, node) { if (context->n_notifiers < VMCI_MAX_CONTEXTS) {
if (vmci_handle_is_equal(n->handle, notifier->handle)) { list_for_each_entry(n, &context->notifier_list, node) {
exists = true; if (vmci_handle_is_equal(n->handle, notifier->handle)) {
break; exists = true;
break;
}
} }
}
if (exists) { if (exists) {
kfree(notifier); kfree(notifier);
result = VMCI_ERROR_ALREADY_EXISTS; result = VMCI_ERROR_ALREADY_EXISTS;
} else {
list_add_tail_rcu(&notifier->node,
&context->notifier_list);
context->n_notifiers++;
result = VMCI_SUCCESS;
}
} else { } else {
list_add_tail_rcu(&notifier->node, &context->notifier_list); kfree(notifier);
context->n_notifiers++; result = VMCI_ERROR_NO_MEM;
result = VMCI_SUCCESS;
} }
spin_unlock(&context->lock); spin_unlock(&context->lock);
@ -728,8 +740,7 @@ static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context,
u32 *buf_size, void **pbuf) u32 *buf_size, void **pbuf)
{ {
struct dbell_cpt_state *dbells; struct dbell_cpt_state *dbells;
size_t n_doorbells; u32 i, n_doorbells;
int i;
n_doorbells = vmci_handle_arr_get_size(context->doorbell_array); n_doorbells = vmci_handle_arr_get_size(context->doorbell_array);
if (n_doorbells > 0) { if (n_doorbells > 0) {
@ -867,7 +878,8 @@ int vmci_ctx_rcv_notifications_get(u32 context_id,
spin_lock(&context->lock); spin_lock(&context->lock);
*db_handle_array = context->pending_doorbell_array; *db_handle_array = context->pending_doorbell_array;
context->pending_doorbell_array = vmci_handle_arr_create(0); context->pending_doorbell_array =
vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
if (!context->pending_doorbell_array) { if (!context->pending_doorbell_array) {
context->pending_doorbell_array = *db_handle_array; context->pending_doorbell_array = *db_handle_array;
*db_handle_array = NULL; *db_handle_array = NULL;
@ -949,12 +961,11 @@ int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle)
return VMCI_ERROR_NOT_FOUND; return VMCI_ERROR_NOT_FOUND;
spin_lock(&context->lock); spin_lock(&context->lock);
if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) { if (!vmci_handle_arr_has_entry(context->doorbell_array, handle))
vmci_handle_arr_append_entry(&context->doorbell_array, handle); result = vmci_handle_arr_append_entry(&context->doorbell_array,
result = VMCI_SUCCESS; handle);
} else { else
result = VMCI_ERROR_DUPLICATE_ENTRY; result = VMCI_ERROR_DUPLICATE_ENTRY;
}
spin_unlock(&context->lock); spin_unlock(&context->lock);
vmci_ctx_put(context); vmci_ctx_put(context);
@ -1090,15 +1101,16 @@ int vmci_ctx_notify_dbell(u32 src_cid,
if (!vmci_handle_arr_has_entry( if (!vmci_handle_arr_has_entry(
dst_context->pending_doorbell_array, dst_context->pending_doorbell_array,
handle)) { handle)) {
vmci_handle_arr_append_entry( result = vmci_handle_arr_append_entry(
&dst_context->pending_doorbell_array, &dst_context->pending_doorbell_array,
handle); handle);
if (result == VMCI_SUCCESS) {
ctx_signal_notify(dst_context); ctx_signal_notify(dst_context);
wake_up(&dst_context->host_context.wait_queue); wake_up(&dst_context->host_context.wait_queue);
}
} else {
result = VMCI_SUCCESS;
} }
result = VMCI_SUCCESS;
} }
spin_unlock(&dst_context->lock); spin_unlock(&dst_context->lock);
} }
@ -1125,13 +1137,11 @@ int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle)
if (context == NULL || vmci_handle_is_invalid(handle)) if (context == NULL || vmci_handle_is_invalid(handle))
return VMCI_ERROR_INVALID_ARGS; return VMCI_ERROR_INVALID_ARGS;
if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) { if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle))
vmci_handle_arr_append_entry(&context->queue_pair_array, result = vmci_handle_arr_append_entry(
handle); &context->queue_pair_array, handle);
result = VMCI_SUCCESS; else
} else {
result = VMCI_ERROR_DUPLICATE_ENTRY; result = VMCI_ERROR_DUPLICATE_ENTRY;
}
return result; return result;
} }

View file

@ -16,24 +16,29 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "vmci_handle_array.h" #include "vmci_handle_array.h"
static size_t handle_arr_calc_size(size_t capacity) static size_t handle_arr_calc_size(u32 capacity)
{ {
return sizeof(struct vmci_handle_arr) + return VMCI_HANDLE_ARRAY_HEADER_SIZE +
capacity * sizeof(struct vmci_handle); capacity * sizeof(struct vmci_handle);
} }
struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity)
{ {
struct vmci_handle_arr *array; struct vmci_handle_arr *array;
if (max_capacity == 0 || capacity > max_capacity)
return NULL;
if (capacity == 0) if (capacity == 0)
capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE; capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY,
max_capacity);
array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
if (!array) if (!array)
return NULL; return NULL;
array->capacity = capacity; array->capacity = capacity;
array->max_capacity = max_capacity;
array->size = 0; array->size = 0;
return array; return array;
@ -44,27 +49,34 @@ void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
kfree(array); kfree(array);
} }
void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
struct vmci_handle handle) struct vmci_handle handle)
{ {
struct vmci_handle_arr *array = *array_ptr; struct vmci_handle_arr *array = *array_ptr;
if (unlikely(array->size >= array->capacity)) { if (unlikely(array->size >= array->capacity)) {
/* reallocate. */ /* reallocate. */
struct vmci_handle_arr *new_array; struct vmci_handle_arr *new_array;
size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT; u32 capacity_bump = min(array->max_capacity - array->capacity,
size_t new_size = handle_arr_calc_size(new_capacity); array->capacity);
size_t new_size = handle_arr_calc_size(array->capacity +
capacity_bump);
if (array->size >= array->max_capacity)
return VMCI_ERROR_NO_MEM;
new_array = krealloc(array, new_size, GFP_ATOMIC); new_array = krealloc(array, new_size, GFP_ATOMIC);
if (!new_array) if (!new_array)
return; return VMCI_ERROR_NO_MEM;
new_array->capacity = new_capacity; new_array->capacity += capacity_bump;
*array_ptr = array = new_array; *array_ptr = array = new_array;
} }
array->entries[array->size] = handle; array->entries[array->size] = handle;
array->size++; array->size++;
return VMCI_SUCCESS;
} }
/* /*
@ -74,7 +86,7 @@ struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
struct vmci_handle entry_handle) struct vmci_handle entry_handle)
{ {
struct vmci_handle handle = VMCI_INVALID_HANDLE; struct vmci_handle handle = VMCI_INVALID_HANDLE;
size_t i; u32 i;
for (i = 0; i < array->size; i++) { for (i = 0; i < array->size; i++) {
if (vmci_handle_is_equal(array->entries[i], entry_handle)) { if (vmci_handle_is_equal(array->entries[i], entry_handle)) {
@ -109,7 +121,7 @@ struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
* Handle at given index, VMCI_INVALID_HANDLE if invalid index. * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
*/ */
struct vmci_handle struct vmci_handle
vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index)
{ {
if (unlikely(index >= array->size)) if (unlikely(index >= array->size))
return VMCI_INVALID_HANDLE; return VMCI_INVALID_HANDLE;
@ -120,7 +132,7 @@ vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
struct vmci_handle entry_handle) struct vmci_handle entry_handle)
{ {
size_t i; u32 i;
for (i = 0; i < array->size; i++) for (i = 0; i < array->size; i++)
if (vmci_handle_is_equal(array->entries[i], entry_handle)) if (vmci_handle_is_equal(array->entries[i], entry_handle))

View file

@ -17,32 +17,41 @@
#define _VMCI_HANDLE_ARRAY_H_ #define _VMCI_HANDLE_ARRAY_H_
#include <linux/vmw_vmci_defs.h> #include <linux/vmw_vmci_defs.h>
#include <linux/limits.h>
#include <linux/types.h> #include <linux/types.h>
#define VMCI_HANDLE_ARRAY_DEFAULT_SIZE 4
#define VMCI_ARR_CAP_MULT 2 /* Array capacity multiplier */
struct vmci_handle_arr { struct vmci_handle_arr {
size_t capacity; u32 capacity;
size_t size; u32 max_capacity;
u32 size;
u32 pad;
struct vmci_handle entries[]; struct vmci_handle entries[];
}; };
struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity); #define VMCI_HANDLE_ARRAY_HEADER_SIZE \
offsetof(struct vmci_handle_arr, entries)
/* Select a default capacity that results in a 64 byte sized array */
#define VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY 6
/* Make sure that the max array size can be expressed by a u32 */
#define VMCI_HANDLE_ARRAY_MAX_CAPACITY \
((U32_MAX - VMCI_HANDLE_ARRAY_HEADER_SIZE - 1) / \
sizeof(struct vmci_handle))
struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity);
void vmci_handle_arr_destroy(struct vmci_handle_arr *array); void vmci_handle_arr_destroy(struct vmci_handle_arr *array);
void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
struct vmci_handle handle); struct vmci_handle handle);
struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
struct vmci_handle struct vmci_handle
entry_handle); entry_handle);
struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array); struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array);
struct vmci_handle struct vmci_handle
vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index); vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index);
bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
struct vmci_handle entry_handle); struct vmci_handle entry_handle);
struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array); struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array);
static inline size_t vmci_handle_arr_get_size( static inline u32 vmci_handle_arr_get_size(
const struct vmci_handle_arr *array) const struct vmci_handle_arr *array)
{ {
return array->size; return array->size;

View file

@ -2,10 +2,11 @@ menu "CAN SPI interfaces"
depends on SPI depends on SPI
config CAN_MCP251X config CAN_MCP251X
tristate "Microchip MCP251x SPI CAN controllers" tristate "Microchip MCP251x and MCP25625 SPI CAN controllers"
depends on HAS_DMA depends on HAS_DMA
---help--- ---help---
Driver for the Microchip MCP251x SPI CAN controllers. Driver for the Microchip MCP251x and MCP25625 SPI CAN
controllers.
config CAN_RH850 config CAN_RH850
tristate "Renesas RH850 SPI CAN controller" tristate "Renesas RH850 SPI CAN controller"

View file

@ -1,5 +1,5 @@
/* /*
* CAN bus driver for Microchip 251x CAN Controller with SPI Interface * CAN bus driver for Microchip 251x/25625 CAN Controller with SPI Interface
* *
* MCP2510 support and bug fixes by Christian Pellegrin * MCP2510 support and bug fixes by Christian Pellegrin
* <chripell@evolware.org> * <chripell@evolware.org>
@ -41,7 +41,7 @@
* static struct spi_board_info spi_board_info[] = { * static struct spi_board_info spi_board_info[] = {
* { * {
* .modalias = "mcp2510", * .modalias = "mcp2510",
* // or "mcp2515" depending on your controller * // "mcp2515" or "mcp25625" depending on your controller
* .platform_data = &mcp251x_info, * .platform_data = &mcp251x_info,
* .irq = IRQ_EINT13, * .irq = IRQ_EINT13,
* .max_speed_hz = 2*1000*1000, * .max_speed_hz = 2*1000*1000,
@ -238,6 +238,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = {
enum mcp251x_model { enum mcp251x_model {
CAN_MCP251X_MCP2510 = 0x2510, CAN_MCP251X_MCP2510 = 0x2510,
CAN_MCP251X_MCP2515 = 0x2515, CAN_MCP251X_MCP2515 = 0x2515,
CAN_MCP251X_MCP25625 = 0x25625,
}; };
struct mcp251x_priv { struct mcp251x_priv {
@ -280,7 +281,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \
} }
MCP251X_IS(2510); MCP251X_IS(2510);
MCP251X_IS(2515);
static void mcp251x_clean(struct net_device *net) static void mcp251x_clean(struct net_device *net)
{ {
@ -640,7 +640,7 @@ static int mcp251x_hw_reset(struct spi_device *spi)
/* Wait for oscillator startup timer after reset */ /* Wait for oscillator startup timer after reset */
mdelay(MCP251X_OST_DELAY_MS); mdelay(MCP251X_OST_DELAY_MS);
reg = mcp251x_read_reg(spi, CANSTAT); reg = mcp251x_read_reg(spi, CANSTAT);
if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
return -ENODEV; return -ENODEV;
@ -821,9 +821,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
/* receive buffer 0 */ /* receive buffer 0 */
if (intf & CANINTF_RX0IF) { if (intf & CANINTF_RX0IF) {
mcp251x_hw_rx(spi, 0); mcp251x_hw_rx(spi, 0);
/* /* Free one buffer ASAP
* Free one buffer ASAP * (The MCP2515/25625 does this automatically.)
* (The MCP2515 does this automatically.)
*/ */
if (mcp251x_is_2510(spi)) if (mcp251x_is_2510(spi))
mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
@ -832,7 +831,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
/* receive buffer 1 */ /* receive buffer 1 */
if (intf & CANINTF_RX1IF) { if (intf & CANINTF_RX1IF) {
mcp251x_hw_rx(spi, 1); mcp251x_hw_rx(spi, 1);
/* the MCP2515 does this automatically */ /* The MCP2515/25625 does this automatically. */
if (mcp251x_is_2510(spi)) if (mcp251x_is_2510(spi))
clear_intf |= CANINTF_RX1IF; clear_intf |= CANINTF_RX1IF;
} }
@ -1006,6 +1005,10 @@ static const struct of_device_id mcp251x_of_match[] = {
.compatible = "microchip,mcp2515", .compatible = "microchip,mcp2515",
.data = (void *)CAN_MCP251X_MCP2515, .data = (void *)CAN_MCP251X_MCP2515,
}, },
{
.compatible = "microchip,mcp25625",
.data = (void *)CAN_MCP251X_MCP25625,
},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, mcp251x_of_match); MODULE_DEVICE_TABLE(of, mcp251x_of_match);
@ -1019,6 +1022,10 @@ static const struct spi_device_id mcp251x_id_table[] = {
.name = "mcp2515", .name = "mcp2515",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515,
}, },
{
.name = "mcp25625",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP25625,
},
{ } { }
}; };
MODULE_DEVICE_TABLE(spi, mcp251x_id_table); MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
@ -1254,5 +1261,5 @@ module_spi_driver(mcp251x_can_driver);
MODULE_AUTHOR("Chris Elston <celston@katalix.com>, " MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
"Christian Pellegrin <chripell@evolware.org>"); "Christian Pellegrin <chripell@evolware.org>");
MODULE_DESCRIPTION("Microchip 251x CAN driver"); MODULE_DESCRIPTION("Microchip 251x/25625 CAN driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View file

@ -1559,7 +1559,8 @@ static int bnx2x_get_module_info(struct net_device *dev,
} }
if (!sff8472_comp || if (!sff8472_comp ||
(diag_type & SFP_EEPROM_DIAG_ADDR_CHANGE_REQ)) { (diag_type & SFP_EEPROM_DIAG_ADDR_CHANGE_REQ) ||
!(diag_type & SFP_EEPROM_DDM_IMPLEMENTED)) {
modinfo->type = ETH_MODULE_SFF_8079; modinfo->type = ETH_MODULE_SFF_8079;
modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
} else { } else {

View file

@ -62,6 +62,7 @@
#define SFP_EEPROM_DIAG_TYPE_ADDR 0x5c #define SFP_EEPROM_DIAG_TYPE_ADDR 0x5c
#define SFP_EEPROM_DIAG_TYPE_SIZE 1 #define SFP_EEPROM_DIAG_TYPE_SIZE 1
#define SFP_EEPROM_DIAG_ADDR_CHANGE_REQ (1<<2) #define SFP_EEPROM_DIAG_ADDR_CHANGE_REQ (1<<2)
#define SFP_EEPROM_DDM_IMPLEMENTED (1<<6)
#define SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e #define SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e
#define SFP_EEPROM_SFF_8472_COMP_SIZE 1 #define SFP_EEPROM_SFF_8472_COMP_SIZE 1

View file

@ -868,7 +868,7 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test,
u64 *data) u64 *data)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
int status; int status, cnt;
u8 link_status = 0; u8 link_status = 0;
if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) { if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) {
@ -879,6 +879,9 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test,
memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM); memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
/* check link status before offline tests */
link_status = netif_carrier_ok(netdev);
if (test->flags & ETH_TEST_FL_OFFLINE) { if (test->flags & ETH_TEST_FL_OFFLINE) {
if (be_loopback_test(adapter, BE_MAC_LOOPBACK, &data[0]) != 0) if (be_loopback_test(adapter, BE_MAC_LOOPBACK, &data[0]) != 0)
test->flags |= ETH_TEST_FL_FAILED; test->flags |= ETH_TEST_FL_FAILED;
@ -899,13 +902,26 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test,
test->flags |= ETH_TEST_FL_FAILED; test->flags |= ETH_TEST_FL_FAILED;
} }
status = be_cmd_link_status_query(adapter, NULL, &link_status, 0); /* link status was down prior to test */
if (status) { if (!link_status) {
test->flags |= ETH_TEST_FL_FAILED;
data[4] = -1;
} else if (!link_status) {
test->flags |= ETH_TEST_FL_FAILED; test->flags |= ETH_TEST_FL_FAILED;
data[4] = 1; data[4] = 1;
return;
}
for (cnt = 10; cnt; cnt--) {
status = be_cmd_link_status_query(adapter, NULL, &link_status,
0);
if (status) {
test->flags |= ETH_TEST_FL_FAILED;
data[4] = -1;
break;
}
if (link_status)
break;
msleep_interruptible(500);
} }
} }

View file

@ -4171,7 +4171,7 @@ int e1000e_up(struct e1000_adapter *adapter)
e1000_configure_msix(adapter); e1000_configure_msix(adapter);
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
netif_start_queue(adapter->netdev); /* Tx queue started by watchdog timer when link is up */
/* fire a link change interrupt to start the watchdog */ /* fire a link change interrupt to start the watchdog */
if (adapter->msix_entries) if (adapter->msix_entries)
@ -4539,6 +4539,7 @@ static int e1000_open(struct net_device *netdev)
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev);
/* allocate transmit descriptors */ /* allocate transmit descriptors */
err = e1000e_setup_tx_resources(adapter->tx_ring); err = e1000e_setup_tx_resources(adapter->tx_ring);
@ -4599,7 +4600,6 @@ static int e1000_open(struct net_device *netdev)
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
adapter->tx_hang_recheck = false; adapter->tx_hang_recheck = false;
netif_start_queue(netdev);
hw->mac.get_link_status = true; hw->mac.get_link_status = true;
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
@ -5226,6 +5226,7 @@ static void e1000_watchdog_task(struct work_struct *work)
if (phy->ops.cfg_on_link_up) if (phy->ops.cfg_on_link_up)
phy->ops.cfg_on_link_up(hw); phy->ops.cfg_on_link_up(hw);
netif_wake_queue(netdev);
netif_carrier_on(netdev); netif_carrier_on(netdev);
if (!test_bit(__E1000_DOWN, &adapter->state)) if (!test_bit(__E1000_DOWN, &adapter->state))
@ -5239,6 +5240,7 @@ static void e1000_watchdog_task(struct work_struct *work)
/* Link status message must follow this format */ /* Link status message must follow this format */
pr_info("%s NIC Link is Down\n", adapter->netdev->name); pr_info("%s NIC Link is Down\n", adapter->netdev->name);
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev);
if (!test_bit(__E1000_DOWN, &adapter->state)) if (!test_bit(__E1000_DOWN, &adapter->state))
mod_timer(&adapter->phy_info_timer, mod_timer(&adapter->phy_info_timer,
round_jiffies(jiffies + 2 * HZ)); round_jiffies(jiffies + 2 * HZ));

View file

@ -1058,7 +1058,7 @@ sis900_open(struct net_device *net_dev)
sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */ /* Enable all known interrupts by setting the interrupt mask. */
sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC);
sw32(cr, RxENA | sr32(cr)); sw32(cr, RxENA | sr32(cr));
sw32(ier, IE); sw32(ier, IE);
@ -1581,7 +1581,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
sw32(txdp, sis_priv->tx_ring_dma); sw32(txdp, sis_priv->tx_ring_dma);
/* Enable all known interrupts by setting the interrupt mask. */ /* Enable all known interrupts by setting the interrupt mask. */
sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC);
} }
/** /**
@ -1621,7 +1621,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
spin_unlock_irqrestore(&sis_priv->lock, flags); spin_unlock_irqrestore(&sis_priv->lock, flags);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len); sis_priv->tx_ring[entry].cmdsts = (OWN | INTR | skb->len);
sw32(cr, TxENA | sr32(cr)); sw32(cr, TxENA | sr32(cr));
sis_priv->cur_tx ++; sis_priv->cur_tx ++;
@ -1677,7 +1677,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
do { do {
status = sr32(isr); status = sr32(isr);
if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0) if ((status & (HIBERR|TxURN|TxERR|TxIDLE|TxDESC|RxORN|RxERR|RxOK)) == 0)
/* nothing intresting happened */ /* nothing intresting happened */
break; break;
handled = 1; handled = 1;
@ -1687,7 +1687,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
/* Rx interrupt */ /* Rx interrupt */
sis900_rx(net_dev); sis900_rx(net_dev);
if (status & (TxURN | TxERR | TxIDLE)) if (status & (TxURN | TxERR | TxIDLE | TxDESC))
/* Tx interrupt */ /* Tx interrupt */
sis900_finish_xmit(net_dev); sis900_finish_xmit(net_dev);
@ -1899,8 +1899,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if (tx_status & OWN) { if (tx_status & OWN) {
/* The packet is not transmitted yet (owned by hardware) ! /* The packet is not transmitted yet (owned by hardware) !
* Note: the interrupt is generated only when Tx Machine * Note: this is an almost impossible condition
* is idle, so this is an almost impossible case */ * in case of TxDESC ('descriptor interrupt') */
break; break;
} }
@ -2476,7 +2476,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */ /* Enable all known interrupts by setting the interrupt mask. */
sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC);
sw32(cr, RxENA | sr32(cr)); sw32(cr, RxENA | sr32(cr));
sw32(ier, IE); sw32(ier, IE);

View file

@ -62,6 +62,7 @@ MODULE_AUTHOR("Frank Cusack <fcusack@fcusack.com>");
MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support"); MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE));
MODULE_SOFTDEP("pre: arc4");
MODULE_VERSION("1.0.2"); MODULE_VERSION("1.0.2");
static unsigned int static unsigned int

View file

@ -128,6 +128,8 @@ static struct usb_device_id carl9170_usb_ids[] = {
}; };
MODULE_DEVICE_TABLE(usb, carl9170_usb_ids); MODULE_DEVICE_TABLE(usb, carl9170_usb_ids);
static struct usb_driver carl9170_driver;
static void carl9170_usb_submit_data_urb(struct ar9170 *ar) static void carl9170_usb_submit_data_urb(struct ar9170 *ar)
{ {
struct urb *urb; struct urb *urb;
@ -968,32 +970,28 @@ err_out:
static void carl9170_usb_firmware_failed(struct ar9170 *ar) static void carl9170_usb_firmware_failed(struct ar9170 *ar)
{ {
struct device *parent = ar->udev->dev.parent; /* Store a copies of the usb_interface and usb_device pointer locally.
struct usb_device *udev; * This is because release_driver initiates carl9170_usb_disconnect,
* which in turn frees our driver context (ar).
/*
* Store a copy of the usb_device pointer locally.
* This is because device_release_driver initiates
* carl9170_usb_disconnect, which in turn frees our
* driver context (ar).
*/ */
udev = ar->udev; struct usb_interface *intf = ar->intf;
struct usb_device *udev = ar->udev;
complete(&ar->fw_load_wait); complete(&ar->fw_load_wait);
/* at this point 'ar' could be already freed. Don't use it anymore */
ar = NULL;
/* unbind anything failed */ /* unbind anything failed */
if (parent) usb_lock_device(udev);
device_lock(parent); usb_driver_release_interface(&carl9170_driver, intf);
usb_unlock_device(udev);
device_release_driver(&udev->dev); usb_put_intf(intf);
if (parent)
device_unlock(parent);
usb_put_dev(udev);
} }
static void carl9170_usb_firmware_finish(struct ar9170 *ar) static void carl9170_usb_firmware_finish(struct ar9170 *ar)
{ {
struct usb_interface *intf = ar->intf;
int err; int err;
err = carl9170_parse_firmware(ar); err = carl9170_parse_firmware(ar);
@ -1011,7 +1009,7 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar)
goto err_unrx; goto err_unrx;
complete(&ar->fw_load_wait); complete(&ar->fw_load_wait);
usb_put_dev(ar->udev); usb_put_intf(intf);
return; return;
err_unrx: err_unrx:
@ -1054,7 +1052,6 @@ static int carl9170_usb_probe(struct usb_interface *intf,
return PTR_ERR(ar); return PTR_ERR(ar);
udev = interface_to_usbdev(intf); udev = interface_to_usbdev(intf);
usb_get_dev(udev);
ar->udev = udev; ar->udev = udev;
ar->intf = intf; ar->intf = intf;
ar->features = id->driver_info; ar->features = id->driver_info;
@ -1096,15 +1093,14 @@ static int carl9170_usb_probe(struct usb_interface *intf,
atomic_set(&ar->rx_anch_urbs, 0); atomic_set(&ar->rx_anch_urbs, 0);
atomic_set(&ar->rx_pool_urbs, 0); atomic_set(&ar->rx_pool_urbs, 0);
usb_get_dev(ar->udev); usb_get_intf(intf);
carl9170_set_state(ar, CARL9170_STOPPED); carl9170_set_state(ar, CARL9170_STOPPED);
err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
&ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2);
if (err) { if (err) {
usb_put_dev(udev); usb_put_intf(intf);
usb_put_dev(udev);
carl9170_free(ar); carl9170_free(ar);
} }
return err; return err;
@ -1133,7 +1129,6 @@ static void carl9170_usb_disconnect(struct usb_interface *intf)
carl9170_release_firmware(ar); carl9170_release_firmware(ar);
carl9170_free(ar); carl9170_free(ar);
usb_put_dev(udev);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View file

@ -1589,9 +1589,10 @@ struct mwifiex_ie_types_wmm_queue_status {
struct ieee_types_vendor_header { struct ieee_types_vendor_header {
u8 element_id; u8 element_id;
u8 len; u8 len;
u8 oui[4]; /* 0~2: oui, 3: oui_type */ struct {
u8 oui_subtype; u8 oui[3];
u8 version; u8 oui_type;
} __packed oui;
} __packed; } __packed;
struct ieee_types_wmm_parameter { struct ieee_types_wmm_parameter {
@ -1605,6 +1606,9 @@ struct ieee_types_wmm_parameter {
* Version [1] * Version [1]
*/ */
struct ieee_types_vendor_header vend_hdr; struct ieee_types_vendor_header vend_hdr;
u8 oui_subtype;
u8 version;
u8 qos_info_bitmap; u8 qos_info_bitmap;
u8 reserved; u8 reserved;
struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
@ -1622,6 +1626,8 @@ struct ieee_types_wmm_info {
* Version [1] * Version [1]
*/ */
struct ieee_types_vendor_header vend_hdr; struct ieee_types_vendor_header vend_hdr;
u8 oui_subtype;
u8 version;
u8 qos_info_bitmap; u8 qos_info_bitmap;
} __packed; } __packed;

View file

@ -328,6 +328,8 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
struct ieee80211_vendor_ie *vendorhdr; struct ieee80211_vendor_ie *vendorhdr;
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
int left_len, parsed_len = 0; int left_len, parsed_len = 0;
unsigned int token_len;
int err = 0;
if (!info->tail || !info->tail_len) if (!info->tail || !info->tail_len)
return 0; return 0;
@ -343,6 +345,12 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
*/ */
while (left_len > sizeof(struct ieee_types_header)) { while (left_len > sizeof(struct ieee_types_header)) {
hdr = (void *)(info->tail + parsed_len); hdr = (void *)(info->tail + parsed_len);
token_len = hdr->len + sizeof(struct ieee_types_header);
if (token_len > left_len) {
err = -EINVAL;
goto out;
}
switch (hdr->element_id) { switch (hdr->element_id) {
case WLAN_EID_SSID: case WLAN_EID_SSID:
case WLAN_EID_SUPP_RATES: case WLAN_EID_SUPP_RATES:
@ -356,13 +364,16 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
case WLAN_EID_VENDOR_SPECIFIC: case WLAN_EID_VENDOR_SPECIFIC:
break; break;
default: default:
memcpy(gen_ie->ie_buffer + ie_len, hdr, if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
hdr->len + sizeof(struct ieee_types_header)); err = -EINVAL;
ie_len += hdr->len + sizeof(struct ieee_types_header); goto out;
}
memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
ie_len += token_len;
break; break;
} }
left_len -= hdr->len + sizeof(struct ieee_types_header); left_len -= token_len;
parsed_len += hdr->len + sizeof(struct ieee_types_header); parsed_len += token_len;
} }
/* parse only WPA vendor IE from tail, WMM IE is configured by /* parse only WPA vendor IE from tail, WMM IE is configured by
@ -372,15 +383,17 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
WLAN_OUI_TYPE_MICROSOFT_WPA, WLAN_OUI_TYPE_MICROSOFT_WPA,
info->tail, info->tail_len); info->tail, info->tail_len);
if (vendorhdr) { if (vendorhdr) {
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len = vendorhdr->len + sizeof(struct ieee_types_header);
vendorhdr->len + sizeof(struct ieee_types_header)); if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
ie_len += vendorhdr->len + sizeof(struct ieee_types_header); err = -EINVAL;
goto out;
}
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
ie_len += token_len;
} }
if (!ie_len) { if (!ie_len)
kfree(gen_ie); goto out;
return 0;
}
gen_ie->ie_index = cpu_to_le16(gen_idx); gen_ie->ie_index = cpu_to_le16(gen_idx);
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
@ -390,13 +403,15 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL, if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
NULL, NULL)) { NULL, NULL)) {
kfree(gen_ie); err = -EINVAL;
return -1; goto out;
} }
priv->gen_idx = gen_idx; priv->gen_idx = gen_idx;
out:
kfree(gen_ie); kfree(gen_ie);
return 0; return err;
} }
/* This function parses different IEs-head & tail IEs, beacon IEs, /* This function parses different IEs-head & tail IEs, beacon IEs,

View file

@ -1219,6 +1219,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
} }
switch (element_id) { switch (element_id) {
case WLAN_EID_SSID: case WLAN_EID_SSID:
if (element_len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
bss_entry->ssid.ssid_len = element_len; bss_entry->ssid.ssid_len = element_len;
memcpy(bss_entry->ssid.ssid, (current_ptr + 2), memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
element_len); element_len);
@ -1228,6 +1230,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_SUPP_RATES: case WLAN_EID_SUPP_RATES:
if (element_len > MWIFIEX_SUPPORTED_RATES)
return -EINVAL;
memcpy(bss_entry->data_rates, current_ptr + 2, memcpy(bss_entry->data_rates, current_ptr + 2,
element_len); element_len);
memcpy(bss_entry->supported_rates, current_ptr + 2, memcpy(bss_entry->supported_rates, current_ptr + 2,
@ -1237,6 +1241,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_FH_PARAMS: case WLAN_EID_FH_PARAMS:
if (element_len + 2 < sizeof(*fh_param_set))
return -EINVAL;
fh_param_set = fh_param_set =
(struct ieee_types_fh_param_set *) current_ptr; (struct ieee_types_fh_param_set *) current_ptr;
memcpy(&bss_entry->phy_param_set.fh_param_set, memcpy(&bss_entry->phy_param_set.fh_param_set,
@ -1245,6 +1251,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_DS_PARAMS: case WLAN_EID_DS_PARAMS:
if (element_len + 2 < sizeof(*ds_param_set))
return -EINVAL;
ds_param_set = ds_param_set =
(struct ieee_types_ds_param_set *) current_ptr; (struct ieee_types_ds_param_set *) current_ptr;
@ -1256,6 +1264,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_CF_PARAMS: case WLAN_EID_CF_PARAMS:
if (element_len + 2 < sizeof(*cf_param_set))
return -EINVAL;
cf_param_set = cf_param_set =
(struct ieee_types_cf_param_set *) current_ptr; (struct ieee_types_cf_param_set *) current_ptr;
memcpy(&bss_entry->ss_param_set.cf_param_set, memcpy(&bss_entry->ss_param_set.cf_param_set,
@ -1264,6 +1274,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_IBSS_PARAMS: case WLAN_EID_IBSS_PARAMS:
if (element_len + 2 < sizeof(*ibss_param_set))
return -EINVAL;
ibss_param_set = ibss_param_set =
(struct ieee_types_ibss_param_set *) (struct ieee_types_ibss_param_set *)
current_ptr; current_ptr;
@ -1273,10 +1285,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_ERP_INFO: case WLAN_EID_ERP_INFO:
if (!element_len)
return -EINVAL;
bss_entry->erp_flags = *(current_ptr + 2); bss_entry->erp_flags = *(current_ptr + 2);
break; break;
case WLAN_EID_PWR_CONSTRAINT: case WLAN_EID_PWR_CONSTRAINT:
if (!element_len)
return -EINVAL;
bss_entry->local_constraint = *(current_ptr + 2); bss_entry->local_constraint = *(current_ptr + 2);
bss_entry->sensed_11h = true; bss_entry->sensed_11h = true;
break; break;
@ -1319,15 +1335,22 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
vendor_ie = (struct ieee_types_vendor_specific *) vendor_ie = (struct ieee_types_vendor_specific *)
current_ptr; current_ptr;
if (!memcmp /* 802.11 requires at least 3-byte OUI. */
(vendor_ie->vend_hdr.oui, wpa_oui, if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
sizeof(wpa_oui))) { return -EINVAL;
/* Not long enough for a match? Skip it. */
if (element_len < sizeof(wpa_oui))
break;
if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
sizeof(wpa_oui))) {
bss_entry->bcn_wpa_ie = bss_entry->bcn_wpa_ie =
(struct ieee_types_vendor_specific *) (struct ieee_types_vendor_specific *)
current_ptr; current_ptr;
bss_entry->wpa_offset = (u16) bss_entry->wpa_offset = (u16)
(current_ptr - bss_entry->beacon_buf); (current_ptr - bss_entry->beacon_buf);
} else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
sizeof(wmm_oui))) { sizeof(wmm_oui))) {
if (total_ie_len == if (total_ie_len ==
sizeof(struct ieee_types_wmm_parameter) || sizeof(struct ieee_types_wmm_parameter) ||

View file

@ -1305,7 +1305,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
/* Test to see if it is a WPA IE, if not, then it is a gen IE */ /* Test to see if it is a WPA IE, if not, then it is a gen IE */
if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
(!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) || (!memcmp(&pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
(pvendor_ie->element_id == WLAN_EID_RSN)) { (pvendor_ie->element_id == WLAN_EID_RSN)) {
/* IE is a WPA/WPA2 IE so call set_wpa function */ /* IE is a WPA/WPA2 IE so call set_wpa function */
@ -1330,7 +1330,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
*/ */
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
(!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) { (!memcmp(&pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
priv->wps.session_enable = true; priv->wps.session_enable = true;
mwifiex_dbg(priv->adapter, INFO, mwifiex_dbg(priv->adapter, INFO,
"info: WPS Session Enabled.\n"); "info: WPS Session Enabled.\n");

View file

@ -240,7 +240,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
mwifiex_dbg(priv->adapter, INFO, mwifiex_dbg(priv->adapter, INFO,
"info: WMM Parameter IE: version=%d,\t" "info: WMM Parameter IE: version=%d,\t"
"qos_info Parameter Set Count=%d, Reserved=%#x\n", "qos_info Parameter Set Count=%d, Reserved=%#x\n",
wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & wmm_ie->version, wmm_ie->qos_info_bitmap &
IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK,
wmm_ie->reserved); wmm_ie->reserved);

View file

@ -150,6 +150,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
return -ENOMEM; return -ENOMEM;
} }
irq_ptr_qs[i] = q; irq_ptr_qs[i] = q;
INIT_LIST_HEAD(&q->entry);
} }
return 0; return 0;
} }
@ -178,6 +179,7 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
q->mask = 1 << (31 - i); q->mask = 1 << (31 - i);
q->nr = i; q->nr = i;
q->handler = handler; q->handler = handler;
INIT_LIST_HEAD(&q->entry);
} }
static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,

View file

@ -80,7 +80,6 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
mutex_lock(&tiq_list_lock); mutex_lock(&tiq_list_lock);
list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list); list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
mutex_unlock(&tiq_list_lock); mutex_unlock(&tiq_list_lock);
xchg(irq_ptr->dsci, 1 << 7);
} }
void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
@ -88,14 +87,14 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
struct qdio_q *q; struct qdio_q *q;
q = irq_ptr->input_qs[0]; q = irq_ptr->input_qs[0];
/* if establish triggered an error */ if (!q)
if (!q || !q->entry.prev || !q->entry.next)
return; return;
mutex_lock(&tiq_list_lock); mutex_lock(&tiq_list_lock);
list_del_rcu(&q->entry); list_del_rcu(&q->entry);
mutex_unlock(&tiq_list_lock); mutex_unlock(&tiq_list_lock);
synchronize_rcu(); synchronize_rcu();
INIT_LIST_HEAD(&q->entry);
} }
static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr) static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)

View file

@ -2324,7 +2324,8 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
devpriv->intr_running = false; devpriv->intr_running = false;
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
comedi_handle_events(dev, s_ao); if (s_ao)
comedi_handle_events(dev, s_ao);
comedi_handle_events(dev, s_ai); comedi_handle_events(dev, s_ai);
return IRQ_HANDLED; return IRQ_HANDLED;

View file

@ -553,7 +553,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
} }
#endif #endif
comedi_handle_events(dev, s); comedi_handle_events(dev, s);
comedi_handle_events(dev, s_ao); if (s_ao)
comedi_handle_events(dev, s_ao);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }

View file

@ -217,11 +217,12 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
out = dev->port_usb->out_ep; out = dev->port_usb->out_ep;
else else
out = NULL; out = NULL;
spin_unlock_irqrestore(&dev->lock, flags);
if (!out) if (!out)
{
spin_unlock_irqrestore(&dev->lock, flags);
return -ENOTCONN; return -ENOTCONN;
}
/* Padding up to RX_EXTRA handles minor disagreements with host. /* Padding up to RX_EXTRA handles minor disagreements with host.
* Normally we use the USB "terminate on short read" convention; * Normally we use the USB "terminate on short read" convention;
@ -245,6 +246,7 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
if (dev->port_usb->is_fixed) if (dev->port_usb->is_fixed)
size = max_t(size_t, size, dev->port_usb->fixed_out_len); size = max_t(size_t, size, dev->port_usb->fixed_out_len);
spin_unlock_irqrestore(&dev->lock, flags);
DBG(dev, "%s: size: %zd\n", __func__, size); DBG(dev, "%s: size: %zd\n", __func__, size);
skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);

View file

@ -819,9 +819,8 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
} }
static void usbhsf_dma_complete(void *arg); static void usbhsf_dma_complete(void *arg);
static void xfer_work(struct work_struct *work) static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
{ {
struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_fifo *fifo; struct usbhs_fifo *fifo;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@ -829,12 +828,10 @@ static void xfer_work(struct work_struct *work)
struct dma_chan *chan; struct dma_chan *chan;
struct device *dev = usbhs_priv_to_dev(priv); struct device *dev = usbhs_priv_to_dev(priv);
enum dma_transfer_direction dir; enum dma_transfer_direction dir;
unsigned long flags;
usbhs_lock(priv, flags);
fifo = usbhs_pipe_to_fifo(pipe); fifo = usbhs_pipe_to_fifo(pipe);
if (!fifo) if (!fifo)
goto xfer_work_end; return;
chan = usbhsf_dma_chan_get(fifo, pkt); chan = usbhsf_dma_chan_get(fifo, pkt);
dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
@ -843,7 +840,7 @@ static void xfer_work(struct work_struct *work)
pkt->trans, dir, pkt->trans, dir,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) if (!desc)
goto xfer_work_end; return;
desc->callback = usbhsf_dma_complete; desc->callback = usbhsf_dma_complete;
desc->callback_param = pipe; desc->callback_param = pipe;
@ -851,7 +848,7 @@ static void xfer_work(struct work_struct *work)
pkt->cookie = dmaengine_submit(desc); pkt->cookie = dmaengine_submit(desc);
if (pkt->cookie < 0) { if (pkt->cookie < 0) {
dev_err(dev, "Failed to submit dma descriptor\n"); dev_err(dev, "Failed to submit dma descriptor\n");
goto xfer_work_end; return;
} }
dev_dbg(dev, " %s %d (%d/ %d)\n", dev_dbg(dev, " %s %d (%d/ %d)\n",
@ -862,8 +859,17 @@ static void xfer_work(struct work_struct *work)
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
usbhsf_dma_start(pipe, fifo); usbhsf_dma_start(pipe, fifo);
usbhs_pipe_enable(pipe); usbhs_pipe_enable(pipe);
}
xfer_work_end: static void xfer_work(struct work_struct *work)
{
struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
unsigned long flags;
usbhs_lock(priv, flags);
usbhsf_dma_xfer_preparing(pkt);
usbhs_unlock(priv, flags); usbhs_unlock(priv, flags);
} }
@ -916,8 +922,13 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
pkt->trans = len; pkt->trans = len;
usbhsf_tx_irq_ctrl(pipe, 0); usbhsf_tx_irq_ctrl(pipe, 0);
INIT_WORK(&pkt->work, xfer_work); /* FIXME: Workaound for usb dmac that driver can be used in atomic */
schedule_work(&pkt->work); if (usbhs_get_dparam(priv, has_usb_dmac)) {
usbhsf_dma_xfer_preparing(pkt);
} else {
INIT_WORK(&pkt->work, xfer_work);
schedule_work(&pkt->work);
}
return 0; return 0;
@ -1023,8 +1034,7 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt,
pkt->trans = pkt->length; pkt->trans = pkt->length;
INIT_WORK(&pkt->work, xfer_work); usbhsf_dma_xfer_preparing(pkt);
schedule_work(&pkt->work);
return 0; return 0;

View file

@ -1024,6 +1024,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) }, { USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) },
/* EZPrototypes devices */ /* EZPrototypes devices */
{ USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) }, { USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) },
{ USB_DEVICE_INTERFACE_NUMBER(UNJO_VID, UNJO_ISODEBUG_V1_PID, 1) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };

View file

@ -1542,3 +1542,9 @@
#define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ #define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */
#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ #define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */
#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */ #define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */
/*
* Unjo AB
*/
#define UNJO_VID 0x22B7
#define UNJO_ISODEBUG_V1_PID 0x150D

View file

@ -1338,6 +1338,7 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
{ USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0601, 0xff) }, /* GosunCn ZTE WeLink ME3630 (RNDIS mode) */
{ USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0602, 0xff) }, /* GosunCn ZTE WeLink ME3630 (MBIM mode) */ { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0602, 0xff) }, /* GosunCn ZTE WeLink ME3630 (MBIM mode) */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },

View file

@ -111,6 +111,8 @@ int ext4_process_policy(const struct ext4_encryption_policy *policy,
if (!ext4_inode_has_encryption_context(inode)) { if (!ext4_inode_has_encryption_context(inode)) {
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
return -EINVAL; return -EINVAL;
if (IS_DEADDIR(inode))
return -ENOENT;
if (!ext4_empty_dir(inode)) if (!ext4_empty_dir(inode))
return -ENOTEMPTY; return -ENOTEMPTY;
return ext4_create_encryption_context_from_policy(inode, return ext4_create_encryption_context_from_policy(inode,

View file

@ -415,8 +415,13 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
err = -ENOMEM; err = -ENOMEM;
override_cred = prepare_creds(); override_cred = prepare_creds();
if (override_cred) { if (override_cred) {
override_cred->fsuid = old_cred->fsuid; const struct cred *our_cred;
override_cred->fsgid = old_cred->fsgid;
our_cred = old_cred;
if (!our_cred)
our_cred = current_cred();
override_cred->fsuid = our_cred->fsuid;
override_cred->fsgid = our_cred->fsgid;
put_cred(override_creds(override_cred)); put_cred(override_creds(override_cred));
put_cred(override_cred); put_cred(override_cred);

View file

@ -479,13 +479,15 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block,
return NULL; return NULL;
} }
/* Extend the file by 'blocks' blocks, return the number of extents added */ /* Extend the file with new blocks totaling 'new_block_bytes',
* return the number of extents added
*/
static int udf_do_extend_file(struct inode *inode, static int udf_do_extend_file(struct inode *inode,
struct extent_position *last_pos, struct extent_position *last_pos,
struct kernel_long_ad *last_ext, struct kernel_long_ad *last_ext,
sector_t blocks) loff_t new_block_bytes)
{ {
sector_t add; uint32_t add;
int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct kernel_lb_addr prealloc_loc = {}; struct kernel_lb_addr prealloc_loc = {};
@ -495,7 +497,7 @@ static int udf_do_extend_file(struct inode *inode,
/* The previous extent is fake and we should not extend by anything /* The previous extent is fake and we should not extend by anything
* - there's nothing to do... */ * - there's nothing to do... */
if (!blocks && fake) if (!new_block_bytes && fake)
return 0; return 0;
iinfo = UDF_I(inode); iinfo = UDF_I(inode);
@ -526,13 +528,12 @@ static int udf_do_extend_file(struct inode *inode,
/* Can we merge with the previous extent? */ /* Can we merge with the previous extent? */
if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
EXT_NOT_RECORDED_NOT_ALLOCATED) { EXT_NOT_RECORDED_NOT_ALLOCATED) {
add = ((1 << 30) - sb->s_blocksize - add = (1 << 30) - sb->s_blocksize -
(last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >> (last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
sb->s_blocksize_bits; if (add > new_block_bytes)
if (add > blocks) add = new_block_bytes;
add = blocks; new_block_bytes -= add;
blocks -= add; last_ext->extLength += add;
last_ext->extLength += add << sb->s_blocksize_bits;
} }
if (fake) { if (fake) {
@ -544,28 +545,27 @@ static int udf_do_extend_file(struct inode *inode,
last_ext->extLength, 1); last_ext->extLength, 1);
/* Managed to do everything necessary? */ /* Managed to do everything necessary? */
if (!blocks) if (!new_block_bytes)
goto out; goto out;
/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */ /* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
last_ext->extLocation.logicalBlockNum = 0; last_ext->extLocation.logicalBlockNum = 0;
last_ext->extLocation.partitionReferenceNum = 0; last_ext->extLocation.partitionReferenceNum = 0;
add = (1 << (30-sb->s_blocksize_bits)) - 1; add = (1 << 30) - sb->s_blocksize;
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | add;
(add << sb->s_blocksize_bits);
/* Create enough extents to cover the whole hole */ /* Create enough extents to cover the whole hole */
while (blocks > add) { while (new_block_bytes > add) {
blocks -= add; new_block_bytes -= add;
err = udf_add_aext(inode, last_pos, &last_ext->extLocation, err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
last_ext->extLength, 1); last_ext->extLength, 1);
if (err) if (err)
return err; return err;
count++; count++;
} }
if (blocks) { if (new_block_bytes) {
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
(blocks << sb->s_blocksize_bits); new_block_bytes;
err = udf_add_aext(inode, last_pos, &last_ext->extLocation, err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
last_ext->extLength, 1); last_ext->extLength, 1);
if (err) if (err)
@ -596,6 +596,24 @@ out:
return count; return count;
} }
/* Extend the final block of the file to final_block_len bytes */
static void udf_do_extend_final_block(struct inode *inode,
struct extent_position *last_pos,
struct kernel_long_ad *last_ext,
uint32_t final_block_len)
{
struct super_block *sb = inode->i_sb;
uint32_t added_bytes;
added_bytes = final_block_len -
(last_ext->extLength & (sb->s_blocksize - 1));
last_ext->extLength += added_bytes;
UDF_I(inode)->i_lenExtents += added_bytes;
udf_write_aext(inode, last_pos, &last_ext->extLocation,
last_ext->extLength, 1);
}
static int udf_extend_file(struct inode *inode, loff_t newsize) static int udf_extend_file(struct inode *inode, loff_t newsize)
{ {
@ -605,10 +623,12 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
int8_t etype; int8_t etype;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
sector_t first_block = newsize >> sb->s_blocksize_bits, offset; sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
unsigned long partial_final_block;
int adsize; int adsize;
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
struct kernel_long_ad extent; struct kernel_long_ad extent;
int err; int err = 0;
int within_final_block;
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(struct short_ad); adsize = sizeof(struct short_ad);
@ -618,18 +638,8 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
BUG(); BUG();
etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
within_final_block = (etype != -1);
/* File has extent covering the new size (could happen when extending
* inside a block)? */
if (etype != -1)
return 0;
if (newsize & (sb->s_blocksize - 1))
offset++;
/* Extended file just to the boundary of the last file block? */
if (offset == 0)
return 0;
/* Truncate is extending the file by 'offset' blocks */
if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
(epos.bh && epos.offset == sizeof(struct allocExtDesc))) { (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
/* File has no extents at all or has empty last /* File has no extents at all or has empty last
@ -643,7 +653,22 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
&extent.extLength, 0); &extent.extLength, 0);
extent.extLength |= etype << 30; extent.extLength |= etype << 30;
} }
err = udf_do_extend_file(inode, &epos, &extent, offset);
partial_final_block = newsize & (sb->s_blocksize - 1);
/* File has extent covering the new size (could happen when extending
* inside a block)?
*/
if (within_final_block) {
/* Extending file within the last file block */
udf_do_extend_final_block(inode, &epos, &extent,
partial_final_block);
} else {
loff_t add = ((loff_t)offset << sb->s_blocksize_bits) |
partial_final_block;
err = udf_do_extend_file(inode, &epos, &extent, add);
}
if (err < 0) if (err < 0)
goto out; goto out;
err = 0; err = 0;
@ -748,6 +773,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
/* Are we beyond EOF? */ /* Are we beyond EOF? */
if (etype == -1) { if (etype == -1) {
int ret; int ret;
loff_t hole_len;
isBeyondEOF = true; isBeyondEOF = true;
if (count) { if (count) {
if (c) if (c)
@ -763,7 +789,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
startnum = (offset > 0); startnum = (offset > 0);
} }
/* Create extents for the hole between EOF and offset */ /* Create extents for the hole between EOF and offset */
ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); hole_len = (loff_t)offset << inode->i_blkbits;
ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len);
if (ret < 0) { if (ret < 0) {
brelse(prev_epos.bh); brelse(prev_epos.bh);
brelse(cur_epos.bh); brelse(cur_epos.bh);

View file

@ -75,9 +75,18 @@ enum {
/* /*
* A single VMCI device has an upper limit of 128MB on the amount of * A single VMCI device has an upper limit of 128MB on the amount of
* memory that can be used for queue pairs. * memory that can be used for queue pairs. Since each queue pair
* consists of at least two pages, the memory limit also dictates the
* number of queue pairs a guest can create.
*/ */
#define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024) #define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024)
#define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2)
/*
* There can be at most PAGE_SIZE doorbells since there is one doorbell
* per byte in the doorbell bitmap page.
*/
#define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE
/* /*
* Queues with pre-mapped data pages must be small, so that we don't pin * Queues with pre-mapped data pages must be small, so that we don't pin

View file

@ -5194,7 +5194,7 @@ static void perf_sample_regs_user(struct perf_regs *regs_user,
if (user_mode(regs)) { if (user_mode(regs)) {
regs_user->abi = perf_reg_abi(current); regs_user->abi = perf_reg_abi(current);
regs_user->regs = regs; regs_user->regs = regs;
} else if (current->mm) { } else if (!(current->flags & PF_KTHREAD)) {
perf_get_regs_user(regs_user, regs, regs_user_copy); perf_get_regs_user(regs_user, regs, regs_user_copy);
} else { } else {
regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;

View file

@ -1138,7 +1138,8 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
ifmsh->chsw_ttl = 0; ifmsh->chsw_ttl = 0;
/* Remove the CSA and MCSP elements from the beacon */ /* Remove the CSA and MCSP elements from the beacon */
tmp_csa_settings = rcu_dereference(ifmsh->csa); tmp_csa_settings = rcu_dereference_protected(ifmsh->csa,
lockdep_is_held(&sdata->wdev.mtx));
RCU_INIT_POINTER(ifmsh->csa, NULL); RCU_INIT_POINTER(ifmsh->csa, NULL);
if (tmp_csa_settings) if (tmp_csa_settings)
kfree_rcu(tmp_csa_settings, rcu_head); kfree_rcu(tmp_csa_settings, rcu_head);
@ -1160,6 +1161,8 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
struct mesh_csa_settings *tmp_csa_settings; struct mesh_csa_settings *tmp_csa_settings;
int ret = 0; int ret = 0;
lockdep_assert_held(&sdata->wdev.mtx);
tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings), tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings),
GFP_ATOMIC); GFP_ATOMIC);
if (!tmp_csa_settings) if (!tmp_csa_settings)

View file

@ -336,7 +336,7 @@ void read_trace_pipe(void)
static char buf[4096]; static char buf[4096];
ssize_t sz; ssize_t sz;
sz = read(trace_fd, buf, sizeof(buf)); sz = read(trace_fd, buf, sizeof(buf) - 1);
if (sz > 0) { if (sz > 0) {
buf[sz] = 0; buf[sz] = 0;
puts(buf); puts(buf);