Merge branch 'linux-linaro-lsk-v4.4' into linux-linaro-lsk-v4.4-android
This commit is contained in:
commit
f75c8ea7d1
28 changed files with 387 additions and 133 deletions
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 59
|
||||
SUBLEVEL = 60
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
|
|||
|
|
@ -269,6 +269,11 @@ static void ltq_hw5_irqdispatch(void)
|
|||
DEFINE_HWx_IRQDISPATCH(5)
|
||||
#endif
|
||||
|
||||
static void ltq_hw_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMP
|
||||
void __init arch_init_ipiirq(int irq, struct irqaction *action)
|
||||
{
|
||||
|
|
@ -313,23 +318,19 @@ static struct irqaction irq_call = {
|
|||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
|
||||
unsigned int i;
|
||||
int irq;
|
||||
|
||||
if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) {
|
||||
do_IRQ(MIPS_CPU_TIMER_IRQ);
|
||||
goto out;
|
||||
} else {
|
||||
for (i = 0; i < MAX_IM; i++) {
|
||||
if (pending & (CAUSEF_IP2 << i)) {
|
||||
ltq_hw_irqdispatch(i);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (!pending) {
|
||||
spurious_interrupt();
|
||||
return;
|
||||
}
|
||||
pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
|
||||
|
||||
out:
|
||||
return;
|
||||
pending >>= CAUSEB_IP;
|
||||
while (pending) {
|
||||
irq = fls(pending) - 1;
|
||||
do_IRQ(MIPS_CPU_IRQ_BASE + irq);
|
||||
pending &= ~BIT(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
|
||||
|
|
@ -354,11 +355,6 @@ static const struct irq_domain_ops irq_domain_ops = {
|
|||
.map = icu_map,
|
||||
};
|
||||
|
||||
static struct irqaction cascade = {
|
||||
.handler = no_action,
|
||||
.name = "cascade",
|
||||
};
|
||||
|
||||
int __init icu_of_init(struct device_node *node, struct device_node *parent)
|
||||
{
|
||||
struct device_node *eiu_node;
|
||||
|
|
@ -390,7 +386,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
|
|||
mips_cpu_irq_init();
|
||||
|
||||
for (i = 0; i < MAX_IM; i++)
|
||||
setup_irq(i + 2, &cascade);
|
||||
irq_set_chained_handler(i + 2, ltq_hw_irq_handler);
|
||||
|
||||
if (cpu_has_vint) {
|
||||
pr_info("Setting up vectored interrupts\n");
|
||||
|
|
|
|||
|
|
@ -713,10 +713,9 @@ static void __init xen_reserve_xen_mfnlist(void)
|
|||
size = PFN_PHYS(xen_start_info->nr_p2m_frames);
|
||||
}
|
||||
|
||||
if (!xen_is_e820_reserved(start, size)) {
|
||||
memblock_reserve(start, size);
|
||||
memblock_reserve(start, size);
|
||||
if (!xen_is_e820_reserved(start, size))
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
|
|
@ -727,6 +726,7 @@ static void __init xen_reserve_xen_mfnlist(void)
|
|||
BUG();
|
||||
#else
|
||||
xen_relocate_p2m();
|
||||
memblock_free(start, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
12
block/bio.c
12
block/bio.c
|
|
@ -373,10 +373,14 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
|
|||
bio_list_init(&punt);
|
||||
bio_list_init(&nopunt);
|
||||
|
||||
while ((bio = bio_list_pop(current->bio_list)))
|
||||
while ((bio = bio_list_pop(¤t->bio_list[0])))
|
||||
bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
|
||||
current->bio_list[0] = nopunt;
|
||||
|
||||
*current->bio_list = nopunt;
|
||||
bio_list_init(&nopunt);
|
||||
while ((bio = bio_list_pop(¤t->bio_list[1])))
|
||||
bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
|
||||
current->bio_list[1] = nopunt;
|
||||
|
||||
spin_lock(&bs->rescue_lock);
|
||||
bio_list_merge(&bs->rescue_list, &punt);
|
||||
|
|
@ -464,7 +468,9 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
|
|||
* we retry with the original gfp_flags.
|
||||
*/
|
||||
|
||||
if (current->bio_list && !bio_list_empty(current->bio_list))
|
||||
if (current->bio_list &&
|
||||
(!bio_list_empty(¤t->bio_list[0]) ||
|
||||
!bio_list_empty(¤t->bio_list[1])))
|
||||
gfp_mask &= ~__GFP_DIRECT_RECLAIM;
|
||||
|
||||
p = mempool_alloc(bs->bio_pool, gfp_mask);
|
||||
|
|
|
|||
|
|
@ -2023,7 +2023,14 @@ end_io:
|
|||
*/
|
||||
blk_qc_t generic_make_request(struct bio *bio)
|
||||
{
|
||||
struct bio_list bio_list_on_stack;
|
||||
/*
|
||||
* bio_list_on_stack[0] contains bios submitted by the current
|
||||
* make_request_fn.
|
||||
* bio_list_on_stack[1] contains bios that were submitted before
|
||||
* the current make_request_fn, but that haven't been processed
|
||||
* yet.
|
||||
*/
|
||||
struct bio_list bio_list_on_stack[2];
|
||||
blk_qc_t ret = BLK_QC_T_NONE;
|
||||
|
||||
if (!generic_make_request_checks(bio))
|
||||
|
|
@ -2040,7 +2047,7 @@ blk_qc_t generic_make_request(struct bio *bio)
|
|||
* should be added at the tail
|
||||
*/
|
||||
if (current->bio_list) {
|
||||
bio_list_add(current->bio_list, bio);
|
||||
bio_list_add(¤t->bio_list[0], bio);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -2059,24 +2066,39 @@ blk_qc_t generic_make_request(struct bio *bio)
|
|||
* bio_list, and call into ->make_request() again.
|
||||
*/
|
||||
BUG_ON(bio->bi_next);
|
||||
bio_list_init(&bio_list_on_stack);
|
||||
current->bio_list = &bio_list_on_stack;
|
||||
bio_list_init(&bio_list_on_stack[0]);
|
||||
current->bio_list = bio_list_on_stack;
|
||||
do {
|
||||
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
|
||||
|
||||
if (likely(blk_queue_enter(q, __GFP_DIRECT_RECLAIM) == 0)) {
|
||||
struct bio_list lower, same;
|
||||
|
||||
/* Create a fresh bio_list for all subordinate requests */
|
||||
bio_list_on_stack[1] = bio_list_on_stack[0];
|
||||
bio_list_init(&bio_list_on_stack[0]);
|
||||
|
||||
ret = q->make_request_fn(q, bio);
|
||||
|
||||
blk_queue_exit(q);
|
||||
|
||||
bio = bio_list_pop(current->bio_list);
|
||||
/* sort new bios into those for a lower level
|
||||
* and those for the same level
|
||||
*/
|
||||
bio_list_init(&lower);
|
||||
bio_list_init(&same);
|
||||
while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
|
||||
if (q == bdev_get_queue(bio->bi_bdev))
|
||||
bio_list_add(&same, bio);
|
||||
else
|
||||
bio_list_add(&lower, bio);
|
||||
/* now assemble so we handle the lowest level first */
|
||||
bio_list_merge(&bio_list_on_stack[0], &lower);
|
||||
bio_list_merge(&bio_list_on_stack[0], &same);
|
||||
bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
|
||||
} else {
|
||||
struct bio *bio_next = bio_list_pop(current->bio_list);
|
||||
|
||||
bio_io_error(bio);
|
||||
bio = bio_next;
|
||||
}
|
||||
bio = bio_list_pop(&bio_list_on_stack[0]);
|
||||
} while (bio);
|
||||
current->bio_list = NULL; /* deactivate */
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
# Makefile for the Linux ACPI interpreter
|
||||
#
|
||||
|
||||
ccflags-y := -Os
|
||||
ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -24,9 +24,11 @@
|
|||
ACPI_MODULE_NAME("platform");
|
||||
|
||||
static const struct acpi_device_id forbidden_id_list[] = {
|
||||
{"PNP0000", 0}, /* PIC */
|
||||
{"PNP0100", 0}, /* Timer */
|
||||
{"PNP0200", 0}, /* AT DMA Controller */
|
||||
{"PNP0000", 0}, /* PIC */
|
||||
{"PNP0100", 0}, /* Timer */
|
||||
{"PNP0200", 0}, /* AT DMA Controller */
|
||||
{"ACPI0009", 0}, /* IOxAPIC */
|
||||
{"ACPI000A", 0}, /* IOAPIC */
|
||||
{"", 0},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -213,8 +213,8 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,
|
|||
rbo->placement.num_busy_placement = 0;
|
||||
for (i = 0; i < rbo->placement.num_placement; i++) {
|
||||
if (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) {
|
||||
if (rbo->placements[0].fpfn < fpfn)
|
||||
rbo->placements[0].fpfn = fpfn;
|
||||
if (rbo->placements[i].fpfn < fpfn)
|
||||
rbo->placements[i].fpfn = fpfn;
|
||||
} else {
|
||||
rbo->placement.busy_placement =
|
||||
&rbo->placements[i];
|
||||
|
|
|
|||
|
|
@ -1481,26 +1481,29 @@ static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule)
|
|||
struct dm_offload *o = container_of(cb, struct dm_offload, cb);
|
||||
struct bio_list list;
|
||||
struct bio *bio;
|
||||
int i;
|
||||
|
||||
INIT_LIST_HEAD(&o->cb.list);
|
||||
|
||||
if (unlikely(!current->bio_list))
|
||||
return;
|
||||
|
||||
list = *current->bio_list;
|
||||
bio_list_init(current->bio_list);
|
||||
for (i = 0; i < 2; i++) {
|
||||
list = current->bio_list[i];
|
||||
bio_list_init(¤t->bio_list[i]);
|
||||
|
||||
while ((bio = bio_list_pop(&list))) {
|
||||
struct bio_set *bs = bio->bi_pool;
|
||||
if (unlikely(!bs) || bs == fs_bio_set) {
|
||||
bio_list_add(current->bio_list, bio);
|
||||
continue;
|
||||
while ((bio = bio_list_pop(&list))) {
|
||||
struct bio_set *bs = bio->bi_pool;
|
||||
if (unlikely(!bs) || bs == fs_bio_set) {
|
||||
bio_list_add(¤t->bio_list[i], bio);
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_lock(&bs->rescue_lock);
|
||||
bio_list_add(&bs->rescue_list, bio);
|
||||
queue_work(bs->rescue_workqueue, &bs->rescue_work);
|
||||
spin_unlock(&bs->rescue_lock);
|
||||
}
|
||||
|
||||
spin_lock(&bs->rescue_lock);
|
||||
bio_list_add(&bs->rescue_list, bio);
|
||||
queue_work(bs->rescue_workqueue, &bs->rescue_work);
|
||||
spin_unlock(&bs->rescue_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -877,7 +877,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
|
|||
((conf->start_next_window <
|
||||
conf->next_resync + RESYNC_SECTORS) &&
|
||||
current->bio_list &&
|
||||
!bio_list_empty(current->bio_list))),
|
||||
(!bio_list_empty(¤t->bio_list[0]) ||
|
||||
!bio_list_empty(¤t->bio_list[1])))),
|
||||
conf->resync_lock);
|
||||
conf->nr_waiting--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -946,7 +946,8 @@ static void wait_barrier(struct r10conf *conf)
|
|||
!conf->barrier ||
|
||||
(conf->nr_pending &&
|
||||
current->bio_list &&
|
||||
!bio_list_empty(current->bio_list)),
|
||||
(!bio_list_empty(¤t->bio_list[0]) ||
|
||||
!bio_list_empty(¤t->bio_list[1]))),
|
||||
conf->resync_lock);
|
||||
conf->nr_waiting--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
#include <soc/at91/at91sam9_ddrsdr.h>
|
||||
|
||||
#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
|
||||
#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
|
||||
#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
|
||||
|
|
@ -50,6 +53,7 @@ static const char *shdwc_wakeup_modes[] = {
|
|||
|
||||
static void __iomem *at91_shdwc_base;
|
||||
static struct clk *sclk;
|
||||
static void __iomem *mpddrc_base;
|
||||
|
||||
static void __init at91_wakeup_status(void)
|
||||
{
|
||||
|
|
@ -73,6 +77,29 @@ static void at91_poweroff(void)
|
|||
writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
|
||||
}
|
||||
|
||||
static void at91_lpddr_poweroff(void)
|
||||
{
|
||||
asm volatile(
|
||||
/* Align to cache lines */
|
||||
".balign 32\n\t"
|
||||
|
||||
/* Ensure AT91_SHDW_CR is in the TLB by reading it */
|
||||
" ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
|
||||
|
||||
/* Power down SDRAM0 */
|
||||
" str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
|
||||
/* Shutdown CPU */
|
||||
" str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
|
||||
|
||||
" b .\n\t"
|
||||
:
|
||||
: "r" (mpddrc_base),
|
||||
"r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF),
|
||||
"r" (at91_shdwc_base),
|
||||
"r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW)
|
||||
: "r0");
|
||||
}
|
||||
|
||||
static int at91_poweroff_get_wakeup_mode(struct device_node *np)
|
||||
{
|
||||
const char *pm;
|
||||
|
|
@ -124,6 +151,8 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
|
|||
static int __init at91_poweroff_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct device_node *np;
|
||||
u32 ddr_type;
|
||||
int ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
|
@ -150,12 +179,30 @@ static int __init at91_poweroff_probe(struct platform_device *pdev)
|
|||
|
||||
pm_power_off = at91_poweroff;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
|
||||
if (!np)
|
||||
return 0;
|
||||
|
||||
mpddrc_base = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
|
||||
if (!mpddrc_base)
|
||||
return 0;
|
||||
|
||||
ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
|
||||
if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) ||
|
||||
(ddr_type == AT91_DDRSDRC_MD_LPDDR3))
|
||||
pm_power_off = at91_lpddr_poweroff;
|
||||
else
|
||||
iounmap(mpddrc_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit at91_poweroff_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (pm_power_off == at91_poweroff)
|
||||
if (pm_power_off == at91_poweroff ||
|
||||
pm_power_off == at91_lpddr_poweroff)
|
||||
pm_power_off = NULL;
|
||||
|
||||
clk_disable_unprepare(sclk);
|
||||
|
|
@ -163,6 +210,11 @@ static int __exit at91_poweroff_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id at91_ramc_of_match[] = {
|
||||
{ .compatible = "atmel,sama5d3-ddramc", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static const struct of_device_id at91_poweroff_of_match[] = {
|
||||
{ .compatible = "atmel,at91sam9260-shdwc", },
|
||||
{ .compatible = "atmel,at91sam9rl-shdwc", },
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/bitrev.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define S35390A_CMD_STATUS1 0
|
||||
#define S35390A_CMD_STATUS2 1
|
||||
|
|
@ -34,10 +35,14 @@
|
|||
#define S35390A_ALRM_BYTE_HOURS 1
|
||||
#define S35390A_ALRM_BYTE_MINS 2
|
||||
|
||||
/* flags for STATUS1 */
|
||||
#define S35390A_FLAG_POC 0x01
|
||||
#define S35390A_FLAG_BLD 0x02
|
||||
#define S35390A_FLAG_INT2 0x04
|
||||
#define S35390A_FLAG_24H 0x40
|
||||
#define S35390A_FLAG_RESET 0x80
|
||||
|
||||
/* flag for STATUS2 */
|
||||
#define S35390A_FLAG_TEST 0x01
|
||||
|
||||
#define S35390A_INT2_MODE_MASK 0xF0
|
||||
|
|
@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int s35390a_reset(struct s35390a *s35390a)
|
||||
/*
|
||||
* Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
|
||||
* To keep the information if an irq is pending, pass the value read from
|
||||
* STATUS1 to the caller.
|
||||
*/
|
||||
static int s35390a_reset(struct s35390a *s35390a, char *status1)
|
||||
{
|
||||
char buf[1];
|
||||
char buf;
|
||||
int ret;
|
||||
unsigned initcount = 0;
|
||||
|
||||
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
|
||||
return -EIO;
|
||||
ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
|
||||
if (*status1 & S35390A_FLAG_POC)
|
||||
/*
|
||||
* Do not communicate for 0.5 seconds since the power-on
|
||||
* detection circuit is in operation.
|
||||
*/
|
||||
msleep(500);
|
||||
else if (!(*status1 & S35390A_FLAG_BLD))
|
||||
/*
|
||||
* If both POC and BLD are unset everything is fine.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
|
||||
buf[0] &= 0xf0;
|
||||
return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
|
||||
/*
|
||||
* At least one of POC and BLD are set, so reinitialise chip. Keeping
|
||||
* this information in the hardware to know later that the time isn't
|
||||
* valid is unfortunately not possible because POC and BLD are cleared
|
||||
* on read. So the reset is best done now.
|
||||
*
|
||||
* The 24H bit is kept over reset, so set it already here.
|
||||
*/
|
||||
initialize:
|
||||
*status1 = S35390A_FLAG_24H;
|
||||
buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
|
||||
ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
|
||||
/* Try up to five times to reset the chip */
|
||||
if (initcount < 5) {
|
||||
++initcount;
|
||||
goto initialize;
|
||||
} else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s35390a_disable_test_mode(struct s35390a *s35390a)
|
||||
|
|
@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
|
|||
|
||||
if (alm->time.tm_wday != -1)
|
||||
buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
|
||||
else
|
||||
buf[S35390A_ALRM_BYTE_WDAY] = 0;
|
||||
|
||||
buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
|
||||
alm->time.tm_hour) | 0x80;
|
||||
|
|
@ -265,27 +316,61 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
|
|||
char buf[3], sts;
|
||||
int i, err;
|
||||
|
||||
/*
|
||||
* initialize all members to -1 to signal the core that they are not
|
||||
* defined by the hardware.
|
||||
*/
|
||||
alm->time.tm_sec = -1;
|
||||
alm->time.tm_min = -1;
|
||||
alm->time.tm_hour = -1;
|
||||
alm->time.tm_mday = -1;
|
||||
alm->time.tm_mon = -1;
|
||||
alm->time.tm_year = -1;
|
||||
alm->time.tm_wday = -1;
|
||||
alm->time.tm_yday = -1;
|
||||
alm->time.tm_isdst = -1;
|
||||
|
||||
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
|
||||
return -EINVAL;
|
||||
if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
|
||||
/*
|
||||
* When the alarm isn't enabled, the register to configure
|
||||
* the alarm time isn't accessible.
|
||||
*/
|
||||
alm->enabled = 0;
|
||||
return 0;
|
||||
} else {
|
||||
alm->enabled = 1;
|
||||
}
|
||||
|
||||
err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* This chip returns the bits of each byte in reverse order */
|
||||
for (i = 0; i < 3; ++i) {
|
||||
for (i = 0; i < 3; ++i)
|
||||
buf[i] = bitrev8(buf[i]);
|
||||
buf[i] &= ~0x80;
|
||||
}
|
||||
|
||||
alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
|
||||
alm->time.tm_hour = s35390a_reg2hr(s35390a,
|
||||
buf[S35390A_ALRM_BYTE_HOURS]);
|
||||
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
|
||||
/*
|
||||
* B0 of the three matching registers is an enable flag. Iff it is set
|
||||
* the configured value is used for matching.
|
||||
*/
|
||||
if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
|
||||
alm->time.tm_wday =
|
||||
bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
|
||||
|
||||
if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
|
||||
alm->time.tm_hour =
|
||||
s35390a_reg2hr(s35390a,
|
||||
buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
|
||||
|
||||
if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
|
||||
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
|
||||
|
||||
/* alarm triggers always at s=0 */
|
||||
alm->time.tm_sec = 0;
|
||||
|
||||
dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
|
||||
__func__, alm->time.tm_min, alm->time.tm_hour,
|
||||
|
|
@ -327,11 +412,11 @@ static struct i2c_driver s35390a_driver;
|
|||
static int s35390a_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int err;
|
||||
int err, err_reset;
|
||||
unsigned int i;
|
||||
struct s35390a *s35390a;
|
||||
struct rtc_time tm;
|
||||
char buf[1];
|
||||
char buf, status1;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
err = -ENODEV;
|
||||
|
|
@ -360,29 +445,35 @@ static int s35390a_probe(struct i2c_client *client,
|
|||
}
|
||||
}
|
||||
|
||||
err = s35390a_reset(s35390a);
|
||||
if (err < 0) {
|
||||
err_reset = s35390a_reset(s35390a, &status1);
|
||||
if (err_reset < 0) {
|
||||
err = err_reset;
|
||||
dev_err(&client->dev, "error resetting chip\n");
|
||||
goto exit_dummy;
|
||||
}
|
||||
|
||||
err = s35390a_disable_test_mode(s35390a);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "error disabling test mode\n");
|
||||
goto exit_dummy;
|
||||
}
|
||||
|
||||
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "error checking 12/24 hour mode\n");
|
||||
goto exit_dummy;
|
||||
}
|
||||
if (buf[0] & S35390A_FLAG_24H)
|
||||
if (status1 & S35390A_FLAG_24H)
|
||||
s35390a->twentyfourhour = 1;
|
||||
else
|
||||
s35390a->twentyfourhour = 0;
|
||||
|
||||
if (s35390a_get_datetime(client, &tm) < 0)
|
||||
if (status1 & S35390A_FLAG_INT2) {
|
||||
/* disable alarm (and maybe test mode) */
|
||||
buf = 0;
|
||||
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "error disabling alarm");
|
||||
goto exit_dummy;
|
||||
}
|
||||
} else {
|
||||
err = s35390a_disable_test_mode(s35390a);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "error disabling test mode\n");
|
||||
goto exit_dummy;
|
||||
}
|
||||
}
|
||||
|
||||
if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
|
||||
dev_warn(&client->dev, "clock needs to be set\n");
|
||||
|
||||
device_set_wakeup_capable(&client->dev, 1);
|
||||
|
|
@ -395,6 +486,10 @@ static int s35390a_probe(struct i2c_client *client,
|
|||
err = PTR_ERR(s35390a->rtc);
|
||||
goto exit_dummy;
|
||||
}
|
||||
|
||||
if (status1 & S35390A_FLAG_INT2)
|
||||
rtc_update_irq(s35390a->rtc, 1, RTC_AF);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_dummy:
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
|
|||
task->num_scatter = qc->n_elem;
|
||||
} else {
|
||||
for_each_sg(qc->sg, sg, qc->n_elem, si)
|
||||
xfer += sg->length;
|
||||
xfer += sg_dma_len(sg);
|
||||
|
||||
task->total_xfer_len = xfer;
|
||||
task->num_scatter = si;
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ struct MPT3SAS_TARGET {
|
|||
* @eedp_enable: eedp support enable bit
|
||||
* @eedp_type: 0(type_1), 1(type_2), 2(type_3)
|
||||
* @eedp_block_length: block size
|
||||
* @ata_command_pending: SATL passthrough outstanding for device
|
||||
*/
|
||||
struct MPT3SAS_DEVICE {
|
||||
struct MPT3SAS_TARGET *sas_target;
|
||||
|
|
@ -398,6 +399,17 @@ struct MPT3SAS_DEVICE {
|
|||
u8 configured_lun;
|
||||
u8 block;
|
||||
u8 tlr_snoop_check;
|
||||
/*
|
||||
* Bug workaround for SATL handling: the mpt2/3sas firmware
|
||||
* doesn't return BUSY or TASK_SET_FULL for subsequent
|
||||
* commands while a SATL pass through is in operation as the
|
||||
* spec requires, it simply does nothing with them until the
|
||||
* pass through completes, causing them possibly to timeout if
|
||||
* the passthrough is a long executing command (like format or
|
||||
* secure erase). This variable allows us to do the right
|
||||
* thing while a SATL command is pending.
|
||||
*/
|
||||
unsigned long ata_command_pending;
|
||||
};
|
||||
|
||||
#define MPT3_CMD_NOT_USED 0x8000 /* free */
|
||||
|
|
|
|||
|
|
@ -3707,9 +3707,18 @@ _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd)
|
||||
static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
|
||||
{
|
||||
return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16);
|
||||
struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
|
||||
|
||||
if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
|
||||
return 0;
|
||||
|
||||
if (pending)
|
||||
return test_and_set_bit(0, &priv->ata_command_pending);
|
||||
|
||||
clear_bit(0, &priv->ata_command_pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3733,9 +3742,7 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
|
|||
if (!scmd)
|
||||
continue;
|
||||
count++;
|
||||
if (ata_12_16_cmd(scmd))
|
||||
scsi_internal_device_unblock(scmd->device,
|
||||
SDEV_RUNNING);
|
||||
_scsih_set_satl_pending(scmd, false);
|
||||
mpt3sas_base_free_smid(ioc, smid);
|
||||
scsi_dma_unmap(scmd);
|
||||
if (ioc->pci_error_recovery)
|
||||
|
|
@ -3866,13 +3873,6 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
|
|||
if (ioc->logging_level & MPT_DEBUG_SCSI)
|
||||
scsi_print_command(scmd);
|
||||
|
||||
/*
|
||||
* Lock the device for any subsequent command until command is
|
||||
* done.
|
||||
*/
|
||||
if (ata_12_16_cmd(scmd))
|
||||
scsi_internal_device_block(scmd->device);
|
||||
|
||||
sas_device_priv_data = scmd->device->hostdata;
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
|
|
@ -3886,6 +3886,19 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bug work around for firmware SATL handling. The loop
|
||||
* is based on atomic operations and ensures consistency
|
||||
* since we're lockless at this point
|
||||
*/
|
||||
do {
|
||||
if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
|
||||
scmd->result = SAM_STAT_BUSY;
|
||||
scmd->scsi_done(scmd);
|
||||
return 0;
|
||||
}
|
||||
} while (_scsih_set_satl_pending(scmd, true));
|
||||
|
||||
sas_target_priv_data = sas_device_priv_data->sas_target;
|
||||
|
||||
/* invalid device handle */
|
||||
|
|
@ -4445,8 +4458,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
|
|||
if (scmd == NULL)
|
||||
return 1;
|
||||
|
||||
if (ata_12_16_cmd(scmd))
|
||||
scsi_internal_device_unblock(scmd->device, SDEV_RUNNING);
|
||||
_scsih_set_satl_pending(scmd, false);
|
||||
|
||||
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
|||
result = get_user(val, ip);
|
||||
if (result)
|
||||
return result;
|
||||
if (val > SG_MAX_CDB_SIZE)
|
||||
return -ENOMEM;
|
||||
sfp->next_cmd_len = (val > 0) ? val : 0;
|
||||
return 0;
|
||||
case SG_GET_VERSION_NUM:
|
||||
|
|
|
|||
|
|
@ -1987,6 +1987,11 @@ static void atmel_flush_buffer(struct uart_port *port)
|
|||
atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
|
||||
atmel_port->pdc_tx.ofs = 0;
|
||||
}
|
||||
/*
|
||||
* in uart_flush_buffer(), the xmit circular buffer has just
|
||||
* been cleared, so we have to reset tx_len accordingly.
|
||||
*/
|
||||
atmel_port->tx_len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2499,6 +2504,9 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
|
|||
pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
|
||||
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
|
||||
|
||||
/* Make sure that tx path is actually able to send characters */
|
||||
atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
|
||||
|
||||
uart_console_write(port, s, count, atmel_console_putchar);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -499,8 +499,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
|
|||
*/
|
||||
tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
|
||||
tbuf = kzalloc(tbuf_size, GFP_KERNEL);
|
||||
if (!tbuf)
|
||||
return -ENOMEM;
|
||||
if (!tbuf) {
|
||||
status = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
bufp = tbuf;
|
||||
|
||||
|
|
@ -705,6 +707,7 @@ error:
|
|||
}
|
||||
|
||||
kfree(tbuf);
|
||||
err_alloc:
|
||||
|
||||
/* any errors get returned through the urb completion */
|
||||
spin_lock_irq(&hcd_root_hub_lock);
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
|
|||
int len, void *val);
|
||||
int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
int len, struct kvm_io_device *dev);
|
||||
int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
|
||||
struct kvm_io_device *dev);
|
||||
void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
|
||||
struct kvm_io_device *dev);
|
||||
|
||||
#ifdef CONFIG_KVM_ASYNC_PF
|
||||
struct kvm_async_pf {
|
||||
|
|
|
|||
|
|
@ -189,19 +189,20 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd)
|
|||
|
||||
reorder = &next_queue->reorder;
|
||||
|
||||
spin_lock(&reorder->lock);
|
||||
if (!list_empty(&reorder->list)) {
|
||||
padata = list_entry(reorder->list.next,
|
||||
struct padata_priv, list);
|
||||
|
||||
spin_lock(&reorder->lock);
|
||||
list_del_init(&padata->list);
|
||||
atomic_dec(&pd->reorder_objects);
|
||||
spin_unlock(&reorder->lock);
|
||||
|
||||
pd->processed++;
|
||||
|
||||
spin_unlock(&reorder->lock);
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&reorder->lock);
|
||||
|
||||
if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) {
|
||||
padata = ERR_PTR(-ENODATA);
|
||||
|
|
|
|||
|
|
@ -4362,6 +4362,7 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
|
|||
{
|
||||
struct page *page = NULL;
|
||||
spinlock_t *ptl;
|
||||
pte_t pte;
|
||||
retry:
|
||||
ptl = pmd_lockptr(mm, pmd);
|
||||
spin_lock(ptl);
|
||||
|
|
@ -4371,12 +4372,13 @@ retry:
|
|||
*/
|
||||
if (!pmd_huge(*pmd))
|
||||
goto out;
|
||||
if (pmd_present(*pmd)) {
|
||||
pte = huge_ptep_get((pte_t *)pmd);
|
||||
if (pte_present(pte)) {
|
||||
page = pmd_page(*pmd) + ((address & ~PMD_MASK) >> PAGE_SHIFT);
|
||||
if (flags & FOLL_GET)
|
||||
get_page(page);
|
||||
} else {
|
||||
if (is_hugetlb_entry_migration(huge_ptep_get((pte_t *)pmd))) {
|
||||
if (is_hugetlb_entry_migration(pte)) {
|
||||
spin_unlock(ptl);
|
||||
__migration_entry_wait(mm, (pte_t *)pmd, ptl);
|
||||
goto retry;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/string.h>
|
||||
|
|
@ -478,11 +479,16 @@ static int ceph_tcp_connect(struct ceph_connection *con)
|
|||
{
|
||||
struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
|
||||
struct socket *sock;
|
||||
unsigned int noio_flag;
|
||||
int ret;
|
||||
|
||||
BUG_ON(con->sock);
|
||||
|
||||
/* sock_create_kern() allocates with GFP_KERNEL */
|
||||
noio_flag = memalloc_noio_save();
|
||||
ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family,
|
||||
SOCK_STREAM, IPPROTO_TCP, &sock);
|
||||
memalloc_noio_restore(noio_flag);
|
||||
if (ret)
|
||||
return ret;
|
||||
sock->sk->sk_allocation = GFP_NOFS;
|
||||
|
|
|
|||
|
|
@ -265,6 +265,10 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
|
|||
/* NOTE: overflow flag is not cleared */
|
||||
spin_unlock_irqrestore(&f->lock, flags);
|
||||
|
||||
/* close the old pool and wait until all users are gone */
|
||||
snd_seq_pool_mark_closing(oldpool);
|
||||
snd_use_lock_sync(&f->use_lock);
|
||||
|
||||
/* release cells in old pool */
|
||||
for (cell = oldhead; cell; cell = next) {
|
||||
next = cell->next;
|
||||
|
|
|
|||
|
|
@ -4831,6 +4831,7 @@ enum {
|
|||
ALC292_FIXUP_DISABLE_AAMIX,
|
||||
ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
|
||||
ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
|
||||
ALC275_FIXUP_DELL_XPS,
|
||||
ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
|
||||
ALC293_FIXUP_LENOVO_SPK_NOISE,
|
||||
|
|
@ -5429,6 +5430,15 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_HEADSET_MODE
|
||||
},
|
||||
[ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
|
||||
{ }
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_HEADSET_MODE
|
||||
},
|
||||
[ALC275_FIXUP_DELL_XPS] = {
|
||||
.type = HDA_FIXUP_VERBS,
|
||||
.v.verbs = (const struct hda_verb[]) {
|
||||
|
|
@ -5501,7 +5511,7 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc298_fixup_speaker_volume,
|
||||
.chained = true,
|
||||
.chain_id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
.chain_id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
|
||||
},
|
||||
[ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai,
|
|||
}
|
||||
|
||||
#define CLASSD_ACLK_RATE_11M2896_MPY_8 (112896 * 100 * 8)
|
||||
#define CLASSD_ACLK_RATE_12M288_MPY_8 (12228 * 1000 * 8)
|
||||
#define CLASSD_ACLK_RATE_12M288_MPY_8 (12288 * 1000 * 8)
|
||||
|
||||
static struct {
|
||||
int rate;
|
||||
|
|
|
|||
|
|
@ -868,7 +868,8 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
|
|||
continue;
|
||||
|
||||
kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
|
||||
kvm->buses[bus_idx]->ioeventfd_count--;
|
||||
if (kvm->buses[bus_idx])
|
||||
kvm->buses[bus_idx]->ioeventfd_count--;
|
||||
ioeventfd_release(p);
|
||||
ret = 0;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -654,8 +654,11 @@ static void kvm_destroy_vm(struct kvm *kvm)
|
|||
list_del(&kvm->vm_list);
|
||||
spin_unlock(&kvm_lock);
|
||||
kvm_free_irq_routing(kvm);
|
||||
for (i = 0; i < KVM_NR_BUSES; i++)
|
||||
kvm_io_bus_destroy(kvm->buses[i]);
|
||||
for (i = 0; i < KVM_NR_BUSES; i++) {
|
||||
if (kvm->buses[i])
|
||||
kvm_io_bus_destroy(kvm->buses[i]);
|
||||
kvm->buses[i] = NULL;
|
||||
}
|
||||
kvm_coalesced_mmio_free(kvm);
|
||||
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
|
||||
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
|
||||
|
|
@ -3271,6 +3274,8 @@ int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
|
|||
};
|
||||
|
||||
bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
r = __kvm_io_bus_write(vcpu, bus, &range, val);
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
|
@ -3288,6 +3293,8 @@ int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
|
|||
};
|
||||
|
||||
bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
/* First try the device referenced by cookie. */
|
||||
if ((cookie >= 0) && (cookie < bus->dev_count) &&
|
||||
|
|
@ -3338,6 +3345,8 @@ int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
|
|||
};
|
||||
|
||||
bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
r = __kvm_io_bus_read(vcpu, bus, &range, val);
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
|
@ -3350,6 +3359,9 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
|||
struct kvm_io_bus *new_bus, *bus;
|
||||
|
||||
bus = kvm->buses[bus_idx];
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
/* exclude ioeventfd which is limited by maximum fd */
|
||||
if (bus->dev_count - bus->ioeventfd_count > NR_IOBUS_DEVS - 1)
|
||||
return -ENOSPC;
|
||||
|
|
@ -3369,37 +3381,41 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
|||
}
|
||||
|
||||
/* Caller must hold slots_lock. */
|
||||
int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
|
||||
struct kvm_io_device *dev)
|
||||
void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
|
||||
struct kvm_io_device *dev)
|
||||
{
|
||||
int i, r;
|
||||
int i;
|
||||
struct kvm_io_bus *new_bus, *bus;
|
||||
|
||||
bus = kvm->buses[bus_idx];
|
||||
r = -ENOENT;
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
for (i = 0; i < bus->dev_count; i++)
|
||||
if (bus->range[i].dev == dev) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
if (i == bus->dev_count)
|
||||
return;
|
||||
|
||||
new_bus = kmalloc(sizeof(*bus) + ((bus->dev_count - 1) *
|
||||
sizeof(struct kvm_io_range)), GFP_KERNEL);
|
||||
if (!new_bus)
|
||||
return -ENOMEM;
|
||||
if (!new_bus) {
|
||||
pr_err("kvm: failed to shrink bus, removing it completely\n");
|
||||
goto broken;
|
||||
}
|
||||
|
||||
memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range));
|
||||
new_bus->dev_count--;
|
||||
memcpy(new_bus->range + i, bus->range + i + 1,
|
||||
(new_bus->dev_count - i) * sizeof(struct kvm_io_range));
|
||||
|
||||
broken:
|
||||
rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
|
||||
synchronize_srcu_expedited(&kvm->srcu);
|
||||
kfree(bus);
|
||||
return r;
|
||||
return;
|
||||
}
|
||||
|
||||
static struct notifier_block kvm_cpu_notifier = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue