mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
Merge 4.9.50 into android-4.9
Changes in 4.9.50 mtd: nand: mxc: Fix mxc_v1 ooblayout mtd: nand: qcom: fix read failure without complete bootchain mtd: nand: qcom: fix config error for BCH nvme-fabrics: generate spec-compliant UUID NQNs btrfs: resume qgroup rescan on rw remount selftests/x86/fsgsbase: Test selectors 1, 2, and 3 mm/memory.c: fix mem_cgroup_oom_disable() call missing locktorture: Fix potential memory leak with rw lock test ALSA: msnd: Optimize / harden DSP and MIDI loops Bluetooth: Properly check L2CAP config option output buffer length ARM64: dts: marvell: armada-37xx: Fix GIC maintenance interrupt ARM: 8692/1: mm: abort uaccess retries upon fatal signal NFS: Fix 2 use after free issues in the I/O code NFS: Sync the correct byte range during synchronous writes xfs: XFS_IS_REALTIME_INODE() should be false if no rt device present Linux 4.9.50 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 49
|
||||
SUBLEVEL = 50
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -314,8 +314,11 @@ retry:
|
||||
* signal first. We do not need to release the mmap_sem because
|
||||
* it would already be released in __lock_page_or_retry in
|
||||
* mm/filemap.c. */
|
||||
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
|
||||
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Major/minor page fault accounting is only done on the
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
interrupt-controller;
|
||||
reg = <0x1d00000 0x10000>, /* GICD */
|
||||
<0x1d40000 0x40000>; /* GICR */
|
||||
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -877,6 +877,8 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
|
||||
}
|
||||
}
|
||||
|
||||
#define MXC_V1_ECCBYTES 5
|
||||
|
||||
static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *oobregion)
|
||||
{
|
||||
@@ -886,7 +888,7 @@ static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
return -ERANGE;
|
||||
|
||||
oobregion->offset = (section * 16) + 6;
|
||||
oobregion->length = nand_chip->ecc.bytes;
|
||||
oobregion->length = MXC_V1_ECCBYTES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -908,8 +910,7 @@ static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
oobregion->length = 4;
|
||||
}
|
||||
} else {
|
||||
oobregion->offset = ((section - 1) * 16) +
|
||||
nand_chip->ecc.bytes + 6;
|
||||
oobregion->offset = ((section - 1) * 16) + MXC_V1_ECCBYTES + 6;
|
||||
if (section < nand_chip->ecc.steps)
|
||||
oobregion->length = (section * 16) + 6 -
|
||||
oobregion->offset;
|
||||
|
||||
@@ -109,7 +109,11 @@
|
||||
#define READ_ADDR 0
|
||||
|
||||
/* NAND_DEV_CMD_VLD bits */
|
||||
#define READ_START_VLD 0
|
||||
#define READ_START_VLD BIT(0)
|
||||
#define READ_STOP_VLD BIT(1)
|
||||
#define WRITE_START_VLD BIT(2)
|
||||
#define ERASE_START_VLD BIT(3)
|
||||
#define SEQ_READ_START_VLD BIT(4)
|
||||
|
||||
/* NAND_EBI2_ECC_BUF_CFG bits */
|
||||
#define NUM_STEPS 0
|
||||
@@ -148,6 +152,10 @@
|
||||
#define FETCH_ID 0xb
|
||||
#define RESET_DEVICE 0xd
|
||||
|
||||
/* Default Value for NAND_DEV_CMD_VLD */
|
||||
#define NAND_DEV_CMD_VLD_VAL (READ_START_VLD | WRITE_START_VLD | \
|
||||
ERASE_START_VLD | SEQ_READ_START_VLD)
|
||||
|
||||
/*
|
||||
* the NAND controller performs reads/writes with ECC in 516 byte chunks.
|
||||
* the driver calls the chunks 'step' or 'codeword' interchangeably
|
||||
@@ -672,8 +680,7 @@ static int nandc_param(struct qcom_nand_host *host)
|
||||
|
||||
/* configure CMD1 and VLD for ONFI param probing */
|
||||
nandc_set_reg(nandc, NAND_DEV_CMD_VLD,
|
||||
(nandc->vld & ~(1 << READ_START_VLD))
|
||||
| 0 << READ_START_VLD);
|
||||
(nandc->vld & ~READ_START_VLD));
|
||||
nandc_set_reg(nandc, NAND_DEV_CMD1,
|
||||
(nandc->cmd1 & ~(0xFF << READ_ADDR))
|
||||
| NAND_CMD_PARAM << READ_ADDR);
|
||||
@@ -1893,7 +1900,7 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
|
||||
| wide_bus << WIDE_FLASH
|
||||
| 1 << DEV0_CFG1_ECC_DISABLE;
|
||||
|
||||
host->ecc_bch_cfg = host->bch_enabled << ECC_CFG_ECC_DISABLE
|
||||
host->ecc_bch_cfg = !host->bch_enabled << ECC_CFG_ECC_DISABLE
|
||||
| 0 << ECC_SW_RESET
|
||||
| host->cw_data << ECC_NUM_DATA_BYTES
|
||||
| 1 << ECC_FORCE_CLK_OPEN
|
||||
@@ -1972,13 +1979,14 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
/* kill onenand */
|
||||
nandc_write(nandc, SFLASHC_BURST_CFG, 0);
|
||||
nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
|
||||
|
||||
/* enable ADM DMA */
|
||||
nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
|
||||
|
||||
/* save the original values of these registers */
|
||||
nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
|
||||
nandc->vld = nandc_read(nandc, NAND_DEV_CMD_VLD);
|
||||
nandc->vld = NAND_DEV_CMD_VLD_VAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ static struct nvmf_host *nvmf_host_default(void)
|
||||
kref_init(&host->ref);
|
||||
uuid_be_gen(&host->id);
|
||||
snprintf(host->nqn, NVMF_NQN_SIZE,
|
||||
"nqn.2014-08.org.nvmexpress:NVMf:uuid:%pUb", &host->id);
|
||||
"nqn.2014-08.org.nvmexpress:uuid:%pUb", &host->id);
|
||||
|
||||
mutex_lock(&nvmf_hosts_mutex);
|
||||
list_add_tail(&host->list, &nvmf_hosts);
|
||||
|
||||
@@ -1834,6 +1834,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
|
||||
goto restore;
|
||||
}
|
||||
|
||||
btrfs_qgroup_rescan_resume(fs_info);
|
||||
|
||||
if (!fs_info->uuid_root) {
|
||||
btrfs_info(fs_info, "creating UUID tree");
|
||||
ret = btrfs_create_uuid_tree(fs_info);
|
||||
|
||||
@@ -636,11 +636,11 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (result <= 0)
|
||||
goto out;
|
||||
|
||||
result = generic_write_sync(iocb, result);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
written = result;
|
||||
iocb->ki_pos += written;
|
||||
result = generic_write_sync(iocb, written);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
/* Return error values */
|
||||
if (nfs_need_check_write(file, inode)) {
|
||||
|
||||
@@ -248,7 +248,6 @@ int nfs_iocounter_wait(struct nfs_lock_context *l_ctx);
|
||||
extern const struct nfs_pageio_ops nfs_pgio_rw_ops;
|
||||
struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *);
|
||||
void nfs_pgio_header_free(struct nfs_pgio_header *);
|
||||
void nfs_pgio_data_destroy(struct nfs_pgio_header *);
|
||||
int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);
|
||||
int nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_header *hdr,
|
||||
struct rpc_cred *cred, const struct nfs_rpc_ops *rpc_ops,
|
||||
|
||||
@@ -497,16 +497,6 @@ struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *ops)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_pgio_header_alloc);
|
||||
|
||||
/*
|
||||
* nfs_pgio_header_free - Free a read or write header
|
||||
* @hdr: The header to free
|
||||
*/
|
||||
void nfs_pgio_header_free(struct nfs_pgio_header *hdr)
|
||||
{
|
||||
hdr->rw_ops->rw_free_header(hdr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_pgio_header_free);
|
||||
|
||||
/**
|
||||
* nfs_pgio_data_destroy - make @hdr suitable for reuse
|
||||
*
|
||||
@@ -515,14 +505,24 @@ EXPORT_SYMBOL_GPL(nfs_pgio_header_free);
|
||||
*
|
||||
* @hdr: A header that has had nfs_generic_pgio called
|
||||
*/
|
||||
void nfs_pgio_data_destroy(struct nfs_pgio_header *hdr)
|
||||
static void nfs_pgio_data_destroy(struct nfs_pgio_header *hdr)
|
||||
{
|
||||
if (hdr->args.context)
|
||||
put_nfs_open_context(hdr->args.context);
|
||||
if (hdr->page_array.pagevec != hdr->page_array.page_array)
|
||||
kfree(hdr->page_array.pagevec);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_pgio_data_destroy);
|
||||
|
||||
/*
|
||||
* nfs_pgio_header_free - Free a read or write header
|
||||
* @hdr: The header to free
|
||||
*/
|
||||
void nfs_pgio_header_free(struct nfs_pgio_header *hdr)
|
||||
{
|
||||
nfs_pgio_data_destroy(hdr);
|
||||
hdr->rw_ops->rw_free_header(hdr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_pgio_header_free);
|
||||
|
||||
/**
|
||||
* nfs_pgio_rpcsetup - Set up arguments for a pageio call
|
||||
@@ -636,7 +636,6 @@ EXPORT_SYMBOL_GPL(nfs_initiate_pgio);
|
||||
static void nfs_pgio_error(struct nfs_pgio_header *hdr)
|
||||
{
|
||||
set_bit(NFS_IOHDR_REDO, &hdr->flags);
|
||||
nfs_pgio_data_destroy(hdr);
|
||||
hdr->completion_ops->completion(hdr);
|
||||
}
|
||||
|
||||
@@ -647,7 +646,6 @@ static void nfs_pgio_error(struct nfs_pgio_header *hdr)
|
||||
static void nfs_pgio_release(void *calldata)
|
||||
{
|
||||
struct nfs_pgio_header *hdr = calldata;
|
||||
nfs_pgio_data_destroy(hdr);
|
||||
hdr->completion_ops->completion(hdr);
|
||||
}
|
||||
|
||||
|
||||
@@ -2145,7 +2145,6 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
|
||||
nfs_pageio_reset_write_mds(desc);
|
||||
mirror->pg_recoalesce = 1;
|
||||
}
|
||||
nfs_pgio_data_destroy(hdr);
|
||||
hdr->release(hdr);
|
||||
}
|
||||
|
||||
@@ -2257,7 +2256,6 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
|
||||
nfs_pageio_reset_read_mds(desc);
|
||||
mirror->pg_recoalesce = 1;
|
||||
}
|
||||
nfs_pgio_data_destroy(hdr);
|
||||
hdr->release(hdr);
|
||||
}
|
||||
|
||||
|
||||
@@ -363,7 +363,14 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef CONFIG_XFS_RT
|
||||
#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME)
|
||||
|
||||
/*
|
||||
* make sure we ignore the inode flag if the filesystem doesn't have a
|
||||
* configured realtime device.
|
||||
*/
|
||||
#define XFS_IS_REALTIME_INODE(ip) \
|
||||
(((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) && \
|
||||
(ip)->i_mount->m_rtdev_targp)
|
||||
#else
|
||||
#define XFS_IS_REALTIME_INODE(ip) (0)
|
||||
#endif
|
||||
|
||||
@@ -780,6 +780,10 @@ static void lock_torture_cleanup(void)
|
||||
else
|
||||
lock_torture_print_module_parms(cxt.cur_ops,
|
||||
"End of test: SUCCESS");
|
||||
|
||||
kfree(cxt.lwsa);
|
||||
kfree(cxt.lrsa);
|
||||
|
||||
end:
|
||||
torture_cleanup_end();
|
||||
}
|
||||
@@ -924,6 +928,8 @@ static int __init lock_torture_init(void)
|
||||
GFP_KERNEL);
|
||||
if (reader_tasks == NULL) {
|
||||
VERBOSE_TOROUT_ERRSTRING("reader_tasks: Out of memory");
|
||||
kfree(writer_tasks);
|
||||
writer_tasks = NULL;
|
||||
firsterr = -ENOMEM;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
10
mm/memory.c
10
mm/memory.c
@@ -3596,6 +3596,11 @@ int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
|
||||
/* do counter updates before entering really critical section. */
|
||||
check_sync_rss_stat(current);
|
||||
|
||||
if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
|
||||
flags & FAULT_FLAG_INSTRUCTION,
|
||||
flags & FAULT_FLAG_REMOTE))
|
||||
return VM_FAULT_SIGSEGV;
|
||||
|
||||
/*
|
||||
* Enable the memcg OOM handling for faults triggered in user
|
||||
* space. Kernel faults are handled more gracefully.
|
||||
@@ -3603,11 +3608,6 @@ int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
|
||||
if (flags & FAULT_FLAG_USER)
|
||||
mem_cgroup_oom_enable();
|
||||
|
||||
if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
|
||||
flags & FAULT_FLAG_INSTRUCTION,
|
||||
flags & FAULT_FLAG_REMOTE))
|
||||
return VM_FAULT_SIGSEGV;
|
||||
|
||||
if (unlikely(is_vm_hugetlb_page(vma)))
|
||||
ret = hugetlb_fault(vma->vm_mm, vma, address, flags);
|
||||
else
|
||||
|
||||
@@ -58,7 +58,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
|
||||
u8 code, u8 ident, u16 dlen, void *data);
|
||||
static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
|
||||
void *data);
|
||||
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
|
||||
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
|
||||
static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
|
||||
|
||||
static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
|
||||
@@ -1473,7 +1473,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
|
||||
|
||||
set_bit(CONF_REQ_SENT, &chan->conf_state);
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, buf), buf);
|
||||
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
|
||||
chan->num_conf_req++;
|
||||
}
|
||||
|
||||
@@ -2977,12 +2977,15 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
|
||||
return len;
|
||||
}
|
||||
|
||||
static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
|
||||
static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
|
||||
{
|
||||
struct l2cap_conf_opt *opt = *ptr;
|
||||
|
||||
BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
|
||||
|
||||
if (size < L2CAP_CONF_OPT_SIZE + len)
|
||||
return;
|
||||
|
||||
opt->type = type;
|
||||
opt->len = len;
|
||||
|
||||
@@ -3007,7 +3010,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
|
||||
*ptr += L2CAP_CONF_OPT_SIZE + len;
|
||||
}
|
||||
|
||||
static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
|
||||
static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
|
||||
{
|
||||
struct l2cap_conf_efs efs;
|
||||
|
||||
@@ -3035,7 +3038,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
|
||||
}
|
||||
|
||||
l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
|
||||
(unsigned long) &efs);
|
||||
(unsigned long) &efs, size);
|
||||
}
|
||||
|
||||
static void l2cap_ack_timeout(struct work_struct *work)
|
||||
@@ -3181,11 +3184,12 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
|
||||
chan->ack_win = chan->tx_win;
|
||||
}
|
||||
|
||||
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
|
||||
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
|
||||
{
|
||||
struct l2cap_conf_req *req = data;
|
||||
struct l2cap_conf_rfc rfc = { .mode = chan->mode };
|
||||
void *ptr = req->data;
|
||||
void *endptr = data + data_size;
|
||||
u16 size;
|
||||
|
||||
BT_DBG("chan %p", chan);
|
||||
@@ -3210,7 +3214,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
|
||||
|
||||
done:
|
||||
if (chan->imtu != L2CAP_DEFAULT_MTU)
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
|
||||
|
||||
switch (chan->mode) {
|
||||
case L2CAP_MODE_BASIC:
|
||||
@@ -3229,7 +3233,7 @@ done:
|
||||
rfc.max_pdu_size = 0;
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
|
||||
(unsigned long) &rfc);
|
||||
(unsigned long) &rfc, endptr - ptr);
|
||||
break;
|
||||
|
||||
case L2CAP_MODE_ERTM:
|
||||
@@ -3249,21 +3253,21 @@ done:
|
||||
L2CAP_DEFAULT_TX_WINDOW);
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
|
||||
(unsigned long) &rfc);
|
||||
(unsigned long) &rfc, endptr - ptr);
|
||||
|
||||
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
|
||||
l2cap_add_opt_efs(&ptr, chan);
|
||||
l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
|
||||
|
||||
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
|
||||
chan->tx_win);
|
||||
chan->tx_win, endptr - ptr);
|
||||
|
||||
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
|
||||
if (chan->fcs == L2CAP_FCS_NONE ||
|
||||
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
|
||||
chan->fcs = L2CAP_FCS_NONE;
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
|
||||
chan->fcs);
|
||||
chan->fcs, endptr - ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3281,17 +3285,17 @@ done:
|
||||
rfc.max_pdu_size = cpu_to_le16(size);
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
|
||||
(unsigned long) &rfc);
|
||||
(unsigned long) &rfc, endptr - ptr);
|
||||
|
||||
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
|
||||
l2cap_add_opt_efs(&ptr, chan);
|
||||
l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
|
||||
|
||||
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
|
||||
if (chan->fcs == L2CAP_FCS_NONE ||
|
||||
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
|
||||
chan->fcs = L2CAP_FCS_NONE;
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
|
||||
chan->fcs);
|
||||
chan->fcs, endptr - ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3302,10 +3306,11 @@ done:
|
||||
return ptr - data;
|
||||
}
|
||||
|
||||
static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
|
||||
static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
|
||||
{
|
||||
struct l2cap_conf_rsp *rsp = data;
|
||||
void *ptr = rsp->data;
|
||||
void *endptr = data + data_size;
|
||||
void *req = chan->conf_req;
|
||||
int len = chan->conf_len;
|
||||
int type, hint, olen;
|
||||
@@ -3407,7 +3412,7 @@ done:
|
||||
return -ECONNREFUSED;
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
|
||||
(unsigned long) &rfc);
|
||||
(unsigned long) &rfc, endptr - ptr);
|
||||
}
|
||||
|
||||
if (result == L2CAP_CONF_SUCCESS) {
|
||||
@@ -3420,7 +3425,7 @@ done:
|
||||
chan->omtu = mtu;
|
||||
set_bit(CONF_MTU_DONE, &chan->conf_state);
|
||||
}
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
|
||||
|
||||
if (remote_efs) {
|
||||
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
|
||||
@@ -3434,7 +3439,7 @@ done:
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
|
||||
sizeof(efs),
|
||||
(unsigned long) &efs);
|
||||
(unsigned long) &efs, endptr - ptr);
|
||||
} else {
|
||||
/* Send PENDING Conf Rsp */
|
||||
result = L2CAP_CONF_PENDING;
|
||||
@@ -3467,7 +3472,7 @@ done:
|
||||
set_bit(CONF_MODE_DONE, &chan->conf_state);
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
|
||||
sizeof(rfc), (unsigned long) &rfc);
|
||||
sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
|
||||
|
||||
if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
|
||||
chan->remote_id = efs.id;
|
||||
@@ -3481,7 +3486,7 @@ done:
|
||||
le32_to_cpu(efs.sdu_itime);
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
|
||||
sizeof(efs),
|
||||
(unsigned long) &efs);
|
||||
(unsigned long) &efs, endptr - ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3495,7 +3500,7 @@ done:
|
||||
set_bit(CONF_MODE_DONE, &chan->conf_state);
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
|
||||
(unsigned long) &rfc);
|
||||
(unsigned long) &rfc, endptr - ptr);
|
||||
|
||||
break;
|
||||
|
||||
@@ -3517,10 +3522,11 @@ done:
|
||||
}
|
||||
|
||||
static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
||||
void *data, u16 *result)
|
||||
void *data, size_t size, u16 *result)
|
||||
{
|
||||
struct l2cap_conf_req *req = data;
|
||||
void *ptr = req->data;
|
||||
void *endptr = data + size;
|
||||
int type, olen;
|
||||
unsigned long val;
|
||||
struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
|
||||
@@ -3538,13 +3544,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
||||
chan->imtu = L2CAP_DEFAULT_MIN_MTU;
|
||||
} else
|
||||
chan->imtu = val;
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
|
||||
break;
|
||||
|
||||
case L2CAP_CONF_FLUSH_TO:
|
||||
chan->flush_to = val;
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
|
||||
2, chan->flush_to);
|
||||
2, chan->flush_to, endptr - ptr);
|
||||
break;
|
||||
|
||||
case L2CAP_CONF_RFC:
|
||||
@@ -3558,13 +3564,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
||||
chan->fcs = 0;
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
|
||||
sizeof(rfc), (unsigned long) &rfc);
|
||||
sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
|
||||
break;
|
||||
|
||||
case L2CAP_CONF_EWS:
|
||||
chan->ack_win = min_t(u16, val, chan->ack_win);
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
|
||||
chan->tx_win);
|
||||
chan->tx_win, endptr - ptr);
|
||||
break;
|
||||
|
||||
case L2CAP_CONF_EFS:
|
||||
@@ -3577,7 +3583,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
||||
return -ECONNREFUSED;
|
||||
|
||||
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
|
||||
(unsigned long) &efs);
|
||||
(unsigned long) &efs, endptr - ptr);
|
||||
break;
|
||||
|
||||
case L2CAP_CONF_FCS:
|
||||
@@ -3682,7 +3688,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
|
||||
return;
|
||||
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, buf), buf);
|
||||
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
|
||||
chan->num_conf_req++;
|
||||
}
|
||||
|
||||
@@ -3890,7 +3896,7 @@ sendresp:
|
||||
u8 buf[128];
|
||||
set_bit(CONF_REQ_SENT, &chan->conf_state);
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, buf), buf);
|
||||
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
|
||||
chan->num_conf_req++;
|
||||
}
|
||||
|
||||
@@ -3968,7 +3974,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
|
||||
break;
|
||||
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, req), req);
|
||||
l2cap_build_conf_req(chan, req, sizeof(req)), req);
|
||||
chan->num_conf_req++;
|
||||
break;
|
||||
|
||||
@@ -4080,7 +4086,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
|
||||
}
|
||||
|
||||
/* Complete config. */
|
||||
len = l2cap_parse_conf_req(chan, rsp);
|
||||
len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
|
||||
if (len < 0) {
|
||||
l2cap_send_disconn_req(chan, ECONNRESET);
|
||||
goto unlock;
|
||||
@@ -4114,7 +4120,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
|
||||
if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
|
||||
u8 buf[64];
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, buf), buf);
|
||||
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
|
||||
chan->num_conf_req++;
|
||||
}
|
||||
|
||||
@@ -4174,7 +4180,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
|
||||
char buf[64];
|
||||
|
||||
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
|
||||
buf, &result);
|
||||
buf, sizeof(buf), &result);
|
||||
if (len < 0) {
|
||||
l2cap_send_disconn_req(chan, ECONNRESET);
|
||||
goto done;
|
||||
@@ -4204,7 +4210,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
|
||||
/* throw out any old stored conf requests */
|
||||
result = L2CAP_CONF_SUCCESS;
|
||||
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
|
||||
req, &result);
|
||||
req, sizeof(req), &result);
|
||||
if (len < 0) {
|
||||
l2cap_send_disconn_req(chan, ECONNRESET);
|
||||
goto done;
|
||||
@@ -4781,7 +4787,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
|
||||
set_bit(CONF_REQ_SENT, &chan->conf_state);
|
||||
l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
|
||||
L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, buf), buf);
|
||||
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
|
||||
chan->num_conf_req++;
|
||||
}
|
||||
}
|
||||
@@ -7457,7 +7463,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
||||
set_bit(CONF_REQ_SENT, &chan->conf_state);
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn),
|
||||
L2CAP_CONF_REQ,
|
||||
l2cap_build_conf_req(chan, buf),
|
||||
l2cap_build_conf_req(chan, buf, sizeof(buf)),
|
||||
buf);
|
||||
chan->num_conf_req++;
|
||||
}
|
||||
|
||||
@@ -120,24 +120,24 @@ void snd_msndmidi_input_read(void *mpuv)
|
||||
unsigned long flags;
|
||||
struct snd_msndmidi *mpu = mpuv;
|
||||
void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF;
|
||||
u16 head, tail, size;
|
||||
|
||||
spin_lock_irqsave(&mpu->input_lock, flags);
|
||||
while (readw(mpu->dev->MIDQ + JQS_wTail) !=
|
||||
readw(mpu->dev->MIDQ + JQS_wHead)) {
|
||||
u16 wTmp, val;
|
||||
val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead));
|
||||
head = readw(mpu->dev->MIDQ + JQS_wHead);
|
||||
tail = readw(mpu->dev->MIDQ + JQS_wTail);
|
||||
size = readw(mpu->dev->MIDQ + JQS_wSize);
|
||||
if (head > size || tail > size)
|
||||
goto out;
|
||||
while (head != tail) {
|
||||
unsigned char val = readw(pwMIDQData + 2 * head);
|
||||
|
||||
if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER,
|
||||
&mpu->mode))
|
||||
snd_rawmidi_receive(mpu->substream_input,
|
||||
(unsigned char *)&val, 1);
|
||||
|
||||
wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1;
|
||||
if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize))
|
||||
writew(0, mpu->dev->MIDQ + JQS_wHead);
|
||||
else
|
||||
writew(wTmp, mpu->dev->MIDQ + JQS_wHead);
|
||||
if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
|
||||
snd_rawmidi_receive(mpu->substream_input, &val, 1);
|
||||
if (++head > size)
|
||||
head = 0;
|
||||
writew(head, mpu->dev->MIDQ + JQS_wHead);
|
||||
}
|
||||
out:
|
||||
spin_unlock_irqrestore(&mpu->input_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(snd_msndmidi_input_read);
|
||||
|
||||
@@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct snd_msnd *chip = dev_id;
|
||||
void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
|
||||
u16 head, tail, size;
|
||||
|
||||
/* Send ack to DSP */
|
||||
/* inb(chip->io + HP_RXL); */
|
||||
|
||||
/* Evaluate queued DSP messages */
|
||||
while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) {
|
||||
u16 wTmp;
|
||||
|
||||
snd_msnd_eval_dsp_msg(chip,
|
||||
readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead)));
|
||||
|
||||
wTmp = readw(chip->DSPQ + JQS_wHead) + 1;
|
||||
if (wTmp > readw(chip->DSPQ + JQS_wSize))
|
||||
writew(0, chip->DSPQ + JQS_wHead);
|
||||
else
|
||||
writew(wTmp, chip->DSPQ + JQS_wHead);
|
||||
head = readw(chip->DSPQ + JQS_wHead);
|
||||
tail = readw(chip->DSPQ + JQS_wTail);
|
||||
size = readw(chip->DSPQ + JQS_wSize);
|
||||
if (head > size || tail > size)
|
||||
goto out;
|
||||
while (head != tail) {
|
||||
snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head));
|
||||
if (++head > size)
|
||||
head = 0;
|
||||
writew(head, chip->DSPQ + JQS_wHead);
|
||||
}
|
||||
out:
|
||||
/* Send ack to DSP */
|
||||
inb(chip->io + HP_RXL);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
@@ -285,9 +285,12 @@ static void *threadproc(void *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
|
||||
static void set_gs_and_switch_to(unsigned long local,
|
||||
unsigned short force_sel,
|
||||
unsigned long remote)
|
||||
{
|
||||
unsigned long base;
|
||||
unsigned short sel_pre_sched, sel_post_sched;
|
||||
|
||||
bool hard_zero = false;
|
||||
if (local == HARD_ZERO) {
|
||||
@@ -297,6 +300,8 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
|
||||
|
||||
printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
|
||||
local, hard_zero ? " and clear gs" : "", remote);
|
||||
if (force_sel)
|
||||
printf("\tBefore schedule, set selector to 0x%hx\n", force_sel);
|
||||
if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
|
||||
err(1, "ARCH_SET_GS");
|
||||
if (hard_zero)
|
||||
@@ -307,18 +312,35 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
|
||||
printf("[FAIL]\tGSBASE wasn't set as expected\n");
|
||||
}
|
||||
|
||||
if (force_sel) {
|
||||
asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
|
||||
sel_pre_sched = force_sel;
|
||||
local = read_base(GS);
|
||||
|
||||
/*
|
||||
* Signal delivery seems to mess up weird selectors. Put it
|
||||
* back.
|
||||
*/
|
||||
asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
|
||||
} else {
|
||||
asm volatile ("mov %%gs, %0" : "=rm" (sel_pre_sched));
|
||||
}
|
||||
|
||||
remote_base = remote;
|
||||
ftx = 1;
|
||||
syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
|
||||
while (ftx != 0)
|
||||
syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
|
||||
|
||||
asm volatile ("mov %%gs, %0" : "=rm" (sel_post_sched));
|
||||
base = read_base(GS);
|
||||
if (base == local) {
|
||||
printf("[OK]\tGSBASE remained 0x%lx\n", local);
|
||||
if (base == local && sel_pre_sched == sel_post_sched) {
|
||||
printf("[OK]\tGS/BASE remained 0x%hx/0x%lx\n",
|
||||
sel_pre_sched, local);
|
||||
} else {
|
||||
nerrs++;
|
||||
printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
|
||||
printf("[FAIL]\tGS/BASE changed from 0x%hx/0x%lx to 0x%hx/0x%lx\n",
|
||||
sel_pre_sched, local, sel_post_sched, base);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,8 +403,15 @@ int main()
|
||||
|
||||
for (int local = 0; local < 4; local++) {
|
||||
for (int remote = 0; remote < 4; remote++) {
|
||||
set_gs_and_switch_to(bases_with_hard_zero[local],
|
||||
bases_with_hard_zero[remote]);
|
||||
for (unsigned short s = 0; s < 5; s++) {
|
||||
unsigned short sel = s;
|
||||
if (s == 4)
|
||||
asm ("mov %%ss, %0" : "=rm" (sel));
|
||||
set_gs_and_switch_to(
|
||||
bases_with_hard_zero[local],
|
||||
sel,
|
||||
bases_with_hard_zero[remote]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user