This is the 4.19.302 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmV53vEACgkQONu9yGCS aT4wng/9ECVr1tNbX+0oo5p4GFnY2wR3I39TslGkS048Yo1UiW/m7WX2nDJPhJXO YLLiSsm0xOKZEn1xDh99L5kIWZHeHywajMdrIDZwRhOtBj8RHX0NyWQQzxg2ftxs 7IrgXyt/38b6kcQ2or8rqPqINGeZWAErukMfGMQZIMkp48D68cyfPDk0xfFwryAL mfn1tQOe6OgPFSbNR7MiV1mWzC6f06J6ZOx3kUvS6tqu0ZF61yhE8QkB/U2dQb/z S7VTM4BQ5NuW9BiGfLF39OAppEZ7jB/JZjCzh5h2ZUWpKhxl09u5FFqT81fOqtBN b/rhPnNnG1gFarGChrRbdvU4YnomBce7f7knpe0/vUiZW+UBxIW5yagUoXz7Eo0X Lyowuj5bXhDAJ1T/G/AV8Fv0eIunBRUyXcdeF6qeHWV2NzDmcYbswY6gh5eWDZL3 ST83NvEq+p5uGzZHEbjbP3AX0P5wHDPAkhLXKLCwTsylHKrfL12e1+FWY2Jv40PA Ze+8SNCZrdHIYXZWSczrGZJM+GJh1KCkOQt/wSkGzPPAmoqcOTyMqD7Tj7o8qUER lQGDYzEO7+ZGMQ3QtSqQ//3Mlaeh4JYjzEYgpuXA7bFeepn/9FVDUurKZW39A/o5 0TTWsgwRlt2j92Jfi8ajbT5aAVJ0+o6KFqElUhc2onMMEWngUXs= =Ryx9 -----END PGP SIGNATURE----- Merge 4.19.302 into android-4.19-stable Changes in 4.19.302 spi: imx: add a device specific prepare_message callback spi: imx: move wml setting to later than setup_transfer spi: imx: correct wml as the last sg length spi: imx: mx51-ecspi: Move some initialisation to prepare_message hook. media: davinci: vpif_capture: fix potential double free hrtimers: Push pending hrtimers away from outgoing CPU earlier netfilter: ipset: fix race condition between swap/destroy and kernel side add/del/test tg3: Move the [rt]x_dropped counters to tg3_napi tg3: Increment tx_dropped in tg3_tso_bug() kconfig: fix memory leak from range properties drm/amdgpu: correct chunk_ptr to a pointer to chunk. ipv6: fix potential NULL deref in fib6_add() hv_netvsc: rndis_filter needs to select NLS net: arcnet: Fix RESET flag handling net: arcnet: com20020 fix error handling arcnet: restoring support for multiple Sohard Arcnet cards ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit() net: hns: fix fake link up on xge port netfilter: xt_owner: Add supplementary groups option netfilter: xt_owner: Fix for unsafe access of sk->sk_socket tcp: do not accept ACK of bytes we never sent RDMA/bnxt_re: Correct module description string hwmon: (acpi_power_meter) Fix 4.29 MW bug tracing: Fix a warning when allocating buffered events fails scsi: be2iscsi: Fix a memleak in beiscsi_init_wrb_handle() ARM: imx: Check return value of devm_kasprintf in imx_mmdc_perf_init ARM: dts: imx: make gpt node name generic ARM: dts: imx7: Declare timers compatible with fsl,imx6dl-gpt ALSA: pcm: fix out-of-bounds in snd_pcm_state_names packet: Move reference count in packet_sock to atomic_long_t nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage() tracing: Always update snapshot buffer size tracing: Fix incomplete locking when disabling buffered events tracing: Fix a possible race when disabling buffered events perf/core: Add a new read format to get a number of lost samples perf: Fix perf_event_validate_size() gpiolib: sysfs: Fix error handling on failed export usb: gadget: f_hid: fix report descriptor allocation parport: Add support for Brainboxes IX/UC/PX parallel cards usb: typec: class: fix typec_altmode_put_partner to put plugs serial: sc16is7xx: address RX timeout interrupt errata serial: 8250_omap: Add earlycon support for the AM654 UART controller x86/CPU/AMD: Check vendor in the AMD microcode callback KVM: s390/mm: Properly reset no-dat nilfs2: fix missing error check for sb_set_blocksize call netlink: don't call ->netlink_bind with table lock held genetlink: add CAP_NET_ADMIN test for multicast bind psample: Require 'CAP_NET_ADMIN' when joining "packets" group drop_monitor: Require 'CAP_SYS_ADMIN' when joining "events" group tools headers UAPI: Sync linux/perf_event.h with the kernel sources IB/isert: Fix unaligned immediate-data handling devcoredump : Serialize devcd_del work devcoredump: Send uevent once devcd is ready Linux 4.19.302 Change-Id: If04a1c5d3950ac7c1cbe4b71df951dcf3e8e8ed1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
cd086b6516
63 changed files with 794 additions and 360 deletions
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 19
|
PATCHLEVEL = 19
|
||||||
SUBLEVEL = 301
|
SUBLEVEL = 302
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = "People's Front"
|
NAME = "People's Front"
|
||||||
|
|
||||||
|
|
|
@ -565,7 +565,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt: gpt@2098000 {
|
gpt: timer@2098000 {
|
||||||
compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
|
compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
|
||||||
reg = <0x02098000 0x4000>;
|
reg = <0x02098000 0x4000>;
|
||||||
interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
|
@ -374,7 +374,7 @@
|
||||||
clock-names = "ipg", "per";
|
clock-names = "ipg", "per";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt: gpt@2098000 {
|
gpt: timer@2098000 {
|
||||||
compatible = "fsl,imx6sl-gpt";
|
compatible = "fsl,imx6sl-gpt";
|
||||||
reg = <0x02098000 0x4000>;
|
reg = <0x02098000 0x4000>;
|
||||||
interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
|
@ -468,7 +468,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt: gpt@2098000 {
|
gpt: timer@2098000 {
|
||||||
compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
|
compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
|
||||||
reg = <0x02098000 0x4000>;
|
reg = <0x02098000 0x4000>;
|
||||||
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
|
@ -423,7 +423,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt1: gpt@2098000 {
|
gpt1: timer@2098000 {
|
||||||
compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt";
|
compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt";
|
||||||
reg = <0x02098000 0x4000>;
|
reg = <0x02098000 0x4000>;
|
||||||
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
@ -696,7 +696,7 @@
|
||||||
reg = <0x020e4000 0x4000>;
|
reg = <0x020e4000 0x4000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt2: gpt@20e8000 {
|
gpt2: timer@20e8000 {
|
||||||
compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt";
|
compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt";
|
||||||
reg = <0x020e8000 0x4000>;
|
reg = <0x020e8000 0x4000>;
|
||||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
|
@ -439,8 +439,8 @@
|
||||||
fsl,input-sel = <&iomuxc>;
|
fsl,input-sel = <&iomuxc>;
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt1: gpt@302d0000 {
|
gpt1: timer@302d0000 {
|
||||||
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
|
compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
|
||||||
reg = <0x302d0000 0x10000>;
|
reg = <0x302d0000 0x10000>;
|
||||||
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
|
clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
|
||||||
|
@ -448,8 +448,8 @@
|
||||||
clock-names = "ipg", "per";
|
clock-names = "ipg", "per";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt2: gpt@302e0000 {
|
gpt2: timer@302e0000 {
|
||||||
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
|
compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
|
||||||
reg = <0x302e0000 0x10000>;
|
reg = <0x302e0000 0x10000>;
|
||||||
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
|
clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
|
||||||
|
@ -458,8 +458,8 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt3: gpt@302f0000 {
|
gpt3: timer@302f0000 {
|
||||||
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
|
compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
|
||||||
reg = <0x302f0000 0x10000>;
|
reg = <0x302f0000 0x10000>;
|
||||||
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
|
clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
|
||||||
|
@ -468,8 +468,8 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpt4: gpt@30300000 {
|
gpt4: timer@30300000 {
|
||||||
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
|
compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
|
||||||
reg = <0x30300000 0x10000>;
|
reg = <0x30300000 0x10000>;
|
||||||
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
|
clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
|
||||||
|
|
|
@ -513,6 +513,10 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b
|
||||||
|
|
||||||
name = devm_kasprintf(&pdev->dev,
|
name = devm_kasprintf(&pdev->dev,
|
||||||
GFP_KERNEL, "mmdc%d", ret);
|
GFP_KERNEL, "mmdc%d", ret);
|
||||||
|
if (!name) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto pmu_release_id;
|
||||||
|
}
|
||||||
|
|
||||||
pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk;
|
pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk;
|
||||||
pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data;
|
pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data;
|
||||||
|
@ -535,9 +539,10 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b
|
||||||
|
|
||||||
pmu_register_err:
|
pmu_register_err:
|
||||||
pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
|
pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
|
||||||
ida_simple_remove(&mmdc_ida, pmu_mmdc->id);
|
|
||||||
cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
|
cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
|
||||||
hrtimer_cancel(&pmu_mmdc->hrtimer);
|
hrtimer_cancel(&pmu_mmdc->hrtimer);
|
||||||
|
pmu_release_id:
|
||||||
|
ida_simple_remove(&mmdc_ida, pmu_mmdc->id);
|
||||||
pmu_free:
|
pmu_free:
|
||||||
kfree(pmu_mmdc);
|
kfree(pmu_mmdc);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -699,7 +699,7 @@ void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
|
||||||
pte_clear(mm, addr, ptep);
|
pte_clear(mm, addr, ptep);
|
||||||
}
|
}
|
||||||
if (reset)
|
if (reset)
|
||||||
pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
|
pgste_val(pgste) &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT);
|
||||||
pgste_set_unlock(ptep, pgste);
|
pgste_set_unlock(ptep, pgste);
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1253,5 +1253,8 @@ static void zenbleed_check_cpu(void *unused)
|
||||||
|
|
||||||
void amd_check_microcode(void)
|
void amd_check_microcode(void)
|
||||||
{
|
{
|
||||||
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
||||||
|
return;
|
||||||
|
|
||||||
on_each_cpu(zenbleed_check_cpu, NULL, 1);
|
on_each_cpu(zenbleed_check_cpu, NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,47 @@ struct devcd_entry {
|
||||||
struct device devcd_dev;
|
struct device devcd_dev;
|
||||||
void *data;
|
void *data;
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
|
/*
|
||||||
|
* Here, mutex is required to serialize the calls to del_wk work between
|
||||||
|
* user/kernel space which happens when devcd is added with device_add()
|
||||||
|
* and that sends uevent to user space. User space reads the uevents,
|
||||||
|
* and calls to devcd_data_write() which try to modify the work which is
|
||||||
|
* not even initialized/queued from devcoredump.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* cpu0(X) cpu1(Y)
|
||||||
|
*
|
||||||
|
* dev_coredump() uevent sent to user space
|
||||||
|
* device_add() ======================> user space process Y reads the
|
||||||
|
* uevents writes to devcd fd
|
||||||
|
* which results into writes to
|
||||||
|
*
|
||||||
|
* devcd_data_write()
|
||||||
|
* mod_delayed_work()
|
||||||
|
* try_to_grab_pending()
|
||||||
|
* del_timer()
|
||||||
|
* debug_assert_init()
|
||||||
|
* INIT_DELAYED_WORK()
|
||||||
|
* schedule_delayed_work()
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Also, mutex alone would not be enough to avoid scheduling of
|
||||||
|
* del_wk work after it get flush from a call to devcd_free()
|
||||||
|
* mentioned as below.
|
||||||
|
*
|
||||||
|
* disabled_store()
|
||||||
|
* devcd_free()
|
||||||
|
* mutex_lock() devcd_data_write()
|
||||||
|
* flush_delayed_work()
|
||||||
|
* mutex_unlock()
|
||||||
|
* mutex_lock()
|
||||||
|
* mod_delayed_work()
|
||||||
|
* mutex_unlock()
|
||||||
|
* So, delete_work flag is required.
|
||||||
|
*/
|
||||||
|
struct mutex mutex;
|
||||||
|
bool delete_work;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
ssize_t (*read)(char *buffer, loff_t offset, size_t count,
|
ssize_t (*read)(char *buffer, loff_t offset, size_t count,
|
||||||
void *data, size_t datalen);
|
void *data, size_t datalen);
|
||||||
|
@ -88,7 +129,12 @@ static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
|
||||||
struct device *dev = kobj_to_dev(kobj);
|
struct device *dev = kobj_to_dev(kobj);
|
||||||
struct devcd_entry *devcd = dev_to_devcd(dev);
|
struct devcd_entry *devcd = dev_to_devcd(dev);
|
||||||
|
|
||||||
mod_delayed_work(system_wq, &devcd->del_wk, 0);
|
mutex_lock(&devcd->mutex);
|
||||||
|
if (!devcd->delete_work) {
|
||||||
|
devcd->delete_work = true;
|
||||||
|
mod_delayed_work(system_wq, &devcd->del_wk, 0);
|
||||||
|
}
|
||||||
|
mutex_unlock(&devcd->mutex);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +162,12 @@ static int devcd_free(struct device *dev, void *data)
|
||||||
{
|
{
|
||||||
struct devcd_entry *devcd = dev_to_devcd(dev);
|
struct devcd_entry *devcd = dev_to_devcd(dev);
|
||||||
|
|
||||||
|
mutex_lock(&devcd->mutex);
|
||||||
|
if (!devcd->delete_work)
|
||||||
|
devcd->delete_work = true;
|
||||||
|
|
||||||
flush_delayed_work(&devcd->del_wk);
|
flush_delayed_work(&devcd->del_wk);
|
||||||
|
mutex_unlock(&devcd->mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +177,30 @@ static ssize_t disabled_show(struct class *class, struct class_attribute *attr,
|
||||||
return sprintf(buf, "%d\n", devcd_disabled);
|
return sprintf(buf, "%d\n", devcd_disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* disabled_store() worker()
|
||||||
|
* class_for_each_device(&devcd_class,
|
||||||
|
* NULL, NULL, devcd_free)
|
||||||
|
* ...
|
||||||
|
* ...
|
||||||
|
* while ((dev = class_dev_iter_next(&iter))
|
||||||
|
* devcd_del()
|
||||||
|
* device_del()
|
||||||
|
* put_device() <- last reference
|
||||||
|
* error = fn(dev, data) devcd_dev_release()
|
||||||
|
* devcd_free(dev, data) kfree(devcd)
|
||||||
|
* mutex_lock(&devcd->mutex);
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* In the above diagram, It looks like disabled_store() would be racing with parallely
|
||||||
|
* running devcd_del() and result in memory abort while acquiring devcd->mutex which
|
||||||
|
* is called after kfree of devcd memory after dropping its last reference with
|
||||||
|
* put_device(). However, this will not happens as fn(dev, data) runs
|
||||||
|
* with its own reference to device via klist_node so it is not its last reference.
|
||||||
|
* so, above situation would not occur.
|
||||||
|
*/
|
||||||
|
|
||||||
static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
|
static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -291,13 +366,17 @@ void dev_coredumpm(struct device *dev, struct module *owner,
|
||||||
devcd->read = read;
|
devcd->read = read;
|
||||||
devcd->free = free;
|
devcd->free = free;
|
||||||
devcd->failing_dev = get_device(dev);
|
devcd->failing_dev = get_device(dev);
|
||||||
|
devcd->delete_work = false;
|
||||||
|
|
||||||
|
mutex_init(&devcd->mutex);
|
||||||
device_initialize(&devcd->devcd_dev);
|
device_initialize(&devcd->devcd_dev);
|
||||||
|
|
||||||
dev_set_name(&devcd->devcd_dev, "devcd%d",
|
dev_set_name(&devcd->devcd_dev, "devcd%d",
|
||||||
atomic_inc_return(&devcd_count));
|
atomic_inc_return(&devcd_count));
|
||||||
devcd->devcd_dev.class = &devcd_class;
|
devcd->devcd_dev.class = &devcd_class;
|
||||||
|
|
||||||
|
mutex_lock(&devcd->mutex);
|
||||||
|
dev_set_uevent_suppress(&devcd->devcd_dev, true);
|
||||||
if (device_add(&devcd->devcd_dev))
|
if (device_add(&devcd->devcd_dev))
|
||||||
goto put_device;
|
goto put_device;
|
||||||
|
|
||||||
|
@ -309,12 +388,15 @@ void dev_coredumpm(struct device *dev, struct module *owner,
|
||||||
"devcoredump"))
|
"devcoredump"))
|
||||||
/* nothing - symlink will be missing */;
|
/* nothing - symlink will be missing */;
|
||||||
|
|
||||||
|
dev_set_uevent_suppress(&devcd->devcd_dev, false);
|
||||||
|
kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD);
|
||||||
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
|
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
|
||||||
schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
|
schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
|
||||||
|
mutex_unlock(&devcd->mutex);
|
||||||
return;
|
return;
|
||||||
put_device:
|
put_device:
|
||||||
put_device(&devcd->devcd_dev);
|
put_device(&devcd->devcd_dev);
|
||||||
|
mutex_unlock(&devcd->mutex);
|
||||||
put_module:
|
put_module:
|
||||||
module_put(owner);
|
module_put(owner);
|
||||||
free:
|
free:
|
||||||
|
|
|
@ -495,14 +495,17 @@ static ssize_t export_store(struct class *class,
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gpiod_set_transitory(desc, false);
|
status = gpiod_set_transitory(desc, false);
|
||||||
if (!status) {
|
if (status) {
|
||||||
status = gpiod_export(desc, true);
|
gpiod_free(desc);
|
||||||
if (status < 0)
|
goto done;
|
||||||
gpiod_free(desc);
|
|
||||||
else
|
|
||||||
set_bit(FLAG_SYSFS, &desc->flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = gpiod_export(desc, true);
|
||||||
|
if (status < 0)
|
||||||
|
gpiod_free(desc);
|
||||||
|
else
|
||||||
|
set_bit(FLAG_SYSFS, &desc->flags);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (status)
|
if (status)
|
||||||
pr_debug("%s: status %d\n", __func__, status);
|
pr_debug("%s: status %d\n", __func__, status);
|
||||||
|
|
|
@ -147,7 +147,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < p->nchunks; i++) {
|
for (i = 0; i < p->nchunks; i++) {
|
||||||
struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL;
|
struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL;
|
||||||
struct drm_amdgpu_cs_chunk user_chunk;
|
struct drm_amdgpu_cs_chunk user_chunk;
|
||||||
uint32_t __user *cdata;
|
uint32_t __user *cdata;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ ACPI_MODULE_NAME(ACPI_POWER_METER_NAME);
|
||||||
#define POWER_METER_CAN_NOTIFY (1 << 3)
|
#define POWER_METER_CAN_NOTIFY (1 << 3)
|
||||||
#define POWER_METER_IS_BATTERY (1 << 8)
|
#define POWER_METER_IS_BATTERY (1 << 8)
|
||||||
#define UNKNOWN_HYSTERESIS 0xFFFFFFFF
|
#define UNKNOWN_HYSTERESIS 0xFFFFFFFF
|
||||||
|
#define UNKNOWN_POWER 0xFFFFFFFF
|
||||||
|
|
||||||
#define METER_NOTIFY_CONFIG 0x80
|
#define METER_NOTIFY_CONFIG 0x80
|
||||||
#define METER_NOTIFY_TRIP 0x81
|
#define METER_NOTIFY_TRIP 0x81
|
||||||
|
@ -356,6 +357,9 @@ static ssize_t show_power(struct device *dev,
|
||||||
update_meter(resource);
|
update_meter(resource);
|
||||||
mutex_unlock(&resource->lock);
|
mutex_unlock(&resource->lock);
|
||||||
|
|
||||||
|
if (resource->power == UNKNOWN_POWER)
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
return sprintf(buf, "%llu\n", resource->power * 1000);
|
return sprintf(buf, "%llu\n", resource->power * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ static char version[] =
|
||||||
BNXT_RE_DESC " v" ROCE_DRV_MODULE_VERSION "\n";
|
BNXT_RE_DESC " v" ROCE_DRV_MODULE_VERSION "\n";
|
||||||
|
|
||||||
MODULE_AUTHOR("Eddie Wai <eddie.wai@broadcom.com>");
|
MODULE_AUTHOR("Eddie Wai <eddie.wai@broadcom.com>");
|
||||||
MODULE_DESCRIPTION(BNXT_RE_DESC " Driver");
|
MODULE_DESCRIPTION(BNXT_RE_DESC);
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
|
|
|
@ -190,15 +190,15 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
|
||||||
rx_desc = isert_conn->rx_descs;
|
rx_desc = isert_conn->rx_descs;
|
||||||
|
|
||||||
for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++) {
|
for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++) {
|
||||||
dma_addr = ib_dma_map_single(ib_dev, (void *)rx_desc,
|
dma_addr = ib_dma_map_single(ib_dev, rx_desc->buf,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
if (ib_dma_mapping_error(ib_dev, dma_addr))
|
if (ib_dma_mapping_error(ib_dev, dma_addr))
|
||||||
goto dma_map_fail;
|
goto dma_map_fail;
|
||||||
|
|
||||||
rx_desc->dma_addr = dma_addr;
|
rx_desc->dma_addr = dma_addr;
|
||||||
|
|
||||||
rx_sg = &rx_desc->rx_sg;
|
rx_sg = &rx_desc->rx_sg;
|
||||||
rx_sg->addr = rx_desc->dma_addr;
|
rx_sg->addr = rx_desc->dma_addr + isert_get_hdr_offset(rx_desc);
|
||||||
rx_sg->length = ISER_RX_PAYLOAD_SIZE;
|
rx_sg->length = ISER_RX_PAYLOAD_SIZE;
|
||||||
rx_sg->lkey = device->pd->local_dma_lkey;
|
rx_sg->lkey = device->pd->local_dma_lkey;
|
||||||
rx_desc->rx_cqe.done = isert_recv_done;
|
rx_desc->rx_cqe.done = isert_recv_done;
|
||||||
|
@ -210,7 +210,7 @@ dma_map_fail:
|
||||||
rx_desc = isert_conn->rx_descs;
|
rx_desc = isert_conn->rx_descs;
|
||||||
for (j = 0; j < i; j++, rx_desc++) {
|
for (j = 0; j < i; j++, rx_desc++) {
|
||||||
ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
|
ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
kfree(isert_conn->rx_descs);
|
kfree(isert_conn->rx_descs);
|
||||||
isert_conn->rx_descs = NULL;
|
isert_conn->rx_descs = NULL;
|
||||||
|
@ -231,7 +231,7 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn)
|
||||||
rx_desc = isert_conn->rx_descs;
|
rx_desc = isert_conn->rx_descs;
|
||||||
for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++) {
|
for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++) {
|
||||||
ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
|
ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(isert_conn->rx_descs);
|
kfree(isert_conn->rx_descs);
|
||||||
|
@ -416,10 +416,9 @@ isert_free_login_buf(struct isert_conn *isert_conn)
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_TO_DEVICE);
|
ISER_RX_PAYLOAD_SIZE, DMA_TO_DEVICE);
|
||||||
kfree(isert_conn->login_rsp_buf);
|
kfree(isert_conn->login_rsp_buf);
|
||||||
|
|
||||||
ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
|
ib_dma_unmap_single(ib_dev, isert_conn->login_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE,
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
DMA_FROM_DEVICE);
|
kfree(isert_conn->login_desc);
|
||||||
kfree(isert_conn->login_req_buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -428,25 +427,25 @@ isert_alloc_login_buf(struct isert_conn *isert_conn,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
isert_conn->login_req_buf = kzalloc(sizeof(*isert_conn->login_req_buf),
|
isert_conn->login_desc = kzalloc(sizeof(*isert_conn->login_desc),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!isert_conn->login_req_buf)
|
if (!isert_conn->login_desc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
isert_conn->login_req_dma = ib_dma_map_single(ib_dev,
|
isert_conn->login_desc->dma_addr = ib_dma_map_single(ib_dev,
|
||||||
isert_conn->login_req_buf,
|
isert_conn->login_desc->buf,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
ret = ib_dma_mapping_error(ib_dev, isert_conn->login_req_dma);
|
ret = ib_dma_mapping_error(ib_dev, isert_conn->login_desc->dma_addr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
isert_err("login_req_dma mapping error: %d\n", ret);
|
isert_err("login_desc dma mapping error: %d\n", ret);
|
||||||
isert_conn->login_req_dma = 0;
|
isert_conn->login_desc->dma_addr = 0;
|
||||||
goto out_free_login_req_buf;
|
goto out_free_login_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
isert_conn->login_rsp_buf = kzalloc(ISER_RX_PAYLOAD_SIZE, GFP_KERNEL);
|
isert_conn->login_rsp_buf = kzalloc(ISER_RX_PAYLOAD_SIZE, GFP_KERNEL);
|
||||||
if (!isert_conn->login_rsp_buf) {
|
if (!isert_conn->login_rsp_buf) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_unmap_login_req_buf;
|
goto out_unmap_login_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
isert_conn->login_rsp_dma = ib_dma_map_single(ib_dev,
|
isert_conn->login_rsp_dma = ib_dma_map_single(ib_dev,
|
||||||
|
@ -463,11 +462,11 @@ isert_alloc_login_buf(struct isert_conn *isert_conn,
|
||||||
|
|
||||||
out_free_login_rsp_buf:
|
out_free_login_rsp_buf:
|
||||||
kfree(isert_conn->login_rsp_buf);
|
kfree(isert_conn->login_rsp_buf);
|
||||||
out_unmap_login_req_buf:
|
out_unmap_login_desc:
|
||||||
ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
|
ib_dma_unmap_single(ib_dev, isert_conn->login_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
out_free_login_req_buf:
|
out_free_login_desc:
|
||||||
kfree(isert_conn->login_req_buf);
|
kfree(isert_conn->login_desc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +585,7 @@ isert_connect_release(struct isert_conn *isert_conn)
|
||||||
ib_destroy_qp(isert_conn->qp);
|
ib_destroy_qp(isert_conn->qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isert_conn->login_req_buf)
|
if (isert_conn->login_desc)
|
||||||
isert_free_login_buf(isert_conn);
|
isert_free_login_buf(isert_conn);
|
||||||
|
|
||||||
isert_device_put(device);
|
isert_device_put(device);
|
||||||
|
@ -976,17 +975,18 @@ isert_login_post_recv(struct isert_conn *isert_conn)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&sge, 0, sizeof(struct ib_sge));
|
memset(&sge, 0, sizeof(struct ib_sge));
|
||||||
sge.addr = isert_conn->login_req_dma;
|
sge.addr = isert_conn->login_desc->dma_addr +
|
||||||
|
isert_get_hdr_offset(isert_conn->login_desc);
|
||||||
sge.length = ISER_RX_PAYLOAD_SIZE;
|
sge.length = ISER_RX_PAYLOAD_SIZE;
|
||||||
sge.lkey = isert_conn->device->pd->local_dma_lkey;
|
sge.lkey = isert_conn->device->pd->local_dma_lkey;
|
||||||
|
|
||||||
isert_dbg("Setup sge: addr: %llx length: %d 0x%08x\n",
|
isert_dbg("Setup sge: addr: %llx length: %d 0x%08x\n",
|
||||||
sge.addr, sge.length, sge.lkey);
|
sge.addr, sge.length, sge.lkey);
|
||||||
|
|
||||||
isert_conn->login_req_buf->rx_cqe.done = isert_login_recv_done;
|
isert_conn->login_desc->rx_cqe.done = isert_login_recv_done;
|
||||||
|
|
||||||
memset(&rx_wr, 0, sizeof(struct ib_recv_wr));
|
memset(&rx_wr, 0, sizeof(struct ib_recv_wr));
|
||||||
rx_wr.wr_cqe = &isert_conn->login_req_buf->rx_cqe;
|
rx_wr.wr_cqe = &isert_conn->login_desc->rx_cqe;
|
||||||
rx_wr.sg_list = &sge;
|
rx_wr.sg_list = &sge;
|
||||||
rx_wr.num_sge = 1;
|
rx_wr.num_sge = 1;
|
||||||
|
|
||||||
|
@ -1063,7 +1063,7 @@ post_send:
|
||||||
static void
|
static void
|
||||||
isert_rx_login_req(struct isert_conn *isert_conn)
|
isert_rx_login_req(struct isert_conn *isert_conn)
|
||||||
{
|
{
|
||||||
struct iser_rx_desc *rx_desc = isert_conn->login_req_buf;
|
struct iser_rx_desc *rx_desc = isert_conn->login_desc;
|
||||||
int rx_buflen = isert_conn->login_req_len;
|
int rx_buflen = isert_conn->login_req_len;
|
||||||
struct iscsi_conn *conn = isert_conn->conn;
|
struct iscsi_conn *conn = isert_conn->conn;
|
||||||
struct iscsi_login *login = conn->conn_login;
|
struct iscsi_login *login = conn->conn_login;
|
||||||
|
@ -1075,7 +1075,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
|
||||||
|
|
||||||
if (login->first_request) {
|
if (login->first_request) {
|
||||||
struct iscsi_login_req *login_req =
|
struct iscsi_login_req *login_req =
|
||||||
(struct iscsi_login_req *)&rx_desc->iscsi_header;
|
(struct iscsi_login_req *)isert_get_iscsi_hdr(rx_desc);
|
||||||
/*
|
/*
|
||||||
* Setup the initial iscsi_login values from the leading
|
* Setup the initial iscsi_login values from the leading
|
||||||
* login request PDU.
|
* login request PDU.
|
||||||
|
@ -1094,13 +1094,13 @@ isert_rx_login_req(struct isert_conn *isert_conn)
|
||||||
login->tsih = be16_to_cpu(login_req->tsih);
|
login->tsih = be16_to_cpu(login_req->tsih);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&login->req[0], (void *)&rx_desc->iscsi_header, ISCSI_HDR_LEN);
|
memcpy(&login->req[0], isert_get_iscsi_hdr(rx_desc), ISCSI_HDR_LEN);
|
||||||
|
|
||||||
size = min(rx_buflen, MAX_KEY_VALUE_PAIRS);
|
size = min(rx_buflen, MAX_KEY_VALUE_PAIRS);
|
||||||
isert_dbg("Using login payload size: %d, rx_buflen: %d "
|
isert_dbg("Using login payload size: %d, rx_buflen: %d "
|
||||||
"MAX_KEY_VALUE_PAIRS: %d\n", size, rx_buflen,
|
"MAX_KEY_VALUE_PAIRS: %d\n", size, rx_buflen,
|
||||||
MAX_KEY_VALUE_PAIRS);
|
MAX_KEY_VALUE_PAIRS);
|
||||||
memcpy(login->req_buf, &rx_desc->data[0], size);
|
memcpy(login->req_buf, isert_get_data(rx_desc), size);
|
||||||
|
|
||||||
if (login->first_request) {
|
if (login->first_request) {
|
||||||
complete(&isert_conn->login_comp);
|
complete(&isert_conn->login_comp);
|
||||||
|
@ -1165,14 +1165,15 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
|
||||||
if (imm_data_len != data_len) {
|
if (imm_data_len != data_len) {
|
||||||
sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
|
sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
|
||||||
sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
|
sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
|
||||||
&rx_desc->data[0], imm_data_len);
|
isert_get_data(rx_desc), imm_data_len);
|
||||||
isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
|
isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
|
||||||
sg_nents, imm_data_len);
|
sg_nents, imm_data_len);
|
||||||
} else {
|
} else {
|
||||||
sg_init_table(&isert_cmd->sg, 1);
|
sg_init_table(&isert_cmd->sg, 1);
|
||||||
cmd->se_cmd.t_data_sg = &isert_cmd->sg;
|
cmd->se_cmd.t_data_sg = &isert_cmd->sg;
|
||||||
cmd->se_cmd.t_data_nents = 1;
|
cmd->se_cmd.t_data_nents = 1;
|
||||||
sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
|
sg_set_buf(&isert_cmd->sg, isert_get_data(rx_desc),
|
||||||
|
imm_data_len);
|
||||||
isert_dbg("Transfer Immediate imm_data_len: %d\n",
|
isert_dbg("Transfer Immediate imm_data_len: %d\n",
|
||||||
imm_data_len);
|
imm_data_len);
|
||||||
}
|
}
|
||||||
|
@ -1241,9 +1242,9 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
|
||||||
}
|
}
|
||||||
isert_dbg("Copying DataOut: sg_start: %p, sg_off: %u "
|
isert_dbg("Copying DataOut: sg_start: %p, sg_off: %u "
|
||||||
"sg_nents: %u from %p %u\n", sg_start, sg_off,
|
"sg_nents: %u from %p %u\n", sg_start, sg_off,
|
||||||
sg_nents, &rx_desc->data[0], unsol_data_len);
|
sg_nents, isert_get_data(rx_desc), unsol_data_len);
|
||||||
|
|
||||||
sg_copy_from_buffer(sg_start, sg_nents, &rx_desc->data[0],
|
sg_copy_from_buffer(sg_start, sg_nents, isert_get_data(rx_desc),
|
||||||
unsol_data_len);
|
unsol_data_len);
|
||||||
|
|
||||||
rc = iscsit_check_dataout_payload(cmd, hdr, false);
|
rc = iscsit_check_dataout_payload(cmd, hdr, false);
|
||||||
|
@ -1302,7 +1303,7 @@ isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd
|
||||||
}
|
}
|
||||||
cmd->text_in_ptr = text_in;
|
cmd->text_in_ptr = text_in;
|
||||||
|
|
||||||
memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length);
|
memcpy(cmd->text_in_ptr, isert_get_data(rx_desc), payload_length);
|
||||||
|
|
||||||
return iscsit_process_text_cmd(conn, cmd, hdr);
|
return iscsit_process_text_cmd(conn, cmd, hdr);
|
||||||
}
|
}
|
||||||
|
@ -1312,7 +1313,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
|
||||||
uint32_t read_stag, uint64_t read_va,
|
uint32_t read_stag, uint64_t read_va,
|
||||||
uint32_t write_stag, uint64_t write_va)
|
uint32_t write_stag, uint64_t write_va)
|
||||||
{
|
{
|
||||||
struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
|
struct iscsi_hdr *hdr = isert_get_iscsi_hdr(rx_desc);
|
||||||
struct iscsi_conn *conn = isert_conn->conn;
|
struct iscsi_conn *conn = isert_conn->conn;
|
||||||
struct iscsi_cmd *cmd;
|
struct iscsi_cmd *cmd;
|
||||||
struct isert_cmd *isert_cmd;
|
struct isert_cmd *isert_cmd;
|
||||||
|
@ -1410,8 +1411,8 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||||
struct isert_conn *isert_conn = wc->qp->qp_context;
|
struct isert_conn *isert_conn = wc->qp->qp_context;
|
||||||
struct ib_device *ib_dev = isert_conn->cm_id->device;
|
struct ib_device *ib_dev = isert_conn->cm_id->device;
|
||||||
struct iser_rx_desc *rx_desc = cqe_to_rx_desc(wc->wr_cqe);
|
struct iser_rx_desc *rx_desc = cqe_to_rx_desc(wc->wr_cqe);
|
||||||
struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
|
struct iscsi_hdr *hdr = isert_get_iscsi_hdr(rx_desc);
|
||||||
struct iser_ctrl *iser_ctrl = &rx_desc->iser_header;
|
struct iser_ctrl *iser_ctrl = isert_get_iser_hdr(rx_desc);
|
||||||
uint64_t read_va = 0, write_va = 0;
|
uint64_t read_va = 0, write_va = 0;
|
||||||
uint32_t read_stag = 0, write_stag = 0;
|
uint32_t read_stag = 0, write_stag = 0;
|
||||||
|
|
||||||
|
@ -1425,7 +1426,7 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||||
rx_desc->in_use = true;
|
rx_desc->in_use = true;
|
||||||
|
|
||||||
ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
|
ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n",
|
isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n",
|
||||||
rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags,
|
rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags,
|
||||||
|
@ -1460,7 +1461,7 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||||
read_stag, read_va, write_stag, write_va);
|
read_stag, read_va, write_stag, write_va);
|
||||||
|
|
||||||
ib_dma_sync_single_for_device(ib_dev, rx_desc->dma_addr,
|
ib_dma_sync_single_for_device(ib_dev, rx_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1474,8 +1475,8 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_req_dma,
|
ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN;
|
isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN;
|
||||||
|
|
||||||
|
@ -1490,8 +1491,8 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||||
complete(&isert_conn->login_req_comp);
|
complete(&isert_conn->login_req_comp);
|
||||||
mutex_unlock(&isert_conn->mutex);
|
mutex_unlock(&isert_conn->mutex);
|
||||||
|
|
||||||
ib_dma_sync_single_for_device(ib_dev, isert_conn->login_req_dma,
|
ib_dma_sync_single_for_device(ib_dev, isert_conn->login_desc->dma_addr,
|
||||||
ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
|
ISER_RX_SIZE, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -59,9 +59,11 @@
|
||||||
ISERT_MAX_TX_MISC_PDUS + \
|
ISERT_MAX_TX_MISC_PDUS + \
|
||||||
ISERT_MAX_RX_MISC_PDUS)
|
ISERT_MAX_RX_MISC_PDUS)
|
||||||
|
|
||||||
#define ISER_RX_PAD_SIZE (ISCSI_DEF_MAX_RECV_SEG_LEN + 4096 - \
|
/*
|
||||||
(ISER_RX_PAYLOAD_SIZE + sizeof(u64) + sizeof(struct ib_sge) + \
|
* RX size is default of 8k plus headers, but data needs to align to
|
||||||
sizeof(struct ib_cqe) + sizeof(bool)))
|
* 512 boundary, so use 1024 to have the extra space for alignment.
|
||||||
|
*/
|
||||||
|
#define ISER_RX_SIZE (ISCSI_DEF_MAX_RECV_SEG_LEN + 1024)
|
||||||
|
|
||||||
#define ISCSI_ISER_SG_TABLESIZE 256
|
#define ISCSI_ISER_SG_TABLESIZE 256
|
||||||
|
|
||||||
|
@ -80,21 +82,41 @@ enum iser_conn_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iser_rx_desc {
|
struct iser_rx_desc {
|
||||||
struct iser_ctrl iser_header;
|
char buf[ISER_RX_SIZE];
|
||||||
struct iscsi_hdr iscsi_header;
|
|
||||||
char data[ISCSI_DEF_MAX_RECV_SEG_LEN];
|
|
||||||
u64 dma_addr;
|
u64 dma_addr;
|
||||||
struct ib_sge rx_sg;
|
struct ib_sge rx_sg;
|
||||||
struct ib_cqe rx_cqe;
|
struct ib_cqe rx_cqe;
|
||||||
bool in_use;
|
bool in_use;
|
||||||
char pad[ISER_RX_PAD_SIZE];
|
};
|
||||||
} __packed;
|
|
||||||
|
|
||||||
static inline struct iser_rx_desc *cqe_to_rx_desc(struct ib_cqe *cqe)
|
static inline struct iser_rx_desc *cqe_to_rx_desc(struct ib_cqe *cqe)
|
||||||
{
|
{
|
||||||
return container_of(cqe, struct iser_rx_desc, rx_cqe);
|
return container_of(cqe, struct iser_rx_desc, rx_cqe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *isert_get_iser_hdr(struct iser_rx_desc *desc)
|
||||||
|
{
|
||||||
|
return PTR_ALIGN(desc->buf + ISER_HEADERS_LEN, 512) - ISER_HEADERS_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t isert_get_hdr_offset(struct iser_rx_desc *desc)
|
||||||
|
{
|
||||||
|
return isert_get_iser_hdr(desc) - (void *)desc->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *isert_get_iscsi_hdr(struct iser_rx_desc *desc)
|
||||||
|
{
|
||||||
|
return isert_get_iser_hdr(desc) + sizeof(struct iser_ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *isert_get_data(struct iser_rx_desc *desc)
|
||||||
|
{
|
||||||
|
void *data = isert_get_iser_hdr(desc) + ISER_HEADERS_LEN;
|
||||||
|
|
||||||
|
WARN_ON((uintptr_t)data & 511);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
struct iser_tx_desc {
|
struct iser_tx_desc {
|
||||||
struct iser_ctrl iser_header;
|
struct iser_ctrl iser_header;
|
||||||
struct iscsi_hdr iscsi_header;
|
struct iscsi_hdr iscsi_header;
|
||||||
|
@ -141,9 +163,8 @@ struct isert_conn {
|
||||||
u32 responder_resources;
|
u32 responder_resources;
|
||||||
u32 initiator_depth;
|
u32 initiator_depth;
|
||||||
bool pi_support;
|
bool pi_support;
|
||||||
struct iser_rx_desc *login_req_buf;
|
struct iser_rx_desc *login_desc;
|
||||||
char *login_rsp_buf;
|
char *login_rsp_buf;
|
||||||
u64 login_req_dma;
|
|
||||||
int login_req_len;
|
int login_req_len;
|
||||||
u64 login_rsp_dma;
|
u64 login_rsp_dma;
|
||||||
struct iser_rx_desc *rx_descs;
|
struct iser_rx_desc *rx_descs;
|
||||||
|
|
|
@ -1489,8 +1489,6 @@ probe_out:
|
||||||
/* Unregister video device */
|
/* Unregister video device */
|
||||||
video_unregister_device(&ch->video_dev);
|
video_unregister_device(&ch->video_dev);
|
||||||
}
|
}
|
||||||
kfree(vpif_obj.sd);
|
|
||||||
v4l2_device_unregister(&vpif_obj.v4l2_dev);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,7 +332,7 @@ static int __init arc_rimi_init(void)
|
||||||
dev->irq = 9;
|
dev->irq = 9;
|
||||||
|
|
||||||
if (arcrimi_probe(dev)) {
|
if (arcrimi_probe(dev)) {
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ static void __exit arc_rimi_exit(void)
|
||||||
iounmap(lp->mem_start);
|
iounmap(lp->mem_start);
|
||||||
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
|
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
|
||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
|
|
|
@ -191,6 +191,8 @@ do { \
|
||||||
#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */
|
#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */
|
||||||
#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit,
|
#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit,
|
||||||
but default is 2.5MBit. */
|
but default is 2.5MBit. */
|
||||||
|
#define ARC_HAS_LED 4 /* card has software controlled LEDs */
|
||||||
|
#define ARC_HAS_ROTARY 8 /* card has rotary encoder */
|
||||||
|
|
||||||
/* information needed to define an encapsulation driver */
|
/* information needed to define an encapsulation driver */
|
||||||
struct ArcProto {
|
struct ArcProto {
|
||||||
|
@ -303,6 +305,10 @@ struct arcnet_local {
|
||||||
|
|
||||||
int excnak_pending; /* We just got an excesive nak interrupt */
|
int excnak_pending; /* We just got an excesive nak interrupt */
|
||||||
|
|
||||||
|
/* RESET flag handling */
|
||||||
|
int reset_in_progress;
|
||||||
|
struct work_struct reset_work;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16_t sequence; /* sequence number (incs with each packet) */
|
uint16_t sequence; /* sequence number (incs with each packet) */
|
||||||
__be16 aborted_seq;
|
__be16 aborted_seq;
|
||||||
|
@ -355,7 +361,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
|
||||||
|
|
||||||
void arcnet_unregister_proto(struct ArcProto *proto);
|
void arcnet_unregister_proto(struct ArcProto *proto);
|
||||||
irqreturn_t arcnet_interrupt(int irq, void *dev_id);
|
irqreturn_t arcnet_interrupt(int irq, void *dev_id);
|
||||||
|
|
||||||
struct net_device *alloc_arcdev(const char *name);
|
struct net_device *alloc_arcdev(const char *name);
|
||||||
|
void free_arcdev(struct net_device *dev);
|
||||||
|
|
||||||
int arcnet_open(struct net_device *dev);
|
int arcnet_open(struct net_device *dev);
|
||||||
int arcnet_close(struct net_device *dev);
|
int arcnet_close(struct net_device *dev);
|
||||||
|
|
|
@ -387,10 +387,44 @@ static void arcnet_timer(struct timer_list *t)
|
||||||
struct arcnet_local *lp = from_timer(lp, t, timer);
|
struct arcnet_local *lp = from_timer(lp, t, timer);
|
||||||
struct net_device *dev = lp->dev;
|
struct net_device *dev = lp->dev;
|
||||||
|
|
||||||
if (!netif_carrier_ok(dev)) {
|
spin_lock_irq(&lp->lock);
|
||||||
|
|
||||||
|
if (!lp->reset_in_progress && !netif_carrier_ok(dev)) {
|
||||||
netif_carrier_on(dev);
|
netif_carrier_on(dev);
|
||||||
netdev_info(dev, "link up\n");
|
netdev_info(dev, "link up\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irq(&lp->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_device_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct arcnet_local *lp;
|
||||||
|
struct net_device *dev;
|
||||||
|
|
||||||
|
lp = container_of(work, struct arcnet_local, reset_work);
|
||||||
|
dev = lp->dev;
|
||||||
|
|
||||||
|
/* Do not bring the network interface back up if an ifdown
|
||||||
|
* was already done.
|
||||||
|
*/
|
||||||
|
if (!netif_running(dev) || !lp->reset_in_progress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
|
|
||||||
|
/* Do another check, in case of an ifdown that was triggered in
|
||||||
|
* the small race window between the exit condition above and
|
||||||
|
* acquiring RTNL.
|
||||||
|
*/
|
||||||
|
if (!netif_running(dev) || !lp->reset_in_progress)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dev_close(dev);
|
||||||
|
dev_open(dev);
|
||||||
|
|
||||||
|
out:
|
||||||
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arcnet_reply_tasklet(unsigned long data)
|
static void arcnet_reply_tasklet(unsigned long data)
|
||||||
|
@ -452,12 +486,25 @@ struct net_device *alloc_arcdev(const char *name)
|
||||||
lp->dev = dev;
|
lp->dev = dev;
|
||||||
spin_lock_init(&lp->lock);
|
spin_lock_init(&lp->lock);
|
||||||
timer_setup(&lp->timer, arcnet_timer, 0);
|
timer_setup(&lp->timer, arcnet_timer, 0);
|
||||||
|
INIT_WORK(&lp->reset_work, reset_device_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(alloc_arcdev);
|
EXPORT_SYMBOL(alloc_arcdev);
|
||||||
|
|
||||||
|
void free_arcdev(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct arcnet_local *lp = netdev_priv(dev);
|
||||||
|
|
||||||
|
/* Do not cancel this at ->ndo_close(), as the workqueue itself
|
||||||
|
* indirectly calls the ifdown path through dev_close().
|
||||||
|
*/
|
||||||
|
cancel_work_sync(&lp->reset_work);
|
||||||
|
free_netdev(dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(free_arcdev);
|
||||||
|
|
||||||
/* Open/initialize the board. This is called sometime after booting when
|
/* Open/initialize the board. This is called sometime after booting when
|
||||||
* the 'ifconfig' program is run.
|
* the 'ifconfig' program is run.
|
||||||
*
|
*
|
||||||
|
@ -587,6 +634,10 @@ int arcnet_close(struct net_device *dev)
|
||||||
|
|
||||||
/* shut down the card */
|
/* shut down the card */
|
||||||
lp->hw.close(dev);
|
lp->hw.close(dev);
|
||||||
|
|
||||||
|
/* reset counters */
|
||||||
|
lp->reset_in_progress = 0;
|
||||||
|
|
||||||
module_put(lp->hw.owner);
|
module_put(lp->hw.owner);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -820,6 +871,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
||||||
|
|
||||||
spin_lock_irqsave(&lp->lock, flags);
|
spin_lock_irqsave(&lp->lock, flags);
|
||||||
|
|
||||||
|
if (lp->reset_in_progress)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* RESET flag was enabled - if device is not running, we must
|
/* RESET flag was enabled - if device is not running, we must
|
||||||
* clear it right away (but nothing else).
|
* clear it right away (but nothing else).
|
||||||
*/
|
*/
|
||||||
|
@ -852,11 +906,14 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
||||||
if (status & RESETflag) {
|
if (status & RESETflag) {
|
||||||
arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n",
|
arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n",
|
||||||
status);
|
status);
|
||||||
arcnet_close(dev);
|
|
||||||
arcnet_open(dev);
|
lp->reset_in_progress = 1;
|
||||||
|
netif_stop_queue(dev);
|
||||||
|
netif_carrier_off(dev);
|
||||||
|
schedule_work(&lp->reset_work);
|
||||||
|
|
||||||
/* get out of the interrupt handler! */
|
/* get out of the interrupt handler! */
|
||||||
break;
|
goto out;
|
||||||
}
|
}
|
||||||
/* RX is inhibited - we must have received something.
|
/* RX is inhibited - we must have received something.
|
||||||
* Prepare to receive into the next buffer.
|
* Prepare to receive into the next buffer.
|
||||||
|
@ -1052,6 +1109,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
||||||
udelay(1);
|
udelay(1);
|
||||||
lp->hw.intmask(dev, lp->intmask);
|
lp->hw.intmask(dev, lp->intmask);
|
||||||
|
|
||||||
|
out:
|
||||||
spin_unlock_irqrestore(&lp->lock, flags);
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ static int __init com20020_init(void)
|
||||||
dev->irq = 9;
|
dev->irq = 9;
|
||||||
|
|
||||||
if (com20020isa_probe(dev)) {
|
if (com20020isa_probe(dev)) {
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ static void __exit com20020_exit(void)
|
||||||
unregister_netdev(my_dev);
|
unregister_netdev(my_dev);
|
||||||
free_irq(my_dev->irq, my_dev);
|
free_irq(my_dev->irq, my_dev);
|
||||||
release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
|
release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
|
||||||
free_netdev(my_dev);
|
free_arcdev(my_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
|
|
|
@ -127,6 +127,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
||||||
int i, ioaddr, ret;
|
int i, ioaddr, ret;
|
||||||
struct resource *r;
|
struct resource *r;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
if (pci_enable_device(pdev))
|
if (pci_enable_device(pdev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
@ -142,6 +144,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
||||||
priv->ci = ci;
|
priv->ci = ci;
|
||||||
mm = &ci->misc_map;
|
mm = &ci->misc_map;
|
||||||
|
|
||||||
|
pci_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&priv->list_dev);
|
INIT_LIST_HEAD(&priv->list_dev);
|
||||||
|
|
||||||
if (mm->size) {
|
if (mm->size) {
|
||||||
|
@ -164,7 +168,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
||||||
dev = alloc_arcdev(device);
|
dev = alloc_arcdev(device);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_port;
|
break;
|
||||||
}
|
}
|
||||||
dev->dev_port = i;
|
dev->dev_port = i;
|
||||||
|
|
||||||
|
@ -181,7 +185,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
||||||
pr_err("IO region %xh-%xh already allocated\n",
|
pr_err("IO region %xh-%xh already allocated\n",
|
||||||
ioaddr, ioaddr + cm->size - 1);
|
ioaddr, ioaddr + cm->size - 1);
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto out_port;
|
goto err_free_arcdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dummy access after Reset
|
/* Dummy access after Reset
|
||||||
|
@ -209,76 +213,79 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
||||||
if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15))
|
if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15))
|
||||||
lp->backplane = 1;
|
lp->backplane = 1;
|
||||||
|
|
||||||
/* Get the dev_id from the PLX rotary coder */
|
if (ci->flags & ARC_HAS_ROTARY) {
|
||||||
if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
|
/* Get the dev_id from the PLX rotary coder */
|
||||||
dev_id_mask = 0x3;
|
if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
|
||||||
dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
|
dev_id_mask = 0x3;
|
||||||
|
dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
|
||||||
snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
|
snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
|
||||||
|
}
|
||||||
|
|
||||||
if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
|
if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
|
||||||
pr_err("IO address %Xh is empty!\n", ioaddr);
|
pr_err("IO address %Xh is empty!\n", ioaddr);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out_port;
|
goto err_free_arcdev;
|
||||||
}
|
}
|
||||||
if (com20020_check(dev)) {
|
if (com20020_check(dev)) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out_port;
|
goto err_free_arcdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = com20020_found(dev, IRQF_SHARED);
|
||||||
|
if (ret)
|
||||||
|
goto err_free_arcdev;
|
||||||
|
|
||||||
card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
|
card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!card) {
|
if (!card) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_port;
|
goto err_free_arcdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
card->index = i;
|
card->index = i;
|
||||||
card->pci_priv = priv;
|
card->pci_priv = priv;
|
||||||
card->tx_led.brightness_set = led_tx_set;
|
|
||||||
card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
|
|
||||||
GFP_KERNEL, "arc%d-%d-tx",
|
|
||||||
dev->dev_id, i);
|
|
||||||
card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
|
||||||
"pci:green:tx:%d-%d",
|
|
||||||
dev->dev_id, i);
|
|
||||||
|
|
||||||
card->tx_led.dev = &dev->dev;
|
if (ci->flags & ARC_HAS_LED) {
|
||||||
card->recon_led.brightness_set = led_recon_set;
|
card->tx_led.brightness_set = led_tx_set;
|
||||||
card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
|
card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
|
||||||
GFP_KERNEL, "arc%d-%d-recon",
|
GFP_KERNEL, "arc%d-%d-tx",
|
||||||
dev->dev_id, i);
|
dev->dev_id, i);
|
||||||
card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
||||||
"pci:red:recon:%d-%d",
|
"pci:green:tx:%d-%d",
|
||||||
dev->dev_id, i);
|
dev->dev_id, i);
|
||||||
card->recon_led.dev = &dev->dev;
|
|
||||||
|
card->tx_led.dev = &dev->dev;
|
||||||
|
card->recon_led.brightness_set = led_recon_set;
|
||||||
|
card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
|
||||||
|
GFP_KERNEL, "arc%d-%d-recon",
|
||||||
|
dev->dev_id, i);
|
||||||
|
card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
||||||
|
"pci:red:recon:%d-%d",
|
||||||
|
dev->dev_id, i);
|
||||||
|
card->recon_led.dev = &dev->dev;
|
||||||
|
|
||||||
|
ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
|
||||||
|
if (ret)
|
||||||
|
goto err_free_arcdev;
|
||||||
|
|
||||||
|
ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
|
||||||
|
if (ret)
|
||||||
|
goto err_free_arcdev;
|
||||||
|
|
||||||
|
dev_set_drvdata(&dev->dev, card);
|
||||||
|
devm_arcnet_led_init(dev, dev->dev_id, i);
|
||||||
|
}
|
||||||
|
|
||||||
card->dev = dev;
|
card->dev = dev;
|
||||||
|
|
||||||
ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
|
|
||||||
if (ret)
|
|
||||||
goto out_port;
|
|
||||||
|
|
||||||
ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
|
|
||||||
if (ret)
|
|
||||||
goto out_port;
|
|
||||||
|
|
||||||
dev_set_drvdata(&dev->dev, card);
|
|
||||||
|
|
||||||
ret = com20020_found(dev, IRQF_SHARED);
|
|
||||||
if (ret)
|
|
||||||
goto out_port;
|
|
||||||
|
|
||||||
devm_arcnet_led_init(dev, dev->dev_id, i);
|
|
||||||
|
|
||||||
list_add(&card->list, &priv->list_dev);
|
list_add(&card->list, &priv->list_dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
err_free_arcdev:
|
||||||
|
free_arcdev(dev);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (ret)
|
||||||
pci_set_drvdata(pdev, priv);
|
com20020pci_remove(pdev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_port:
|
|
||||||
com20020pci_remove(pdev);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +301,7 @@ static void com20020pci_remove(struct pci_dev *pdev)
|
||||||
|
|
||||||
unregister_netdev(dev);
|
unregister_netdev(dev);
|
||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +332,7 @@ static struct com20020_pci_card_info card_info_5mbit = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct com20020_pci_card_info card_info_sohard = {
|
static struct com20020_pci_card_info card_info_sohard = {
|
||||||
.name = "PLX-PCI",
|
.name = "SOHARD SH ARC-PCI",
|
||||||
.devcount = 1,
|
.devcount = 1,
|
||||||
/* SOHARD needs PCI base addr 4 */
|
/* SOHARD needs PCI base addr 4 */
|
||||||
.chan_map_tbl = {
|
.chan_map_tbl = {
|
||||||
|
@ -360,7 +367,7 @@ static struct com20020_pci_card_info card_info_eae_arc1 = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.rotary = 0x0,
|
.rotary = 0x0,
|
||||||
.flags = ARC_CAN_10MBIT,
|
.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct com20020_pci_card_info card_info_eae_ma1 = {
|
static struct com20020_pci_card_info card_info_eae_ma1 = {
|
||||||
|
@ -392,7 +399,7 @@ static struct com20020_pci_card_info card_info_eae_ma1 = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.rotary = 0x0,
|
.rotary = 0x0,
|
||||||
.flags = ARC_CAN_10MBIT,
|
.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct com20020_pci_card_info card_info_eae_fb2 = {
|
static struct com20020_pci_card_info card_info_eae_fb2 = {
|
||||||
|
@ -417,7 +424,7 @@ static struct com20020_pci_card_info card_info_eae_fb2 = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.rotary = 0x0,
|
.rotary = 0x0,
|
||||||
.flags = ARC_CAN_10MBIT,
|
.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pci_device_id com20020pci_id_table[] = {
|
static const struct pci_device_id com20020pci_id_table[] = {
|
||||||
|
|
|
@ -177,7 +177,7 @@ static void com20020_detach(struct pcmcia_device *link)
|
||||||
dev = info->dev;
|
dev = info->dev;
|
||||||
if (dev) {
|
if (dev) {
|
||||||
dev_dbg(&link->dev, "kfree...\n");
|
dev_dbg(&link->dev, "kfree...\n");
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
}
|
}
|
||||||
dev_dbg(&link->dev, "kfree2...\n");
|
dev_dbg(&link->dev, "kfree2...\n");
|
||||||
kfree(info);
|
kfree(info);
|
||||||
|
|
|
@ -394,7 +394,7 @@ static int __init com90io_init(void)
|
||||||
err = com90io_probe(dev);
|
err = com90io_probe(dev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ static void __exit com90io_exit(void)
|
||||||
|
|
||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
|
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(com90io_init)
|
module_init(com90io_init)
|
||||||
|
|
|
@ -554,7 +554,7 @@ err_free_irq:
|
||||||
err_release_mem:
|
err_release_mem:
|
||||||
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
|
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
|
||||||
err_free_dev:
|
err_free_dev:
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,7 +672,7 @@ static void __exit com90xx_exit(void)
|
||||||
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
|
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
|
||||||
release_mem_region(dev->mem_start,
|
release_mem_region(dev->mem_start,
|
||||||
dev->mem_end - dev->mem_start + 1);
|
dev->mem_end - dev->mem_start + 1);
|
||||||
free_netdev(dev);
|
free_arcdev(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6859,7 +6859,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
|
||||||
desc_idx, *post_ptr);
|
desc_idx, *post_ptr);
|
||||||
drop_it_no_recycle:
|
drop_it_no_recycle:
|
||||||
/* Other statistics kept track of by card. */
|
/* Other statistics kept track of by card. */
|
||||||
tp->rx_dropped++;
|
tnapi->rx_dropped++;
|
||||||
goto next_pkt;
|
goto next_pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7889,8 +7889,10 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
|
||||||
|
|
||||||
segs = skb_gso_segment(skb, tp->dev->features &
|
segs = skb_gso_segment(skb, tp->dev->features &
|
||||||
~(NETIF_F_TSO | NETIF_F_TSO6));
|
~(NETIF_F_TSO | NETIF_F_TSO6));
|
||||||
if (IS_ERR(segs) || !segs)
|
if (IS_ERR(segs) || !segs) {
|
||||||
|
tnapi->tx_dropped++;
|
||||||
goto tg3_tso_bug_end;
|
goto tg3_tso_bug_end;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
nskb = segs;
|
nskb = segs;
|
||||||
|
@ -8163,7 +8165,7 @@ dma_error:
|
||||||
drop:
|
drop:
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
drop_nofree:
|
drop_nofree:
|
||||||
tp->tx_dropped++;
|
tnapi->tx_dropped++;
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9342,7 +9344,7 @@ static void __tg3_set_rx_mode(struct net_device *);
|
||||||
/* tp->lock is held. */
|
/* tp->lock is held. */
|
||||||
static int tg3_halt(struct tg3 *tp, int kind, bool silent)
|
static int tg3_halt(struct tg3 *tp, int kind, bool silent)
|
||||||
{
|
{
|
||||||
int err;
|
int err, i;
|
||||||
|
|
||||||
tg3_stop_fw(tp);
|
tg3_stop_fw(tp);
|
||||||
|
|
||||||
|
@ -9363,6 +9365,13 @@ static int tg3_halt(struct tg3 *tp, int kind, bool silent)
|
||||||
|
|
||||||
/* And make sure the next sample is new data */
|
/* And make sure the next sample is new data */
|
||||||
memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
|
memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
|
||||||
|
|
||||||
|
for (i = 0; i < TG3_IRQ_MAX_VECS; ++i) {
|
||||||
|
struct tg3_napi *tnapi = &tp->napi[i];
|
||||||
|
|
||||||
|
tnapi->rx_dropped = 0;
|
||||||
|
tnapi->tx_dropped = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -11919,6 +11928,9 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats)
|
||||||
{
|
{
|
||||||
struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev;
|
struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev;
|
||||||
struct tg3_hw_stats *hw_stats = tp->hw_stats;
|
struct tg3_hw_stats *hw_stats = tp->hw_stats;
|
||||||
|
unsigned long rx_dropped;
|
||||||
|
unsigned long tx_dropped;
|
||||||
|
int i;
|
||||||
|
|
||||||
stats->rx_packets = old_stats->rx_packets +
|
stats->rx_packets = old_stats->rx_packets +
|
||||||
get_stat64(&hw_stats->rx_ucast_packets) +
|
get_stat64(&hw_stats->rx_ucast_packets) +
|
||||||
|
@ -11965,8 +11977,26 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats)
|
||||||
stats->rx_missed_errors = old_stats->rx_missed_errors +
|
stats->rx_missed_errors = old_stats->rx_missed_errors +
|
||||||
get_stat64(&hw_stats->rx_discards);
|
get_stat64(&hw_stats->rx_discards);
|
||||||
|
|
||||||
stats->rx_dropped = tp->rx_dropped;
|
/* Aggregate per-queue counters. The per-queue counters are updated
|
||||||
stats->tx_dropped = tp->tx_dropped;
|
* by a single writer, race-free. The result computed by this loop
|
||||||
|
* might not be 100% accurate (counters can be updated in the middle of
|
||||||
|
* the loop) but the next tg3_get_nstats() will recompute the current
|
||||||
|
* value so it is acceptable.
|
||||||
|
*
|
||||||
|
* Note that these counters wrap around at 4G on 32bit machines.
|
||||||
|
*/
|
||||||
|
rx_dropped = (unsigned long)(old_stats->rx_dropped);
|
||||||
|
tx_dropped = (unsigned long)(old_stats->tx_dropped);
|
||||||
|
|
||||||
|
for (i = 0; i < tp->irq_cnt; i++) {
|
||||||
|
struct tg3_napi *tnapi = &tp->napi[i];
|
||||||
|
|
||||||
|
rx_dropped += tnapi->rx_dropped;
|
||||||
|
tx_dropped += tnapi->tx_dropped;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats->rx_dropped = rx_dropped;
|
||||||
|
stats->tx_dropped = tx_dropped;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tg3_get_regs_len(struct net_device *dev)
|
static int tg3_get_regs_len(struct net_device *dev)
|
||||||
|
|
|
@ -3018,6 +3018,7 @@ struct tg3_napi {
|
||||||
u16 *rx_rcb_prod_idx;
|
u16 *rx_rcb_prod_idx;
|
||||||
struct tg3_rx_prodring_set prodring;
|
struct tg3_rx_prodring_set prodring;
|
||||||
struct tg3_rx_buffer_desc *rx_rcb;
|
struct tg3_rx_buffer_desc *rx_rcb;
|
||||||
|
unsigned long rx_dropped;
|
||||||
|
|
||||||
u32 tx_prod ____cacheline_aligned;
|
u32 tx_prod ____cacheline_aligned;
|
||||||
u32 tx_cons;
|
u32 tx_cons;
|
||||||
|
@ -3026,6 +3027,7 @@ struct tg3_napi {
|
||||||
u32 prodmbox;
|
u32 prodmbox;
|
||||||
struct tg3_tx_buffer_desc *tx_ring;
|
struct tg3_tx_buffer_desc *tx_ring;
|
||||||
struct tg3_tx_ring_info *tx_buffers;
|
struct tg3_tx_ring_info *tx_buffers;
|
||||||
|
unsigned long tx_dropped;
|
||||||
|
|
||||||
dma_addr_t status_mapping;
|
dma_addr_t status_mapping;
|
||||||
dma_addr_t rx_rcb_mapping;
|
dma_addr_t rx_rcb_mapping;
|
||||||
|
@ -3219,8 +3221,6 @@ struct tg3 {
|
||||||
|
|
||||||
|
|
||||||
/* begin "everything else" cacheline(s) section */
|
/* begin "everything else" cacheline(s) section */
|
||||||
unsigned long rx_dropped;
|
|
||||||
unsigned long tx_dropped;
|
|
||||||
struct rtnl_link_stats64 net_stats_prev;
|
struct rtnl_link_stats64 net_stats_prev;
|
||||||
struct tg3_ethtool_stats estats_prev;
|
struct tg3_ethtool_stats estats_prev;
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,27 @@ static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 hns_mac_link_anti_shake(struct mac_driver *mac_ctrl_drv)
|
||||||
|
{
|
||||||
|
#define HNS_MAC_LINK_WAIT_TIME 5
|
||||||
|
#define HNS_MAC_LINK_WAIT_CNT 40
|
||||||
|
|
||||||
|
u32 link_status = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!mac_ctrl_drv->get_link_status)
|
||||||
|
return link_status;
|
||||||
|
|
||||||
|
for (i = 0; i < HNS_MAC_LINK_WAIT_CNT; i++) {
|
||||||
|
msleep(HNS_MAC_LINK_WAIT_TIME);
|
||||||
|
mac_ctrl_drv->get_link_status(mac_ctrl_drv, &link_status);
|
||||||
|
if (!link_status)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return link_status;
|
||||||
|
}
|
||||||
|
|
||||||
void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
|
void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
|
||||||
{
|
{
|
||||||
struct mac_driver *mac_ctrl_drv;
|
struct mac_driver *mac_ctrl_drv;
|
||||||
|
@ -87,6 +108,14 @@ void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
|
||||||
&sfp_prsnt);
|
&sfp_prsnt);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
*link_status = *link_status && sfp_prsnt;
|
*link_status = *link_status && sfp_prsnt;
|
||||||
|
|
||||||
|
/* for FIBER port, it may have a fake link up.
|
||||||
|
* when the link status changes from down to up, we need to do
|
||||||
|
* anti-shake. the anti-shake time is base on tests.
|
||||||
|
* only FIBER port need to do this.
|
||||||
|
*/
|
||||||
|
if (*link_status && !mac_cb->link)
|
||||||
|
*link_status = hns_mac_link_anti_shake(mac_ctrl_drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
mac_cb->link = *link_status;
|
mac_cb->link = *link_status;
|
||||||
|
|
|
@ -2,5 +2,6 @@ config HYPERV_NET
|
||||||
tristate "Microsoft Hyper-V virtual network driver"
|
tristate "Microsoft Hyper-V virtual network driver"
|
||||||
depends on HYPERV
|
depends on HYPERV
|
||||||
select UCS2_STRING
|
select UCS2_STRING
|
||||||
|
select NLS
|
||||||
help
|
help
|
||||||
Select this option to enable the Hyper-V virtual network driver.
|
Select this option to enable the Hyper-V virtual network driver.
|
||||||
|
|
|
@ -2647,6 +2647,8 @@ enum parport_pc_pci_cards {
|
||||||
netmos_9865,
|
netmos_9865,
|
||||||
quatech_sppxp100,
|
quatech_sppxp100,
|
||||||
wch_ch382l,
|
wch_ch382l,
|
||||||
|
brainboxes_uc146,
|
||||||
|
brainboxes_px203,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2710,6 +2712,8 @@ static struct parport_pc_pci {
|
||||||
/* netmos_9865 */ { 1, { { 0, -1 }, } },
|
/* netmos_9865 */ { 1, { { 0, -1 }, } },
|
||||||
/* quatech_sppxp100 */ { 1, { { 0, 1 }, } },
|
/* quatech_sppxp100 */ { 1, { { 0, 1 }, } },
|
||||||
/* wch_ch382l */ { 1, { { 2, -1 }, } },
|
/* wch_ch382l */ { 1, { { 2, -1 }, } },
|
||||||
|
/* brainboxes_uc146 */ { 1, { { 3, -1 }, } },
|
||||||
|
/* brainboxes_px203 */ { 1, { { 0, -1 }, } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pci_device_id parport_pc_pci_tbl[] = {
|
static const struct pci_device_id parport_pc_pci_tbl[] = {
|
||||||
|
@ -2801,6 +2805,23 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
|
||||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
|
||||||
/* WCH CH382L PCI-E single parallel port card */
|
/* WCH CH382L PCI-E single parallel port card */
|
||||||
{ 0x1c00, 0x3050, 0x1c00, 0x3050, 0, 0, wch_ch382l },
|
{ 0x1c00, 0x3050, 0x1c00, 0x3050, 0, 0, wch_ch382l },
|
||||||
|
/* Brainboxes IX-500/550 */
|
||||||
|
{ PCI_VENDOR_ID_INTASHIELD, 0x402a,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
|
||||||
|
/* Brainboxes UC-146/UC-157 */
|
||||||
|
{ PCI_VENDOR_ID_INTASHIELD, 0x0be1,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc146 },
|
||||||
|
{ PCI_VENDOR_ID_INTASHIELD, 0x0be2,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc146 },
|
||||||
|
/* Brainboxes PX-146/PX-257 */
|
||||||
|
{ PCI_VENDOR_ID_INTASHIELD, 0x401c,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
|
||||||
|
/* Brainboxes PX-203 */
|
||||||
|
{ PCI_VENDOR_ID_INTASHIELD, 0x4007,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_px203 },
|
||||||
|
/* Brainboxes PX-475 */
|
||||||
|
{ PCI_VENDOR_ID_INTASHIELD, 0x401f,
|
||||||
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
|
||||||
{ 0, } /* terminate list */
|
{ 0, } /* terminate list */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, parport_pc_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, parport_pc_pci_tbl);
|
||||||
|
|
|
@ -2713,6 +2713,7 @@ init_wrb_hndl_failed:
|
||||||
kfree(pwrb_context->pwrb_handle_base);
|
kfree(pwrb_context->pwrb_handle_base);
|
||||||
kfree(pwrb_context->pwrb_handle_basestd);
|
kfree(pwrb_context->pwrb_handle_basestd);
|
||||||
}
|
}
|
||||||
|
kfree(phwi_ctxt->be_wrbq);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,10 +59,12 @@ struct spi_imx_data;
|
||||||
|
|
||||||
struct spi_imx_devtype_data {
|
struct spi_imx_devtype_data {
|
||||||
void (*intctrl)(struct spi_imx_data *, int);
|
void (*intctrl)(struct spi_imx_data *, int);
|
||||||
|
int (*prepare_message)(struct spi_imx_data *, struct spi_message *);
|
||||||
int (*config)(struct spi_device *);
|
int (*config)(struct spi_device *);
|
||||||
void (*trigger)(struct spi_imx_data *);
|
void (*trigger)(struct spi_imx_data *);
|
||||||
int (*rx_available)(struct spi_imx_data *);
|
int (*rx_available)(struct spi_imx_data *);
|
||||||
void (*reset)(struct spi_imx_data *);
|
void (*reset)(struct spi_imx_data *);
|
||||||
|
void (*setup_wml)(struct spi_imx_data *);
|
||||||
void (*disable)(struct spi_imx_data *);
|
void (*disable)(struct spi_imx_data *);
|
||||||
bool has_dmamode;
|
bool has_dmamode;
|
||||||
bool has_slavemode;
|
bool has_slavemode;
|
||||||
|
@ -216,7 +218,6 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
|
||||||
struct spi_transfer *transfer)
|
struct spi_transfer *transfer)
|
||||||
{
|
{
|
||||||
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
|
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
|
||||||
unsigned int bytes_per_word, i;
|
|
||||||
|
|
||||||
if (!master->dma_rx)
|
if (!master->dma_rx)
|
||||||
return false;
|
return false;
|
||||||
|
@ -224,14 +225,6 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
|
||||||
if (spi_imx->slave_mode)
|
if (spi_imx->slave_mode)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word);
|
|
||||||
|
|
||||||
for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) {
|
|
||||||
if (!(transfer->len % (i * bytes_per_word)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_imx->wml = i;
|
|
||||||
spi_imx->dynamic_burst = 0;
|
spi_imx->dynamic_burst = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -502,11 +495,12 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
|
||||||
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
|
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mx51_ecspi_config(struct spi_device *spi)
|
static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
|
||||||
|
struct spi_message *msg)
|
||||||
{
|
{
|
||||||
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
struct spi_device *spi = msg->spi;
|
||||||
u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
|
u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
|
||||||
u32 clk = spi_imx->speed_hz, delay, reg;
|
u32 testreg;
|
||||||
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
|
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
|
||||||
|
|
||||||
/* set Master or Slave mode */
|
/* set Master or Slave mode */
|
||||||
|
@ -521,19 +515,21 @@ static int mx51_ecspi_config(struct spi_device *spi)
|
||||||
if (spi->mode & SPI_READY)
|
if (spi->mode & SPI_READY)
|
||||||
ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
|
ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
|
||||||
|
|
||||||
/* set clock speed */
|
|
||||||
ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk);
|
|
||||||
spi_imx->spi_bus_clk = clk;
|
|
||||||
|
|
||||||
/* set chip select to use */
|
/* set chip select to use */
|
||||||
ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
|
ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
|
||||||
|
|
||||||
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
|
/*
|
||||||
ctrl |= (spi_imx->slave_burst * 8 - 1)
|
* The ctrl register must be written first, with the EN bit set other
|
||||||
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
* registers must not be written to.
|
||||||
|
*/
|
||||||
|
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
|
||||||
|
|
||||||
|
testreg = readl(spi_imx->base + MX51_ECSPI_TESTREG);
|
||||||
|
if (spi->mode & SPI_LOOP)
|
||||||
|
testreg |= MX51_ECSPI_TESTREG_LBC;
|
||||||
else
|
else
|
||||||
ctrl |= (spi_imx->bits_per_word - 1)
|
testreg &= ~MX51_ECSPI_TESTREG_LBC;
|
||||||
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* eCSPI burst completion by Chip Select signal in Slave mode
|
* eCSPI burst completion by Chip Select signal in Slave mode
|
||||||
|
@ -557,26 +553,43 @@ static int mx51_ecspi_config(struct spi_device *spi)
|
||||||
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select);
|
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select);
|
||||||
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select);
|
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spi->mode & SPI_CS_HIGH)
|
if (spi->mode & SPI_CS_HIGH)
|
||||||
cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
|
cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
|
||||||
else
|
else
|
||||||
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
|
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
|
||||||
|
|
||||||
|
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mx51_ecspi_config(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
||||||
|
u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
|
||||||
|
u32 clk = spi_imx->speed_hz, delay;
|
||||||
|
|
||||||
|
/* Clear BL field and set the right value */
|
||||||
|
ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
|
||||||
|
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
|
||||||
|
ctrl |= (spi_imx->slave_burst * 8 - 1)
|
||||||
|
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
||||||
|
else
|
||||||
|
ctrl |= (spi_imx->bits_per_word - 1)
|
||||||
|
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
||||||
|
|
||||||
|
/* set clock speed */
|
||||||
|
ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET |
|
||||||
|
0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET);
|
||||||
|
ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk);
|
||||||
|
spi_imx->spi_bus_clk = clk;
|
||||||
|
|
||||||
if (spi_imx->usedma)
|
if (spi_imx->usedma)
|
||||||
ctrl |= MX51_ECSPI_CTRL_SMC;
|
ctrl |= MX51_ECSPI_CTRL_SMC;
|
||||||
|
|
||||||
/* CTRL register always go first to bring out controller from reset */
|
|
||||||
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
|
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
|
||||||
|
|
||||||
reg = readl(spi_imx->base + MX51_ECSPI_TESTREG);
|
|
||||||
if (spi->mode & SPI_LOOP)
|
|
||||||
reg |= MX51_ECSPI_TESTREG_LBC;
|
|
||||||
else
|
|
||||||
reg &= ~MX51_ECSPI_TESTREG_LBC;
|
|
||||||
writel(reg, spi_imx->base + MX51_ECSPI_TESTREG);
|
|
||||||
|
|
||||||
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait until the changes in the configuration register CONFIGREG
|
* Wait until the changes in the configuration register CONFIGREG
|
||||||
* propagate into the hardware. It takes exactly one tick of the
|
* propagate into the hardware. It takes exactly one tick of the
|
||||||
|
@ -594,18 +607,20 @@ static int mx51_ecspi_config(struct spi_device *spi)
|
||||||
else /* SCLK is _very_ slow */
|
else /* SCLK is _very_ slow */
|
||||||
usleep_range(delay, delay + 10);
|
usleep_range(delay, delay + 10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mx51_setup_wml(struct spi_imx_data *spi_imx)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Configure the DMA register: setup the watermark
|
* Configure the DMA register: setup the watermark
|
||||||
* and enable DMA request.
|
* and enable DMA request.
|
||||||
*/
|
*/
|
||||||
|
writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) |
|
||||||
writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) |
|
|
||||||
MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
|
MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
|
||||||
MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
|
MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
|
||||||
MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
|
MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
|
||||||
MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
|
MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
|
static int mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
|
||||||
|
@ -672,6 +687,12 @@ static void mx31_trigger(struct spi_imx_data *spi_imx)
|
||||||
writel(reg, spi_imx->base + MXC_CSPICTRL);
|
writel(reg, spi_imx->base + MXC_CSPICTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mx31_prepare_message(struct spi_imx_data *spi_imx,
|
||||||
|
struct spi_message *msg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mx31_config(struct spi_device *spi)
|
static int mx31_config(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
||||||
|
@ -768,6 +789,12 @@ static void mx21_trigger(struct spi_imx_data *spi_imx)
|
||||||
writel(reg, spi_imx->base + MXC_CSPICTRL);
|
writel(reg, spi_imx->base + MXC_CSPICTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mx21_prepare_message(struct spi_imx_data *spi_imx,
|
||||||
|
struct spi_message *msg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mx21_config(struct spi_device *spi)
|
static int mx21_config(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
||||||
|
@ -837,6 +864,12 @@ static void mx1_trigger(struct spi_imx_data *spi_imx)
|
||||||
writel(reg, spi_imx->base + MXC_CSPICTRL);
|
writel(reg, spi_imx->base + MXC_CSPICTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mx1_prepare_message(struct spi_imx_data *spi_imx,
|
||||||
|
struct spi_message *msg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mx1_config(struct spi_device *spi)
|
static int mx1_config(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
||||||
|
@ -871,6 +904,7 @@ static void mx1_reset(struct spi_imx_data *spi_imx)
|
||||||
|
|
||||||
static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
|
static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
|
||||||
.intctrl = mx1_intctrl,
|
.intctrl = mx1_intctrl,
|
||||||
|
.prepare_message = mx1_prepare_message,
|
||||||
.config = mx1_config,
|
.config = mx1_config,
|
||||||
.trigger = mx1_trigger,
|
.trigger = mx1_trigger,
|
||||||
.rx_available = mx1_rx_available,
|
.rx_available = mx1_rx_available,
|
||||||
|
@ -884,6 +918,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
|
||||||
|
|
||||||
static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
|
static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
|
||||||
.intctrl = mx21_intctrl,
|
.intctrl = mx21_intctrl,
|
||||||
|
.prepare_message = mx21_prepare_message,
|
||||||
.config = mx21_config,
|
.config = mx21_config,
|
||||||
.trigger = mx21_trigger,
|
.trigger = mx21_trigger,
|
||||||
.rx_available = mx21_rx_available,
|
.rx_available = mx21_rx_available,
|
||||||
|
@ -898,6 +933,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
|
||||||
static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
|
static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
|
||||||
/* i.mx27 cspi shares the functions with i.mx21 one */
|
/* i.mx27 cspi shares the functions with i.mx21 one */
|
||||||
.intctrl = mx21_intctrl,
|
.intctrl = mx21_intctrl,
|
||||||
|
.prepare_message = mx21_prepare_message,
|
||||||
.config = mx21_config,
|
.config = mx21_config,
|
||||||
.trigger = mx21_trigger,
|
.trigger = mx21_trigger,
|
||||||
.rx_available = mx21_rx_available,
|
.rx_available = mx21_rx_available,
|
||||||
|
@ -911,6 +947,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
|
||||||
|
|
||||||
static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
|
static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
|
||||||
.intctrl = mx31_intctrl,
|
.intctrl = mx31_intctrl,
|
||||||
|
.prepare_message = mx31_prepare_message,
|
||||||
.config = mx31_config,
|
.config = mx31_config,
|
||||||
.trigger = mx31_trigger,
|
.trigger = mx31_trigger,
|
||||||
.rx_available = mx31_rx_available,
|
.rx_available = mx31_rx_available,
|
||||||
|
@ -925,6 +962,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
|
||||||
static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
|
static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
|
||||||
/* i.mx35 and later cspi shares the functions with i.mx31 one */
|
/* i.mx35 and later cspi shares the functions with i.mx31 one */
|
||||||
.intctrl = mx31_intctrl,
|
.intctrl = mx31_intctrl,
|
||||||
|
.prepare_message = mx31_prepare_message,
|
||||||
.config = mx31_config,
|
.config = mx31_config,
|
||||||
.trigger = mx31_trigger,
|
.trigger = mx31_trigger,
|
||||||
.rx_available = mx31_rx_available,
|
.rx_available = mx31_rx_available,
|
||||||
|
@ -938,10 +976,12 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
|
||||||
|
|
||||||
static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
|
static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
|
||||||
.intctrl = mx51_ecspi_intctrl,
|
.intctrl = mx51_ecspi_intctrl,
|
||||||
|
.prepare_message = mx51_ecspi_prepare_message,
|
||||||
.config = mx51_ecspi_config,
|
.config = mx51_ecspi_config,
|
||||||
.trigger = mx51_ecspi_trigger,
|
.trigger = mx51_ecspi_trigger,
|
||||||
.rx_available = mx51_ecspi_rx_available,
|
.rx_available = mx51_ecspi_rx_available,
|
||||||
.reset = mx51_ecspi_reset,
|
.reset = mx51_ecspi_reset,
|
||||||
|
.setup_wml = mx51_setup_wml,
|
||||||
.fifo_size = 64,
|
.fifo_size = 64,
|
||||||
.has_dmamode = true,
|
.has_dmamode = true,
|
||||||
.dynamic_burst = true,
|
.dynamic_burst = true,
|
||||||
|
@ -952,6 +992,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
|
||||||
|
|
||||||
static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
|
static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
|
||||||
.intctrl = mx51_ecspi_intctrl,
|
.intctrl = mx51_ecspi_intctrl,
|
||||||
|
.prepare_message = mx51_ecspi_prepare_message,
|
||||||
.config = mx51_ecspi_config,
|
.config = mx51_ecspi_config,
|
||||||
.trigger = mx51_ecspi_trigger,
|
.trigger = mx51_ecspi_trigger,
|
||||||
.rx_available = mx51_ecspi_rx_available,
|
.rx_available = mx51_ecspi_rx_available,
|
||||||
|
@ -1149,7 +1190,6 @@ static int spi_imx_setupxfer(struct spi_device *spi,
|
||||||
struct spi_transfer *t)
|
struct spi_transfer *t)
|
||||||
{
|
{
|
||||||
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1190,12 +1230,6 @@ static int spi_imx_setupxfer(struct spi_device *spi,
|
||||||
else
|
else
|
||||||
spi_imx->usedma = 0;
|
spi_imx->usedma = 0;
|
||||||
|
|
||||||
if (spi_imx->usedma) {
|
|
||||||
ret = spi_imx_dma_configure(spi->master);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
|
if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
|
||||||
spi_imx->rx = mx53_ecspi_rx_slave;
|
spi_imx->rx = mx53_ecspi_rx_slave;
|
||||||
spi_imx->tx = mx53_ecspi_tx_slave;
|
spi_imx->tx = mx53_ecspi_tx_slave;
|
||||||
|
@ -1300,6 +1334,31 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
struct spi_master *master = spi_imx->bitbang.master;
|
struct spi_master *master = spi_imx->bitbang.master;
|
||||||
struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
|
struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
|
||||||
|
struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents);
|
||||||
|
unsigned int bytes_per_word, i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Get the right burst length from the last sg to ensure no tail data */
|
||||||
|
bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word);
|
||||||
|
for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) {
|
||||||
|
if (!(sg_dma_len(last_sg) % (i * bytes_per_word)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Use 1 as wml in case no available burst length got */
|
||||||
|
if (i == 0)
|
||||||
|
i = 1;
|
||||||
|
|
||||||
|
spi_imx->wml = i;
|
||||||
|
|
||||||
|
ret = spi_imx_dma_configure(master);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!spi_imx->devtype_data->setup_wml) {
|
||||||
|
dev_err(spi_imx->dev, "No setup_wml()?\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
spi_imx->devtype_data->setup_wml(spi_imx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The TX DMA setup starts the transfer, so make sure RX is configured
|
* The TX DMA setup starts the transfer, so make sure RX is configured
|
||||||
|
@ -1486,7 +1545,13 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret = spi_imx->devtype_data->prepare_message(spi_imx, msg);
|
||||||
|
if (ret) {
|
||||||
|
clk_disable(spi_imx->clk_ipg);
|
||||||
|
clk_disable(spi_imx->clk_per);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -176,6 +176,7 @@ static int __init early_omap8250_setup(struct earlycon_device *device,
|
||||||
OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup);
|
OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup);
|
||||||
OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
|
OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
|
||||||
OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
|
OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
|
||||||
|
OF_EARLYCON_DECLARE(omap8250, "ti,am654-uart", early_omap8250_setup);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -694,6 +694,18 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
|
||||||
case SC16IS7XX_IIR_RTOI_SRC:
|
case SC16IS7XX_IIR_RTOI_SRC:
|
||||||
case SC16IS7XX_IIR_XOFFI_SRC:
|
case SC16IS7XX_IIR_XOFFI_SRC:
|
||||||
rxlen = sc16is7xx_port_read(port, SC16IS7XX_RXLVL_REG);
|
rxlen = sc16is7xx_port_read(port, SC16IS7XX_RXLVL_REG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is a silicon bug that makes the chip report a
|
||||||
|
* time-out interrupt but no data in the FIFO. This is
|
||||||
|
* described in errata section 18.1.4.
|
||||||
|
*
|
||||||
|
* When this happens, read one byte from the FIFO to
|
||||||
|
* clear the interrupt.
|
||||||
|
*/
|
||||||
|
if (iir == SC16IS7XX_IIR_RTOI_SRC && !rxlen)
|
||||||
|
rxlen = 1;
|
||||||
|
|
||||||
if (rxlen)
|
if (rxlen)
|
||||||
sc16is7xx_handle_rx(port, rxlen, iir);
|
sc16is7xx_handle_rx(port, rxlen, iir);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -88,6 +88,7 @@ static void hidg_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct f_hidg *hidg = container_of(dev, struct f_hidg, dev);
|
struct f_hidg *hidg = container_of(dev, struct f_hidg, dev);
|
||||||
|
|
||||||
|
kfree(hidg->report_desc);
|
||||||
kfree(hidg->set_report_buf);
|
kfree(hidg->set_report_buf);
|
||||||
kfree(hidg);
|
kfree(hidg);
|
||||||
}
|
}
|
||||||
|
@ -1293,9 +1294,9 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi)
|
||||||
hidg->report_length = opts->report_length;
|
hidg->report_length = opts->report_length;
|
||||||
hidg->report_desc_length = opts->report_desc_length;
|
hidg->report_desc_length = opts->report_desc_length;
|
||||||
if (opts->report_desc) {
|
if (opts->report_desc) {
|
||||||
hidg->report_desc = devm_kmemdup(&hidg->dev, opts->report_desc,
|
hidg->report_desc = kmemdup(opts->report_desc,
|
||||||
opts->report_desc_length,
|
opts->report_desc_length,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!hidg->report_desc) {
|
if (!hidg->report_desc) {
|
||||||
put_device(&hidg->dev);
|
put_device(&hidg->dev);
|
||||||
--opts->refcnt;
|
--opts->refcnt;
|
||||||
|
|
|
@ -193,7 +193,7 @@ static void typec_altmode_put_partner(struct altmode *altmode)
|
||||||
if (!partner)
|
if (!partner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
adev = &partner->adev;
|
adev = &altmode->adev;
|
||||||
|
|
||||||
if (is_typec_plug(adev->dev.parent)) {
|
if (is_typec_plug(adev->dev.parent)) {
|
||||||
struct typec_plug *plug = to_typec_plug(adev->dev.parent);
|
struct typec_plug *plug = to_typec_plug(adev->dev.parent);
|
||||||
|
@ -477,7 +477,8 @@ static void typec_altmode_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct altmode *alt = to_altmode(to_typec_altmode(dev));
|
struct altmode *alt = to_altmode(to_typec_altmode(dev));
|
||||||
|
|
||||||
typec_altmode_put_partner(alt);
|
if (!is_typec_port(dev->parent))
|
||||||
|
typec_altmode_put_partner(alt);
|
||||||
|
|
||||||
altmode_id_remove(alt->adev.dev.parent, alt->id);
|
altmode_id_remove(alt->adev.dev.parent, alt->id);
|
||||||
kfree(alt);
|
kfree(alt);
|
||||||
|
|
|
@ -504,15 +504,38 @@ int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum)
|
||||||
|
|
||||||
down_write(&NILFS_MDT(sufile)->mi_sem);
|
down_write(&NILFS_MDT(sufile)->mi_sem);
|
||||||
ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh);
|
ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh);
|
||||||
if (!ret) {
|
if (ret)
|
||||||
mark_buffer_dirty(bh);
|
goto out_sem;
|
||||||
nilfs_mdt_mark_dirty(sufile);
|
|
||||||
kaddr = kmap_atomic(bh->b_page);
|
kaddr = kmap_atomic(bh->b_page);
|
||||||
su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
|
su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
|
||||||
nilfs_segment_usage_set_dirty(su);
|
if (unlikely(nilfs_segment_usage_error(su))) {
|
||||||
|
struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
|
||||||
|
|
||||||
kunmap_atomic(kaddr);
|
kunmap_atomic(kaddr);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
if (nilfs_segment_is_active(nilfs, segnum)) {
|
||||||
|
nilfs_error(sufile->i_sb,
|
||||||
|
"active segment %llu is erroneous",
|
||||||
|
(unsigned long long)segnum);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Segments marked erroneous are never allocated by
|
||||||
|
* nilfs_sufile_alloc(); only active segments, ie,
|
||||||
|
* the segments indexed by ns_segnum or ns_nextnum,
|
||||||
|
* can be erroneous here.
|
||||||
|
*/
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
}
|
||||||
|
ret = -EIO;
|
||||||
|
} else {
|
||||||
|
nilfs_segment_usage_set_dirty(su);
|
||||||
|
kunmap_atomic(kaddr);
|
||||||
|
mark_buffer_dirty(bh);
|
||||||
|
nilfs_mdt_mark_dirty(sufile);
|
||||||
|
brelse(bh);
|
||||||
}
|
}
|
||||||
|
out_sem:
|
||||||
up_write(&NILFS_MDT(sufile)->mi_sem);
|
up_write(&NILFS_MDT(sufile)->mi_sem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -539,9 +562,14 @@ int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
|
||||||
|
|
||||||
kaddr = kmap_atomic(bh->b_page);
|
kaddr = kmap_atomic(bh->b_page);
|
||||||
su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
|
su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
|
||||||
WARN_ON(nilfs_segment_usage_error(su));
|
if (modtime) {
|
||||||
if (modtime)
|
/*
|
||||||
|
* Check segusage error and set su_lastmod only when updating
|
||||||
|
* this entry with a valid timestamp, not for cancellation.
|
||||||
|
*/
|
||||||
|
WARN_ON_ONCE(nilfs_segment_usage_error(su));
|
||||||
su->su_lastmod = cpu_to_le64(modtime);
|
su->su_lastmod = cpu_to_le64(modtime);
|
||||||
|
}
|
||||||
su->su_nblocks = cpu_to_le32(nblocks);
|
su->su_nblocks = cpu_to_le32(nblocks);
|
||||||
kunmap_atomic(kaddr);
|
kunmap_atomic(kaddr);
|
||||||
|
|
||||||
|
|
|
@ -688,7 +688,11 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
|
||||||
goto failed_sbh;
|
goto failed_sbh;
|
||||||
}
|
}
|
||||||
nilfs_release_super_block(nilfs);
|
nilfs_release_super_block(nilfs);
|
||||||
sb_set_blocksize(sb, blocksize);
|
if (!sb_set_blocksize(sb, blocksize)) {
|
||||||
|
nilfs_msg(sb, KERN_ERR, "bad blocksize %d", blocksize);
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
|
err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -145,6 +145,7 @@ enum cpuhp_state {
|
||||||
CPUHP_AP_ARM_CORESIGHT_STARTING,
|
CPUHP_AP_ARM_CORESIGHT_STARTING,
|
||||||
CPUHP_AP_ARM64_ISNDEP_STARTING,
|
CPUHP_AP_ARM64_ISNDEP_STARTING,
|
||||||
CPUHP_AP_SMPCFD_DYING,
|
CPUHP_AP_SMPCFD_DYING,
|
||||||
|
CPUHP_AP_HRTIMERS_DYING,
|
||||||
CPUHP_AP_X86_TBOOT_DYING,
|
CPUHP_AP_X86_TBOOT_DYING,
|
||||||
CPUHP_AP_ARM_CACHE_B15_RAC_DYING,
|
CPUHP_AP_ARM_CACHE_B15_RAC_DYING,
|
||||||
CPUHP_AP_ONLINE,
|
CPUHP_AP_ONLINE,
|
||||||
|
|
|
@ -497,9 +497,9 @@ extern void sysrq_timer_list_show(void);
|
||||||
|
|
||||||
int hrtimers_prepare_cpu(unsigned int cpu);
|
int hrtimers_prepare_cpu(unsigned int cpu);
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
int hrtimers_dead_cpu(unsigned int cpu);
|
int hrtimers_cpu_dying(unsigned int cpu);
|
||||||
#else
|
#else
|
||||||
#define hrtimers_dead_cpu NULL
|
#define hrtimers_cpu_dying NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -692,6 +692,8 @@ struct perf_event {
|
||||||
struct pid_namespace *ns;
|
struct pid_namespace *ns;
|
||||||
u64 id;
|
u64 id;
|
||||||
|
|
||||||
|
atomic64_t lost_samples;
|
||||||
|
|
||||||
u64 (*clock)(void);
|
u64 (*clock)(void);
|
||||||
perf_overflow_handler_t overflow_handler;
|
perf_overflow_handler_t overflow_handler;
|
||||||
void *overflow_handler_context;
|
void *overflow_handler_context;
|
||||||
|
|
|
@ -11,9 +11,12 @@
|
||||||
/**
|
/**
|
||||||
* struct genl_multicast_group - generic netlink multicast group
|
* struct genl_multicast_group - generic netlink multicast group
|
||||||
* @name: name of the multicast group, names are per-family
|
* @name: name of the multicast group, names are per-family
|
||||||
|
* @cap_sys_admin: whether %CAP_SYS_ADMIN is required for binding
|
||||||
*/
|
*/
|
||||||
struct genl_multicast_group {
|
struct genl_multicast_group {
|
||||||
char name[GENL_NAMSIZ];
|
char name[GENL_NAMSIZ];
|
||||||
|
u8 flags;
|
||||||
|
u8 cap_sys_admin:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct genl_ops;
|
struct genl_ops;
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
XT_OWNER_UID = 1 << 0,
|
XT_OWNER_UID = 1 << 0,
|
||||||
XT_OWNER_GID = 1 << 1,
|
XT_OWNER_GID = 1 << 1,
|
||||||
XT_OWNER_SOCKET = 1 << 2,
|
XT_OWNER_SOCKET = 1 << 2,
|
||||||
|
XT_OWNER_SUPPL_GROUPS = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xt_owner_match_info {
|
struct xt_owner_match_info {
|
||||||
|
|
|
@ -273,6 +273,7 @@ enum {
|
||||||
* { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
|
* { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
|
||||||
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
||||||
* { u64 id; } && PERF_FORMAT_ID
|
* { u64 id; } && PERF_FORMAT_ID
|
||||||
|
* { u64 lost; } && PERF_FORMAT_LOST
|
||||||
* } && !PERF_FORMAT_GROUP
|
* } && !PERF_FORMAT_GROUP
|
||||||
*
|
*
|
||||||
* { u64 nr;
|
* { u64 nr;
|
||||||
|
@ -280,6 +281,7 @@ enum {
|
||||||
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
||||||
* { u64 value;
|
* { u64 value;
|
||||||
* { u64 id; } && PERF_FORMAT_ID
|
* { u64 id; } && PERF_FORMAT_ID
|
||||||
|
* { u64 lost; } && PERF_FORMAT_LOST
|
||||||
* } cntr[nr];
|
* } cntr[nr];
|
||||||
* } && PERF_FORMAT_GROUP
|
* } && PERF_FORMAT_GROUP
|
||||||
* };
|
* };
|
||||||
|
@ -289,8 +291,9 @@ enum perf_event_read_format {
|
||||||
PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
|
PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
|
||||||
PERF_FORMAT_ID = 1U << 2,
|
PERF_FORMAT_ID = 1U << 2,
|
||||||
PERF_FORMAT_GROUP = 1U << 3,
|
PERF_FORMAT_GROUP = 1U << 3,
|
||||||
|
PERF_FORMAT_LOST = 1U << 4,
|
||||||
|
|
||||||
PERF_FORMAT_MAX = 1U << 4, /* non-ABI */
|
PERF_FORMAT_MAX = 1U << 5, /* non-ABI */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
|
#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
|
||||||
|
|
|
@ -1464,7 +1464,7 @@ static struct cpuhp_step cpuhp_hp_states[] = {
|
||||||
[CPUHP_HRTIMERS_PREPARE] = {
|
[CPUHP_HRTIMERS_PREPARE] = {
|
||||||
.name = "hrtimers:prepare",
|
.name = "hrtimers:prepare",
|
||||||
.startup.single = hrtimers_prepare_cpu,
|
.startup.single = hrtimers_prepare_cpu,
|
||||||
.teardown.single = hrtimers_dead_cpu,
|
.teardown.single = NULL,
|
||||||
},
|
},
|
||||||
[CPUHP_SMPCFD_PREPARE] = {
|
[CPUHP_SMPCFD_PREPARE] = {
|
||||||
.name = "smpcfd:prepare",
|
.name = "smpcfd:prepare",
|
||||||
|
@ -1531,6 +1531,12 @@ static struct cpuhp_step cpuhp_hp_states[] = {
|
||||||
.startup.single = NULL,
|
.startup.single = NULL,
|
||||||
.teardown.single = smpcfd_dying_cpu,
|
.teardown.single = smpcfd_dying_cpu,
|
||||||
},
|
},
|
||||||
|
[CPUHP_AP_HRTIMERS_DYING] = {
|
||||||
|
.name = "hrtimers:dying",
|
||||||
|
.startup.single = NULL,
|
||||||
|
.teardown.single = hrtimers_cpu_dying,
|
||||||
|
},
|
||||||
|
|
||||||
/* Entry state on starting. Interrupts enabled from here on. Transient
|
/* Entry state on starting. Interrupts enabled from here on. Transient
|
||||||
* state for synchronsization */
|
* state for synchronsization */
|
||||||
[CPUHP_AP_ONLINE] = {
|
[CPUHP_AP_ONLINE] = {
|
||||||
|
|
|
@ -1710,28 +1710,34 @@ static inline void perf_event__state_init(struct perf_event *event)
|
||||||
PERF_EVENT_STATE_INACTIVE;
|
PERF_EVENT_STATE_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
|
static int __perf_event_read_size(u64 read_format, int nr_siblings)
|
||||||
{
|
{
|
||||||
int entry = sizeof(u64); /* value */
|
int entry = sizeof(u64); /* value */
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int nr = 1;
|
int nr = 1;
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
entry += sizeof(u64);
|
entry += sizeof(u64);
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_GROUP) {
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
entry += sizeof(u64);
|
||||||
|
|
||||||
|
if (read_format & PERF_FORMAT_GROUP) {
|
||||||
nr += nr_siblings;
|
nr += nr_siblings;
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
size += entry * nr;
|
/*
|
||||||
event->read_size = size;
|
* Since perf_event_validate_size() limits this to 16k and inhibits
|
||||||
|
* adding more siblings, this will never overflow.
|
||||||
|
*/
|
||||||
|
return size + nr * entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
||||||
|
@ -1772,8 +1778,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
||||||
*/
|
*/
|
||||||
static void perf_event__header_size(struct perf_event *event)
|
static void perf_event__header_size(struct perf_event *event)
|
||||||
{
|
{
|
||||||
__perf_event_read_size(event,
|
event->read_size =
|
||||||
event->group_leader->nr_siblings);
|
__perf_event_read_size(event->attr.read_format,
|
||||||
|
event->group_leader->nr_siblings);
|
||||||
__perf_event_header_size(event, event->attr.sample_type);
|
__perf_event_header_size(event, event->attr.sample_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1804,24 +1811,35 @@ static void perf_event__id_header_size(struct perf_event *event)
|
||||||
event->id_header_size = size;
|
event->id_header_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that adding an event to the group does not result in anybody
|
||||||
|
* overflowing the 64k event limit imposed by the output buffer.
|
||||||
|
*
|
||||||
|
* Specifically, check that the read_size for the event does not exceed 16k,
|
||||||
|
* read_size being the one term that grows with groups size. Since read_size
|
||||||
|
* depends on per-event read_format, also (re)check the existing events.
|
||||||
|
*
|
||||||
|
* This leaves 48k for the constant size fields and things like callchains,
|
||||||
|
* branch stacks and register sets.
|
||||||
|
*/
|
||||||
static bool perf_event_validate_size(struct perf_event *event)
|
static bool perf_event_validate_size(struct perf_event *event)
|
||||||
{
|
{
|
||||||
/*
|
struct perf_event *sibling, *group_leader = event->group_leader;
|
||||||
* The values computed here will be over-written when we actually
|
|
||||||
* attach the event.
|
|
||||||
*/
|
|
||||||
__perf_event_read_size(event, event->group_leader->nr_siblings + 1);
|
|
||||||
__perf_event_header_size(event, event->attr.sample_type & ~PERF_SAMPLE_READ);
|
|
||||||
perf_event__id_header_size(event);
|
|
||||||
|
|
||||||
/*
|
if (__perf_event_read_size(event->attr.read_format,
|
||||||
* Sum the lot; should not exceed the 64k limit we have on records.
|
group_leader->nr_siblings + 1) > 16*1024)
|
||||||
* Conservative limit to allow for callchains and other variable fields.
|
|
||||||
*/
|
|
||||||
if (event->read_size + event->header_size +
|
|
||||||
event->id_header_size + sizeof(struct perf_event_header) >= 16*1024)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (__perf_event_read_size(group_leader->attr.read_format,
|
||||||
|
group_leader->nr_siblings + 1) > 16*1024)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for_each_sibling_event(sibling, group_leader) {
|
||||||
|
if (__perf_event_read_size(sibling->attr.read_format,
|
||||||
|
group_leader->nr_siblings + 1) > 16*1024)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4797,11 +4815,15 @@ static int __perf_read_group_add(struct perf_event *leader,
|
||||||
values[n++] += perf_event_count(leader);
|
values[n++] += perf_event_count(leader);
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
values[n++] = primary_event_id(leader);
|
values[n++] = primary_event_id(leader);
|
||||||
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
values[n++] = atomic64_read(&leader->lost_samples);
|
||||||
|
|
||||||
for_each_sibling_event(sub, leader) {
|
for_each_sibling_event(sub, leader) {
|
||||||
values[n++] += perf_event_count(sub);
|
values[n++] += perf_event_count(sub);
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
values[n++] = primary_event_id(sub);
|
values[n++] = primary_event_id(sub);
|
||||||
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
values[n++] = atomic64_read(&sub->lost_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
|
@ -4855,7 +4877,7 @@ static int perf_read_one(struct perf_event *event,
|
||||||
u64 read_format, char __user *buf)
|
u64 read_format, char __user *buf)
|
||||||
{
|
{
|
||||||
u64 enabled, running;
|
u64 enabled, running;
|
||||||
u64 values[4];
|
u64 values[5];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
values[n++] = __perf_event_read_value(event, &enabled, &running);
|
values[n++] = __perf_event_read_value(event, &enabled, &running);
|
||||||
|
@ -4865,6 +4887,8 @@ static int perf_read_one(struct perf_event *event,
|
||||||
values[n++] = running;
|
values[n++] = running;
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
values[n++] = primary_event_id(event);
|
values[n++] = primary_event_id(event);
|
||||||
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
values[n++] = atomic64_read(&event->lost_samples);
|
||||||
|
|
||||||
if (copy_to_user(buf, values, n * sizeof(u64)))
|
if (copy_to_user(buf, values, n * sizeof(u64)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -6187,7 +6211,7 @@ static void perf_output_read_one(struct perf_output_handle *handle,
|
||||||
u64 enabled, u64 running)
|
u64 enabled, u64 running)
|
||||||
{
|
{
|
||||||
u64 read_format = event->attr.read_format;
|
u64 read_format = event->attr.read_format;
|
||||||
u64 values[4];
|
u64 values[5];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
values[n++] = perf_event_count(event);
|
values[n++] = perf_event_count(event);
|
||||||
|
@ -6201,6 +6225,8 @@ static void perf_output_read_one(struct perf_output_handle *handle,
|
||||||
}
|
}
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
values[n++] = primary_event_id(event);
|
values[n++] = primary_event_id(event);
|
||||||
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
values[n++] = atomic64_read(&event->lost_samples);
|
||||||
|
|
||||||
__output_copy(handle, values, n * sizeof(u64));
|
__output_copy(handle, values, n * sizeof(u64));
|
||||||
}
|
}
|
||||||
|
@ -6211,7 +6237,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
|
||||||
{
|
{
|
||||||
struct perf_event *leader = event->group_leader, *sub;
|
struct perf_event *leader = event->group_leader, *sub;
|
||||||
u64 read_format = event->attr.read_format;
|
u64 read_format = event->attr.read_format;
|
||||||
u64 values[5];
|
u64 values[6];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
values[n++] = 1 + leader->nr_siblings;
|
values[n++] = 1 + leader->nr_siblings;
|
||||||
|
@ -6229,6 +6255,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
|
||||||
values[n++] = perf_event_count(leader);
|
values[n++] = perf_event_count(leader);
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
values[n++] = primary_event_id(leader);
|
values[n++] = primary_event_id(leader);
|
||||||
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
values[n++] = atomic64_read(&leader->lost_samples);
|
||||||
|
|
||||||
__output_copy(handle, values, n * sizeof(u64));
|
__output_copy(handle, values, n * sizeof(u64));
|
||||||
|
|
||||||
|
@ -6242,6 +6270,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
|
||||||
values[n++] = perf_event_count(sub);
|
values[n++] = perf_event_count(sub);
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
values[n++] = primary_event_id(sub);
|
values[n++] = primary_event_id(sub);
|
||||||
|
if (read_format & PERF_FORMAT_LOST)
|
||||||
|
values[n++] = atomic64_read(&sub->lost_samples);
|
||||||
|
|
||||||
__output_copy(handle, values, n * sizeof(u64));
|
__output_copy(handle, values, n * sizeof(u64));
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,8 +165,10 @@ __perf_output_begin(struct perf_output_handle *handle,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (unlikely(rb->paused)) {
|
if (unlikely(rb->paused)) {
|
||||||
if (rb->nr_pages)
|
if (rb->nr_pages) {
|
||||||
local_inc(&rb->lost);
|
local_inc(&rb->lost);
|
||||||
|
atomic64_inc(&event->lost_samples);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +251,7 @@ __perf_output_begin(struct perf_output_handle *handle,
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
local_inc(&rb->lost);
|
local_inc(&rb->lost);
|
||||||
|
atomic64_inc(&event->lost_samples);
|
||||||
perf_output_put_handle(handle);
|
perf_output_put_handle(handle);
|
||||||
out:
|
out:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
|
@ -1922,29 +1922,22 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hrtimers_dead_cpu(unsigned int scpu)
|
int hrtimers_cpu_dying(unsigned int dying_cpu)
|
||||||
{
|
{
|
||||||
struct hrtimer_cpu_base *old_base, *new_base;
|
struct hrtimer_cpu_base *old_base, *new_base;
|
||||||
int i;
|
int i, ncpu = cpumask_first(cpu_active_mask);
|
||||||
|
|
||||||
BUG_ON(cpu_online(scpu));
|
tick_cancel_sched_timer(dying_cpu);
|
||||||
tick_cancel_sched_timer(scpu);
|
|
||||||
|
old_base = this_cpu_ptr(&hrtimer_bases);
|
||||||
|
new_base = &per_cpu(hrtimer_bases, ncpu);
|
||||||
|
|
||||||
/*
|
|
||||||
* this BH disable ensures that raise_softirq_irqoff() does
|
|
||||||
* not wakeup ksoftirqd (and acquire the pi-lock) while
|
|
||||||
* holding the cpu_base lock
|
|
||||||
*/
|
|
||||||
local_bh_disable();
|
|
||||||
local_irq_disable();
|
|
||||||
old_base = &per_cpu(hrtimer_bases, scpu);
|
|
||||||
new_base = this_cpu_ptr(&hrtimer_bases);
|
|
||||||
/*
|
/*
|
||||||
* The caller is globally serialized and nobody else
|
* The caller is globally serialized and nobody else
|
||||||
* takes two locks at once, deadlock is not possible.
|
* takes two locks at once, deadlock is not possible.
|
||||||
*/
|
*/
|
||||||
raw_spin_lock(&new_base->lock);
|
raw_spin_lock(&old_base->lock);
|
||||||
raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
|
raw_spin_lock_nested(&new_base->lock, SINGLE_DEPTH_NESTING);
|
||||||
|
|
||||||
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
|
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
|
||||||
migrate_hrtimer_list(&old_base->clock_base[i],
|
migrate_hrtimer_list(&old_base->clock_base[i],
|
||||||
|
@ -1955,15 +1948,13 @@ int hrtimers_dead_cpu(unsigned int scpu)
|
||||||
* The migration might have changed the first expiring softirq
|
* The migration might have changed the first expiring softirq
|
||||||
* timer on this CPU. Update it.
|
* timer on this CPU. Update it.
|
||||||
*/
|
*/
|
||||||
hrtimer_update_softirq_timer(new_base, false);
|
__hrtimer_get_next_event(new_base, HRTIMER_ACTIVE_SOFT);
|
||||||
|
/* Tell the other CPU to retrigger the next event */
|
||||||
|
smp_call_function_single(ncpu, retrigger_next_event, NULL, 0);
|
||||||
|
|
||||||
raw_spin_unlock(&old_base->lock);
|
|
||||||
raw_spin_unlock(&new_base->lock);
|
raw_spin_unlock(&new_base->lock);
|
||||||
|
raw_spin_unlock(&old_base->lock);
|
||||||
|
|
||||||
/* Check, if we got expired work to do */
|
|
||||||
__hrtimer_peek_ahead_timers();
|
|
||||||
local_irq_enable();
|
|
||||||
local_bh_enable();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2209,8 +2209,11 @@ void trace_buffered_event_enable(void)
|
||||||
for_each_tracing_cpu(cpu) {
|
for_each_tracing_cpu(cpu) {
|
||||||
page = alloc_pages_node(cpu_to_node(cpu),
|
page = alloc_pages_node(cpu_to_node(cpu),
|
||||||
GFP_KERNEL | __GFP_NORETRY, 0);
|
GFP_KERNEL | __GFP_NORETRY, 0);
|
||||||
if (!page)
|
/* This is just an optimization and can handle failures */
|
||||||
goto failed;
|
if (!page) {
|
||||||
|
pr_err("Failed to allocate event buffer\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
event = page_address(page);
|
event = page_address(page);
|
||||||
memset(event, 0, sizeof(*event));
|
memset(event, 0, sizeof(*event));
|
||||||
|
@ -2224,10 +2227,6 @@ void trace_buffered_event_enable(void)
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
failed:
|
|
||||||
trace_buffered_event_disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enable_trace_buffered_event(void *data)
|
static void enable_trace_buffered_event(void *data)
|
||||||
|
@ -2262,11 +2261,9 @@ void trace_buffered_event_disable(void)
|
||||||
if (--trace_buffered_event_ref)
|
if (--trace_buffered_event_ref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
preempt_disable();
|
|
||||||
/* For each CPU, set the buffer as used. */
|
/* For each CPU, set the buffer as used. */
|
||||||
smp_call_function_many(tracing_buffer_mask,
|
on_each_cpu_mask(tracing_buffer_mask, disable_trace_buffered_event,
|
||||||
disable_trace_buffered_event, NULL, 1);
|
NULL, true);
|
||||||
preempt_enable();
|
|
||||||
|
|
||||||
/* Wait for all current users to finish */
|
/* Wait for all current users to finish */
|
||||||
synchronize_sched();
|
synchronize_sched();
|
||||||
|
@ -2275,17 +2272,19 @@ void trace_buffered_event_disable(void)
|
||||||
free_page((unsigned long)per_cpu(trace_buffered_event, cpu));
|
free_page((unsigned long)per_cpu(trace_buffered_event, cpu));
|
||||||
per_cpu(trace_buffered_event, cpu) = NULL;
|
per_cpu(trace_buffered_event, cpu) = NULL;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Make sure trace_buffered_event is NULL before clearing
|
|
||||||
* trace_buffered_event_cnt.
|
|
||||||
*/
|
|
||||||
smp_wmb();
|
|
||||||
|
|
||||||
preempt_disable();
|
/*
|
||||||
/* Do the work on each cpu */
|
* Wait for all CPUs that potentially started checking if they can use
|
||||||
smp_call_function_many(tracing_buffer_mask,
|
* their event buffer only after the previous synchronize_rcu() call and
|
||||||
enable_trace_buffered_event, NULL, 1);
|
* they still read a valid pointer from trace_buffered_event. It must be
|
||||||
preempt_enable();
|
* ensured they don't see cleared trace_buffered_event_cnt else they
|
||||||
|
* could wrongly decide to use the pointed-to buffer which is now freed.
|
||||||
|
*/
|
||||||
|
synchronize_rcu();
|
||||||
|
|
||||||
|
/* For each CPU, relinquish the buffer */
|
||||||
|
on_each_cpu_mask(tracing_buffer_mask, enable_trace_buffered_event, NULL,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ring_buffer *temp_buffer;
|
static struct ring_buffer *temp_buffer;
|
||||||
|
@ -5259,8 +5258,7 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
#ifdef CONFIG_TRACER_MAX_TRACE
|
#ifdef CONFIG_TRACER_MAX_TRACE
|
||||||
if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL) ||
|
if (!tr->current_trace->use_max_tr)
|
||||||
!tr->current_trace->use_max_tr)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = ring_buffer_resize(tr->max_buffer.buffer, size, cpu);
|
ret = ring_buffer_resize(tr->max_buffer.buffer, size, cpu);
|
||||||
|
|
|
@ -122,7 +122,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct genl_multicast_group dropmon_mcgrps[] = {
|
static const struct genl_multicast_group dropmon_mcgrps[] = {
|
||||||
{ .name = "events", },
|
{ .name = "events", .cap_sys_admin = 1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void send_dm_alert(struct work_struct *work)
|
static void send_dm_alert(struct work_struct *work)
|
||||||
|
@ -370,10 +370,12 @@ static const struct genl_ops dropmon_ops[] = {
|
||||||
{
|
{
|
||||||
.cmd = NET_DM_CMD_START,
|
.cmd = NET_DM_CMD_START,
|
||||||
.doit = net_dm_cmd_trace,
|
.doit = net_dm_cmd_trace,
|
||||||
|
.flags = GENL_ADMIN_PERM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.cmd = NET_DM_CMD_STOP,
|
.cmd = NET_DM_CMD_STOP,
|
||||||
.doit = net_dm_cmd_trace,
|
.doit = net_dm_cmd_trace,
|
||||||
|
.flags = GENL_ADMIN_PERM,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -683,15 +683,18 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->header_ops) {
|
if (dev->header_ops) {
|
||||||
|
int pull_len = tunnel->hlen + sizeof(struct iphdr);
|
||||||
|
|
||||||
if (skb_cow_head(skb, 0))
|
if (skb_cow_head(skb, 0))
|
||||||
goto free_skb;
|
goto free_skb;
|
||||||
|
|
||||||
tnl_params = (const struct iphdr *)skb->data;
|
tnl_params = (const struct iphdr *)skb->data;
|
||||||
|
|
||||||
/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
|
if (!pskb_network_may_pull(skb, pull_len))
|
||||||
* to gre header.
|
goto free_skb;
|
||||||
*/
|
|
||||||
skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
|
/* ip_tunnel_xmit() needs skb->data pointing to gre header. */
|
||||||
|
skb_pull(skb, pull_len);
|
||||||
skb_reset_mac_header(skb);
|
skb_reset_mac_header(skb);
|
||||||
|
|
||||||
if (skb->ip_summed == CHECKSUM_PARTIAL &&
|
if (skb->ip_summed == CHECKSUM_PARTIAL &&
|
||||||
|
|
|
@ -3640,8 +3640,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
||||||
* then we can probably ignore it.
|
* then we can probably ignore it.
|
||||||
*/
|
*/
|
||||||
if (before(ack, prior_snd_una)) {
|
if (before(ack, prior_snd_una)) {
|
||||||
|
u32 max_window;
|
||||||
|
|
||||||
|
/* do not accept ACK for bytes we never sent. */
|
||||||
|
max_window = min_t(u64, tp->max_window, tp->bytes_acked);
|
||||||
/* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
|
/* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
|
||||||
if (before(ack, prior_snd_una - tp->max_window)) {
|
if (before(ack, prior_snd_una - max_window)) {
|
||||||
if (!(flag & FLAG_NO_CHALLENGE_ACK))
|
if (!(flag & FLAG_NO_CHALLENGE_ACK))
|
||||||
tcp_send_challenge_ack(sk, skb);
|
tcp_send_challenge_ack(sk, skb);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1351,13 +1351,9 @@ out:
|
||||||
if (!pn_leaf && !(pn->fn_flags & RTN_RTINFO)) {
|
if (!pn_leaf && !(pn->fn_flags & RTN_RTINFO)) {
|
||||||
pn_leaf = fib6_find_prefix(info->nl_net, table,
|
pn_leaf = fib6_find_prefix(info->nl_net, table,
|
||||||
pn);
|
pn);
|
||||||
#if RT6_DEBUG >= 2
|
if (!pn_leaf)
|
||||||
if (!pn_leaf) {
|
|
||||||
WARN_ON(!pn_leaf);
|
|
||||||
pn_leaf =
|
pn_leaf =
|
||||||
info->nl_net->ipv6.fib6_null_entry;
|
info->nl_net->ipv6.fib6_null_entry;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
fib6_info_hold(pn_leaf);
|
fib6_info_hold(pn_leaf);
|
||||||
rcu_assign_pointer(pn->leaf, pn_leaf);
|
rcu_assign_pointer(pn->leaf, pn_leaf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
|
||||||
ip_set_dereference((inst)->ip_set_list)[id]
|
ip_set_dereference((inst)->ip_set_list)[id]
|
||||||
#define ip_set_ref_netlink(inst,id) \
|
#define ip_set_ref_netlink(inst,id) \
|
||||||
rcu_dereference_raw((inst)->ip_set_list)[id]
|
rcu_dereference_raw((inst)->ip_set_list)[id]
|
||||||
|
#define ip_set_dereference_nfnl(p) \
|
||||||
|
rcu_dereference_check(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
|
||||||
|
|
||||||
/* The set types are implemented in modules and registered set types
|
/* The set types are implemented in modules and registered set types
|
||||||
* can be found in ip_set_type_list. Adding/deleting types is
|
* can be found in ip_set_type_list. Adding/deleting types is
|
||||||
|
@ -552,15 +554,10 @@ __ip_set_put_netlink(struct ip_set *set)
|
||||||
static inline struct ip_set *
|
static inline struct ip_set *
|
||||||
ip_set_rcu_get(struct net *net, ip_set_id_t index)
|
ip_set_rcu_get(struct net *net, ip_set_id_t index)
|
||||||
{
|
{
|
||||||
struct ip_set *set;
|
|
||||||
struct ip_set_net *inst = ip_set_pernet(net);
|
struct ip_set_net *inst = ip_set_pernet(net);
|
||||||
|
|
||||||
rcu_read_lock();
|
/* ip_set_list and the set pointer need to be protected */
|
||||||
/* ip_set_list itself needs to be protected */
|
return ip_set_dereference_nfnl(inst->ip_set_list)[index];
|
||||||
set = rcu_dereference(inst->ip_set_list)[index];
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1227,6 +1224,9 @@ static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb,
|
||||||
ip_set(inst, to_id) = from;
|
ip_set(inst, to_id) = from;
|
||||||
write_unlock_bh(&ip_set_ref_lock);
|
write_unlock_bh(&ip_set_ref_lock);
|
||||||
|
|
||||||
|
/* Make sure all readers of the old set pointers are completed. */
|
||||||
|
synchronize_rcu();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,29 +76,54 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||||
*/
|
*/
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
filp = sk->sk_socket->file;
|
read_lock_bh(&sk->sk_callback_lock);
|
||||||
if (filp == NULL)
|
filp = sk->sk_socket ? sk->sk_socket->file : NULL;
|
||||||
|
if (filp == NULL) {
|
||||||
|
read_unlock_bh(&sk->sk_callback_lock);
|
||||||
return ((info->match ^ info->invert) &
|
return ((info->match ^ info->invert) &
|
||||||
(XT_OWNER_UID | XT_OWNER_GID)) == 0;
|
(XT_OWNER_UID | XT_OWNER_GID)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->match & XT_OWNER_UID) {
|
if (info->match & XT_OWNER_UID) {
|
||||||
kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
|
kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
|
||||||
kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
|
kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
|
||||||
if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
|
if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
|
||||||
uid_lte(filp->f_cred->fsuid, uid_max)) ^
|
uid_lte(filp->f_cred->fsuid, uid_max)) ^
|
||||||
!(info->invert & XT_OWNER_UID))
|
!(info->invert & XT_OWNER_UID)) {
|
||||||
|
read_unlock_bh(&sk->sk_callback_lock);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->match & XT_OWNER_GID) {
|
if (info->match & XT_OWNER_GID) {
|
||||||
|
unsigned int i, match = false;
|
||||||
kgid_t gid_min = make_kgid(net->user_ns, info->gid_min);
|
kgid_t gid_min = make_kgid(net->user_ns, info->gid_min);
|
||||||
kgid_t gid_max = make_kgid(net->user_ns, info->gid_max);
|
kgid_t gid_max = make_kgid(net->user_ns, info->gid_max);
|
||||||
if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
|
struct group_info *gi = filp->f_cred->group_info;
|
||||||
gid_lte(filp->f_cred->fsgid, gid_max)) ^
|
|
||||||
!(info->invert & XT_OWNER_GID))
|
if (gid_gte(filp->f_cred->fsgid, gid_min) &&
|
||||||
|
gid_lte(filp->f_cred->fsgid, gid_max))
|
||||||
|
match = true;
|
||||||
|
|
||||||
|
if (!match && (info->match & XT_OWNER_SUPPL_GROUPS) && gi) {
|
||||||
|
for (i = 0; i < gi->ngroups; ++i) {
|
||||||
|
kgid_t group = gi->gid[i];
|
||||||
|
|
||||||
|
if (gid_gte(group, gid_min) &&
|
||||||
|
gid_lte(group, gid_max)) {
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match ^ !(info->invert & XT_OWNER_GID)) {
|
||||||
|
read_unlock_bh(&sk->sk_callback_lock);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_unlock_bh(&sk->sk_callback_lock);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1030,7 +1030,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
netlink_lock_table();
|
|
||||||
if (nlk->netlink_bind && groups) {
|
if (nlk->netlink_bind && groups) {
|
||||||
int group;
|
int group;
|
||||||
|
|
||||||
|
@ -1042,13 +1041,14 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
|
||||||
if (!err)
|
if (!err)
|
||||||
continue;
|
continue;
|
||||||
netlink_undo_bind(group, groups, sk);
|
netlink_undo_bind(group, groups, sk);
|
||||||
goto unlock;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No need for barriers here as we return to user-space without
|
/* No need for barriers here as we return to user-space without
|
||||||
* using any of the bound attributes.
|
* using any of the bound attributes.
|
||||||
*/
|
*/
|
||||||
|
netlink_lock_table();
|
||||||
if (!bound) {
|
if (!bound) {
|
||||||
err = nladdr->nl_pid ?
|
err = nladdr->nl_pid ?
|
||||||
netlink_insert(sk, nladdr->nl_pid) :
|
netlink_insert(sk, nladdr->nl_pid) :
|
||||||
|
|
|
@ -988,33 +988,12 @@ static int genl_bind(struct net *net, int group)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void genl_unbind(struct net *net, int group)
|
|
||||||
{
|
|
||||||
struct genl_family *f;
|
|
||||||
unsigned int id;
|
|
||||||
|
|
||||||
down_read(&cb_lock);
|
|
||||||
|
|
||||||
idr_for_each_entry(&genl_fam_idr, f, id) {
|
|
||||||
if (group >= f->mcgrp_offset &&
|
|
||||||
group < f->mcgrp_offset + f->n_mcgrps) {
|
|
||||||
int fam_grp = group - f->mcgrp_offset;
|
|
||||||
|
|
||||||
if (f->mcast_unbind)
|
|
||||||
f->mcast_unbind(net, fam_grp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
up_read(&cb_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __net_init genl_pernet_init(struct net *net)
|
static int __net_init genl_pernet_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct netlink_kernel_cfg cfg = {
|
struct netlink_kernel_cfg cfg = {
|
||||||
.input = genl_rcv,
|
.input = genl_rcv,
|
||||||
.flags = NL_CFG_F_NONROOT_RECV,
|
.flags = NL_CFG_F_NONROOT_RECV,
|
||||||
.bind = genl_bind,
|
.bind = genl_bind,
|
||||||
.unbind = genl_unbind,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* we'll bump the group number right afterwards */
|
/* we'll bump the group number right afterwards */
|
||||||
|
|
|
@ -4214,7 +4214,7 @@ static void packet_mm_open(struct vm_area_struct *vma)
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
|
|
||||||
if (sk)
|
if (sk)
|
||||||
atomic_inc(&pkt_sk(sk)->mapped);
|
atomic_long_inc(&pkt_sk(sk)->mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void packet_mm_close(struct vm_area_struct *vma)
|
static void packet_mm_close(struct vm_area_struct *vma)
|
||||||
|
@ -4224,7 +4224,7 @@ static void packet_mm_close(struct vm_area_struct *vma)
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
|
|
||||||
if (sk)
|
if (sk)
|
||||||
atomic_dec(&pkt_sk(sk)->mapped);
|
atomic_long_dec(&pkt_sk(sk)->mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct vm_operations_struct packet_mmap_ops = {
|
static const struct vm_operations_struct packet_mmap_ops = {
|
||||||
|
@ -4319,7 +4319,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
||||||
|
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
if (!closing) {
|
if (!closing) {
|
||||||
if (atomic_read(&po->mapped))
|
if (atomic_long_read(&po->mapped))
|
||||||
goto out;
|
goto out;
|
||||||
if (packet_read_pending(rb))
|
if (packet_read_pending(rb))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -4422,7 +4422,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
||||||
|
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
mutex_lock(&po->pg_vec_lock);
|
mutex_lock(&po->pg_vec_lock);
|
||||||
if (closing || atomic_read(&po->mapped) == 0) {
|
if (closing || atomic_long_read(&po->mapped) == 0) {
|
||||||
err = 0;
|
err = 0;
|
||||||
spin_lock_bh(&rb_queue->lock);
|
spin_lock_bh(&rb_queue->lock);
|
||||||
swap(rb->pg_vec, pg_vec);
|
swap(rb->pg_vec, pg_vec);
|
||||||
|
@ -4440,9 +4440,9 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
||||||
po->prot_hook.func = (po->rx_ring.pg_vec) ?
|
po->prot_hook.func = (po->rx_ring.pg_vec) ?
|
||||||
tpacket_rcv : packet_rcv;
|
tpacket_rcv : packet_rcv;
|
||||||
skb_queue_purge(rb_queue);
|
skb_queue_purge(rb_queue);
|
||||||
if (atomic_read(&po->mapped))
|
if (atomic_long_read(&po->mapped))
|
||||||
pr_err("packet_mmap: vma is busy: %d\n",
|
pr_err("packet_mmap: vma is busy: %ld\n",
|
||||||
atomic_read(&po->mapped));
|
atomic_long_read(&po->mapped));
|
||||||
}
|
}
|
||||||
mutex_unlock(&po->pg_vec_lock);
|
mutex_unlock(&po->pg_vec_lock);
|
||||||
|
|
||||||
|
@ -4520,7 +4520,7 @@ static int packet_mmap(struct file *file, struct socket *sock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_inc(&po->mapped);
|
atomic_long_inc(&po->mapped);
|
||||||
vma->vm_ops = &packet_mmap_ops;
|
vma->vm_ops = &packet_mmap_ops;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ struct packet_sock {
|
||||||
__be16 num;
|
__be16 num;
|
||||||
struct packet_rollover *rollover;
|
struct packet_rollover *rollover;
|
||||||
struct packet_mclist *mclist;
|
struct packet_mclist *mclist;
|
||||||
atomic_t mapped;
|
atomic_long_t mapped;
|
||||||
enum tpacket_versions tp_version;
|
enum tpacket_versions tp_version;
|
||||||
unsigned int tp_hdrlen;
|
unsigned int tp_hdrlen;
|
||||||
unsigned int tp_reserve;
|
unsigned int tp_reserve;
|
||||||
|
|
|
@ -31,7 +31,8 @@ enum psample_nl_multicast_groups {
|
||||||
|
|
||||||
static const struct genl_multicast_group psample_nl_mcgrps[] = {
|
static const struct genl_multicast_group psample_nl_mcgrps[] = {
|
||||||
[PSAMPLE_NL_MCGRP_CONFIG] = { .name = PSAMPLE_NL_MCGRP_CONFIG_NAME },
|
[PSAMPLE_NL_MCGRP_CONFIG] = { .name = PSAMPLE_NL_MCGRP_CONFIG_NAME },
|
||||||
[PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME },
|
[PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME,
|
||||||
|
.flags = GENL_UNS_ADMIN_PERM },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct genl_family psample_nl_family __ro_after_init;
|
static struct genl_family psample_nl_family __ro_after_init;
|
||||||
|
|
|
@ -119,9 +119,9 @@ static long long sym_get_range_val(struct symbol *sym, int base)
|
||||||
static void sym_validate_range(struct symbol *sym)
|
static void sym_validate_range(struct symbol *sym)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
struct symbol *range_sym;
|
||||||
int base;
|
int base;
|
||||||
long long val, val2;
|
long long val, val2;
|
||||||
char str[64];
|
|
||||||
|
|
||||||
switch (sym->type) {
|
switch (sym->type) {
|
||||||
case S_INT:
|
case S_INT:
|
||||||
|
@ -137,17 +137,15 @@ static void sym_validate_range(struct symbol *sym)
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return;
|
return;
|
||||||
val = strtoll(sym->curr.val, NULL, base);
|
val = strtoll(sym->curr.val, NULL, base);
|
||||||
val2 = sym_get_range_val(prop->expr->left.sym, base);
|
range_sym = prop->expr->left.sym;
|
||||||
|
val2 = sym_get_range_val(range_sym, base);
|
||||||
if (val >= val2) {
|
if (val >= val2) {
|
||||||
val2 = sym_get_range_val(prop->expr->right.sym, base);
|
range_sym = prop->expr->right.sym;
|
||||||
|
val2 = sym_get_range_val(range_sym, base);
|
||||||
if (val <= val2)
|
if (val <= val2)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sym->type == S_INT)
|
sym->curr.val = range_sym->curr.val;
|
||||||
sprintf(str, "%lld", val2);
|
|
||||||
else
|
|
||||||
sprintf(str, "0x%llx", val2);
|
|
||||||
sym->curr.val = xstrdup(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sym_set_changed(struct symbol *sym)
|
static void sym_set_changed(struct symbol *sym)
|
||||||
|
|
|
@ -266,6 +266,7 @@ static char *snd_pcm_state_names[] = {
|
||||||
STATE(DRAINING),
|
STATE(DRAINING),
|
||||||
STATE(PAUSED),
|
STATE(PAUSED),
|
||||||
STATE(SUSPENDED),
|
STATE(SUSPENDED),
|
||||||
|
STATE(DISCONNECTED),
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *snd_pcm_access_names[] = {
|
static char *snd_pcm_access_names[] = {
|
||||||
|
|
|
@ -273,6 +273,7 @@ enum {
|
||||||
* { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
|
* { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
|
||||||
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
||||||
* { u64 id; } && PERF_FORMAT_ID
|
* { u64 id; } && PERF_FORMAT_ID
|
||||||
|
* { u64 lost; } && PERF_FORMAT_LOST
|
||||||
* } && !PERF_FORMAT_GROUP
|
* } && !PERF_FORMAT_GROUP
|
||||||
*
|
*
|
||||||
* { u64 nr;
|
* { u64 nr;
|
||||||
|
@ -280,6 +281,7 @@ enum {
|
||||||
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
||||||
* { u64 value;
|
* { u64 value;
|
||||||
* { u64 id; } && PERF_FORMAT_ID
|
* { u64 id; } && PERF_FORMAT_ID
|
||||||
|
* { u64 lost; } && PERF_FORMAT_LOST
|
||||||
* } cntr[nr];
|
* } cntr[nr];
|
||||||
* } && PERF_FORMAT_GROUP
|
* } && PERF_FORMAT_GROUP
|
||||||
* };
|
* };
|
||||||
|
@ -289,8 +291,9 @@ enum perf_event_read_format {
|
||||||
PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
|
PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
|
||||||
PERF_FORMAT_ID = 1U << 2,
|
PERF_FORMAT_ID = 1U << 2,
|
||||||
PERF_FORMAT_GROUP = 1U << 3,
|
PERF_FORMAT_GROUP = 1U << 3,
|
||||||
|
PERF_FORMAT_LOST = 1U << 4,
|
||||||
|
|
||||||
PERF_FORMAT_MAX = 1U << 4, /* non-ABI */
|
PERF_FORMAT_MAX = 1U << 5, /* non-ABI */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
|
#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
|
||||||
|
|
Loading…
Reference in a new issue