This is the 5.4.283 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmbYQYIACgkQONu9yGCS aT5Yvg//a5nvSr37zxUnJ8Km+d2X4RysNh+853C/ydDj3Vr/zy/RrLPq2XQ9Cvfl 0zW6VLkrC+g8tQFBdJKYZH/EFRTriKNhMnjudgoanLCm8KaA7UbR/Zp9h9L9Czzi G1aUvS/+ZBe83BLCQQul8sonlVE8AtfjwVjEkj6rXJZMn3URh278i84CuosZRg5R Ao45mn8Gv+gxCrUtLU6Qy5gHKFJ2zGXyYP4Mn1UyUkLkgnUm7E1ZFelyrOxryILP mEcs700qT5BIlbodKdNQDP/ezbrLbljKliVS/z1YLZLfVI5v6OTGzMc81GPILHXj 1pK+DwQIZnFB/1E+AyER+i7n1i7id2lIRxmaJ4+TSxoNUKBP0+KuuZSFsAsDSXbS NXnGpPC5wJQcyf+DD7l9+XbdViCoDfTXMlIBMpmAdBhvsPfhAhtsgJV/DPiir6V7 JszP1AZlhwvvb4FOyr8AJ6jmFxDBfM3HniWDEn/zN/1GBMebwghchLP4CFflV6aN 1BqTONiWHvtqRm6nvBJVBV2frWzm4TmKr/RdlMGPTBr60GJqV/qwO5m7a7c+OBnF WscJ2wht2P2RgWOhnaS4NQF+IIbRaQm9AisvQCYoZlQIplS9RH61pnutfpYWNUZJ Zd7lIDLbifojX9mGTg1fUcrffHFnewSAag0oEeuMFuZOR6WaQs0= =2It1 -----END PGP SIGNATURE----- Merge 5.4.283 into android11-5.4-lts Changes in 5.4.283 fuse: Initialize beyond-EOF page contents before setting uptodate ALSA: usb-audio: Support Yamaha P-125 quirk entry xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration s390/dasd: fix error recovery leading to data corruption on ESE devices arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to NUMA_NO_NODE dm resume: don't return EINVAL when signalled dm persistent data: fix memory allocation failure vfs: Don't evict inode under the inode lru traversing context bitmap: introduce generic optimized bitmap_size() fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE selinux: fix potential counting error in avc_add_xperms_decision() drm/amdgpu: Actually check flags for all context ops. memcg_write_event_control(): fix a user-triggerable oops overflow.h: Add flex_array_size() helper overflow: Implement size_t saturating arithmetic helpers s390/cio: rename bitmap_size() -> idset_bitmap_size() btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits() s390/uv: Panic for set and remove shared access UVC errors net/mlx5e: Correctly report errors for ethtool rx flows atm: idt77252: prevent use after free in dequeue_rx() net: axienet: Fix DMA descriptor cleanup path net: axienet: Improve DMA error handling net: axienet: Factor out TX descriptor chain cleanup net: axienet: Check for DMA mapping errors net: axienet: Drop MDIO interrupt registers from ethtools dump net: axienet: Wrap DMA pointer writes to prepare for 64 bit net: axienet: Upgrade descriptors to hold 64-bit addresses net: axienet: Autodetect 64-bit DMA capability net: axienet: Fix register defines comment description net: dsa: vsc73xx: pass value in phy_write operation net: hns3: fix a deadlock problem when config TC during resetting ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7 ssb: Fix division by zero issue in ssb_calc_clock_rate wifi: cw1200: Avoid processing an invalid TIM IE i2c: riic: avoid potential division by zero media: radio-isa: use dev_name to fill in bus_info staging: ks7010: disable bh on tx_dev_lock binfmt_misc: cleanup on filesystem umount scsi: spi: Fix sshdr use gfs2: setattr_chown: Add missing initialization wifi: iwlwifi: abort scan when rfkill on but device enabled IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu nvmet-trace: avoid dereferencing pointer too early ext4: do not trim the group with corrupted block bitmap quota: Remove BUG_ON from dqget() media: pci: cx23885: check cx23885_vdev_init() return fs: binfmt_elf_efpic: don't use missing interpreter's properties scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list() net/sun3_82586: Avoid reading past buffer in debug output drm/lima: set gp bus_stop bit before hard reset virtiofs: forbid newlines in tags md: clean up invalid BUG_ON in md_ioctl x86: Increase brk randomness entropy for 64-bit systems parisc: Use irq_enter_rcu() to fix warning at kernel/context_tracking.c:367 powerpc/boot: Handle allocation failure in simple_realloc() powerpc/boot: Only free if realloc() succeeds btrfs: change BUG_ON to assertion when checking for delayed_node root btrfs: handle invalid root reference found in may_destroy_subvol() btrfs: send: handle unexpected data in header buffer in begin_cmd() btrfs: delete pointless BUG_ON check on quota root in btrfs_qgroup_account_extent() f2fs: fix to do sanity check in update_sit_entry usb: gadget: fsl: Increase size of name buffer for endpoints nvme: clear caller pointer on identify failure Bluetooth: bnep: Fix out-of-bound access nvmet-tcp: do not continue for invalid icreq NFS: avoid infinite loop in pnfs_update_layout. openrisc: Call setup_memory() earlier in the init sequence s390/iucv: fix receive buffer virtual vs physical address confusion usb: dwc3: core: Skip setting event buffers for host only controllers irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc ext4: set the type of max_zeroout to unsigned int to avoid overflow nvmet-rdma: fix possible bad dereference when freeing rsps hrtimer: Prevent queuing of hrtimer without a function callback gtp: pull network headers in gtp_dev_xmit() block: use "unsigned long" for blk_validate_block_size(). media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c) dm mpath: pass IO start time to path selector dm: do not use waitqueue for request-based DM dm suspend: return -ERESTARTSYS instead of -EINTR Bluetooth: Make use of __check_timeout on hci_sched_le Bluetooth: hci_core: Fix not handling link timeouts propertly Bluetooth: hci_core: Fix LE quote calculation tc-testing: don't access non-existent variable on exception kcm: Serialise kcm_sendmsg() for the same socket. netfilter: nft_counter: Synchronize nft_counter_reset() against reader. net: dsa: mv88e6xxx: global2: Expose ATU stats register net: dsa: mv88e6xxx: global1_atu: Add helper for get next net: dsa: mv88e6xxx: read FID when handling ATU violations net: dsa: mv88e6xxx: replace ATU violation prints with trace points net: dsa: mv88e6xxx: Fix out-of-bound access netem: fix return value if duplicate enqueue fails ipv6: prevent UAF in ip6_send_skb() net: xilinx: axienet: Always disable promiscuous mode net: xilinx: axienet: Fix dangling multicast addresses drm/msm: use drm_debug_enabled() to check for debug categories drm/msm/dpu: don't play tricks with debug macros mmc: mmc_test: Fix NULL dereference on allocation failure Bluetooth: MGMT: Add error handling to pair_device() HID: wacom: Defer calculation of resolution until resolution_code is known HID: microsoft: Add rumble support to latest xbox controllers cxgb4: add forgotten u64 ivlan cast before shift mmc: dw_mmc: allow biu and ciu clocks to defer ALSA: timer: Relax start tick time check for slave timer elements Bluetooth: hci_ldisc: check HCI_UART_PROTO_READY flag in HCIUARTGETPROTO Input: MT - limit max slots tools: move alignment-related macros to new <linux/align.h> drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc pinctrl: single: fix potential NULL dereference in pcs_get_function() wifi: mwifiex: duplicate static structs used in driver instances ipc: replace costly bailout check in sysvipc_find_ipc() drm/amdkfd: don't allow mapping the MMIO HDP page with large pages filelock: Correct the filelock owner in fcntl_setlk/fcntl_setlk64 media: uvcvideo: Fix integer overflow calculating timestamp ata: libata-core: Fix null pointer dereference on error cgroup/cpuset: Prevent UAF in proc_cpuset_show() net:rds: Fix possible deadlock in rds_message_put soundwire: stream: fix programming slave ports for non-continous port maps r8152: Factor out OOB link list waits ethtool: check device is present when getting link settings gtp: fix a potential NULL pointer dereference net: busy-poll: use ktime_get_ns() instead of local_clock() nfc: pn533: Add dev_up/dev_down hooks to phy_ops nfc: pn533: Add autopoll capability nfc: pn533: Add poll mod list filling check soc: qcom: cmd-db: Map shared memory as WC, not WB cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller USB: serial: option: add MeiG Smart SRM825L usb: dwc3: omap: add missing depopulate in probe error path usb: dwc3: core: Prevent USB core invalid event buffer address access usb: dwc3: st: fix probed platform device ref count on probe error path usb: dwc3: st: add missing depopulate in probe error path usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in remove_power_attributes() net: dsa: mv8e6xxx: Fix stub function parameters scsi: aacraid: Fix double-free on probe failure Linux 5.4.283 Change-Id: I78f8124947acd3af2d3059f4be29388e41e6950f Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
ac0b99d778
Documentation/process
Makefilearch
arm64/kernel
openrisc/kernel
parisc/kernel
powerpc
s390/include/asm
x86/kernel
drivers
ata
atm
bluetooth
gpu/drm
hid
i2c/busses
infiniband/hw/hfi1
input
irqchip
md
dm-clone-metadata.cdm-ioctl.cdm-mpath.cdm-path-selector.hdm-queue-length.cdm-rq.cdm-service-time.cdm.cmd.c
persistent-data
media
mmc
net
nfc/pn533
nvme
pinctrl
s390
scsi
soc/qcom
soundwire
ssb
staging/ks7010
usb
class
core
dwc3
gadget/udc
host
serial
fs
@ -48,6 +48,9 @@ Instead, the 2-factor form of the allocator should be used::
|
||||
|
||||
foo = kmalloc_array(count, size, GFP_KERNEL);
|
||||
|
||||
Specifically, kmalloc() can be replaced with kmalloc_array(), and
|
||||
kzalloc() can be replaced with kcalloc().
|
||||
|
||||
If no 2-factor form is available, the saturate-on-overflow helpers should
|
||||
be used::
|
||||
|
||||
@ -63,9 +66,20 @@ Instead, use the helper::
|
||||
|
||||
header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
|
||||
|
||||
See :c:func:`array_size`, :c:func:`array3_size`, and :c:func:`struct_size`,
|
||||
for more details as well as the related :c:func:`check_add_overflow` and
|
||||
:c:func:`check_mul_overflow` family of functions.
|
||||
For other calculations, please compose the use of the size_mul(),
|
||||
size_add(), and size_sub() helpers. For example, in the case of::
|
||||
|
||||
foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
|
||||
|
||||
Instead, use the helpers::
|
||||
|
||||
foo = krealloc(size_add(current_size,
|
||||
size_mul(chunk_size,
|
||||
size_sub(count, 3))), GFP_KERNEL);
|
||||
|
||||
For more details, also see array3_size() and flex_array_size(),
|
||||
as well as the related check_mul_overflow(), check_add_overflow(),
|
||||
check_sub_overflow(), and check_shl_overflow() family of functions.
|
||||
|
||||
simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
|
||||
----------------------------------------------------------------------
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 282
|
||||
SUBLEVEL = 283
|
||||
EXTRAVERSION =
|
||||
NAME = Kleptomaniac Octopus
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include <asm/numa.h>
|
||||
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE };
|
||||
|
||||
int __init acpi_numa_get_nid(unsigned int cpu)
|
||||
{
|
||||
|
@ -280,6 +280,9 @@ void calibrate_delay(void)
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
/* setup memblock allocator */
|
||||
setup_memory();
|
||||
|
||||
unflatten_and_copy_device_tree();
|
||||
|
||||
setup_cpuinfo();
|
||||
@ -304,9 +307,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
initrd_below_start_ok = 1;
|
||||
#endif
|
||||
|
||||
/* setup memblock allocator */
|
||||
setup_memory();
|
||||
|
||||
/* paging_init() sets up the MMU and marks all pages as reserved */
|
||||
paging_init();
|
||||
|
||||
|
@ -520,7 +520,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
local_irq_disable();
|
||||
irq_enter();
|
||||
irq_enter_rcu();
|
||||
|
||||
eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
|
||||
if (!eirr_val)
|
||||
@ -555,7 +555,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
|
||||
#endif /* CONFIG_IRQSTACKS */
|
||||
|
||||
out:
|
||||
irq_exit();
|
||||
irq_exit_rcu();
|
||||
set_irq_regs(old_regs);
|
||||
return;
|
||||
|
||||
|
@ -114,8 +114,11 @@ static void *simple_realloc(void *ptr, unsigned long size)
|
||||
return ptr;
|
||||
|
||||
new = simple_malloc(size);
|
||||
memcpy(new, ptr, p->size);
|
||||
simple_free(ptr);
|
||||
if (new) {
|
||||
memcpy(new, ptr, p->size);
|
||||
simple_free(ptr);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
@ -235,6 +235,8 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr,
|
||||
rname = kasprintf(GFP_KERNEL, "CPU %d [0x%x] Interrupt Presentation",
|
||||
cpu, hw_id);
|
||||
|
||||
if (!rname)
|
||||
return -ENOMEM;
|
||||
if (!request_mem_region(addr, size, rname)) {
|
||||
pr_warn("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n",
|
||||
cpu, hw_id);
|
||||
|
@ -97,7 +97,10 @@ static inline int share(unsigned long addr, u16 cmd)
|
||||
|
||||
if (!uv_call(0, (u64)&uvcb))
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
pr_err("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n",
|
||||
uvcb.header.cmd == UVC_CMD_SET_SHARED_ACCESS ? "Share" : "Unshare",
|
||||
uvcb.header.rc, uvcb.header.rrc);
|
||||
panic("System security cannot be guaranteed unless the system panics now.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -793,7 +793,10 @@ unsigned long arch_align_stack(unsigned long sp)
|
||||
|
||||
unsigned long arch_randomize_brk(struct mm_struct *mm)
|
||||
{
|
||||
return randomize_page(mm->brk, 0x02000000);
|
||||
if (mmap_is_ia32())
|
||||
return randomize_page(mm->brk, SZ_32M);
|
||||
|
||||
return randomize_page(mm->brk, SZ_1G);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6141,6 +6141,9 @@ static void ata_host_release(struct kref *kref)
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap = host->ports[i];
|
||||
|
||||
if (!ap)
|
||||
continue;
|
||||
|
||||
kfree(ap->pmp_link);
|
||||
kfree(ap->slave_link);
|
||||
kfree(ap);
|
||||
|
@ -1117,8 +1117,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
|
||||
rpp->len += skb->len;
|
||||
|
||||
if (stat & SAR_RSQE_EPDU) {
|
||||
unsigned int len, truesize;
|
||||
unsigned char *l1l2;
|
||||
unsigned int len;
|
||||
|
||||
l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
|
||||
|
||||
@ -1188,14 +1188,15 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
|
||||
ATM_SKB(skb)->vcc = vcc;
|
||||
__net_timestamp(skb);
|
||||
|
||||
truesize = skb->truesize;
|
||||
vcc->push(vcc, skb);
|
||||
atomic_inc(&vcc->stats->rx);
|
||||
|
||||
if (skb->truesize > SAR_FB_SIZE_3)
|
||||
if (truesize > SAR_FB_SIZE_3)
|
||||
add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
|
||||
else if (skb->truesize > SAR_FB_SIZE_2)
|
||||
else if (truesize > SAR_FB_SIZE_2)
|
||||
add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
|
||||
else if (skb->truesize > SAR_FB_SIZE_1)
|
||||
else if (truesize > SAR_FB_SIZE_1)
|
||||
add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
|
||||
else
|
||||
add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
|
||||
|
@ -765,7 +765,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
break;
|
||||
|
||||
case HCIUARTGETPROTO:
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags) &&
|
||||
test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
err = hu->proto->id;
|
||||
else
|
||||
err = -EUNATCH;
|
||||
|
@ -401,16 +401,24 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
switch (args->in.op) {
|
||||
case AMDGPU_CTX_OP_ALLOC_CTX:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
|
||||
args->out.alloc.ctx_id = id;
|
||||
break;
|
||||
case AMDGPU_CTX_OP_FREE_CTX:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_free(fpriv, id);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_QUERY_STATE:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_QUERY_STATE2:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
default:
|
||||
|
@ -715,7 +715,8 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
|
||||
uint32_t created = 0;
|
||||
uint32_t allocated = 0;
|
||||
uint32_t tmp, handle = 0;
|
||||
uint32_t *size = &tmp;
|
||||
uint32_t dummy = 0xffffffff;
|
||||
uint32_t *size = &dummy;
|
||||
unsigned idx;
|
||||
int i, r = 0;
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
|
||||
if (args->size != PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
offset = amdgpu_amdkfd_get_mmio_remap_phys_addr(dev->kgd);
|
||||
if (!offset)
|
||||
if (!offset || (PAGE_SIZE > 4096))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1872,6 +1872,9 @@ static int kfd_mmio_mmap(struct kfd_dev *dev, struct kfd_process *process,
|
||||
if (vma->vm_end - vma->vm_start != PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (PAGE_SIZE > 4096)
|
||||
return -EINVAL;
|
||||
|
||||
address = amdgpu_amdkfd_get_mmio_remap_phys_addr(dev->kgd);
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE |
|
||||
|
@ -138,6 +138,11 @@ static void lima_gp_task_run(struct lima_sched_pipe *pipe,
|
||||
gp_write(LIMA_GP_CMD, cmd);
|
||||
}
|
||||
|
||||
static int lima_gp_bus_stop_poll(struct lima_ip *ip)
|
||||
{
|
||||
return !!(gp_read(LIMA_GP_STATUS) & LIMA_GP_STATUS_BUS_STOPPED);
|
||||
}
|
||||
|
||||
static int lima_gp_hard_reset_poll(struct lima_ip *ip)
|
||||
{
|
||||
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
|
||||
@ -151,6 +156,13 @@ static int lima_gp_hard_reset(struct lima_ip *ip)
|
||||
|
||||
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
|
||||
gp_write(LIMA_GP_INT_MASK, 0);
|
||||
|
||||
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_STOP_BUS);
|
||||
ret = lima_poll_timeout(ip, lima_gp_bus_stop_poll, 10, 100);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "%s bus stop timeout\n", lima_ip_name(ip));
|
||||
return ret;
|
||||
}
|
||||
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
|
||||
ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
|
||||
if (ret) {
|
||||
|
@ -30,24 +30,14 @@
|
||||
* @fmt: Pointer to format string
|
||||
*/
|
||||
#define DPU_DEBUG(fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_KMS)) \
|
||||
DRM_DEBUG(fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* DPU_DEBUG_DRIVER - macro for hardware driver logging
|
||||
* @fmt: Pointer to format string
|
||||
*/
|
||||
#define DPU_DEBUG_DRIVER(fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
|
||||
DRM_ERROR(fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)
|
||||
#define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
|
||||
|
@ -866,7 +866,15 @@
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
|
||||
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
|
||||
#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de
|
||||
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
|
||||
/*
|
||||
* For a description of the Xbox controller models, refer to:
|
||||
* https://en.wikipedia.org/wiki/Xbox_Wireless_Controller#Summary
|
||||
*/
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708 0x02fd
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE 0x0b20
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914 0x0b13
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797 0x0b05
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE 0x0b22
|
||||
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
|
||||
#define SPI_DEVICE_ID_MS_SURFACE_D6_0 0x0c1d
|
||||
#define SPI_DEVICE_ID_MS_SURFACE_D6_1 0x0c42
|
||||
|
@ -456,7 +456,16 @@ static const struct hid_device_id ms_devices[] = {
|
||||
.driver_data = MS_PRESENTER },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
|
||||
.driver_data = MS_SURFACE_DIAL },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
|
||||
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_SPI_DEVICE(USB_VENDOR_ID_MICROSOFT, SPI_DEVICE_ID_MS_SURFACE_D6_0),
|
||||
.driver_data = MS_NOHIDINPUT },
|
||||
|
@ -1920,12 +1920,14 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
|
||||
int fmax = field->logical_maximum;
|
||||
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
int resolution_code = code;
|
||||
int resolution = hidinput_calc_abs_res(field, resolution_code);
|
||||
int resolution;
|
||||
|
||||
if (equivalent_usage == HID_DG_TWIST) {
|
||||
resolution_code = ABS_RZ;
|
||||
}
|
||||
|
||||
resolution = hidinput_calc_abs_res(field, resolution_code);
|
||||
|
||||
if (equivalent_usage == HID_GD_X) {
|
||||
fmin += features->offset_left;
|
||||
fmax -= features->offset_right;
|
||||
|
@ -312,7 +312,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
|
||||
* frequency with only 62 clock ticks max (31 high, 31 low).
|
||||
* Aim for a duty of 60% LOW, 40% HIGH.
|
||||
*/
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
|
||||
|
||||
for (cks = 0; cks < 7; cks++) {
|
||||
/*
|
||||
|
@ -13067,15 +13067,16 @@ static void read_mod_write(struct hfi1_devdata *dd, u16 src, u64 bits,
|
||||
{
|
||||
u64 reg;
|
||||
u16 idx = src / BITS_PER_REGISTER;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&dd->irq_src_lock);
|
||||
spin_lock_irqsave(&dd->irq_src_lock, flags);
|
||||
reg = read_csr(dd, CCE_INT_MASK + (8 * idx));
|
||||
if (set)
|
||||
reg |= bits;
|
||||
else
|
||||
reg &= ~bits;
|
||||
write_csr(dd, CCE_INT_MASK + (8 * idx), reg);
|
||||
spin_unlock(&dd->irq_src_lock);
|
||||
spin_unlock_irqrestore(&dd->irq_src_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,6 +45,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
|
||||
return 0;
|
||||
if (mt)
|
||||
return mt->num_slots != num_slots ? -EINVAL : 0;
|
||||
/* Arbitrary limit for avoiding too large memory allocation. */
|
||||
if (num_slots > 1024)
|
||||
return -EINVAL;
|
||||
|
||||
mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
|
||||
if (!mt)
|
||||
|
@ -3085,8 +3085,6 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
|
||||
struct page *vprop_page;
|
||||
int base, nr_ids, i, err = 0;
|
||||
|
||||
BUG_ON(!vm);
|
||||
|
||||
bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids);
|
||||
if (!bitmap)
|
||||
return -ENOMEM;
|
||||
|
@ -471,11 +471,6 @@ static void __destroy_persistent_data_structures(struct dm_clone_metadata *cmd)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static size_t bitmap_size(unsigned long nr_bits)
|
||||
{
|
||||
return BITS_TO_LONGS(nr_bits) * sizeof(long);
|
||||
}
|
||||
|
||||
static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
|
||||
unsigned long nr_regions)
|
||||
{
|
||||
|
@ -1064,8 +1064,26 @@ static int do_resume(struct dm_ioctl *param)
|
||||
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
|
||||
if (param->flags & DM_NOFLUSH_FLAG)
|
||||
suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
|
||||
if (!dm_suspended_md(md))
|
||||
dm_suspend(md, suspend_flags);
|
||||
if (!dm_suspended_md(md)) {
|
||||
r = dm_suspend(md, suspend_flags);
|
||||
if (r) {
|
||||
down_write(&_hash_lock);
|
||||
hc = dm_get_mdptr(md);
|
||||
if (hc && !hc->new_map) {
|
||||
hc->new_map = new_map;
|
||||
new_map = NULL;
|
||||
} else {
|
||||
r = -ENXIO;
|
||||
}
|
||||
up_write(&_hash_lock);
|
||||
if (new_map) {
|
||||
dm_sync_table(md);
|
||||
dm_table_destroy(new_map);
|
||||
}
|
||||
dm_put(md);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
old_map = dm_swap_table(md, new_map);
|
||||
if (IS_ERR(old_map)) {
|
||||
|
@ -558,7 +558,8 @@ static void multipath_release_clone(struct request *clone,
|
||||
if (pgpath && pgpath->pg->ps.type->end_io)
|
||||
pgpath->pg->ps.type->end_io(&pgpath->pg->ps,
|
||||
&pgpath->path,
|
||||
mpio->nr_bytes);
|
||||
mpio->nr_bytes,
|
||||
clone->io_start_time_ns);
|
||||
}
|
||||
|
||||
blk_put_request(clone);
|
||||
@ -1568,7 +1569,8 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
|
||||
struct path_selector *ps = &pgpath->pg->ps;
|
||||
|
||||
if (ps->type->end_io)
|
||||
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
|
||||
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes,
|
||||
clone->io_start_time_ns);
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -1612,7 +1614,8 @@ done:
|
||||
struct path_selector *ps = &pgpath->pg->ps;
|
||||
|
||||
if (ps->type->end_io)
|
||||
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
|
||||
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes,
|
||||
dm_start_time_ns_from_clone(clone));
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -74,7 +74,7 @@ struct path_selector_type {
|
||||
int (*start_io) (struct path_selector *ps, struct dm_path *path,
|
||||
size_t nr_bytes);
|
||||
int (*end_io) (struct path_selector *ps, struct dm_path *path,
|
||||
size_t nr_bytes);
|
||||
size_t nr_bytes, u64 start_time);
|
||||
};
|
||||
|
||||
/* Register a path selector */
|
||||
|
@ -227,7 +227,7 @@ static int ql_start_io(struct path_selector *ps, struct dm_path *path,
|
||||
}
|
||||
|
||||
static int ql_end_io(struct path_selector *ps, struct dm_path *path,
|
||||
size_t nr_bytes)
|
||||
size_t nr_bytes, u64 start_time)
|
||||
{
|
||||
struct path_info *pi = path->pscontext;
|
||||
|
||||
|
@ -143,10 +143,6 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig)
|
||||
*/
|
||||
static void rq_completed(struct mapped_device *md)
|
||||
{
|
||||
/* nudge anyone waiting on suspend queue */
|
||||
if (unlikely(wq_has_sleeper(&md->wait)))
|
||||
wake_up(&md->wait);
|
||||
|
||||
/*
|
||||
* dm_put() must be at the end of this function. See the comment above
|
||||
*/
|
||||
|
@ -309,7 +309,7 @@ static int st_start_io(struct path_selector *ps, struct dm_path *path,
|
||||
}
|
||||
|
||||
static int st_end_io(struct path_selector *ps, struct dm_path *path,
|
||||
size_t nr_bytes)
|
||||
size_t nr_bytes, u64 start_time)
|
||||
{
|
||||
struct path_info *pi = path->pscontext;
|
||||
|
||||
|
@ -665,27 +665,14 @@ static void free_tio(struct dm_target_io *tio)
|
||||
bio_put(&tio->clone);
|
||||
}
|
||||
|
||||
static bool md_in_flight_bios(struct mapped_device *md)
|
||||
u64 dm_start_time_ns_from_clone(struct bio *bio)
|
||||
{
|
||||
int cpu;
|
||||
struct hd_struct *part = &dm_disk(md)->part0;
|
||||
long sum = 0;
|
||||
struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
|
||||
struct dm_io *io = tio->io;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
|
||||
sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
|
||||
}
|
||||
|
||||
return sum != 0;
|
||||
}
|
||||
|
||||
static bool md_in_flight(struct mapped_device *md)
|
||||
{
|
||||
if (queue_is_mq(md->queue))
|
||||
return blk_mq_queue_inflight(md->queue);
|
||||
else
|
||||
return md_in_flight_bios(md);
|
||||
return jiffies_to_nsecs(io->start_time);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone);
|
||||
|
||||
static void start_io_acct(struct dm_io *io)
|
||||
{
|
||||
@ -2571,19 +2558,33 @@ void dm_put(struct mapped_device *md)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_put);
|
||||
|
||||
static int dm_wait_for_completion(struct mapped_device *md, long task_state)
|
||||
static bool md_in_flight_bios(struct mapped_device *md)
|
||||
{
|
||||
int cpu;
|
||||
struct hd_struct *part = &dm_disk(md)->part0;
|
||||
long sum = 0;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
|
||||
sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
|
||||
}
|
||||
|
||||
return sum != 0;
|
||||
}
|
||||
|
||||
static int dm_wait_for_bios_completion(struct mapped_device *md, long task_state)
|
||||
{
|
||||
int r = 0;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
prepare_to_wait(&md->wait, &wait, task_state);
|
||||
|
||||
if (!md_in_flight(md))
|
||||
if (!md_in_flight_bios(md))
|
||||
break;
|
||||
|
||||
if (signal_pending_state(task_state, current)) {
|
||||
r = -EINTR;
|
||||
r = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2596,6 +2597,28 @@ static int dm_wait_for_completion(struct mapped_device *md, long task_state)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int dm_wait_for_completion(struct mapped_device *md, long task_state)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (!queue_is_mq(md->queue))
|
||||
return dm_wait_for_bios_completion(md, task_state);
|
||||
|
||||
while (true) {
|
||||
if (!blk_mq_queue_inflight(md->queue))
|
||||
break;
|
||||
|
||||
if (signal_pending_state(task_state, current)) {
|
||||
r = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(5);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the deferred bios
|
||||
*/
|
||||
|
@ -7396,11 +7396,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
|
||||
mddev = bdev->bd_disk->private_data;
|
||||
|
||||
if (!mddev) {
|
||||
BUG();
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Some actions do not requires the mutex */
|
||||
switch (cmd) {
|
||||
case GET_ARRAY_INFO:
|
||||
|
@ -275,7 +275,7 @@ static void sm_metadata_destroy(struct dm_space_map *sm)
|
||||
{
|
||||
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
|
||||
|
||||
kfree(smm);
|
||||
kvfree(smm);
|
||||
}
|
||||
|
||||
static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
|
||||
@ -759,7 +759,7 @@ struct dm_space_map *dm_sm_metadata_init(void)
|
||||
{
|
||||
struct sm_metadata *smm;
|
||||
|
||||
smm = kmalloc(sizeof(*smm), GFP_KERNEL);
|
||||
smm = kvmalloc(sizeof(*smm), GFP_KERNEL);
|
||||
if (!smm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -1299,6 +1299,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
/* register Video device */
|
||||
dev->video_dev = cx23885_vdev_init(dev, dev->pci,
|
||||
&cx23885_video_template, "video");
|
||||
if (!dev->video_dev) {
|
||||
err = -ENOMEM;
|
||||
goto fail_unreg;
|
||||
}
|
||||
dev->video_dev->queue = &dev->vb2_vidq;
|
||||
dev->video_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
||||
V4L2_CAP_AUDIO | V4L2_CAP_VIDEO_CAPTURE;
|
||||
@ -1317,6 +1321,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
/* register VBI device */
|
||||
dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
|
||||
&cx23885_vbi_template, "vbi");
|
||||
if (!dev->vbi_dev) {
|
||||
err = -ENOMEM;
|
||||
goto fail_unreg;
|
||||
}
|
||||
dev->vbi_dev->queue = &dev->vb2_vbiq;
|
||||
dev->vbi_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
||||
V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE;
|
||||
|
@ -57,16 +57,16 @@
|
||||
#define SOLO_MP4E_EXT_ADDR(__solo) \
|
||||
(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
|
||||
#define SOLO_MP4E_EXT_SIZE(__solo) \
|
||||
max((__solo->nr_chans * 0x00080000), \
|
||||
min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
|
||||
clamp(__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo) - \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo), \
|
||||
__solo->nr_chans * 0x00080000, 0x00ff0000)
|
||||
|
||||
#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000)
|
||||
#define SOLO_JPEG_EXT_ADDR(__solo) \
|
||||
(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
|
||||
#define SOLO_JPEG_EXT_SIZE(__solo) \
|
||||
max(__SOLO_JPEG_MIN_SIZE(__solo), \
|
||||
min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
|
||||
clamp(__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo), \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo), 0x00ff0000)
|
||||
|
||||
#define SOLO_SDRAM_END(__solo) \
|
||||
(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
|
||||
|
@ -36,7 +36,7 @@ static int radio_isa_querycap(struct file *file, void *priv,
|
||||
|
||||
strscpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
|
||||
strscpy(v->card, isa->drv->card, sizeof(v->card));
|
||||
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
|
||||
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev_name(isa->v4l2_dev.dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -723,11 +723,11 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
unsigned long flags;
|
||||
u64 timestamp;
|
||||
u32 delta_stc;
|
||||
u32 y1, y2;
|
||||
u32 y1;
|
||||
u32 x1, x2;
|
||||
u32 mean;
|
||||
u32 sof;
|
||||
u64 y;
|
||||
u64 y, y2;
|
||||
|
||||
if (!uvc_hw_timestamps_param)
|
||||
return;
|
||||
@ -767,7 +767,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
sof = y;
|
||||
|
||||
uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
|
||||
"(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
|
||||
"(x1 %u x2 %u y1 %u y2 %llu SOF offset %u)\n",
|
||||
stream->dev->name, buf->pts,
|
||||
y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
|
||||
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
|
||||
@ -782,7 +782,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
goto done;
|
||||
|
||||
y1 = NSEC_PER_SEC;
|
||||
y2 = (u32)ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1;
|
||||
y2 = ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1;
|
||||
|
||||
/* Interpolated and host SOF timestamps can wrap around at slightly
|
||||
* different times. Handle this by adding or removing 2048 to or from
|
||||
@ -802,7 +802,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
|
||||
timestamp = ktime_to_ns(first->host_time) + y - y1;
|
||||
|
||||
uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu "
|
||||
"buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
|
||||
"buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %llu)\n",
|
||||
stream->dev->name,
|
||||
sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
|
||||
y, timestamp, vbuf->vb2_buf.timestamp,
|
||||
|
@ -3097,13 +3097,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
|
||||
test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
|
||||
if (!test->highmem) {
|
||||
count = -ENOMEM;
|
||||
goto free_test_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
if (test->buffer && test->highmem) {
|
||||
#else
|
||||
if (test->buffer) {
|
||||
#endif
|
||||
mutex_lock(&mmc_test_lock);
|
||||
mmc_test_run(test, testcase);
|
||||
mutex_unlock(&mmc_test_lock);
|
||||
@ -3111,6 +3111,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
__free_pages(test->highmem, BUFFER_ORDER);
|
||||
free_test_buffer:
|
||||
#endif
|
||||
kfree(test->buffer);
|
||||
kfree(test);
|
||||
|
@ -3179,6 +3179,10 @@ int dw_mci_probe(struct dw_mci *host)
|
||||
host->biu_clk = devm_clk_get(host->dev, "biu");
|
||||
if (IS_ERR(host->biu_clk)) {
|
||||
dev_dbg(host->dev, "biu clock not available\n");
|
||||
ret = PTR_ERR(host->biu_clk);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
ret = clk_prepare_enable(host->biu_clk);
|
||||
if (ret) {
|
||||
@ -3190,6 +3194,10 @@ int dw_mci_probe(struct dw_mci *host)
|
||||
host->ciu_clk = devm_clk_get(host->dev, "ciu");
|
||||
if (IS_ERR(host->ciu_clk)) {
|
||||
dev_dbg(host->dev, "ciu clock not available\n");
|
||||
ret = PTR_ERR(host->ciu_clk);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto err_clk_biu;
|
||||
|
||||
host->bus_hz = host->pdata->bus_hz;
|
||||
} else {
|
||||
ret = clk_prepare_enable(host->ciu_clk);
|
||||
|
@ -14,3 +14,7 @@ mv88e6xxx-objs += port_hidden.o
|
||||
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o
|
||||
mv88e6xxx-objs += serdes.o
|
||||
mv88e6xxx-objs += smi.o
|
||||
mv88e6xxx-objs += trace.o
|
||||
|
||||
# for tracing framework to find trace.h
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
@ -339,5 +339,6 @@ int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
|
||||
int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip);
|
||||
int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip);
|
||||
void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip);
|
||||
int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid);
|
||||
|
||||
#endif /* _MV88E6XXX_GLOBAL1_H */
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "chip.h"
|
||||
#include "global1.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* Offset 0x01: ATU FID Register */
|
||||
|
||||
@ -82,6 +83,19 @@ static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
|
||||
return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_g1_read_atu_violation(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_OP,
|
||||
MV88E6XXX_G1_ATU_OP_BUSY |
|
||||
MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mv88e6xxx_g1_atu_op_wait(chip);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
|
||||
{
|
||||
u16 val;
|
||||
@ -122,6 +136,46 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
|
||||
return mv88e6xxx_g1_atu_op_wait(chip);
|
||||
}
|
||||
|
||||
int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid)
|
||||
{
|
||||
return mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_g1_atu_fid_read(struct mv88e6xxx_chip *chip, u16 *fid)
|
||||
{
|
||||
u16 val = 0, upper = 0, op = 0;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
if (mv88e6xxx_num_databases(chip) > 256) {
|
||||
err = mv88e6xxx_g1_read(chip, MV88E6352_G1_ATU_FID, &val);
|
||||
val &= 0xfff;
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_OP, &op);
|
||||
if (err)
|
||||
return err;
|
||||
if (mv88e6xxx_num_databases(chip) > 64) {
|
||||
/* ATU DBNum[7:4] are located in ATU Control 15:12 */
|
||||
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL,
|
||||
&upper);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
upper = (upper >> 8) & 0x00f0;
|
||||
} else if (mv88e6xxx_num_databases(chip) > 16) {
|
||||
/* ATU DBNum[5:4] are located in ATU Operation 9:8 */
|
||||
upper = (op >> 4) & 0x30;
|
||||
}
|
||||
|
||||
/* ATU DBNum[3:0] are located in ATU Operation 3:0 */
|
||||
val = (op & 0xf) | upper;
|
||||
}
|
||||
*fid = val;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Offset 0x0C: ATU Data Register */
|
||||
|
||||
static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip *chip,
|
||||
@ -316,14 +370,12 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = dev_id;
|
||||
struct mv88e6xxx_atu_entry entry;
|
||||
int spid;
|
||||
int err;
|
||||
u16 val;
|
||||
int err, spid;
|
||||
u16 val, fid;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
err = mv88e6xxx_g1_atu_op(chip, 0,
|
||||
MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION);
|
||||
err = mv88e6xxx_g1_read_atu_violation(chip);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -331,6 +383,10 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mv88e6xxx_g1_atu_fid_read(chip, &fid);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mv88e6xxx_g1_atu_data_read(chip, &entry);
|
||||
if (err)
|
||||
goto out;
|
||||
@ -348,24 +404,25 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
|
||||
dev_err_ratelimited(chip->dev,
|
||||
"ATU member violation for %pM portvec %x spid %d\n",
|
||||
entry.mac, entry.portvec, spid);
|
||||
trace_mv88e6xxx_atu_member_violation(chip->dev, spid,
|
||||
entry.portvec, entry.mac,
|
||||
fid);
|
||||
chip->ports[spid].atu_member_violation++;
|
||||
}
|
||||
|
||||
if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
|
||||
dev_err_ratelimited(chip->dev,
|
||||
"ATU miss violation for %pM portvec %x spid %d\n",
|
||||
entry.mac, entry.portvec, spid);
|
||||
trace_mv88e6xxx_atu_miss_violation(chip->dev, spid,
|
||||
entry.portvec, entry.mac,
|
||||
fid);
|
||||
chip->ports[spid].atu_miss_violation++;
|
||||
}
|
||||
|
||||
if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
|
||||
dev_err_ratelimited(chip->dev,
|
||||
"ATU full violation for %pM portvec %x spid %d\n",
|
||||
entry.mac, entry.portvec, spid);
|
||||
chip->ports[spid].atu_full_violation++;
|
||||
trace_mv88e6xxx_atu_full_violation(chip->dev, spid,
|
||||
entry.portvec, entry.mac,
|
||||
fid);
|
||||
if (spid < ARRAY_SIZE(chip->ports))
|
||||
chip->ports[spid].atu_full_violation++;
|
||||
}
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
|
@ -280,6 +280,19 @@ int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Offset 0x0E: ATU Statistics */
|
||||
|
||||
int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin)
|
||||
{
|
||||
return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_ATU_STATS,
|
||||
kind | bin);
|
||||
}
|
||||
|
||||
int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats)
|
||||
{
|
||||
return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_ATU_STATS, stats);
|
||||
}
|
||||
|
||||
/* Offset 0x0F: Priority Override Table */
|
||||
|
||||
static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
|
||||
|
@ -113,7 +113,16 @@
|
||||
#define MV88E6XXX_G2_SWITCH_MAC_DATA_MASK 0x00ff
|
||||
|
||||
/* Offset 0x0E: ATU Stats Register */
|
||||
#define MV88E6XXX_G2_ATU_STATS 0x0e
|
||||
#define MV88E6XXX_G2_ATU_STATS 0x0e
|
||||
#define MV88E6XXX_G2_ATU_STATS_BIN_0 (0x0 << 14)
|
||||
#define MV88E6XXX_G2_ATU_STATS_BIN_1 (0x1 << 14)
|
||||
#define MV88E6XXX_G2_ATU_STATS_BIN_2 (0x2 << 14)
|
||||
#define MV88E6XXX_G2_ATU_STATS_BIN_3 (0x3 << 14)
|
||||
#define MV88E6XXX_G2_ATU_STATS_MODE_ALL (0x0 << 12)
|
||||
#define MV88E6XXX_G2_ATU_STATS_MODE_ALL_DYNAMIC (0x1 << 12)
|
||||
#define MV88E6XXX_G2_ATU_STATS_MODE_FID_ALL (0x2 << 12)
|
||||
#define MV88E6XXX_G2_ATU_STATS_MODE_FID_ALL_DYNAMIC (0x3 << 12)
|
||||
#define MV88E6XXX_G2_ATU_STATS_MASK 0x0fff
|
||||
|
||||
/* Offset 0x0F: Priority Override Table */
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE 0x0f
|
||||
@ -354,6 +363,8 @@ extern const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops;
|
||||
|
||||
int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip,
|
||||
bool external);
|
||||
int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin);
|
||||
int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats);
|
||||
|
||||
#else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
|
||||
|
||||
@ -516,6 +527,18 @@ static inline int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip,
|
||||
u16 kind, u16 bin)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip,
|
||||
u16 *stats)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
|
||||
|
||||
#endif /* _MV88E6XXX_GLOBAL2_H */
|
||||
|
6
drivers/net/dsa/mv88e6xxx/trace.c
Normal file
6
drivers/net/dsa/mv88e6xxx/trace.c
Normal file
@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Copyright 2022 NXP
|
||||
*/
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
66
drivers/net/dsa/mv88e6xxx/trace.h
Normal file
66
drivers/net/dsa/mv88e6xxx/trace.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright 2022 NXP
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM mv88e6xxx
|
||||
|
||||
#if !defined(_MV88E6XXX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _MV88E6XXX_TRACE_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
DECLARE_EVENT_CLASS(mv88e6xxx_atu_violation,
|
||||
|
||||
TP_PROTO(const struct device *dev, int spid, u16 portvec,
|
||||
const unsigned char *addr, u16 fid),
|
||||
|
||||
TP_ARGS(dev, spid, portvec, addr, fid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, dev_name(dev))
|
||||
__field(int, spid)
|
||||
__field(u16, portvec)
|
||||
__array(unsigned char, addr, ETH_ALEN)
|
||||
__field(u16, fid)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, dev_name(dev));
|
||||
__entry->spid = spid;
|
||||
__entry->portvec = portvec;
|
||||
memcpy(__entry->addr, addr, ETH_ALEN);
|
||||
__entry->fid = fid;
|
||||
),
|
||||
|
||||
TP_printk("dev %s spid %d portvec 0x%x addr %pM fid %u",
|
||||
__get_str(name), __entry->spid, __entry->portvec,
|
||||
__entry->addr, __entry->fid)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_member_violation,
|
||||
TP_PROTO(const struct device *dev, int spid, u16 portvec,
|
||||
const unsigned char *addr, u16 fid),
|
||||
TP_ARGS(dev, spid, portvec, addr, fid));
|
||||
|
||||
DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_miss_violation,
|
||||
TP_PROTO(const struct device *dev, int spid, u16 portvec,
|
||||
const unsigned char *addr, u16 fid),
|
||||
TP_ARGS(dev, spid, portvec, addr, fid));
|
||||
|
||||
DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_full_violation,
|
||||
TP_PROTO(const struct device *dev, int spid, u16 portvec,
|
||||
const unsigned char *addr, u16 fid),
|
||||
TP_ARGS(dev, spid, portvec, addr, fid));
|
||||
|
||||
#endif /* _MV88E6XXX_TRACE_H */
|
||||
|
||||
/* We don't want to use include/trace/events */
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
@ -531,7 +531,7 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum,
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd = (phy << 21) | (regnum << 16);
|
||||
cmd = (phy << 21) | (regnum << 16) | val;
|
||||
ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -969,7 +969,8 @@ static u64 hash_filter_ntuple(struct ch_filter_specification *fs,
|
||||
* in the Compressed Filter Tuple.
|
||||
*/
|
||||
if (tp->vlan_shift >= 0 && fs->mask.ivlan)
|
||||
ntuple |= (FT_VLAN_VLD_F | fs->val.ivlan) << tp->vlan_shift;
|
||||
ntuple |= (u64)(FT_VLAN_VLD_F |
|
||||
fs->val.ivlan) << tp->vlan_shift;
|
||||
|
||||
if (tp->port_shift >= 0 && fs->mask.iport)
|
||||
ntuple |= (u64)fs->val.iport << tp->port_shift;
|
||||
|
@ -4388,6 +4388,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
int ret;
|
||||
|
||||
if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
|
||||
hns3_nic_net_stop(netdev);
|
||||
|
||||
if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
|
||||
netdev_warn(netdev, "already uninitialized\n");
|
||||
return 0;
|
||||
|
@ -990,7 +990,7 @@ static void sun3_82586_timeout(struct net_device *dev)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
|
||||
printk("%s: command-stats: %04x %04x\n",dev->name,swab16(p->xmit_cmds[0]->cmd_status),swab16(p->xmit_cmds[1]->cmd_status));
|
||||
printk("%s: command-stats: %04x\n", dev->name, swab16(p->xmit_cmds[0]->cmd_status));
|
||||
printk("%s: check, whether you set the right interrupt number!\n",dev->name);
|
||||
#endif
|
||||
sun3_82586_close(dev);
|
||||
|
@ -676,7 +676,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
|
||||
if (num_tuples <= 0) {
|
||||
netdev_warn(priv->netdev, "%s: flow is not valid %d\n",
|
||||
__func__, num_tuples);
|
||||
return num_tuples;
|
||||
return num_tuples < 0 ? num_tuples : -EINVAL;
|
||||
}
|
||||
|
||||
eth_ft = get_flow_table(priv, fs, num_tuples);
|
||||
|
@ -159,22 +159,17 @@
|
||||
#define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */
|
||||
#define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */
|
||||
#define XAE_FCC_OFFSET 0x0000040C /* Flow Control Configuration */
|
||||
#define XAE_EMMC_OFFSET 0x00000410 /* EMAC mode configuration */
|
||||
#define XAE_PHYC_OFFSET 0x00000414 /* RGMII/SGMII configuration */
|
||||
#define XAE_MDIO_MC_OFFSET 0x00000500 /* MII Management Config */
|
||||
#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MII Management Control */
|
||||
#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MII Management Write Data */
|
||||
#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MII Management Read Data */
|
||||
#define XAE_MDIO_MIS_OFFSET 0x00000600 /* MII Management Interrupt Status */
|
||||
/* MII Mgmt Interrupt Pending register offset */
|
||||
#define XAE_MDIO_MIP_OFFSET 0x00000620
|
||||
/* MII Management Interrupt Enable register offset */
|
||||
#define XAE_MDIO_MIE_OFFSET 0x00000640
|
||||
/* MII Management Interrupt Clear register offset. */
|
||||
#define XAE_MDIO_MIC_OFFSET 0x00000660
|
||||
#define XAE_EMMC_OFFSET 0x00000410 /* MAC speed configuration */
|
||||
#define XAE_PHYC_OFFSET 0x00000414 /* RX Max Frame Configuration */
|
||||
#define XAE_ID_OFFSET 0x000004F8 /* Identification register */
|
||||
#define XAE_MDIO_MC_OFFSET 0x00000500 /* MDIO Setup */
|
||||
#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MDIO Control */
|
||||
#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MDIO Write Data */
|
||||
#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MDIO Read Data */
|
||||
#define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */
|
||||
#define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */
|
||||
#define XAE_FMI_OFFSET 0x00000708 /* Filter Mask Index */
|
||||
#define XAE_FMI_OFFSET 0x00000708 /* Frame Filter Control */
|
||||
#define XAE_FFE_OFFSET 0x0000070C /* Frame Filter Enable */
|
||||
#define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */
|
||||
#define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */
|
||||
|
||||
@ -313,7 +308,7 @@
|
||||
*/
|
||||
#define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF
|
||||
|
||||
/* Bit masks for Axi Ethernet FMI register */
|
||||
/* Bit masks for Axi Ethernet FMC register */
|
||||
#define XAE_FMI_PM_MASK 0x80000000 /* Promis. mode enable */
|
||||
#define XAE_FMI_IND_MASK 0x00000003 /* Index Mask */
|
||||
|
||||
@ -335,6 +330,7 @@
|
||||
#define XAE_FEATURE_PARTIAL_TX_CSUM (1 << 1)
|
||||
#define XAE_FEATURE_FULL_RX_CSUM (1 << 2)
|
||||
#define XAE_FEATURE_FULL_TX_CSUM (1 << 3)
|
||||
#define XAE_FEATURE_DMA_64BIT (1 << 4)
|
||||
|
||||
#define XAE_NO_CSUM_OFFLOAD 0
|
||||
|
||||
@ -347,9 +343,9 @@
|
||||
/**
|
||||
* struct axidma_bd - Axi Dma buffer descriptor layout
|
||||
* @next: MM2S/S2MM Next Descriptor Pointer
|
||||
* @reserved1: Reserved and not used
|
||||
* @next_msb: MM2S/S2MM Next Descriptor Pointer (high 32 bits)
|
||||
* @phys: MM2S/S2MM Buffer Address
|
||||
* @reserved2: Reserved and not used
|
||||
* @phys_msb: MM2S/S2MM Buffer Address (high 32 bits)
|
||||
* @reserved3: Reserved and not used
|
||||
* @reserved4: Reserved and not used
|
||||
* @cntrl: MM2S/S2MM Control value
|
||||
@ -362,9 +358,9 @@
|
||||
*/
|
||||
struct axidma_bd {
|
||||
u32 next; /* Physical address of next buffer descriptor */
|
||||
u32 reserved1;
|
||||
u32 next_msb; /* high 32 bits for IP >= v7.1, reserved on older IP */
|
||||
u32 phys;
|
||||
u32 reserved2;
|
||||
u32 phys_msb; /* for IP >= v7.1, reserved for older IP */
|
||||
u32 reserved3;
|
||||
u32 reserved4;
|
||||
u32 cntrl;
|
||||
|
@ -148,6 +148,34 @@ static inline void axienet_dma_out32(struct axienet_local *lp,
|
||||
iowrite32(value, lp->dma_regs + reg);
|
||||
}
|
||||
|
||||
static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
axienet_dma_out32(lp, reg, lower_32_bits(addr));
|
||||
|
||||
if (lp->features & XAE_FEATURE_DMA_64BIT)
|
||||
axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
|
||||
}
|
||||
|
||||
static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
|
||||
struct axidma_bd *desc)
|
||||
{
|
||||
desc->phys = lower_32_bits(addr);
|
||||
if (lp->features & XAE_FEATURE_DMA_64BIT)
|
||||
desc->phys_msb = upper_32_bits(addr);
|
||||
}
|
||||
|
||||
static dma_addr_t desc_get_phys_addr(struct axienet_local *lp,
|
||||
struct axidma_bd *desc)
|
||||
{
|
||||
dma_addr_t ret = desc->phys;
|
||||
|
||||
if (lp->features & XAE_FEATURE_DMA_64BIT)
|
||||
ret |= ((dma_addr_t)desc->phys_msb << 16) << 16;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* axienet_dma_bd_release - Release buffer descriptor rings
|
||||
* @ndev: Pointer to the net_device structure
|
||||
@ -161,24 +189,41 @@ static void axienet_dma_bd_release(struct net_device *ndev)
|
||||
int i;
|
||||
struct axienet_local *lp = netdev_priv(ndev);
|
||||
|
||||
/* If we end up here, tx_bd_v must have been DMA allocated. */
|
||||
dma_free_coherent(ndev->dev.parent,
|
||||
sizeof(*lp->tx_bd_v) * lp->tx_bd_num,
|
||||
lp->tx_bd_v,
|
||||
lp->tx_bd_p);
|
||||
|
||||
if (!lp->rx_bd_v)
|
||||
return;
|
||||
|
||||
for (i = 0; i < lp->rx_bd_num; i++) {
|
||||
dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
|
||||
lp->max_frm_size, DMA_FROM_DEVICE);
|
||||
dma_addr_t phys;
|
||||
|
||||
/* A NULL skb means this descriptor has not been initialised
|
||||
* at all.
|
||||
*/
|
||||
if (!lp->rx_bd_v[i].skb)
|
||||
break;
|
||||
|
||||
dev_kfree_skb(lp->rx_bd_v[i].skb);
|
||||
|
||||
/* For each descriptor, we programmed cntrl with the (non-zero)
|
||||
* descriptor size, after it had been successfully allocated.
|
||||
* So a non-zero value in there means we need to unmap it.
|
||||
*/
|
||||
if (lp->rx_bd_v[i].cntrl) {
|
||||
phys = desc_get_phys_addr(lp, &lp->rx_bd_v[i]);
|
||||
dma_unmap_single(ndev->dev.parent, phys,
|
||||
lp->max_frm_size, DMA_FROM_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
if (lp->rx_bd_v) {
|
||||
dma_free_coherent(ndev->dev.parent,
|
||||
sizeof(*lp->rx_bd_v) * lp->rx_bd_num,
|
||||
lp->rx_bd_v,
|
||||
lp->rx_bd_p);
|
||||
}
|
||||
if (lp->tx_bd_v) {
|
||||
dma_free_coherent(ndev->dev.parent,
|
||||
sizeof(*lp->tx_bd_v) * lp->tx_bd_num,
|
||||
lp->tx_bd_v,
|
||||
lp->tx_bd_p);
|
||||
}
|
||||
dma_free_coherent(ndev->dev.parent,
|
||||
sizeof(*lp->rx_bd_v) * lp->rx_bd_num,
|
||||
lp->rx_bd_v,
|
||||
lp->rx_bd_p);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,7 +253,7 @@ static int axienet_dma_bd_init(struct net_device *ndev)
|
||||
sizeof(*lp->tx_bd_v) * lp->tx_bd_num,
|
||||
&lp->tx_bd_p, GFP_KERNEL);
|
||||
if (!lp->tx_bd_v)
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
|
||||
lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
|
||||
sizeof(*lp->rx_bd_v) * lp->rx_bd_num,
|
||||
@ -217,25 +262,37 @@ static int axienet_dma_bd_init(struct net_device *ndev)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < lp->tx_bd_num; i++) {
|
||||
lp->tx_bd_v[i].next = lp->tx_bd_p +
|
||||
sizeof(*lp->tx_bd_v) *
|
||||
((i + 1) % lp->tx_bd_num);
|
||||
dma_addr_t addr = lp->tx_bd_p +
|
||||
sizeof(*lp->tx_bd_v) *
|
||||
((i + 1) % lp->tx_bd_num);
|
||||
|
||||
lp->tx_bd_v[i].next = lower_32_bits(addr);
|
||||
if (lp->features & XAE_FEATURE_DMA_64BIT)
|
||||
lp->tx_bd_v[i].next_msb = upper_32_bits(addr);
|
||||
}
|
||||
|
||||
for (i = 0; i < lp->rx_bd_num; i++) {
|
||||
lp->rx_bd_v[i].next = lp->rx_bd_p +
|
||||
sizeof(*lp->rx_bd_v) *
|
||||
((i + 1) % lp->rx_bd_num);
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = lp->rx_bd_p + sizeof(*lp->rx_bd_v) *
|
||||
((i + 1) % lp->rx_bd_num);
|
||||
lp->rx_bd_v[i].next = lower_32_bits(addr);
|
||||
if (lp->features & XAE_FEATURE_DMA_64BIT)
|
||||
lp->rx_bd_v[i].next_msb = upper_32_bits(addr);
|
||||
|
||||
skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
lp->rx_bd_v[i].skb = skb;
|
||||
lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
|
||||
skb->data,
|
||||
lp->max_frm_size,
|
||||
DMA_FROM_DEVICE);
|
||||
addr = dma_map_single(ndev->dev.parent, skb->data,
|
||||
lp->max_frm_size, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(ndev->dev.parent, addr)) {
|
||||
netdev_err(ndev, "DMA mapping error\n");
|
||||
goto out;
|
||||
}
|
||||
desc_set_phys_addr(lp, addr, &lp->rx_bd_v[i]);
|
||||
|
||||
lp->rx_bd_v[i].cntrl = lp->max_frm_size;
|
||||
}
|
||||
|
||||
@ -268,18 +325,18 @@ static int axienet_dma_bd_init(struct net_device *ndev)
|
||||
/* Populate the tail pointer and bring the Rx Axi DMA engine out of
|
||||
* halted state. This will make the Rx side ready for reception.
|
||||
*/
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
|
||||
axienet_dma_out_addr(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
|
||||
cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
|
||||
cr | XAXIDMA_CR_RUNSTOP_MASK);
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
|
||||
(sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1)));
|
||||
axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
|
||||
(sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1)));
|
||||
|
||||
/* Write to the RS (Run-stop) bit in the Tx channel control register.
|
||||
* Tx channel is now ready to run. But only after we write to the
|
||||
* tail pointer register that the Tx channel will start transmitting.
|
||||
*/
|
||||
axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
|
||||
axienet_dma_out_addr(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
|
||||
cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
|
||||
axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
|
||||
cr | XAXIDMA_CR_RUNSTOP_MASK);
|
||||
@ -352,7 +409,7 @@ static int netdev_set_mac_address(struct net_device *ndev, void *p)
|
||||
*/
|
||||
static void axienet_set_multicast_list(struct net_device *ndev)
|
||||
{
|
||||
int i;
|
||||
int i = 0;
|
||||
u32 reg, af0reg, af1reg;
|
||||
struct axienet_local *lp = netdev_priv(ndev);
|
||||
|
||||
@ -370,7 +427,10 @@ static void axienet_set_multicast_list(struct net_device *ndev)
|
||||
} else if (!netdev_mc_empty(ndev)) {
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
i = 0;
|
||||
reg = axienet_ior(lp, XAE_FMI_OFFSET);
|
||||
reg &= ~XAE_FMI_PM_MASK;
|
||||
axienet_iow(lp, XAE_FMI_OFFSET, reg);
|
||||
|
||||
netdev_for_each_mc_addr(ha, ndev) {
|
||||
if (i >= XAE_MULTICAST_CAM_TABLE_NUM)
|
||||
break;
|
||||
@ -389,6 +449,7 @@ static void axienet_set_multicast_list(struct net_device *ndev)
|
||||
axienet_iow(lp, XAE_FMI_OFFSET, reg);
|
||||
axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
|
||||
axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
|
||||
axienet_iow(lp, XAE_FFE_OFFSET, 1);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
@ -396,18 +457,15 @@ static void axienet_set_multicast_list(struct net_device *ndev)
|
||||
reg &= ~XAE_FMI_PM_MASK;
|
||||
|
||||
axienet_iow(lp, XAE_FMI_OFFSET, reg);
|
||||
|
||||
for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
|
||||
reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
|
||||
reg |= i;
|
||||
|
||||
axienet_iow(lp, XAE_FMI_OFFSET, reg);
|
||||
axienet_iow(lp, XAE_AF0_OFFSET, 0);
|
||||
axienet_iow(lp, XAE_AF1_OFFSET, 0);
|
||||
}
|
||||
|
||||
dev_info(&ndev->dev, "Promiscuous mode disabled.\n");
|
||||
}
|
||||
|
||||
for (; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
|
||||
reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
|
||||
reg |= i;
|
||||
axienet_iow(lp, XAE_FMI_OFFSET, reg);
|
||||
axienet_iow(lp, XAE_FFE_OFFSET, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -532,6 +590,64 @@ static int axienet_device_reset(struct net_device *ndev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* axienet_free_tx_chain - Clean up a series of linked TX descriptors.
|
||||
* @ndev: Pointer to the net_device structure
|
||||
* @first_bd: Index of first descriptor to clean up
|
||||
* @nr_bds: Number of descriptors to clean up, can be -1 if unknown.
|
||||
* @sizep: Pointer to a u32 filled with the total sum of all bytes
|
||||
* in all cleaned-up descriptors. Ignored if NULL.
|
||||
*
|
||||
* Would either be called after a successful transmit operation, or after
|
||||
* there was an error when setting up the chain.
|
||||
* Returns the number of descriptors handled.
|
||||
*/
|
||||
static int axienet_free_tx_chain(struct net_device *ndev, u32 first_bd,
|
||||
int nr_bds, u32 *sizep)
|
||||
{
|
||||
struct axienet_local *lp = netdev_priv(ndev);
|
||||
struct axidma_bd *cur_p;
|
||||
int max_bds = nr_bds;
|
||||
unsigned int status;
|
||||
dma_addr_t phys;
|
||||
int i;
|
||||
|
||||
if (max_bds == -1)
|
||||
max_bds = lp->tx_bd_num;
|
||||
|
||||
for (i = 0; i < max_bds; i++) {
|
||||
cur_p = &lp->tx_bd_v[(first_bd + i) % lp->tx_bd_num];
|
||||
status = cur_p->status;
|
||||
|
||||
/* If no number is given, clean up *all* descriptors that have
|
||||
* been completed by the MAC.
|
||||
*/
|
||||
if (nr_bds == -1 && !(status & XAXIDMA_BD_STS_COMPLETE_MASK))
|
||||
break;
|
||||
|
||||
phys = desc_get_phys_addr(lp, cur_p);
|
||||
dma_unmap_single(ndev->dev.parent, phys,
|
||||
(cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK))
|
||||
dev_consume_skb_irq(cur_p->skb);
|
||||
|
||||
cur_p->cntrl = 0;
|
||||
cur_p->app0 = 0;
|
||||
cur_p->app1 = 0;
|
||||
cur_p->app2 = 0;
|
||||
cur_p->app4 = 0;
|
||||
cur_p->status = 0;
|
||||
cur_p->skb = NULL;
|
||||
|
||||
if (sizep)
|
||||
*sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* axienet_start_xmit_done - Invoked once a transmit is completed by the
|
||||
* Axi DMA Tx channel.
|
||||
@ -545,36 +661,15 @@ static int axienet_device_reset(struct net_device *ndev)
|
||||
*/
|
||||
static void axienet_start_xmit_done(struct net_device *ndev)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 packets = 0;
|
||||
struct axienet_local *lp = netdev_priv(ndev);
|
||||
struct axidma_bd *cur_p;
|
||||
unsigned int status = 0;
|
||||
u32 packets = 0;
|
||||
u32 size = 0;
|
||||
|
||||
cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
|
||||
status = cur_p->status;
|
||||
while (status & XAXIDMA_BD_STS_COMPLETE_MASK) {
|
||||
dma_unmap_single(ndev->dev.parent, cur_p->phys,
|
||||
(cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
|
||||
DMA_TO_DEVICE);
|
||||
if (cur_p->skb)
|
||||
dev_consume_skb_irq(cur_p->skb);
|
||||
/*cur_p->phys = 0;*/
|
||||
cur_p->app0 = 0;
|
||||
cur_p->app1 = 0;
|
||||
cur_p->app2 = 0;
|
||||
cur_p->app4 = 0;
|
||||
cur_p->status = 0;
|
||||
cur_p->skb = NULL;
|
||||
packets = axienet_free_tx_chain(ndev, lp->tx_bd_ci, -1, &size);
|
||||
|
||||
size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
|
||||
packets++;
|
||||
|
||||
if (++lp->tx_bd_ci >= lp->tx_bd_num)
|
||||
lp->tx_bd_ci = 0;
|
||||
cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
|
||||
status = cur_p->status;
|
||||
}
|
||||
lp->tx_bd_ci += packets;
|
||||
if (lp->tx_bd_ci >= lp->tx_bd_num)
|
||||
lp->tx_bd_ci -= lp->tx_bd_num;
|
||||
|
||||
ndev->stats.tx_packets += packets;
|
||||
ndev->stats.tx_bytes += size;
|
||||
@ -629,9 +724,10 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
u32 csum_start_off;
|
||||
u32 csum_index_off;
|
||||
skb_frag_t *frag;
|
||||
dma_addr_t tail_p;
|
||||
dma_addr_t tail_p, phys;
|
||||
struct axienet_local *lp = netdev_priv(ndev);
|
||||
struct axidma_bd *cur_p;
|
||||
u32 orig_tail_ptr = lp->tx_bd_tail;
|
||||
|
||||
num_frag = skb_shinfo(skb)->nr_frags;
|
||||
cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
|
||||
@ -667,19 +763,37 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */
|
||||
}
|
||||
|
||||
phys = dma_map_single(ndev->dev.parent, skb->data,
|
||||
skb_headlen(skb), DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(ndev->dev.parent, phys))) {
|
||||
if (net_ratelimit())
|
||||
netdev_err(ndev, "TX DMA mapping error\n");
|
||||
ndev->stats.tx_dropped++;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
desc_set_phys_addr(lp, phys, cur_p);
|
||||
cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK;
|
||||
cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
|
||||
skb_headlen(skb), DMA_TO_DEVICE);
|
||||
|
||||
for (ii = 0; ii < num_frag; ii++) {
|
||||
if (++lp->tx_bd_tail >= lp->tx_bd_num)
|
||||
lp->tx_bd_tail = 0;
|
||||
cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
|
||||
frag = &skb_shinfo(skb)->frags[ii];
|
||||
cur_p->phys = dma_map_single(ndev->dev.parent,
|
||||
skb_frag_address(frag),
|
||||
skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
phys = dma_map_single(ndev->dev.parent,
|
||||
skb_frag_address(frag),
|
||||
skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(ndev->dev.parent, phys))) {
|
||||
if (net_ratelimit())
|
||||
netdev_err(ndev, "TX DMA mapping error\n");
|
||||
ndev->stats.tx_dropped++;
|
||||
axienet_free_tx_chain(ndev, orig_tail_ptr, ii + 1,
|
||||
NULL);
|
||||
lp->tx_bd_tail = orig_tail_ptr;
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
desc_set_phys_addr(lp, phys, cur_p);
|
||||
cur_p->cntrl = skb_frag_size(frag);
|
||||
}
|
||||
|
||||
@ -688,7 +802,7 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
|
||||
tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
|
||||
/* Start the transfer */
|
||||
axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
|
||||
axienet_dma_out_addr(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
|
||||
if (++lp->tx_bd_tail >= lp->tx_bd_num)
|
||||
lp->tx_bd_tail = 0;
|
||||
|
||||
@ -718,10 +832,12 @@ static void axienet_recv(struct net_device *ndev)
|
||||
cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
|
||||
|
||||
while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
|
||||
dma_addr_t phys;
|
||||
|
||||
tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
|
||||
|
||||
dma_unmap_single(ndev->dev.parent, cur_p->phys,
|
||||
lp->max_frm_size,
|
||||
phys = desc_get_phys_addr(lp, cur_p);
|
||||
dma_unmap_single(ndev->dev.parent, phys, lp->max_frm_size,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
skb = cur_p->skb;
|
||||
@ -757,9 +873,17 @@ static void axienet_recv(struct net_device *ndev)
|
||||
if (!new_skb)
|
||||
return;
|
||||
|
||||
cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
|
||||
lp->max_frm_size,
|
||||
DMA_FROM_DEVICE);
|
||||
phys = dma_map_single(ndev->dev.parent, new_skb->data,
|
||||
lp->max_frm_size,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(ndev->dev.parent, phys))) {
|
||||
if (net_ratelimit())
|
||||
netdev_err(ndev, "RX DMA mapping error\n");
|
||||
dev_kfree_skb(new_skb);
|
||||
return;
|
||||
}
|
||||
desc_set_phys_addr(lp, phys, cur_p);
|
||||
|
||||
cur_p->cntrl = lp->max_frm_size;
|
||||
cur_p->status = 0;
|
||||
cur_p->skb = new_skb;
|
||||
@ -773,7 +897,7 @@ static void axienet_recv(struct net_device *ndev)
|
||||
ndev->stats.rx_bytes += size;
|
||||
|
||||
if (tail_p)
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
|
||||
axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -803,7 +927,8 @@ static irqreturn_t axienet_tx_irq(int irq, void *_ndev)
|
||||
return IRQ_NONE;
|
||||
if (status & XAXIDMA_IRQ_ERROR_MASK) {
|
||||
dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
|
||||
dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
|
||||
dev_err(&ndev->dev, "Current BD is at: 0x%x%08x\n",
|
||||
(lp->tx_bd_v[lp->tx_bd_ci]).phys_msb,
|
||||
(lp->tx_bd_v[lp->tx_bd_ci]).phys);
|
||||
|
||||
cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
|
||||
@ -852,7 +977,8 @@ static irqreturn_t axienet_rx_irq(int irq, void *_ndev)
|
||||
return IRQ_NONE;
|
||||
if (status & XAXIDMA_IRQ_ERROR_MASK) {
|
||||
dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
|
||||
dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
|
||||
dev_err(&ndev->dev, "Current BD is at: 0x%x%08x\n",
|
||||
(lp->rx_bd_v[lp->rx_bd_ci]).phys_msb,
|
||||
(lp->rx_bd_v[lp->rx_bd_ci]).phys);
|
||||
|
||||
cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
|
||||
@ -1182,10 +1308,6 @@ static void axienet_ethtools_get_regs(struct net_device *ndev,
|
||||
data[20] = axienet_ior(lp, XAE_MDIO_MCR_OFFSET);
|
||||
data[21] = axienet_ior(lp, XAE_MDIO_MWD_OFFSET);
|
||||
data[22] = axienet_ior(lp, XAE_MDIO_MRD_OFFSET);
|
||||
data[23] = axienet_ior(lp, XAE_MDIO_MIS_OFFSET);
|
||||
data[24] = axienet_ior(lp, XAE_MDIO_MIP_OFFSET);
|
||||
data[25] = axienet_ior(lp, XAE_MDIO_MIE_OFFSET);
|
||||
data[26] = axienet_ior(lp, XAE_MDIO_MIC_OFFSET);
|
||||
data[27] = axienet_ior(lp, XAE_UAW0_OFFSET);
|
||||
data[28] = axienet_ior(lp, XAE_UAW1_OFFSET);
|
||||
data[29] = axienet_ior(lp, XAE_FMI_OFFSET);
|
||||
@ -1549,14 +1671,18 @@ static void axienet_dma_err_handler(struct work_struct *work)
|
||||
|
||||
for (i = 0; i < lp->tx_bd_num; i++) {
|
||||
cur_p = &lp->tx_bd_v[i];
|
||||
if (cur_p->phys)
|
||||
dma_unmap_single(ndev->dev.parent, cur_p->phys,
|
||||
if (cur_p->cntrl) {
|
||||
dma_addr_t addr = desc_get_phys_addr(lp, cur_p);
|
||||
|
||||
dma_unmap_single(ndev->dev.parent, addr,
|
||||
(cur_p->cntrl &
|
||||
XAXIDMA_BD_CTRL_LENGTH_MASK),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
if (cur_p->skb)
|
||||
dev_kfree_skb_irq(cur_p->skb);
|
||||
cur_p->phys = 0;
|
||||
cur_p->phys_msb = 0;
|
||||
cur_p->cntrl = 0;
|
||||
cur_p->status = 0;
|
||||
cur_p->app0 = 0;
|
||||
@ -1610,18 +1736,18 @@ static void axienet_dma_err_handler(struct work_struct *work)
|
||||
/* Populate the tail pointer and bring the Rx Axi DMA engine out of
|
||||
* halted state. This will make the Rx side ready for reception.
|
||||
*/
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
|
||||
axienet_dma_out_addr(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
|
||||
cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
|
||||
cr | XAXIDMA_CR_RUNSTOP_MASK);
|
||||
axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
|
||||
(sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1)));
|
||||
axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
|
||||
(sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1)));
|
||||
|
||||
/* Write to the RS (Run-stop) bit in the Tx channel control register.
|
||||
* Tx channel is now ready to run. But only after we write to the
|
||||
* tail pointer register that the Tx channel will start transmitting
|
||||
*/
|
||||
axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
|
||||
axienet_dma_out_addr(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
|
||||
cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
|
||||
axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
|
||||
cr | XAXIDMA_CR_RUNSTOP_MASK);
|
||||
@ -1832,6 +1958,29 @@ static int axienet_probe(struct platform_device *pdev)
|
||||
goto free_netdev;
|
||||
}
|
||||
|
||||
/* Autodetect the need for 64-bit DMA pointers.
|
||||
* When the IP is configured for a bus width bigger than 32 bits,
|
||||
* writing the MSB registers is mandatory, even if they are all 0.
|
||||
* We can detect this case by writing all 1's to one such register
|
||||
* and see if that sticks: when the IP is configured for 32 bits
|
||||
* only, those registers are RES0.
|
||||
* Those MSB registers were introduced in IP v7.1, which we check first.
|
||||
*/
|
||||
if ((axienet_ior(lp, XAE_ID_OFFSET) >> 24) >= 0x9) {
|
||||
void __iomem *desc = lp->dma_regs + XAXIDMA_TX_CDESC_OFFSET + 4;
|
||||
|
||||
iowrite32(0x0, desc);
|
||||
if (ioread32(desc) == 0) { /* sanity check */
|
||||
iowrite32(0xffffffff, desc);
|
||||
if (ioread32(desc) > 0) {
|
||||
lp->features |= XAE_FEATURE_DMA_64BIT;
|
||||
dev_info(&pdev->dev,
|
||||
"autodetected 64-bit DMA range\n");
|
||||
}
|
||||
iowrite32(0x0, desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for Ethernet core IRQ (optional) */
|
||||
if (lp->eth_irq <= 0)
|
||||
dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");
|
||||
|
@ -573,6 +573,9 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (skb_cow_head(skb, dev->needed_headroom))
|
||||
goto tx_err;
|
||||
|
||||
if (!pskb_inet_may_pull(skb))
|
||||
goto tx_err;
|
||||
|
||||
skb_reset_inner_headers(skb);
|
||||
|
||||
/* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */
|
||||
@ -804,7 +807,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
|
||||
sock = sockfd_lookup(fd, &err);
|
||||
if (!sock) {
|
||||
pr_debug("gtp socket fd=%d not found\n", fd);
|
||||
return NULL;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
sk = sock->sk;
|
||||
|
@ -3372,11 +3372,23 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp)
|
||||
set_bit(PHY_RESET, &tp->flags);
|
||||
}
|
||||
|
||||
static void r8152b_exit_oob(struct r8152 *tp)
|
||||
static void wait_oob_link_list_ready(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
static void r8152b_exit_oob(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
|
||||
ocp_data &= ~RCR_ACPT_ALL;
|
||||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
||||
@ -3394,23 +3406,13 @@ static void r8152b_exit_oob(struct r8152 *tp)
|
||||
ocp_data &= ~MCU_BORW_EN;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
||||
ocp_data |= RE_INIT_LL;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
rtl8152_nic_reset(tp);
|
||||
|
||||
@ -3452,7 +3454,6 @@ static void r8152b_exit_oob(struct r8152 *tp)
|
||||
static void r8152b_enter_oob(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
int i;
|
||||
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
ocp_data &= ~NOW_IS_OOB;
|
||||
@ -3464,23 +3465,13 @@ static void r8152b_enter_oob(struct r8152 *tp)
|
||||
|
||||
rtl_disable(tp);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
||||
ocp_data |= RE_INIT_LL;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
||||
|
||||
@ -3705,7 +3696,6 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp)
|
||||
static void r8153_first_init(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
int i;
|
||||
|
||||
rxdy_gated_en(tp, true);
|
||||
r8153_teredo_off(tp);
|
||||
@ -3725,23 +3715,13 @@ static void r8153_first_init(struct r8152 *tp)
|
||||
ocp_data &= ~MCU_BORW_EN;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
||||
ocp_data |= RE_INIT_LL;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
|
||||
|
||||
@ -3766,7 +3746,6 @@ static void r8153_first_init(struct r8152 *tp)
|
||||
static void r8153_enter_oob(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
int i;
|
||||
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
ocp_data &= ~NOW_IS_OOB;
|
||||
@ -3775,23 +3754,13 @@ static void r8153_enter_oob(struct r8152 *tp)
|
||||
rtl_disable(tp);
|
||||
rtl_reset_bmu(tp);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
||||
ocp_data |= RE_INIT_LL;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
||||
if (ocp_data & LINK_LIST_READY)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
wait_oob_link_list_ready(tp);
|
||||
|
||||
ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
|
||||
|
@ -2140,7 +2140,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
|
||||
if (!(mvm->scan_status & type))
|
||||
return 0;
|
||||
|
||||
if (iwl_mvm_is_radio_killed(mvm)) {
|
||||
if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
@ -4319,11 +4319,27 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
||||
if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
|
||||
wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
wiphy->bands[NL80211_BAND_2GHZ] = &mwifiex_band_2ghz;
|
||||
if (adapter->config_bands & BAND_A)
|
||||
wiphy->bands[NL80211_BAND_5GHZ] = &mwifiex_band_5ghz;
|
||||
else
|
||||
wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(adapter->dev,
|
||||
&mwifiex_band_2ghz,
|
||||
sizeof(mwifiex_band_2ghz),
|
||||
GFP_KERNEL);
|
||||
if (!wiphy->bands[NL80211_BAND_2GHZ]) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (adapter->config_bands & BAND_A) {
|
||||
wiphy->bands[NL80211_BAND_5GHZ] = devm_kmemdup(adapter->dev,
|
||||
&mwifiex_band_5ghz,
|
||||
sizeof(mwifiex_band_5ghz),
|
||||
GFP_KERNEL);
|
||||
if (!wiphy->bands[NL80211_BAND_5GHZ]) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
wiphy->bands[NL80211_BAND_5GHZ] = NULL;
|
||||
}
|
||||
|
||||
if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
|
||||
wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
|
||||
@ -4411,8 +4427,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
||||
if (ret < 0) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"%s: wiphy_register failed: %d\n", __func__, ret);
|
||||
wiphy_free(wiphy);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!adapter->regd) {
|
||||
@ -4454,4 +4469,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
||||
|
||||
adapter->wiphy = wiphy;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
wiphy_free(wiphy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1170,7 +1170,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,
|
||||
size_t ies_len = skb->len - (ies - (u8 *)(skb->data));
|
||||
|
||||
tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
|
||||
if (tim_ie) {
|
||||
if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
|
||||
struct ieee80211_tim_ie *tim =
|
||||
(struct ieee80211_tim_ie *)&tim_ie[2];
|
||||
|
||||
|
@ -185,6 +185,32 @@ struct pn533_cmd_jump_dep_response {
|
||||
u8 gt[];
|
||||
} __packed;
|
||||
|
||||
struct pn532_autopoll_resp {
|
||||
u8 type;
|
||||
u8 ln;
|
||||
u8 tg;
|
||||
u8 tgdata[];
|
||||
};
|
||||
|
||||
/* PN532_CMD_IN_AUTOPOLL */
|
||||
#define PN532_AUTOPOLL_POLLNR_INFINITE 0xff
|
||||
#define PN532_AUTOPOLL_PERIOD 0x03 /* in units of 150 ms */
|
||||
|
||||
#define PN532_AUTOPOLL_TYPE_GENERIC_106 0x00
|
||||
#define PN532_AUTOPOLL_TYPE_GENERIC_212 0x01
|
||||
#define PN532_AUTOPOLL_TYPE_GENERIC_424 0x02
|
||||
#define PN532_AUTOPOLL_TYPE_JEWEL 0x04
|
||||
#define PN532_AUTOPOLL_TYPE_MIFARE 0x10
|
||||
#define PN532_AUTOPOLL_TYPE_FELICA212 0x11
|
||||
#define PN532_AUTOPOLL_TYPE_FELICA424 0x12
|
||||
#define PN532_AUTOPOLL_TYPE_ISOA 0x20
|
||||
#define PN532_AUTOPOLL_TYPE_ISOB 0x23
|
||||
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106 0x40
|
||||
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212 0x41
|
||||
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424 0x42
|
||||
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106 0x80
|
||||
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212 0x81
|
||||
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424 0x82
|
||||
|
||||
/* PN533_TG_INIT_AS_TARGET */
|
||||
#define PN533_INIT_TARGET_PASSIVE 0x1
|
||||
@ -1394,6 +1420,101 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pn533_autopoll_complete(struct pn533 *dev, void *arg,
|
||||
struct sk_buff *resp)
|
||||
{
|
||||
struct pn532_autopoll_resp *apr;
|
||||
struct nfc_target nfc_tgt;
|
||||
u8 nbtg;
|
||||
int rc;
|
||||
|
||||
if (IS_ERR(resp)) {
|
||||
rc = PTR_ERR(resp);
|
||||
|
||||
nfc_err(dev->dev, "%s autopoll complete error %d\n",
|
||||
__func__, rc);
|
||||
|
||||
if (rc == -ENOENT) {
|
||||
if (dev->poll_mod_count != 0)
|
||||
return rc;
|
||||
goto stop_poll;
|
||||
} else if (rc < 0) {
|
||||
nfc_err(dev->dev,
|
||||
"Error %d when running autopoll\n", rc);
|
||||
goto stop_poll;
|
||||
}
|
||||
}
|
||||
|
||||
nbtg = resp->data[0];
|
||||
if ((nbtg > 2) || (nbtg <= 0))
|
||||
return -EAGAIN;
|
||||
|
||||
apr = (struct pn532_autopoll_resp *)&resp->data[1];
|
||||
while (nbtg--) {
|
||||
memset(&nfc_tgt, 0, sizeof(struct nfc_target));
|
||||
switch (apr->type) {
|
||||
case PN532_AUTOPOLL_TYPE_ISOA:
|
||||
dev_dbg(dev->dev, "ISOA\n");
|
||||
rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
|
||||
apr->ln - 1);
|
||||
break;
|
||||
case PN532_AUTOPOLL_TYPE_FELICA212:
|
||||
case PN532_AUTOPOLL_TYPE_FELICA424:
|
||||
dev_dbg(dev->dev, "FELICA\n");
|
||||
rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata,
|
||||
apr->ln - 1);
|
||||
break;
|
||||
case PN532_AUTOPOLL_TYPE_JEWEL:
|
||||
dev_dbg(dev->dev, "JEWEL\n");
|
||||
rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata,
|
||||
apr->ln - 1);
|
||||
break;
|
||||
case PN532_AUTOPOLL_TYPE_ISOB:
|
||||
dev_dbg(dev->dev, "ISOB\n");
|
||||
rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata,
|
||||
apr->ln - 1);
|
||||
break;
|
||||
case PN532_AUTOPOLL_TYPE_MIFARE:
|
||||
dev_dbg(dev->dev, "Mifare\n");
|
||||
rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
|
||||
apr->ln - 1);
|
||||
break;
|
||||
default:
|
||||
nfc_err(dev->dev,
|
||||
"Unknown current poll modulation\n");
|
||||
rc = -EPROTO;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
|
||||
nfc_err(dev->dev,
|
||||
"The Tg found doesn't have the desired protocol\n");
|
||||
rc = -EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
dev->tgt_available_prots = nfc_tgt.supported_protocols;
|
||||
apr = (struct pn532_autopoll_resp *)
|
||||
(apr->tgdata + (apr->ln - 1));
|
||||
}
|
||||
|
||||
pn533_poll_reset_mod_list(dev);
|
||||
nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
|
||||
|
||||
done:
|
||||
dev_kfree_skb(resp);
|
||||
return rc;
|
||||
|
||||
stop_poll:
|
||||
nfc_err(dev->dev, "autopoll operation has been stopped\n");
|
||||
|
||||
pn533_poll_reset_mod_list(dev);
|
||||
dev->poll_protocols = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pn533_poll_complete(struct pn533 *dev, void *arg,
|
||||
struct sk_buff *resp)
|
||||
{
|
||||
@ -1537,6 +1658,7 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
|
||||
{
|
||||
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
||||
struct pn533_poll_modulations *cur_mod;
|
||||
struct sk_buff *skb;
|
||||
u8 rand_mod;
|
||||
int rc;
|
||||
|
||||
@ -1562,9 +1684,78 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
|
||||
tm_protocols = 0;
|
||||
}
|
||||
|
||||
pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
|
||||
dev->poll_protocols = im_protocols;
|
||||
dev->listen_protocols = tm_protocols;
|
||||
if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) {
|
||||
skb = pn533_alloc_skb(dev, 4 + 6);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_POLLNR_INFINITE;
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD;
|
||||
|
||||
if ((im_protocols & NFC_PROTO_MIFARE_MASK) &&
|
||||
(im_protocols & NFC_PROTO_ISO14443_MASK) &&
|
||||
(im_protocols & NFC_PROTO_NFC_DEP_MASK))
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_GENERIC_106;
|
||||
else {
|
||||
if (im_protocols & NFC_PROTO_MIFARE_MASK)
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_MIFARE;
|
||||
|
||||
if (im_protocols & NFC_PROTO_ISO14443_MASK)
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_ISOA;
|
||||
|
||||
if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106;
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212;
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424;
|
||||
}
|
||||
}
|
||||
|
||||
if (im_protocols & NFC_PROTO_FELICA_MASK ||
|
||||
im_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_FELICA212;
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_FELICA424;
|
||||
}
|
||||
|
||||
if (im_protocols & NFC_PROTO_JEWEL_MASK)
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_JEWEL;
|
||||
|
||||
if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_ISOB;
|
||||
|
||||
if (tm_protocols)
|
||||
*((u8 *)skb_put(skb, sizeof(u8))) =
|
||||
PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106;
|
||||
|
||||
rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb,
|
||||
pn533_autopoll_complete, NULL);
|
||||
|
||||
if (rc < 0)
|
||||
dev_kfree_skb(skb);
|
||||
else
|
||||
dev->poll_mod_count++;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
|
||||
if (!dev->poll_mod_count) {
|
||||
nfc_err(dev->dev,
|
||||
"Poll mod list is empty\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Do not always start polling from the same modulation */
|
||||
get_random_bytes(&rand_mod, sizeof(rand_mod));
|
||||
@ -2465,7 +2656,11 @@ static int pn533_dev_up(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
||||
|
||||
if (dev->device_type == PN533_DEVICE_PN532) {
|
||||
if (dev->phy_ops->dev_up)
|
||||
dev->phy_ops->dev_up(dev);
|
||||
|
||||
if ((dev->device_type == PN533_DEVICE_PN532) ||
|
||||
(dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) {
|
||||
int rc = pn532_sam_configuration(nfc_dev);
|
||||
|
||||
if (rc)
|
||||
@ -2477,7 +2672,14 @@ static int pn533_dev_up(struct nfc_dev *nfc_dev)
|
||||
|
||||
static int pn533_dev_down(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
return pn533_rf_field(nfc_dev, 0);
|
||||
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
||||
int ret;
|
||||
|
||||
ret = pn533_rf_field(nfc_dev, 0);
|
||||
if (dev->phy_ops->dev_down && !ret)
|
||||
dev->phy_ops->dev_down(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct nfc_ops pn533_nfc_ops = {
|
||||
@ -2505,6 +2707,7 @@ static int pn533_setup(struct pn533 *dev)
|
||||
case PN533_DEVICE_PASORI:
|
||||
case PN533_DEVICE_ACR122U:
|
||||
case PN533_DEVICE_PN532:
|
||||
case PN533_DEVICE_PN532_AUTOPOLL:
|
||||
max_retries.mx_rty_atr = 0x2;
|
||||
max_retries.mx_rty_psl = 0x1;
|
||||
max_retries.mx_rty_passive_act =
|
||||
@ -2541,6 +2744,7 @@ static int pn533_setup(struct pn533 *dev)
|
||||
switch (dev->device_type) {
|
||||
case PN533_DEVICE_STD:
|
||||
case PN533_DEVICE_PN532:
|
||||
case PN533_DEVICE_PN532_AUTOPOLL:
|
||||
break;
|
||||
|
||||
case PN533_DEVICE_PASORI:
|
||||
|
@ -6,10 +6,11 @@
|
||||
* Copyright (C) 2012-2013 Tieto Poland
|
||||
*/
|
||||
|
||||
#define PN533_DEVICE_STD 0x1
|
||||
#define PN533_DEVICE_PASORI 0x2
|
||||
#define PN533_DEVICE_ACR122U 0x3
|
||||
#define PN533_DEVICE_PN532 0x4
|
||||
#define PN533_DEVICE_STD 0x1
|
||||
#define PN533_DEVICE_PASORI 0x2
|
||||
#define PN533_DEVICE_ACR122U 0x3
|
||||
#define PN533_DEVICE_PN532 0x4
|
||||
#define PN533_DEVICE_PN532_AUTOPOLL 0x5
|
||||
|
||||
#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
|
||||
NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
|
||||
@ -70,6 +71,7 @@
|
||||
#define PN533_CMD_IN_ATR 0x50
|
||||
#define PN533_CMD_IN_RELEASE 0x52
|
||||
#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
|
||||
#define PN533_CMD_IN_AUTOPOLL 0x60
|
||||
|
||||
#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
|
||||
#define PN533_CMD_TG_GET_DATA 0x86
|
||||
@ -207,6 +209,15 @@ struct pn533_phy_ops {
|
||||
struct sk_buff *out);
|
||||
int (*send_ack)(struct pn533 *dev, gfp_t flags);
|
||||
void (*abort_cmd)(struct pn533 *priv, gfp_t flags);
|
||||
/*
|
||||
* dev_up and dev_down are optional.
|
||||
* They are used to inform the phy layer that the nfc chip
|
||||
* is going to be really used very soon. The phy layer can then
|
||||
* bring up it's interface to the chip and have it suspended for power
|
||||
* saving reasons otherwise.
|
||||
*/
|
||||
void (*dev_up)(struct pn533 *priv);
|
||||
void (*dev_down)(struct pn533 *priv);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1080,8 +1080,10 @@ static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
|
||||
|
||||
error = nvme_submit_sync_cmd(dev->admin_q, &c, *id,
|
||||
sizeof(struct nvme_id_ctrl));
|
||||
if (error)
|
||||
if (error) {
|
||||
kfree(*id);
|
||||
*id = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1193,6 +1195,7 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl,
|
||||
if (error) {
|
||||
dev_warn(ctrl->device, "Identify namespace failed (%d)\n", error);
|
||||
kfree(*id);
|
||||
*id = NULL;
|
||||
}
|
||||
|
||||
return error;
|
||||
|
@ -428,12 +428,8 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
while (--i >= 0) {
|
||||
struct nvmet_rdma_rsp *rsp = &queue->rsps[i];
|
||||
|
||||
list_del(&rsp->free_list);
|
||||
nvmet_rdma_free_rsp(ndev, rsp);
|
||||
}
|
||||
while (--i >= 0)
|
||||
nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
|
||||
kfree(queue->rsps);
|
||||
out:
|
||||
return ret;
|
||||
@ -444,12 +440,8 @@ static void nvmet_rdma_free_rsps(struct nvmet_rdma_queue *queue)
|
||||
struct nvmet_rdma_device *ndev = queue->dev;
|
||||
int i, nr_rsps = queue->recv_queue_size * 2;
|
||||
|
||||
for (i = 0; i < nr_rsps; i++) {
|
||||
struct nvmet_rdma_rsp *rsp = &queue->rsps[i];
|
||||
|
||||
list_del(&rsp->free_list);
|
||||
nvmet_rdma_free_rsp(ndev, rsp);
|
||||
}
|
||||
for (i = 0; i < nr_rsps; i++)
|
||||
nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
|
||||
kfree(queue->rsps);
|
||||
}
|
||||
|
||||
|
@ -792,6 +792,7 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
|
||||
pr_err("bad nvme-tcp pdu length (%d)\n",
|
||||
le32_to_cpu(icreq->hdr.plen));
|
||||
nvmet_tcp_fatal_error(queue);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (icreq->pfv != NVME_TCP_PFV_1_0) {
|
||||
|
@ -195,7 +195,7 @@ const char *nvmet_trace_disk_name(struct trace_seq *p, char *name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl)
|
||||
const char *nvmet_trace_ctrl_id(struct trace_seq *p, u16 ctrl_id)
|
||||
{
|
||||
const char *ret = trace_seq_buffer_ptr(p);
|
||||
|
||||
@ -208,8 +208,8 @@ const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl)
|
||||
* If we can know the extra data of the connect command in this stage,
|
||||
* we can update this print statement later.
|
||||
*/
|
||||
if (ctrl)
|
||||
trace_seq_printf(p, "%d", ctrl->cntlid);
|
||||
if (ctrl_id)
|
||||
trace_seq_printf(p, "%d", ctrl_id);
|
||||
else
|
||||
trace_seq_printf(p, "_");
|
||||
trace_seq_putc(p, 0);
|
||||
|
@ -32,18 +32,24 @@ const char *nvmet_trace_parse_fabrics_cmd(struct trace_seq *p, u8 fctype,
|
||||
nvmet_trace_parse_nvm_cmd(p, opcode, cdw10) : \
|
||||
nvmet_trace_parse_admin_cmd(p, opcode, cdw10)))
|
||||
|
||||
const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl);
|
||||
#define __print_ctrl_name(ctrl) \
|
||||
nvmet_trace_ctrl_name(p, ctrl)
|
||||
const char *nvmet_trace_ctrl_id(struct trace_seq *p, u16 ctrl_id);
|
||||
#define __print_ctrl_id(ctrl_id) \
|
||||
nvmet_trace_ctrl_id(p, ctrl_id)
|
||||
|
||||
const char *nvmet_trace_disk_name(struct trace_seq *p, char *name);
|
||||
#define __print_disk_name(name) \
|
||||
nvmet_trace_disk_name(p, name)
|
||||
|
||||
#ifndef TRACE_HEADER_MULTI_READ
|
||||
static inline struct nvmet_ctrl *nvmet_req_to_ctrl(struct nvmet_req *req)
|
||||
static inline u16 nvmet_req_to_ctrl_id(struct nvmet_req *req)
|
||||
{
|
||||
return req->sq->ctrl;
|
||||
/*
|
||||
* The queue and controller pointers are not valid until an association
|
||||
* has been established.
|
||||
*/
|
||||
if (!req->sq || !req->sq->ctrl)
|
||||
return 0;
|
||||
return req->sq->ctrl->cntlid;
|
||||
}
|
||||
|
||||
static inline void __assign_req_name(char *name, struct nvmet_req *req)
|
||||
@ -60,7 +66,7 @@ TRACE_EVENT(nvmet_req_init,
|
||||
TP_ARGS(req, cmd),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct nvme_command *, cmd)
|
||||
__field(struct nvmet_ctrl *, ctrl)
|
||||
__field(u16, ctrl_id)
|
||||
__array(char, disk, DISK_NAME_LEN)
|
||||
__field(int, qid)
|
||||
__field(u16, cid)
|
||||
@ -73,7 +79,7 @@ TRACE_EVENT(nvmet_req_init,
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cmd = cmd;
|
||||
__entry->ctrl = nvmet_req_to_ctrl(req);
|
||||
__entry->ctrl_id = nvmet_req_to_ctrl_id(req);
|
||||
__assign_req_name(__entry->disk, req);
|
||||
__entry->qid = req->sq->qid;
|
||||
__entry->cid = cmd->common.command_id;
|
||||
@ -87,7 +93,7 @@ TRACE_EVENT(nvmet_req_init,
|
||||
),
|
||||
TP_printk("nvmet%s: %sqid=%d, cmdid=%u, nsid=%u, flags=%#x, "
|
||||
"meta=%#llx, cmd=(%s, %s)",
|
||||
__print_ctrl_name(__entry->ctrl),
|
||||
__print_ctrl_id(__entry->ctrl_id),
|
||||
__print_disk_name(__entry->disk),
|
||||
__entry->qid, __entry->cid, __entry->nsid,
|
||||
__entry->flags, __entry->metadata,
|
||||
@ -101,7 +107,7 @@ TRACE_EVENT(nvmet_req_complete,
|
||||
TP_PROTO(struct nvmet_req *req),
|
||||
TP_ARGS(req),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct nvmet_ctrl *, ctrl)
|
||||
__field(u16, ctrl_id)
|
||||
__array(char, disk, DISK_NAME_LEN)
|
||||
__field(int, qid)
|
||||
__field(int, cid)
|
||||
@ -109,7 +115,7 @@ TRACE_EVENT(nvmet_req_complete,
|
||||
__field(u16, status)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ctrl = nvmet_req_to_ctrl(req);
|
||||
__entry->ctrl_id = nvmet_req_to_ctrl_id(req);
|
||||
__entry->qid = req->cq->qid;
|
||||
__entry->cid = req->cqe->command_id;
|
||||
__entry->result = le64_to_cpu(req->cqe->result.u64);
|
||||
@ -117,7 +123,7 @@ TRACE_EVENT(nvmet_req_complete,
|
||||
__assign_req_name(__entry->disk, req);
|
||||
),
|
||||
TP_printk("nvmet%s: %sqid=%d, cmdid=%u, res=%#llx, status=%#x",
|
||||
__print_ctrl_name(__entry->ctrl),
|
||||
__print_ctrl_id(__entry->ctrl_id),
|
||||
__print_disk_name(__entry->disk),
|
||||
__entry->qid, __entry->cid, __entry->result, __entry->status)
|
||||
|
||||
|
@ -323,6 +323,8 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
return -ENOTSUPP;
|
||||
fselector = setting->func;
|
||||
function = pinmux_generic_get_function(pctldev, fselector);
|
||||
if (!function)
|
||||
return -EINVAL;
|
||||
*func = function->data;
|
||||
if (!(*func)) {
|
||||
dev_err(pcs->dev, "%s could not find function%i\n",
|
||||
|
@ -1665,9 +1665,15 @@ static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb)
|
||||
if (!sense)
|
||||
return 0;
|
||||
|
||||
return !!(sense[1] & SNS1_NO_REC_FOUND) ||
|
||||
!!(sense[1] & SNS1_FILE_PROTECTED) ||
|
||||
scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
|
||||
if (sense[1] & SNS1_NO_REC_FOUND)
|
||||
return 1;
|
||||
|
||||
if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
|
||||
scsw_is_tm(&irb->scsw) &&
|
||||
!(sense[2] & SNS2_ENV_DATA_PRESENT))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dasd_ese_oos_cond(u8 *sense)
|
||||
@ -1688,7 +1694,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
struct dasd_device *device;
|
||||
unsigned long now;
|
||||
int nrf_suppressed = 0;
|
||||
int fp_suppressed = 0;
|
||||
int it_suppressed = 0;
|
||||
struct request *req;
|
||||
u8 *sense = NULL;
|
||||
int expires;
|
||||
@ -1743,8 +1749,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
*/
|
||||
sense = dasd_get_sense(irb);
|
||||
if (sense) {
|
||||
fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
|
||||
it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) &&
|
||||
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
|
||||
nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
|
||||
|
||||
@ -1759,7 +1766,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!(fp_suppressed || nrf_suppressed))
|
||||
if (!(it_suppressed || nrf_suppressed))
|
||||
device->discipline->dump_sense_dbf(device, irb, "int");
|
||||
|
||||
if (device->features & DASD_FEATURE_ERPLOG)
|
||||
@ -2513,14 +2520,17 @@ retry:
|
||||
rc = 0;
|
||||
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
|
||||
/*
|
||||
* In some cases the 'File Protected' or 'Incorrect Length'
|
||||
* error might be expected and error recovery would be
|
||||
* unnecessary in these cases. Check if the according suppress
|
||||
* bit is set.
|
||||
* In some cases certain errors might be expected and
|
||||
* error recovery would be unnecessary in these cases.
|
||||
* Check if the according suppress bit is set.
|
||||
*/
|
||||
sense = dasd_get_sense(&cqr->irb);
|
||||
if (sense && sense[1] & SNS1_FILE_PROTECTED &&
|
||||
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags))
|
||||
if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
|
||||
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags))
|
||||
continue;
|
||||
if (sense && (sense[1] & SNS1_NO_REC_FOUND) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags))
|
||||
continue;
|
||||
if (scsw_cstat(&cqr->irb.scsw) == 0x40 &&
|
||||
test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags))
|
||||
|
@ -1401,14 +1401,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
|
||||
|
||||
struct dasd_device *device = erp->startdev;
|
||||
|
||||
/*
|
||||
* In some cases the 'File Protected' error might be expected and
|
||||
* log messages shouldn't be written then.
|
||||
* Check if the according suppress bit is set.
|
||||
*/
|
||||
if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags))
|
||||
dev_err(&device->cdev->dev,
|
||||
"Accessing the DASD failed because of a hardware error\n");
|
||||
dev_err(&device->cdev->dev,
|
||||
"Accessing the DASD failed because of a hardware error\n");
|
||||
|
||||
return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
|
||||
|
||||
|
@ -2201,6 +2201,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
|
||||
cqr->status = DASD_CQR_FILLED;
|
||||
/* Set flags to suppress output for expected errors */
|
||||
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
|
||||
|
||||
return cqr;
|
||||
}
|
||||
@ -2482,7 +2483,6 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata,
|
||||
cqr->buildclk = get_tod_clock();
|
||||
cqr->status = DASD_CQR_FILLED;
|
||||
/* Set flags to suppress output for expected errors */
|
||||
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
|
||||
|
||||
return cqr;
|
||||
@ -4031,8 +4031,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
|
||||
|
||||
/* Set flags to suppress output for expected errors */
|
||||
if (dasd_eckd_is_ese(basedev)) {
|
||||
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
|
||||
}
|
||||
|
||||
@ -4534,9 +4532,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
|
||||
|
||||
/* Set flags to suppress output for expected errors */
|
||||
if (dasd_eckd_is_ese(basedev)) {
|
||||
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
|
||||
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
|
||||
}
|
||||
|
||||
return cqr;
|
||||
@ -5706,36 +5703,32 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
|
||||
{
|
||||
u8 *sense = dasd_get_sense(irb);
|
||||
|
||||
if (scsw_is_tm(&irb->scsw)) {
|
||||
/*
|
||||
* In some cases the 'File Protected' or 'Incorrect Length'
|
||||
* error might be expected and log messages shouldn't be written
|
||||
* then. Check if the according suppress bit is set.
|
||||
*/
|
||||
if (sense && (sense[1] & SNS1_FILE_PROTECTED) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_FP, &req->flags))
|
||||
return;
|
||||
if (scsw_cstat(&irb->scsw) == 0x40 &&
|
||||
test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
|
||||
return;
|
||||
/*
|
||||
* In some cases certain errors might be expected and
|
||||
* log messages shouldn't be written then.
|
||||
* Check if the according suppress bit is set.
|
||||
*/
|
||||
if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
|
||||
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
|
||||
test_bit(DASD_CQR_SUPPRESS_IT, &req->flags))
|
||||
return;
|
||||
|
||||
if (sense && sense[0] & SNS0_CMD_REJECT &&
|
||||
test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
|
||||
return;
|
||||
|
||||
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
|
||||
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
|
||||
return;
|
||||
|
||||
if (scsw_cstat(&irb->scsw) == 0x40 &&
|
||||
test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
|
||||
return;
|
||||
|
||||
if (scsw_is_tm(&irb->scsw))
|
||||
dasd_eckd_dump_sense_tcw(device, req, irb);
|
||||
} else {
|
||||
/*
|
||||
* In some cases the 'Command Reject' or 'No Record Found'
|
||||
* error might be expected and log messages shouldn't be
|
||||
* written then. Check if the according suppress bit is set.
|
||||
*/
|
||||
if (sense && sense[0] & SNS0_CMD_REJECT &&
|
||||
test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
|
||||
return;
|
||||
|
||||
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
|
||||
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
|
||||
return;
|
||||
|
||||
else
|
||||
dasd_eckd_dump_sense_ccw(device, req, irb);
|
||||
}
|
||||
}
|
||||
|
||||
static int dasd_eckd_pm_freeze(struct dasd_device *device)
|
||||
|
@ -226,7 +226,7 @@ struct dasd_ccw_req {
|
||||
* The following flags are used to suppress output of certain errors.
|
||||
*/
|
||||
#define DASD_CQR_SUPPRESS_NRF 4 /* Suppress 'No Record Found' error */
|
||||
#define DASD_CQR_SUPPRESS_FP 5 /* Suppress 'File Protected' error*/
|
||||
#define DASD_CQR_SUPPRESS_IT 5 /* Suppress 'Invalid Track' error*/
|
||||
#define DASD_CQR_SUPPRESS_IL 6 /* Suppress 'Incorrect Length' error */
|
||||
#define DASD_CQR_SUPPRESS_CR 7 /* Suppress 'Command Reject' error */
|
||||
|
||||
|
@ -16,20 +16,21 @@ struct idset {
|
||||
unsigned long bitmap[0];
|
||||
};
|
||||
|
||||
static inline unsigned long bitmap_size(int num_ssid, int num_id)
|
||||
static inline unsigned long idset_bitmap_size(int num_ssid, int num_id)
|
||||
{
|
||||
return BITS_TO_LONGS(num_ssid * num_id) * sizeof(unsigned long);
|
||||
return bitmap_size(size_mul(num_ssid, num_id));
|
||||
}
|
||||
|
||||
static struct idset *idset_new(int num_ssid, int num_id)
|
||||
{
|
||||
struct idset *set;
|
||||
|
||||
set = vmalloc(sizeof(struct idset) + bitmap_size(num_ssid, num_id));
|
||||
set = vmalloc(sizeof(struct idset) +
|
||||
idset_bitmap_size(num_ssid, num_id));
|
||||
if (set) {
|
||||
set->num_ssid = num_ssid;
|
||||
set->num_id = num_id;
|
||||
memset(set->bitmap, 0, bitmap_size(num_ssid, num_id));
|
||||
memset(set->bitmap, 0, idset_bitmap_size(num_ssid, num_id));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
@ -41,7 +42,8 @@ void idset_free(struct idset *set)
|
||||
|
||||
void idset_fill(struct idset *set)
|
||||
{
|
||||
memset(set->bitmap, 0xff, bitmap_size(set->num_ssid, set->num_id));
|
||||
memset(set->bitmap, 0xff,
|
||||
idset_bitmap_size(set->num_ssid, set->num_id));
|
||||
}
|
||||
|
||||
static inline void idset_add(struct idset *set, int ssid, int id)
|
||||
|
@ -638,6 +638,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
|
||||
if (aac_comm_init(dev)<0){
|
||||
kfree(dev->queues);
|
||||
dev->queues = NULL;
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
@ -645,6 +646,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
*/
|
||||
if (aac_fib_setup(dev) < 0) {
|
||||
kfree(dev->queues);
|
||||
dev->queues = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -6902,7 +6902,7 @@ lpfc_sli4_repost_sgl_list(struct lpfc_hba *phba,
|
||||
struct lpfc_sglq *sglq_entry = NULL;
|
||||
struct lpfc_sglq *sglq_entry_next = NULL;
|
||||
struct lpfc_sglq *sglq_entry_first = NULL;
|
||||
int status, total_cnt;
|
||||
int status = 0, total_cnt;
|
||||
int post_cnt = 0, num_posted = 0, block_cnt = 0;
|
||||
int last_xritag = NO_XRI;
|
||||
LIST_HEAD(prep_sgl_list);
|
||||
|
@ -677,10 +677,10 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
|
||||
for (r = 0; r < retries; r++) {
|
||||
result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE,
|
||||
buffer, len, &sshdr);
|
||||
if(result || !scsi_device_online(sdev)) {
|
||||
if (result || !scsi_device_online(sdev)) {
|
||||
|
||||
scsi_device_set_state(sdev, SDEV_QUIESCE);
|
||||
if (scsi_sense_valid(&sshdr)
|
||||
if (result > 0 && scsi_sense_valid(&sshdr)
|
||||
&& sshdr.sense_key == ILLEGAL_REQUEST
|
||||
/* INVALID FIELD IN CDB */
|
||||
&& sshdr.asc == 0x24 && sshdr.ascq == 0x00)
|
||||
|
@ -248,7 +248,7 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
|
||||
cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WC);
|
||||
if (!cmd_db_header) {
|
||||
ret = -ENOMEM;
|
||||
cmd_db_header = NULL;
|
||||
|
@ -1407,18 +1407,18 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
|
||||
unsigned int port_num)
|
||||
{
|
||||
struct sdw_dpn_prop *dpn_prop;
|
||||
u8 num_ports;
|
||||
unsigned long mask;
|
||||
int i;
|
||||
|
||||
if (direction == SDW_DATA_DIR_TX) {
|
||||
num_ports = hweight32(slave->prop.source_ports);
|
||||
mask = slave->prop.source_ports;
|
||||
dpn_prop = slave->prop.src_dpn_prop;
|
||||
} else {
|
||||
num_ports = hweight32(slave->prop.sink_ports);
|
||||
mask = slave->prop.sink_ports;
|
||||
dpn_prop = slave->prop.sink_dpn_prop;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_ports; i++) {
|
||||
for_each_set_bit(i, &mask, 32) {
|
||||
if (dpn_prop[i].num == port_num)
|
||||
return &dpn_prop[i];
|
||||
}
|
||||
|
@ -835,7 +835,7 @@ static u32 clkfactor_f6_resolve(u32 v)
|
||||
case SSB_CHIPCO_CLK_F6_7:
|
||||
return 7;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Calculate the speed the backplane would run at a given set of clockcontrol values */
|
||||
|
@ -395,9 +395,9 @@ int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
|
||||
priv->hostt.buff[priv->hostt.qtail] = le16_to_cpu(hdr->event);
|
||||
priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;
|
||||
|
||||
spin_lock(&priv->tx_dev.tx_dev_lock);
|
||||
spin_lock_bh(&priv->tx_dev.tx_dev_lock);
|
||||
result = enqueue_txdev(priv, p, size, complete_handler, skb);
|
||||
spin_unlock(&priv->tx_dev.tx_dev_lock);
|
||||
spin_unlock_bh(&priv->tx_dev.tx_dev_lock);
|
||||
|
||||
if (txq_has_space(priv))
|
||||
queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
|
||||
|
@ -1767,6 +1767,9 @@ static const struct usb_device_id acm_ids[] = {
|
||||
{ USB_DEVICE(0x11ca, 0x0201), /* VeriFone Mx870 Gadget Serial */
|
||||
.driver_info = SINGLE_RX_URB,
|
||||
},
|
||||
{ USB_DEVICE(0x1901, 0x0006), /* GE Healthcare Patient Monitor UI Controller */
|
||||
.driver_info = DISABLE_ECHO, /* DISABLE ECHO in termios flag */
|
||||
},
|
||||
{ USB_DEVICE(0x1965, 0x0018), /* Uniden UBC125XLT */
|
||||
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
|
||||
},
|
||||
|
@ -690,6 +690,7 @@ static int add_power_attributes(struct device *dev)
|
||||
|
||||
static void remove_power_attributes(struct device *dev)
|
||||
{
|
||||
sysfs_unmerge_group(&dev->kobj, &usb3_hardware_lpm_attr_group);
|
||||
sysfs_unmerge_group(&dev->kobj, &usb2_hardware_lpm_attr_group);
|
||||
sysfs_unmerge_group(&dev->kobj, &power_attr_group);
|
||||
}
|
||||
|
@ -385,6 +385,13 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
|
||||
static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
|
||||
{
|
||||
struct dwc3_event_buffer *evt;
|
||||
unsigned int hw_mode;
|
||||
|
||||
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
|
||||
if (hw_mode == DWC3_GHWPARAMS0_MODE_HOST) {
|
||||
dwc->ev_buf = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
evt = dwc3_alloc_one_event_buffer(dwc, length);
|
||||
if (IS_ERR(evt)) {
|
||||
@ -406,6 +413,9 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_event_buffer *evt;
|
||||
|
||||
if (!dwc->ev_buf)
|
||||
return 0;
|
||||
|
||||
evt = dwc->ev_buf;
|
||||
evt->lpos = 0;
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
|
||||
@ -422,6 +432,17 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)
|
||||
void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_event_buffer *evt;
|
||||
u32 reg;
|
||||
|
||||
if (!dwc->ev_buf)
|
||||
return;
|
||||
/*
|
||||
* Exynos platforms may not be able to access event buffer if the
|
||||
* controller failed to halt on dwc3_core_exit().
|
||||
*/
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
|
||||
if (!(reg & DWC3_DSTS_DEVCTRLHLT))
|
||||
return;
|
||||
|
||||
evt = dwc->ev_buf;
|
||||
|
||||
|
@ -527,11 +527,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request IRQ #%d --> %d\n",
|
||||
omap->irq, ret);
|
||||
goto err1;
|
||||
goto err2;
|
||||
}
|
||||
dwc3_omap_enable_irqs(omap);
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
of_platform_depopulate(dev);
|
||||
err1:
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
@ -219,10 +219,8 @@ static int st_dwc3_probe(struct platform_device *pdev)
|
||||
dwc3_data->regmap = regmap;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg-reg");
|
||||
if (!res) {
|
||||
ret = -ENXIO;
|
||||
goto undo_platform_dev_alloc;
|
||||
}
|
||||
if (!res)
|
||||
return -ENXIO;
|
||||
|
||||
dwc3_data->syscfg_reg_off = res->start;
|
||||
|
||||
@ -233,8 +231,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
|
||||
devm_reset_control_get_exclusive(dev, "powerdown");
|
||||
if (IS_ERR(dwc3_data->rstc_pwrdn)) {
|
||||
dev_err(&pdev->dev, "could not get power controller\n");
|
||||
ret = PTR_ERR(dwc3_data->rstc_pwrdn);
|
||||
goto undo_platform_dev_alloc;
|
||||
return PTR_ERR(dwc3_data->rstc_pwrdn);
|
||||
}
|
||||
|
||||
/* Manage PowerDown */
|
||||
@ -269,7 +266,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
|
||||
if (!child_pdev) {
|
||||
dev_err(dev, "failed to find dwc3 core device\n");
|
||||
ret = -ENODEV;
|
||||
goto err_node_put;
|
||||
goto depopulate;
|
||||
}
|
||||
|
||||
dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev);
|
||||
@ -285,6 +282,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
|
||||
ret = st_dwc3_drd_init(dwc3_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "drd initialisation failed\n");
|
||||
of_platform_depopulate(dev);
|
||||
goto undo_softreset;
|
||||
}
|
||||
|
||||
@ -294,14 +292,14 @@ static int st_dwc3_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, dwc3_data);
|
||||
return 0;
|
||||
|
||||
depopulate:
|
||||
of_platform_depopulate(dev);
|
||||
err_node_put:
|
||||
of_node_put(child);
|
||||
undo_softreset:
|
||||
reset_control_assert(dwc3_data->rstc_rst);
|
||||
undo_powerdown:
|
||||
reset_control_assert(dwc3_data->rstc_pwrdn);
|
||||
undo_platform_dev_alloc:
|
||||
platform_device_put(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2503,7 +2503,7 @@ static int fsl_udc_probe(struct platform_device *pdev)
|
||||
/* setup the udc->eps[] for non-control endpoints and link
|
||||
* to gadget.ep_list */
|
||||
for (i = 1; i < (int)(udc_controller->max_ep / 2); i++) {
|
||||
char name[14];
|
||||
char name[16];
|
||||
|
||||
sprintf(name, "ep%dout", i);
|
||||
struct_ep_setup(udc_controller, i * 2, name, 1);
|
||||
|
@ -2819,7 +2819,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
||||
xhci->num_active_eps);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if ((xhci->quirks & XHCI_SW_BW_CHECKING) &&
|
||||
if ((xhci->quirks & XHCI_SW_BW_CHECKING) && !ctx_change &&
|
||||
xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) {
|
||||
if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
|
||||
xhci_free_host_resources(xhci, ctrl_ctx);
|
||||
@ -4231,8 +4231,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
mutex_unlock(&xhci->mutex);
|
||||
ret = xhci_disable_slot(xhci, udev->slot_id);
|
||||
xhci_free_virt_device(xhci, udev->slot_id);
|
||||
if (!ret)
|
||||
xhci_alloc_dev(hcd, udev);
|
||||
if (!ret) {
|
||||
if (xhci_alloc_dev(hcd, udev) == 1)
|
||||
xhci_setup_addressable_virt_dev(xhci, udev);
|
||||
}
|
||||
kfree(command->completion);
|
||||
kfree(command);
|
||||
return -EPROTO;
|
||||
|
@ -619,6 +619,8 @@ static void option_instat_callback(struct urb *urb);
|
||||
|
||||
/* MeiG Smart Technology products */
|
||||
#define MEIGSMART_VENDOR_ID 0x2dee
|
||||
/* MeiG Smart SRM825L based on Qualcomm 315 */
|
||||
#define MEIGSMART_PRODUCT_SRM825L 0x4d22
|
||||
/* MeiG Smart SLM320 based on UNISOC UIS8910 */
|
||||
#define MEIGSMART_PRODUCT_SLM320 0x4d41
|
||||
|
||||
@ -2366,6 +2368,9 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
@ -320,7 +320,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
|
||||
else
|
||||
executable_stack = EXSTACK_DEFAULT;
|
||||
|
||||
if (stack_size == 0) {
|
||||
if (stack_size == 0 && interp_params.flags & ELF_FDPIC_FLAG_PRESENT) {
|
||||
stack_size = interp_params.stack_size;
|
||||
if (interp_params.flags & ELF_FDPIC_FLAG_EXEC_STACK)
|
||||
executable_stack = EXSTACK_ENABLE_X;
|
||||
|
216
fs/binfmt_misc.c
216
fs/binfmt_misc.c
@ -60,12 +60,11 @@ typedef struct {
|
||||
char *name;
|
||||
struct dentry *dentry;
|
||||
struct file *interp_file;
|
||||
refcount_t users; /* sync removal with load_misc_binary() */
|
||||
} Node;
|
||||
|
||||
static DEFINE_RWLOCK(entries_lock);
|
||||
static struct file_system_type bm_fs_type;
|
||||
static struct vfsmount *bm_mnt;
|
||||
static int entry_count;
|
||||
|
||||
/*
|
||||
* Max length of the register string. Determined by:
|
||||
@ -82,19 +81,23 @@ static int entry_count;
|
||||
*/
|
||||
#define MAX_REGISTER_LENGTH 1920
|
||||
|
||||
/*
|
||||
* Check if we support the binfmt
|
||||
* if we do, return the node, else NULL
|
||||
* locking is done in load_misc_binary
|
||||
/**
|
||||
* search_binfmt_handler - search for a binary handler for @bprm
|
||||
* @misc: handle to binfmt_misc instance
|
||||
* @bprm: binary for which we are looking for a handler
|
||||
*
|
||||
* Search for a binary type handler for @bprm in the list of registered binary
|
||||
* type handlers.
|
||||
*
|
||||
* Return: binary type list entry on success, NULL on failure
|
||||
*/
|
||||
static Node *check_file(struct linux_binprm *bprm)
|
||||
static Node *search_binfmt_handler(struct linux_binprm *bprm)
|
||||
{
|
||||
char *p = strrchr(bprm->interp, '.');
|
||||
struct list_head *l;
|
||||
Node *e;
|
||||
|
||||
/* Walk all the registered handlers. */
|
||||
list_for_each(l, &entries) {
|
||||
Node *e = list_entry(l, Node, list);
|
||||
list_for_each_entry(e, &entries, list) {
|
||||
char *s;
|
||||
int j;
|
||||
|
||||
@ -123,9 +126,49 @@ static Node *check_file(struct linux_binprm *bprm)
|
||||
if (j == e->size)
|
||||
return e;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_binfmt_handler - try to find a binary type handler
|
||||
* @misc: handle to binfmt_misc instance
|
||||
* @bprm: binary for which we are looking for a handler
|
||||
*
|
||||
* Try to find a binfmt handler for the binary type. If one is found take a
|
||||
* reference to protect against removal via bm_{entry,status}_write().
|
||||
*
|
||||
* Return: binary type list entry on success, NULL on failure
|
||||
*/
|
||||
static Node *get_binfmt_handler(struct linux_binprm *bprm)
|
||||
{
|
||||
Node *e;
|
||||
|
||||
read_lock(&entries_lock);
|
||||
e = search_binfmt_handler(bprm);
|
||||
if (e)
|
||||
refcount_inc(&e->users);
|
||||
read_unlock(&entries_lock);
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* put_binfmt_handler - put binary handler node
|
||||
* @e: node to put
|
||||
*
|
||||
* Free node syncing with load_misc_binary() and defer final free to
|
||||
* load_misc_binary() in case it is using the binary type handler we were
|
||||
* requested to remove.
|
||||
*/
|
||||
static void put_binfmt_handler(Node *e)
|
||||
{
|
||||
if (refcount_dec_and_test(&e->users)) {
|
||||
if (e->flags & MISC_FMT_OPEN_FILE)
|
||||
filp_close(e->interp_file, NULL);
|
||||
kfree(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the loader itself
|
||||
*/
|
||||
@ -140,12 +183,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
|
||||
if (!enabled)
|
||||
return retval;
|
||||
|
||||
/* to keep locking time low, we copy the interpreter string */
|
||||
read_lock(&entries_lock);
|
||||
fmt = check_file(bprm);
|
||||
if (fmt)
|
||||
dget(fmt->dentry);
|
||||
read_unlock(&entries_lock);
|
||||
fmt = get_binfmt_handler(bprm);
|
||||
if (!fmt)
|
||||
return retval;
|
||||
|
||||
@ -239,7 +277,16 @@ static int load_misc_binary(struct linux_binprm *bprm)
|
||||
goto error;
|
||||
|
||||
ret:
|
||||
dput(fmt->dentry);
|
||||
|
||||
/*
|
||||
* If we actually put the node here all concurrent calls to
|
||||
* load_misc_binary() will have finished. We also know
|
||||
* that for the refcount to be zero ->evict_inode() must have removed
|
||||
* the node to be deleted from the list. All that is left for us is to
|
||||
* close and free.
|
||||
*/
|
||||
put_binfmt_handler(fmt);
|
||||
|
||||
return retval;
|
||||
error:
|
||||
if (fd_binary > 0)
|
||||
@ -600,30 +647,90 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
|
||||
return inode;
|
||||
}
|
||||
|
||||
/**
|
||||
* bm_evict_inode - cleanup data associated with @inode
|
||||
* @inode: inode to which the data is attached
|
||||
*
|
||||
* Cleanup the binary type handler data associated with @inode if a binary type
|
||||
* entry is removed or the filesystem is unmounted and the super block is
|
||||
* shutdown.
|
||||
*
|
||||
* If the ->evict call was not caused by a super block shutdown but by a write
|
||||
* to remove the entry or all entries via bm_{entry,status}_write() the entry
|
||||
* will have already been removed from the list. We keep the list_empty() check
|
||||
* to make that explicit.
|
||||
*/
|
||||
static void bm_evict_inode(struct inode *inode)
|
||||
{
|
||||
Node *e = inode->i_private;
|
||||
|
||||
if (e && e->flags & MISC_FMT_OPEN_FILE)
|
||||
filp_close(e->interp_file, NULL);
|
||||
|
||||
clear_inode(inode);
|
||||
kfree(e);
|
||||
|
||||
if (e) {
|
||||
write_lock(&entries_lock);
|
||||
if (!list_empty(&e->list))
|
||||
list_del_init(&e->list);
|
||||
write_unlock(&entries_lock);
|
||||
put_binfmt_handler(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void kill_node(Node *e)
|
||||
/**
|
||||
* unlink_binfmt_dentry - remove the dentry for the binary type handler
|
||||
* @dentry: dentry associated with the binary type handler
|
||||
*
|
||||
* Do the actual filesystem work to remove a dentry for a registered binary
|
||||
* type handler. Since binfmt_misc only allows simple files to be created
|
||||
* directly under the root dentry of the filesystem we ensure that we are
|
||||
* indeed passed a dentry directly beneath the root dentry, that the inode
|
||||
* associated with the root dentry is locked, and that it is a regular file we
|
||||
* are asked to remove.
|
||||
*/
|
||||
static void unlink_binfmt_dentry(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct dentry *parent = dentry->d_parent;
|
||||
struct inode *inode, *parent_inode;
|
||||
|
||||
/* All entries are immediate descendants of the root dentry. */
|
||||
if (WARN_ON_ONCE(dentry->d_sb->s_root != parent))
|
||||
return;
|
||||
|
||||
/* We only expect to be called on regular files. */
|
||||
inode = d_inode(dentry);
|
||||
if (WARN_ON_ONCE(!S_ISREG(inode->i_mode)))
|
||||
return;
|
||||
|
||||
/* The parent inode must be locked. */
|
||||
parent_inode = d_inode(parent);
|
||||
if (WARN_ON_ONCE(!inode_is_locked(parent_inode)))
|
||||
return;
|
||||
|
||||
if (simple_positive(dentry)) {
|
||||
dget(dentry);
|
||||
simple_unlink(parent_inode, dentry);
|
||||
d_delete(dentry);
|
||||
dput(dentry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove_binfmt_handler - remove a binary type handler
|
||||
* @misc: handle to binfmt_misc instance
|
||||
* @e: binary type handler to remove
|
||||
*
|
||||
* Remove a binary type handler from the list of binary type handlers and
|
||||
* remove its associated dentry. This is called from
|
||||
* binfmt_{entry,status}_write(). In the future, we might want to think about
|
||||
* adding a proper ->unlink() method to binfmt_misc instead of forcing caller's
|
||||
* to use writes to files in order to delete binary type handlers. But it has
|
||||
* worked for so long that it's not a pressing issue.
|
||||
*/
|
||||
static void remove_binfmt_handler(Node *e)
|
||||
{
|
||||
write_lock(&entries_lock);
|
||||
list_del_init(&e->list);
|
||||
write_unlock(&entries_lock);
|
||||
|
||||
dentry = e->dentry;
|
||||
drop_nlink(d_inode(dentry));
|
||||
d_drop(dentry);
|
||||
dput(dentry);
|
||||
simple_release_fs(&bm_mnt, &entry_count);
|
||||
unlink_binfmt_dentry(e->dentry);
|
||||
}
|
||||
|
||||
/* /<entry> */
|
||||
@ -650,8 +757,8 @@ bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
||||
static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct dentry *root;
|
||||
Node *e = file_inode(file)->i_private;
|
||||
struct inode *inode = file_inode(file);
|
||||
Node *e = inode->i_private;
|
||||
int res = parse_command(buffer, count);
|
||||
|
||||
switch (res) {
|
||||
@ -665,13 +772,22 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
|
||||
break;
|
||||
case 3:
|
||||
/* Delete this handler. */
|
||||
root = file_inode(file)->i_sb->s_root;
|
||||
inode_lock(d_inode(root));
|
||||
inode = d_inode(inode->i_sb->s_root);
|
||||
inode_lock(inode);
|
||||
|
||||
/*
|
||||
* In order to add new element or remove elements from the list
|
||||
* via bm_{entry,register,status}_write() inode_lock() on the
|
||||
* root inode must be held.
|
||||
* The lock is exclusive ensuring that the list can't be
|
||||
* modified. Only load_misc_binary() can access but does so
|
||||
* read-only. So we only need to take the write lock when we
|
||||
* actually remove the entry from the list.
|
||||
*/
|
||||
if (!list_empty(&e->list))
|
||||
kill_node(e);
|
||||
remove_binfmt_handler(e);
|
||||
|
||||
inode_unlock(d_inode(root));
|
||||
inode_unlock(inode);
|
||||
break;
|
||||
default:
|
||||
return res;
|
||||
@ -730,13 +846,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
|
||||
if (!inode)
|
||||
goto out2;
|
||||
|
||||
err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
|
||||
if (err) {
|
||||
iput(inode);
|
||||
inode = NULL;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
refcount_set(&e->users, 1);
|
||||
e->dentry = dget(dentry);
|
||||
inode->i_private = e;
|
||||
inode->i_fop = &bm_entry_operations;
|
||||
@ -780,7 +890,8 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int res = parse_command(buffer, count);
|
||||
struct dentry *root;
|
||||
Node *e, *next;
|
||||
struct inode *inode;
|
||||
|
||||
switch (res) {
|
||||
case 1:
|
||||
@ -793,13 +904,22 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
|
||||
break;
|
||||
case 3:
|
||||
/* Delete all handlers. */
|
||||
root = file_inode(file)->i_sb->s_root;
|
||||
inode_lock(d_inode(root));
|
||||
inode = d_inode(file_inode(file)->i_sb->s_root);
|
||||
inode_lock(inode);
|
||||
|
||||
while (!list_empty(&entries))
|
||||
kill_node(list_first_entry(&entries, Node, list));
|
||||
/*
|
||||
* In order to add new element or remove elements from the list
|
||||
* via bm_{entry,register,status}_write() inode_lock() on the
|
||||
* root inode must be held.
|
||||
* The lock is exclusive ensuring that the list can't be
|
||||
* modified. Only load_misc_binary() can access but does so
|
||||
* read-only. So we only need to take the write lock when we
|
||||
* actually remove the entry from the list.
|
||||
*/
|
||||
list_for_each_entry_safe(e, next, &entries, list)
|
||||
remove_binfmt_handler(e);
|
||||
|
||||
inode_unlock(d_inode(root));
|
||||
inode_unlock(inode);
|
||||
break;
|
||||
default:
|
||||
return res;
|
||||
|
@ -988,7 +988,7 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node)
|
||||
|
||||
if (delayed_node &&
|
||||
test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) {
|
||||
BUG_ON(!delayed_node->root);
|
||||
ASSERT(delayed_node->root);
|
||||
clear_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags);
|
||||
delayed_node->count--;
|
||||
|
||||
|
@ -1729,9 +1729,9 @@ static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
|
||||
ctl->free_space -= bytes;
|
||||
}
|
||||
|
||||
static void bitmap_set_bits(struct btrfs_free_space_ctl *ctl,
|
||||
struct btrfs_free_space *info, u64 offset,
|
||||
u64 bytes)
|
||||
static void btrfs_bitmap_set_bits(struct btrfs_free_space_ctl *ctl,
|
||||
struct btrfs_free_space *info, u64 offset,
|
||||
u64 bytes)
|
||||
{
|
||||
unsigned long start, count;
|
||||
|
||||
@ -1988,7 +1988,7 @@ static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl,
|
||||
|
||||
bytes_to_set = min(end - offset, bytes);
|
||||
|
||||
bitmap_set_bits(ctl, info, offset, bytes_to_set);
|
||||
btrfs_bitmap_set_bits(ctl, info, offset, bytes_to_set);
|
||||
|
||||
/*
|
||||
* We set some bytes, we have no idea what the max extent size is
|
||||
|
@ -4520,7 +4520,14 @@ static noinline int may_destroy_subvol(struct btrfs_root *root)
|
||||
ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
BUG_ON(ret == 0);
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* Key with offset -1 found, there would have to exist a root
|
||||
* with such id, but this is out of valid range.
|
||||
*/
|
||||
ret = -EUCLEAN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
if (path->slots[0] > 0) {
|
||||
|
@ -2603,8 +2603,6 @@ int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
|
||||
if (nr_old_roots == 0 && nr_new_roots == 0)
|
||||
goto out_free;
|
||||
|
||||
BUG_ON(!fs_info->quota_root);
|
||||
|
||||
trace_btrfs_qgroup_account_extent(fs_info, trans->transid, bytenr,
|
||||
num_bytes, nr_old_roots, nr_new_roots);
|
||||
|
||||
|
@ -692,7 +692,12 @@ static int begin_cmd(struct send_ctx *sctx, int cmd)
|
||||
if (WARN_ON(!sctx->send_buf))
|
||||
return -EINVAL;
|
||||
|
||||
BUG_ON(sctx->send_size);
|
||||
if (unlikely(sctx->send_size != 0)) {
|
||||
btrfs_err(sctx->send_root->fs_info,
|
||||
"send: command header buffer not empty cmd %d offset %llu",
|
||||
cmd, sctx->send_off);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sctx->send_size += sizeof(*hdr);
|
||||
hdr = (struct btrfs_cmd_header *)sctx->send_buf;
|
||||
|
@ -3591,9 +3591,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
||||
struct ext4_extent *ex, *abut_ex;
|
||||
ext4_lblk_t ee_block, eof_block;
|
||||
unsigned int ee_len, depth, map_len = map->m_len;
|
||||
int allocated = 0, max_zeroout = 0;
|
||||
int err = 0;
|
||||
int split_flag = EXT4_EXT_DATA_VALID2;
|
||||
int allocated = 0;
|
||||
unsigned int max_zeroout = 0;
|
||||
|
||||
ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical"
|
||||
"block %llu, max_blocks %u\n", inode->i_ino,
|
||||
|
@ -5227,6 +5227,9 @@ static int ext4_try_to_trim_range(struct super_block *sb,
|
||||
bool set_trimmed = false;
|
||||
void *bitmap;
|
||||
|
||||
if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
|
||||
return 0;
|
||||
|
||||
last = ext4_last_grp_cluster(sb, e4b->bd_group);
|
||||
bitmap = e4b->bd_bitmap;
|
||||
if (start == 0 && max >= last)
|
||||
|
@ -2138,6 +2138,8 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
|
||||
#endif
|
||||
|
||||
segno = GET_SEGNO(sbi, blkaddr);
|
||||
if (segno == NULL_SEGNO)
|
||||
return;
|
||||
|
||||
se = get_seg_entry(sbi, segno);
|
||||
new_vblocks = se->valid_blocks + del;
|
||||
@ -3149,8 +3151,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
||||
* since SSR needs latest valid block information.
|
||||
*/
|
||||
update_sit_entry(sbi, *new_blkaddr, 1);
|
||||
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
|
||||
update_sit_entry(sbi, old_blkaddr, -1);
|
||||
update_sit_entry(sbi, old_blkaddr, -1);
|
||||
|
||||
if (!__has_curseg_space(sbi, type))
|
||||
sit_i->s_ops->allocate_segment(sbi, type, false);
|
||||
|
28
fs/file.c
28
fs/file.c
@ -41,27 +41,23 @@ static void free_fdtable_rcu(struct rcu_head *rcu)
|
||||
#define BITBIT_NR(nr) BITS_TO_LONGS(BITS_TO_LONGS(nr))
|
||||
#define BITBIT_SIZE(nr) (BITBIT_NR(nr) * sizeof(long))
|
||||
|
||||
#define fdt_words(fdt) ((fdt)->max_fds / BITS_PER_LONG) // words in ->open_fds
|
||||
/*
|
||||
* Copy 'count' fd bits from the old table to the new table and clear the extra
|
||||
* space if any. This does not copy the file pointers. Called with the files
|
||||
* spinlock held for write.
|
||||
*/
|
||||
static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt,
|
||||
unsigned int count)
|
||||
static inline void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt,
|
||||
unsigned int copy_words)
|
||||
{
|
||||
unsigned int cpy, set;
|
||||
unsigned int nwords = fdt_words(nfdt);
|
||||
|
||||
cpy = count / BITS_PER_BYTE;
|
||||
set = (nfdt->max_fds - count) / BITS_PER_BYTE;
|
||||
memcpy(nfdt->open_fds, ofdt->open_fds, cpy);
|
||||
memset((char *)nfdt->open_fds + cpy, 0, set);
|
||||
memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy);
|
||||
memset((char *)nfdt->close_on_exec + cpy, 0, set);
|
||||
|
||||
cpy = BITBIT_SIZE(count);
|
||||
set = BITBIT_SIZE(nfdt->max_fds) - cpy;
|
||||
memcpy(nfdt->full_fds_bits, ofdt->full_fds_bits, cpy);
|
||||
memset((char *)nfdt->full_fds_bits + cpy, 0, set);
|
||||
bitmap_copy_and_extend(nfdt->open_fds, ofdt->open_fds,
|
||||
copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG);
|
||||
bitmap_copy_and_extend(nfdt->close_on_exec, ofdt->close_on_exec,
|
||||
copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG);
|
||||
bitmap_copy_and_extend(nfdt->full_fds_bits, ofdt->full_fds_bits,
|
||||
copy_words, nwords);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -79,7 +75,7 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
|
||||
memcpy(nfdt->fd, ofdt->fd, cpy);
|
||||
memset((char *)nfdt->fd + cpy, 0, set);
|
||||
|
||||
copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
|
||||
copy_fd_bitmaps(nfdt, ofdt, fdt_words(ofdt));
|
||||
}
|
||||
|
||||
static struct fdtable * alloc_fdtable(unsigned int nr)
|
||||
@ -330,7 +326,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
|
||||
open_files = count_open_files(old_fdt);
|
||||
}
|
||||
|
||||
copy_fd_bitmaps(new_fdt, old_fdt, open_files);
|
||||
copy_fd_bitmaps(new_fdt, old_fdt, open_files / BITS_PER_LONG);
|
||||
|
||||
old_fds = old_fdt->fd;
|
||||
new_fds = new_fdt->fd;
|
||||
|
@ -1627,9 +1627,11 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
|
||||
|
||||
this_num = min_t(unsigned, num, PAGE_SIZE - offset);
|
||||
err = fuse_copy_page(cs, &page, offset, this_num, 0);
|
||||
if (!err && offset == 0 &&
|
||||
(this_num == PAGE_SIZE || file_size == end))
|
||||
if (!PageUptodate(page) && !err && offset == 0 &&
|
||||
(this_num == PAGE_SIZE || file_size == end)) {
|
||||
zero_user_segment(page, this_num, PAGE_SIZE);
|
||||
SetPageUptodate(page);
|
||||
}
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
|
@ -237,6 +237,16 @@ static int virtio_fs_read_tag(struct virtio_device *vdev, struct virtio_fs *fs)
|
||||
return -ENOMEM;
|
||||
memcpy(fs->tag, tag_buf, len);
|
||||
fs->tag[len] = '\0';
|
||||
|
||||
/* While the VIRTIO specification allows any character, newlines are
|
||||
* awkward on mount(8) command-lines and cause problems in the sysfs
|
||||
* "tag" attr and uevent TAG= properties. Forbid them.
|
||||
*/
|
||||
if (strchr(fs->tag, '\n')) {
|
||||
dev_dbg(&vdev->dev, "refusing virtiofs tag with newline character\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user