diff options
Diffstat (limited to 'drivers')
54 files changed, 371 insertions, 388 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7a3f535e481..bb80853ff27 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -775,9 +775,11 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, map->format.parse_val(val + i); } else { for (i = 0; i < val_count; i++) { - ret = regmap_read(map, reg + i, val + (i * val_bytes)); + unsigned int ival; + ret = regmap_read(map, reg + i, &ival); if (ret != 0) return ret; + memcpy(val + (i * val_bytes), &ival, val_bytes); } } diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index abfaacaaf34..946166e1395 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2297,7 +2297,7 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms return; } - if (!cap_raised(current_cap(), CAP_SYS_ADMIN)) { + if (!capable(CAP_SYS_ADMIN)) { retcode = ERR_PERM; goto fail; } diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 1adc2ec1e38..4461540653a 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -965,18 +965,15 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) } _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); - _gpio_rmw(base, bank->regs->irqstatus, l, - bank->regs->irqenable_inv == false); - _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->debounce_en != 0); - _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->ctrl != 0); + _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv); if (bank->regs->debounce_en) - _gpio_rmw(base, bank->regs->debounce_en, 0, 1); + __raw_writel(0, base + bank->regs->debounce_en); /* Save OE default value (0xffffffff) in the context */ bank->context.oe = __raw_readl(bank->base + bank->regs->direction); /* Initialize interface clk ungated, module enabled */ if (bank->regs->ctrl) - _gpio_rmw(base, bank->regs->ctrl, 0, 1); + __raw_writel(0, base + bank->regs->ctrl); } static __devinit void diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index e8729cc2ba2..2cd958e0b82 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -230,16 +230,12 @@ static void pch_gpio_setup(struct pch_gpio *chip) static int pch_irq_type(struct irq_data *d, unsigned int type) { - u32 im; - u32 __iomem *im_reg; - u32 ien; - u32 im_pos; - int ch; - unsigned long flags; - u32 val; - int irq = d->irq; struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct pch_gpio *chip = gc->private; + u32 im, im_pos, val; + u32 __iomem *im_reg; + unsigned long flags; + int ch, irq = d->irq; ch = irq - chip->irq_base; if (irq <= chip->irq_base + 7) { @@ -270,30 +266,22 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) case IRQ_TYPE_LEVEL_LOW: val = PCH_LEVEL_L; break; - case IRQ_TYPE_PROBE: - goto end; default: - dev_warn(chip->dev, "%s: unknown type(%dd)", - __func__, type); - goto end; + goto unlock; } /* Set interrupt mode */ im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4)); iowrite32(im | (val << (im_pos * 4)), im_reg); - /* iclr */ - iowrite32(BIT(ch), &chip->reg->iclr); + /* And the handler */ + if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + __irq_set_handler_locked(d->irq, handle_level_irq); + else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + __irq_set_handler_locked(d->irq, handle_edge_irq); - /* IMASKCLR */ - iowrite32(BIT(ch), &chip->reg->imaskclr); - - /* Enable interrupt */ - ien = ioread32(&chip->reg->ien); - iowrite32(ien | BIT(ch), &chip->reg->ien); -end: +unlock: spin_unlock_irqrestore(&chip->spinlock, flags); - return 0; } @@ -313,18 +301,24 @@ static void pch_irq_mask(struct irq_data *d) iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask); } +static void pch_irq_ack(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct pch_gpio *chip = gc->private; + + iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->iclr); +} + static irqreturn_t pch_gpio_handler(int irq, void *dev_id) { struct pch_gpio *chip = dev_id; u32 reg_val = ioread32(&chip->reg->istatus); - int i; - int ret = IRQ_NONE; + int i, ret = IRQ_NONE; for (i = 0; i < gpio_pins[chip->ioh]; i++) { if (reg_val & BIT(i)) { dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n", __func__, i, irq, reg_val); - iowrite32(BIT(i), &chip->reg->iclr); generic_handle_irq(chip->irq_base + i); ret = IRQ_HANDLED; } @@ -343,6 +337,7 @@ static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip, gc->private = chip; ct = gc->chip_types; + ct->chip.irq_ack = pch_irq_ack; ct->chip.irq_mask = pch_irq_mask; ct->chip.irq_unmask = pch_irq_unmask; ct->chip.irq_set_type = pch_irq_type; @@ -357,6 +352,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, s32 ret; struct pch_gpio *chip; int irq_base; + u32 msk; chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) @@ -408,8 +404,13 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, } chip->irq_base = irq_base; + /* Mask all interrupts, but enable them */ + msk = (1 << gpio_pins[chip->ioh]) - 1; + iowrite32(msk, &chip->reg->imask); + iowrite32(msk, &chip->reg->ien); + ret = request_irq(pdev->irq, pch_gpio_handler, - IRQF_SHARED, KBUILD_MODNAME, chip); + IRQF_SHARED, KBUILD_MODNAME, chip); if (ret != 0) { dev_err(&pdev->dev, "%s request_irq failed\n", __func__); @@ -418,8 +419,6 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]); - /* Initialize interrupt ien register */ - iowrite32(0, &chip->reg->ien); end: return 0; diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 19d6fc0229c..e991d917196 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -452,12 +452,14 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = { }; #endif +#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5) static struct samsung_gpio_cfg exynos_gpio_cfg = { .set_pull = exynos_gpio_setpull, .get_pull = exynos_gpio_getpull, .set_config = samsung_gpio_setcfg_4bit, .get_config = samsung_gpio_getcfg_4bit, }; +#endif #if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = { @@ -2123,8 +2125,8 @@ static struct samsung_gpio_chip s5pv210_gpios_4bit[] = { * uses the above macro and depends on the banks being listed in order here. */ -static struct samsung_gpio_chip exynos4_gpios_1[] = { #ifdef CONFIG_ARCH_EXYNOS4 +static struct samsung_gpio_chip exynos4_gpios_1[] = { { .chip = { .base = EXYNOS4_GPA0(0), @@ -2222,11 +2224,11 @@ static struct samsung_gpio_chip exynos4_gpios_1[] = { .label = "GPF3", }, }, -#endif }; +#endif -static struct samsung_gpio_chip exynos4_gpios_2[] = { #ifdef CONFIG_ARCH_EXYNOS4 +static struct samsung_gpio_chip exynos4_gpios_2[] = { { .chip = { .base = EXYNOS4_GPJ0(0), @@ -2367,11 +2369,11 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = { .to_irq = samsung_gpiolib_to_irq, }, }, -#endif }; +#endif -static struct samsung_gpio_chip exynos4_gpios_3[] = { #ifdef CONFIG_ARCH_EXYNOS4 +static struct samsung_gpio_chip exynos4_gpios_3[] = { { .chip = { .base = EXYNOS4_GPZ(0), @@ -2379,8 +2381,8 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { .label = "GPZ", }, }, -#endif }; +#endif #ifdef CONFIG_ARCH_EXYNOS5 static struct samsung_gpio_chip exynos5_gpios_1[] = { @@ -2719,7 +2721,9 @@ static __init int samsung_gpiolib_init(void) { struct samsung_gpio_chip *chip; int i, nr_chips; +#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS5250) void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4; +#endif int group = 0; samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs)); @@ -2971,6 +2975,7 @@ static __init int samsung_gpiolib_init(void) return 0; +#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS5250) err_ioremap4: iounmap(gpio_base3); err_ioremap3: @@ -2979,6 +2984,7 @@ err_ioremap2: iounmap(gpio_base1); err_ioremap1: return -ENOMEM; +#endif } core_initcall(samsung_gpiolib_init); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 80fce51e2f4..62892a826ed 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -398,10 +398,8 @@ static int init_render_ring(struct intel_ring_buffer *ring) return ret; } - if (INTEL_INFO(dev)->gen >= 6) { - I915_WRITE(INSTPM, - INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING); + if (IS_GEN6(dev)) { /* From the Sandybridge PRM, volume 1 part 3, page 24: * "If this bit is set, STCunit will have LRA as replacement * policy. [...] This bit must be reset. LRA replacement @@ -411,6 +409,11 @@ static int init_render_ring(struct intel_ring_buffer *ring) CM0_STC_EVICT_DISABLE_LRA_SNB << CM0_MASK_SHIFT); } + if (INTEL_INFO(dev)->gen >= 6) { + I915_WRITE(INSTPM, + INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING); + } + return ret; } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 232d77d07d8..ae5e748f39b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1220,8 +1220,14 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo) { + struct drm_device *dev = intel_sdvo->base.base.dev; u8 response[2]; + /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise + * on the line. */ + if (IS_I945G(dev) || IS_I945GM(dev)) + return false; + return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, &response, 2) && response[0]; } diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index e2be95af2e5..77e564667b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -29,10 +29,6 @@ #include "nouveau_i2c.h" #include "nouveau_hw.h" -#define T_TIMEOUT 2200000 -#define T_RISEFALL 1000 -#define T_HOLD 5000 - static void i2c_drive_scl(void *data, int state) { @@ -113,175 +109,6 @@ i2c_sense_sda(void *data) return 0; } -static void -i2c_delay(struct nouveau_i2c_chan *port, u32 nsec) -{ - udelay((nsec + 500) / 1000); -} - -static bool -i2c_raise_scl(struct nouveau_i2c_chan *port) -{ - u32 timeout = T_TIMEOUT / T_RISEFALL; - - i2c_drive_scl(port, 1); - do { - i2c_delay(port, T_RISEFALL); - } while (!i2c_sense_scl(port) && --timeout); - - return timeout != 0; -} - -static int -i2c_start(struct nouveau_i2c_chan *port) -{ - int ret = 0; - - port->state = i2c_sense_scl(port); - port->state |= i2c_sense_sda(port) << 1; - if (port->state != 3) { - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 1); - if (!i2c_raise_scl(port)) - ret = -EBUSY; - } - - i2c_drive_sda(port, 0); - i2c_delay(port, T_HOLD); - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); - return ret; -} - -static void -i2c_stop(struct nouveau_i2c_chan *port) -{ - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 0); - i2c_delay(port, T_RISEFALL); - - i2c_drive_scl(port, 1); - i2c_delay(port, T_HOLD); - i2c_drive_sda(port, 1); - i2c_delay(port, T_HOLD); -} - -static int -i2c_bitw(struct nouveau_i2c_chan *port, int sda) -{ - i2c_drive_sda(port, sda); - i2c_delay(port, T_RISEFALL); - - if (!i2c_raise_scl(port)) - return -ETIMEDOUT; - i2c_delay(port, T_HOLD); - - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); - return 0; -} - -static int -i2c_bitr(struct nouveau_i2c_chan *port) -{ - int sda; - - i2c_drive_sda(port, 1); - i2c_delay(port, T_RISEFALL); - - if (!i2c_raise_scl(port)) - return -ETIMEDOUT; - i2c_delay(port, T_HOLD); - - sda = i2c_sense_sda(port); - - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); - return sda; -} - -static int -i2c_get_byte(struct nouveau_i2c_chan *port, u8 *byte, bool last) -{ - int i, bit; - - *byte = 0; - for (i = 7; i >= 0; i--) { - bit = i2c_bitr(port); - if (bit < 0) - return bit; - *byte |= bit << i; - } - - return i2c_bitw(port, last ? 1 : 0); -} - -static int -i2c_put_byte(struct nouveau_i2c_chan *port, u8 byte) -{ - int i, ret; - for (i = 7; i >= 0; i--) { - ret = i2c_bitw(port, !!(byte & (1 << i))); - if (ret < 0) - return ret; - } - - ret = i2c_bitr(port); - if (ret == 1) /* nack */ - ret = -EIO; - return ret; -} - -static int -i2c_addr(struct nouveau_i2c_chan *port, struct i2c_msg *msg) -{ - u32 addr = msg->addr << 1; - if (msg->flags & I2C_M_RD) - addr |= 1; - return i2c_put_byte(port, addr); -} - -static int -i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct nouveau_i2c_chan *port = (struct nouveau_i2c_chan *)adap; - struct i2c_msg *msg = msgs; - int ret = 0, mcnt = num; - - while (!ret && mcnt--) { - u8 remaining = msg->len; - u8 *ptr = msg->buf; - - ret = i2c_start(port); - if (ret == 0) - ret = i2c_addr(port, msg); - - if (msg->flags & I2C_M_RD) { - while (!ret && remaining--) - ret = i2c_get_byte(port, ptr++, !remaining); - } else { - while (!ret && remaining--) - ret = i2c_put_byte(port, *ptr++); - } - - msg++; - } - - i2c_stop(port); - return (ret < 0) ? ret : num; -} - -static u32 -i2c_bit_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -const struct i2c_algorithm nouveau_i2c_bit_algo = { - .master_xfer = i2c_bit_xfer, - .functionality = i2c_bit_func -}; - static const uint32_t nv50_i2c_port[] = { 0x00e138, 0x00e150, 0x00e168, 0x00e180, 0x00e254, 0x00e274, 0x00e764, 0x00e780, @@ -384,12 +211,10 @@ nouveau_i2c_init(struct drm_device *dev) case 0: /* NV04:NV50 */ port->drive = entry[0]; port->sense = entry[1]; - port->adapter.algo = &nouveau_i2c_bit_algo; break; case 4: /* NV4E */ port->drive = 0x600800 + entry[1]; port->sense = port->drive; - port->adapter.algo = &nouveau_i2c_bit_algo; break; case 5: /* NV50- */ port->drive = entry[0] & 0x0f; @@ -402,7 +227,6 @@ nouveau_i2c_init(struct drm_device *dev) port->drive = 0x00d014 + (port->drive * 0x20); port->sense = port->drive; } - port->adapter.algo = &nouveau_i2c_bit_algo; break; case 6: /* NV50- DP AUX */ port->drive = entry[0]; @@ -413,7 +237,7 @@ nouveau_i2c_init(struct drm_device *dev) break; } - if (!port->adapter.algo) { + if (!port->adapter.algo && !port->drive) { NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", i, port->type, port->drive, port->sense); kfree(port); @@ -429,7 +253,26 @@ nouveau_i2c_init(struct drm_device *dev) port->dcb = ROM32(entry[0]); i2c_set_adapdata(&port->adapter, i2c); - ret = i2c_add_adapter(&port->adapter); + if (port->adapter.algo != &nouveau_dp_i2c_algo) { + port->adapter.algo_data = &port->bit; + port->bit.udelay = 10; + port->bit.timeout = usecs_to_jiffies(2200); + port->bit.data = port; + port->bit.setsda = i2c_drive_sda; + port->bit.setscl = i2c_drive_scl; + port->bit.getsda = i2c_sense_sda; + port->bit.getscl = i2c_sense_scl; + + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 1); + i2c_drive_scl(port, 1); + + ret = i2c_bit_add_bus(&port->adapter); + } else { + port->adapter.algo = &nouveau_dp_i2c_algo; + ret = i2c_add_adapter(&port->adapter); + } + if (ret) { NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); kfree(port); diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index 4d2e4e9031b..1d083893a4d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h @@ -34,6 +34,7 @@ struct nouveau_i2c_chan { struct i2c_adapter adapter; struct drm_device *dev; + struct i2c_algo_bit_data bit; struct list_head head; u8 index; u8 type; diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index d8433f2d53b..73973fdbd8b 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -112,7 +112,7 @@ err_free_addr: return err; } -static void __devexit gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) +static void gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) { int i; @@ -294,7 +294,7 @@ static ssize_t netxbig_led_sata_show(struct device *dev, static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); -static void __devexit delete_netxbig_led(struct netxbig_led_data *led_dat) +static void delete_netxbig_led(struct netxbig_led_data *led_dat) { if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) device_remove_file(led_dat->cdev.dev, &dev_attr_sata); diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 2f0a14421a7..01cf89ec694 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -255,7 +255,7 @@ err_free_cmd: return ret; } -static void __devexit delete_ns2_led(struct ns2_led_data *led_dat) +static void delete_ns2_led(struct ns2_led_data *led_dat) { device_remove_file(led_dat->cdev.dev, &dev_attr_sata); led_classdev_unregister(&led_dat->cdev); diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c index 1f23e048f07..08d9a207259 100644 --- a/drivers/md/dm-log-userspace-transfer.c +++ b/drivers/md/dm-log-userspace-transfer.c @@ -134,7 +134,7 @@ static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) { struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1); - if (!cap_raised(current_cap(), CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) return; spin_lock(&receiving_list_lock); diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 922a3385eea..754f38f8a69 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -718,8 +718,8 @@ static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m) return 0; m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); - request_module("scsi_dh_%s", m->hw_handler_name); - if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { + if (!try_then_request_module(scsi_dh_handler_exist(m->hw_handler_name), + "scsi_dh_%s", m->hw_handler_name)) { ti->error = "unknown hardware handler type"; ret = -EINVAL; goto fail; diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 213ae32a0fc..2fd87b544a9 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -279,8 +279,10 @@ static void __cell_release(struct cell *cell, struct bio_list *inmates) hlist_del(&cell->list); - bio_list_add(inmates, cell->holder); - bio_list_merge(inmates, &cell->bios); + if (inmates) { + bio_list_add(inmates, cell->holder); + bio_list_merge(inmates, &cell->bios); + } mempool_free(cell, prison->cell_pool); } @@ -303,9 +305,10 @@ static void cell_release(struct cell *cell, struct bio_list *bios) */ static void __cell_release_singleton(struct cell *cell, struct bio *bio) { - hlist_del(&cell->list); BUG_ON(cell->holder != bio); BUG_ON(!bio_list_empty(&cell->bios)); + + __cell_release(cell, NULL); } static void cell_release_singleton(struct cell *cell, struct bio *bio) @@ -1177,6 +1180,7 @@ static void no_space(struct cell *cell) static void process_discard(struct thin_c *tc, struct bio *bio) { int r; + unsigned long flags; struct pool *pool = tc->pool; struct cell *cell, *cell2; struct cell_key key, key2; @@ -1218,7 +1222,9 @@ static void process_discard(struct thin_c *tc, struct bio *bio) m->bio = bio; if (!ds_add_work(&pool->all_io_ds, &m->list)) { + spin_lock_irqsave(&pool->lock, flags); list_add(&m->list, &pool->prepared_discards); + spin_unlock_irqrestore(&pool->lock, flags); wake_worker(pool); } } else { @@ -2626,8 +2632,10 @@ static int thin_endio(struct dm_target *ti, if (h->all_io_entry) { INIT_LIST_HEAD(&work); |