diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-18 04:30:10 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-18 04:30:10 +0300 |
commit | b1bc554e009e3aeed7e4cfd2e717c7a34a98c683 (patch) | |
tree | db092dd7887e732588250f2c2f932e1bfc3f87a2 /drivers/media/pci | |
parent | 0ffb8a4c96e55ecf0e572aec1a0220af3da84e22 (diff) | |
parent | 68a72104cbcf38ad16500216e213fa4eb21c4be2 (diff) | |
download | linux-b1bc554e009e3aeed7e4cfd2e717c7a34a98c683.tar.xz |
Merge tag 'media/v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- New sensor drivers: gc05a2, gc08a3 and imx283
- New serializer/deserializer drivers: max96714 and max96717
- New JPEG encoder driver: e5010
- Support for Raspberry Pi PiSP Backend (BE) ISP driver
- Old documentation for av7110 driver removed, as a new version was
added as Documentation/userspace-api/media/dvb/legacy*.rst
- atompisp: Linux firmwares are now available, so drop firmware-related
task from TODO and update firmware logic
- The imx258 driver has gained several improvements
- wave5 driver has gained support for HEVC decoding
- em28xx gained support for MyGica UTV3
- av7110 budget-patch driver removed
- Lots of other cleanups, improvements and fixes
* tag 'media/v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (301 commits)
media: raspberrypi: Switch to remove_new
media: uapi: pisp_be_config: Add extra config fields
media: uapi: pisp_be_config: Re-sort pisp_be_tiles_config
media: uapi: pisp_common: Capitalize all macros
media: uapi: pisp_common: Add 32 bpp format test
media: uapi: pisp_be_config: Drop BIT() from uAPI
media: stm32: dcmipp: correct error handling in dcmipp_create_subdevs
media: atomisp: Fix spelling mistakes in sh_css_sp.c
media: atomisp: Fix spelling mistake in ia_css_debug.c
media: atomisp: Fix spelling mistake in hmm_bo.c
media: atomisp: Fix spelling mistake in ia_css_eed1_8.host.c
media: atomisp: Fix spelling mistake in sh_css_internal.h
media: atomisp: Fix spelling mistake "pipline" -> "pipeline"
media: atomisp: Remove unused GPIO related defines and APIs
media: atomisp: Replace COMPILATION_ERROR_IF() by static_assert()
media: atomisp: Clean up unused macros from math_support.h
media: atomisp: csi2-bridge: Add DMI quirk for OV5693 on Xiaomi Mipad2
media: atomisp: Update TODO
media: atomisp: Prefix firmware paths with "intel/ipu/"
media: atomisp: Remove firmware_name module parameter
...
Diffstat (limited to 'drivers/media/pci')
38 files changed, 273 insertions, 297 deletions
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index 90972d6952f1..62a6c4a80bed 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) } if (astat & BT878_ARISCI) { bt->finished_block = (stat & BT878_ARISCS) >> 28; - if (bt->tasklet.callback) - tasklet_schedule(&bt->tasklet); + if (bt->bh_work.func) + queue_work(system_bh_wq, &bt->bh_work); break; } count++; @@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) btwrite(0, BT878_AINT_MASK); bt878_num++; - if (!bt->tasklet.func) - tasklet_disable(&bt->tasklet); + if (!bt->bh_work.func) + disable_work_sync(&bt->bh_work); return 0; @@ -563,4 +563,5 @@ static void __exit bt878_cleanup_module(void) module_init(bt878_init_module); module_exit(bt878_cleanup_module); +MODULE_DESCRIPTION("DVB/ATSC Support for bt878 based TV cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h index fde8db293c54..5b1c7f56e553 100644 --- a/drivers/media/pci/bt8xx/bt878.h +++ b/drivers/media/pci/bt8xx/bt878.h @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include "bt848.h" #include "bttv.h" @@ -120,7 +121,7 @@ struct bt878 { dma_addr_t risc_dma; u32 risc_pos; - struct tasklet_struct tasklet; + struct work_struct bh_work; int shutdown; }; diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 390cbba6c065..f0fbb468aea2 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -39,9 +39,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ -static void dvb_bt8xx_task(struct tasklet_struct *t) +static void dvb_bt8xx_work(struct work_struct *t) { - struct bt878 *bt = from_tasklet(bt, t, tasklet); + struct bt878 *bt = from_work(bt, t, bh_work); struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev); dprintk("%d\n", card->bt->finished_block); @@ -782,7 +782,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) goto err_disconnect_frontend; } - tasklet_setup(&card->bt->tasklet, dvb_bt8xx_task); + INIT_WORK(&card->bt->bh_work, dvb_bt8xx_work); frontend_init(card, type); @@ -922,7 +922,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub) dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); bt878_stop(card->bt); - tasklet_kill(&card->bt->tasklet); + cancel_work_sync(&card->bt->bh_work); dvb_net_release(&card->dvbnet); card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem); card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); diff --git a/drivers/media/pci/cx18/cx18-scb.h b/drivers/media/pci/cx18/cx18-scb.h index f7105421dd25..841edc0712ab 100644 --- a/drivers/media/pci/cx18/cx18-scb.h +++ b/drivers/media/pci/cx18/cx18-scb.h @@ -258,7 +258,7 @@ struct cx18_scb { struct cx18_mailbox ppu2epu_mb; struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS]; - struct cx18_mdl_ent cpu_mdl[1]; + struct cx18_mdl_ent cpu_mdl[]; }; void cx18_init_scb(struct cx18 *cx); diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index f3699dbd193f..f01ecdb0b627 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -298,7 +298,7 @@ struct ddb_link { spinlock_t lock; /* lock link access */ struct mutex flash_mutex; /* lock flash access */ struct ddb_lnb lnb; - struct tasklet_struct tasklet; + struct work_struct bh_work; struct ddb_ids ids; spinlock_t temp_lock; /* lock temp chip access */ diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c index 61750cc98d70..a0e9a71580b5 100644 --- a/drivers/media/pci/intel/ipu-bridge.c +++ b/drivers/media/pci/intel/ipu-bridge.c @@ -43,28 +43,46 @@ * becoming apparent in the future. * * Do not add an entry for a sensor that is not actually supported. + * + * Please keep the list sorted by ACPI HID. */ static const struct ipu_sensor_config ipu_supported_sensors[] = { + /* Himax HM11B1 */ + IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000), + /* Himax HM2170 */ + IPU_SENSOR_CONFIG("HIMX2170", 1, 384000000), + /* Himax HM2172 */ + IPU_SENSOR_CONFIG("HIMX2172", 1, 384000000), + /* GalaxyCore GC0310 */ + IPU_SENSOR_CONFIG("INT0310", 0), /* Omnivision OV5693 */ IPU_SENSOR_CONFIG("INT33BE", 1, 419200000), + /* Omnivision OV2740 */ + IPU_SENSOR_CONFIG("INT3474", 1, 180000000), /* Omnivision OV8865 */ IPU_SENSOR_CONFIG("INT347A", 1, 360000000), /* Omnivision OV7251 */ IPU_SENSOR_CONFIG("INT347E", 1, 319200000), + /* Hynix Hi-556 */ + IPU_SENSOR_CONFIG("INT3537", 1, 437000000), + /* Omnivision OV01A10 / OV01A1S */ + IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000), + IPU_SENSOR_CONFIG("OVTI01AS", 1, 400000000), + /* Omnivision OV02C10 */ + IPU_SENSOR_CONFIG("OVTI02C1", 1, 400000000), + /* Omnivision OV02E10 */ + IPU_SENSOR_CONFIG("OVTI02E1", 1, 360000000), + /* Omnivision OV08A10 */ + IPU_SENSOR_CONFIG("OVTI08A1", 1, 500000000), + /* Omnivision OV08x40 */ + IPU_SENSOR_CONFIG("OVTI08F4", 1, 400000000), + /* Omnivision OV13B10 */ + IPU_SENSOR_CONFIG("OVTI13B1", 1, 560000000), + IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000), /* Omnivision OV2680 */ IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000), - /* Omnivision ov8856 */ + /* Omnivision OV8856 */ IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000), - /* Omnivision ov2740 */ - IPU_SENSOR_CONFIG("INT3474", 1, 180000000), - /* Hynix hi556 */ - IPU_SENSOR_CONFIG("INT3537", 1, 437000000), - /* Omnivision ov13b10 */ - IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000), - /* GalaxyCore GC0310 */ - IPU_SENSOR_CONFIG("INT0310", 0), - /* Omnivision ov01a10 */ - IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000), }; static const struct ipu_property_names prop_names = { diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c index 23c537e7ce1e..e47f84c30e10 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c +++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c @@ -163,8 +163,8 @@ int ipu6_buttress_ipc_reset(struct ipu6_device *isp, writel(ENTRY, isp->base + ipc->csr_out); break; default: - dev_warn_ratelimited(&isp->pdev->dev, - "Unexpected CSR 0x%x\n", val); + dev_dbg_ratelimited(&isp->pdev->dev, + "Unexpected CSR 0x%x\n", val); break; } } while (retries--); diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c index b9ce4324996d..051898ce53f4 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c @@ -345,42 +345,61 @@ static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd, return ret; } -static int set_stream(struct v4l2_subdev *sd, int enable) +static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) { struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd); - struct device *dev = &csi2->isys->adev->auxdev.dev; struct ipu6_isys_csi2_timing timing = { }; - unsigned int nlanes; + struct v4l2_subdev *remote_sd; + struct media_pad *remote_pad; + u64 sink_streams; int ret; - dev_dbg(dev, "csi2 stream %s callback\n", enable ? "on" : "off"); - - if (!enable) { - csi2->stream_count--; - if (csi2->stream_count) - return 0; - - ipu6_isys_csi2_set_stream(sd, &timing, 0, enable); - return 0; - } - - if (csi2->stream_count) { - csi2->stream_count++; - return 0; - } + remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); + remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); - nlanes = csi2->nlanes; + sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC, + CSI2_PAD_SINK, + &streams_mask); ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV); if (ret) return ret; - ret = ipu6_isys_csi2_set_stream(sd, &timing, nlanes, enable); + ret = ipu6_isys_csi2_set_stream(sd, &timing, csi2->nlanes, true); if (ret) return ret; - csi2->stream_count++; + ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index, + sink_streams); + if (ret) { + ipu6_isys_csi2_set_stream(sd, NULL, 0, false); + return ret; + } + + return 0; +} + +static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + struct v4l2_subdev *remote_sd; + struct media_pad *remote_pad; + u64 sink_streams; + + sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC, + CSI2_PAD_SINK, + &streams_mask); + + remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); + remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); + + ipu6_isys_csi2_set_stream(sd, NULL, 0, false); + + v4l2_subdev_disable_streams(remote_sd, remote_pad->index, sink_streams); return 0; } @@ -475,10 +494,6 @@ static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd, return ret; } -static const struct v4l2_subdev_video_ops csi2_sd_video_ops = { - .s_stream = set_stream, -}; - static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = { .get_fmt = v4l2_subdev_get_fmt, .set_fmt = ipu6_isys_subdev_set_fmt, @@ -486,11 +501,12 @@ static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = { .set_selection = ipu6_isys_csi2_set_sel, .enum_mbus_code = ipu6_isys_subdev_enum_mbus_code, .set_routing = ipu6_isys_subdev_set_routing, + .enable_streams = ipu6_isys_csi2_enable_streams, + .disable_streams = ipu6_isys_csi2_disable_streams, }; static const struct v4l2_subdev_ops csi2_sd_ops = { .core = &csi2_sd_core_ops, - .video = &csi2_sd_video_ops, .pad = &csi2_sd_pad_ops, }; @@ -631,33 +647,3 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, return 0; } - -void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status) -{ - struct ipu6_isys_stream *stream = av->stream; - struct v4l2_subdev *sd = &stream->asd->sd; - struct v4l2_subdev_state *state; - struct media_pad *r_pad; - unsigned int i; - u32 r_stream; - - r_pad = media_pad_remote_pad_first(&av->pad); - r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index); - - state = v4l2_subdev_lock_and_get_active_state(sd); - - for (i = 0; i < state->stream_configs.num_configs; i++) { - struct v4l2_subdev_stream_config *cfg = - &state->stream_configs.configs[i]; - - if (cfg->pad == r_pad->index && r_stream == cfg->stream) { - dev_dbg(&av->isys->adev->auxdev.dev, - "%s: pad:%u, stream:%u, status:%u\n", - sd->entity.name, r_pad->index, r_stream, - status); - cfg->enabled = status; - } - } - - v4l2_subdev_unlock_state(state); -} diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h index eba6b29386ea..bc8594c94f99 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h @@ -45,7 +45,6 @@ struct ipu6_isys_csi2 { u32 receiver_errors; unsigned int nlanes; unsigned int port; - unsigned int stream_count; }; struct ipu6_isys_csi2_timing { @@ -77,6 +76,5 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, struct ipu6_isys_csi2 *csi2, struct media_entity *source_entity, struct v4l2_mbus_frame_desc_entry *entry); -void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status); #endif /* IPU6_ISYS_CSI2_H */ diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c index 4bd4e324abc9..03dbb0e0ea79 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c @@ -551,7 +551,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) stream->nr_queues); list_add(&aq->node, &stream->queues); - ipu6_isys_set_csi2_streams_status(av, true); ipu6_isys_configure_stream_watermark(av, true); ipu6_isys_update_stream_watermark(av, true); @@ -598,8 +597,6 @@ static void stop_streaming(struct vb2_queue *q) struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); struct ipu6_isys_stream *stream = av->stream; - ipu6_isys_set_csi2_streams_status(av, false); - mutex_lock(&stream->mutex); ipu6_isys_update_stream_watermark(av, false); diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c index 06090cc0a476..b37561352ead 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c @@ -990,9 +990,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, struct v4l2_subdev_state *subdev_state; struct device *dev = &av->isys->adev->auxdev.dev; struct v4l2_subdev *sd; - struct v4l2_subdev *ssd; struct media_pad *r_pad; - struct media_pad *s_pad; u32 sink_pad, sink_stream; u64 r_stream; u64 stream_mask = 0; @@ -1003,7 +1001,6 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, if (WARN(!stream->source_entity, "No source entity for stream\n")) return -ENODEV; - ssd = media_entity_to_v4l2_subdev(stream->source_entity); sd = &stream->asd->sd; r_pad = media_pad_remote_pad_first(&av->pad); r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index); @@ -1017,27 +1014,15 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, if (ret) return ret; - s_pad = media_pad_remote_pad_first(&stream->asd->pad[sink_pad]); - stream_mask = get_stream_mask_by_pipeline(av); if (!state) { stop_streaming_firmware(av); - /* stop external sub-device now. */ - dev_dbg(dev, "disable streams 0x%llx of %s\n", stream_mask, - ssd->name); - ret = v4l2_subdev_disable_streams(ssd, s_pad->index, - stream_mask); - if (ret) { - dev_err(dev, "disable streams of %s failed with %d\n", - ssd->name, ret); - return ret; - } - /* stop sub-device which connects with video */ - dev_dbg(dev, "stream off entity %s pad:%d\n", sd->name, - r_pad->index); - ret = v4l2_subdev_call(sd, video, s_stream, state); + dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n", + sd->name, r_pad->index, stream_mask); + ret = v4l2_subdev_disable_streams(sd, r_pad->index, + stream_mask); if (ret) { dev_err(dev, "stream off %s failed with %d\n", sd->name, ret); @@ -1052,34 +1037,20 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, } /* start sub-device which connects with video */ - dev_dbg(dev, "stream on %s pad %d\n", sd->name, r_pad->index); - ret = v4l2_subdev_call(sd, video, s_stream, state); + dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name, + r_pad->index, stream_mask); + ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask); if (ret) { dev_err(dev, "stream on %s failed with %d\n", sd->name, ret); goto out_media_entity_stop_streaming_firmware; } - - /* start external sub-device now. */ - dev_dbg(dev, "enable streams 0x%llx of %s\n", stream_mask, - ssd->name); - ret = v4l2_subdev_enable_streams(ssd, s_pad->index, - stream_mask); - if (ret) { - dev_err(dev, - "enable streams 0x%llx of %s failed with %d\n", - stream_mask, stream->source_entity->name, ret); - goto out_media_entity_stop_streaming; - } } av->streaming = state; return 0; -out_media_entity_stop_streaming: - v4l2_subdev_disable_streams(sd, r_pad->index, BIT(r_stream)); - out_media_entity_stop_streaming_firmware: stop_streaming_firmware(av); diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c index f04a89584334..2a9c12c975ca 100644 --- a/drivers/media/pci/intel/ivsc/mei_csi.c +++ b/drivers/media/pci/intel/ivsc/mei_csi.c @@ -126,6 +126,8 @@ struct mei_csi { struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *freq_ctrl; struct v4l2_ctrl *privacy_ctrl; + /* lock for v4l2 controls */ + struct mutex ctrl_lock; unsigned int remote_pad; /* start streaming or not */ int streaming; @@ -136,9 +138,6 @@ struct mei_csi { u32 nr_of_lanes; /* frequency of the CSI-2 link */ u64 link_freq; - - /* privacy status */ - enum ivsc_privacy_status status; }; static const struct v4l2_mbus_framefmt mei_csi_format_mbus_default = { @@ -190,7 +189,11 @@ static int mei_csi_send(struct mei_csi *csi, u8 *buf, size_t len) /* command response status */ ret = csi->cmd_response.status; - if (ret) { + if (ret == -1) { + /* notify privacy on instead of reporting error */ + ret = 0; + v4l2_ctrl_s_ctrl(csi->privacy_ctrl, 1); + } else if (ret) { ret = -EINVAL; goto out; } @@ -265,10 +268,9 @@ static void mei_csi_rx(struct mei_cl_device *cldev) switch (notif.cmd_id) { case CSI_PRIVACY_NOTIF: - if (notif.cont.cont < CSI_PRIVACY_MAX) { - csi->status = notif.cont.cont; - v4l2_ctrl_s_ctrl(csi->privacy_ctrl, csi->status); - } + if (notif.cont.cont < CSI_PRIVACY_MAX) + v4l2_ctrl_s_ctrl(csi->privacy_ctrl, + notif.cont.cont == CSI_PRIVACY_ON); break; case CSI_SET_OWNER: case CSI_SET_CONF: @@ -559,11 +561,13 @@ static int mei_csi_init_controls(struct mei_csi *csi) u32 max; int ret; + mutex_init(&csi->ctrl_lock); + ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 2); if (ret) return ret; - csi->ctrl_handler.lock = &csi->lock; + csi->ctrl_handler.lock = &csi->ctrl_lock; max = ARRAY_SIZE(link_freq_menu_items) - 1; csi->freq_ctrl = v4l2_ctrl_new_int_menu(&csi->ctrl_handler, @@ -755,6 +759,7 @@ err_entity: err_ctrl_handler: v4l2_ctrl_handler_free(&csi->ctrl_handler); + mutex_destroy(&csi->ctrl_lock); v4l2_async_nf_unregister(&csi->notifier); v4l2_async_nf_cleanup(&csi->notifier); @@ -774,6 +779,7 @@ static void mei_csi_remove(struct mei_cl_device *cldev) v4l2_async_nf_unregister(&csi->notifier); v4l2_async_nf_cleanup(&csi->notifier); v4l2_ctrl_handler_free(&csi->ctrl_handler); + mutex_destroy(&csi->ctrl_lock); v4l2_async_unregister_subdev(&csi->subdev); v4l2_subdev_cleanup(&csi->subdev); media_entity_cleanup(&csi->subdev.entity); diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index ba503d820e48..ecc20cd89926 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -371,33 +371,6 @@ int ivtv_msleep_timeout(unsigned int msecs, int intr) return 0; } -/* Release ioremapped memory */ -static void ivtv_iounmap(struct ivtv *itv) -{ - if (itv == NULL) - return; - - /* Release registers memory */ - if (itv->reg_mem != NULL) { - IVTV_DEBUG_INFO("releasing reg_mem\n"); - iounmap(itv->reg_mem); - itv->reg_mem = NULL; - } - /* Release io memory */ - if (itv->has_cx23415 && itv->dec_mem != NULL) { - IVTV_DEBUG_INFO("releasing dec_mem\n"); - iounmap(itv->dec_mem); - } - itv->dec_mem = NULL; - - /* Release io memory */ - if (itv->enc_mem != NULL) { - IVTV_DEBUG_INFO("releasing enc_mem\n"); - iounmap(itv->enc_mem); - itv->enc_mem = NULL; - } -} - /* Hauppauge card? get values from tveeprom */ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) { @@ -833,7 +806,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, IVTV_DEBUG_INFO("Enabling pci device\n"); - if (pci_enable_device(pdev)) { + if (pcim_enable_device(pdev)) { IVTV_ERR("Can't enable device!\n"); return -EIO; } @@ -841,24 +814,24 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, IVTV_ERR("No suitable DMA available.\n"); return -EIO; } - if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) { + if (!devm_request_mem_region(&pdev->dev, itv->base_addr, + IVTV_ENCODER_SIZE, "ivtv encoder")) { IVTV_ERR("Cannot request encoder memory region.\n"); return -EIO; } - if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET, - IVTV_REG_SIZE, "ivtv registers")) { + if (!devm_request_mem_region(&pdev->dev, + itv->base_addr + IVTV_REG_OFFSET, + IVTV_REG_SIZE, "ivtv registers")) { IVTV_ERR("Cannot request register memory region.\n"); - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); return -EIO; } if (itv->has_cx23415 && - !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, - IVTV_DECODER_SIZE, "ivtv decoder")) { + !devm_request_mem_region(&pdev->dev, + itv->base_addr + IVTV_DECODER_OFFSET, + IVTV_DECODER_SIZE, "ivtv decoder")) { IVTV_ERR("Cannot request decoder memory region.\n"); - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); return -EIO; } @@ -870,11 +843,6 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) { IVTV_ERR("Bus Mastering is not enabled\n"); - if (itv->has_cx23415) - release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, - IVTV_DECODER_SIZE); - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); return -ENXIO; } } @@ -1033,37 +1001,37 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) /* PCI Device Setup */ retval = ivtv_setup_pci(itv, pdev, pci_id); - if (retval == -EIO) + if (retval == -EIO || retval == -ENXIO) goto free_worker; - if (retval == -ENXIO) - goto free_mem; /* map io memory */ IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); - itv->enc_mem = ioremap(itv->base_addr + IVTV_ENCODER_OFFSET, - IVTV_ENCODER_SIZE); + itv->enc_mem = devm_ioremap(&pdev->dev, + itv->base_addr + IVTV_ENCODER_OFFSET, + IVTV_ENCODER_SIZE); if (!itv->enc_mem) { IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n"); IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n"); IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n"); retval = -ENOMEM; - goto free_mem; + goto free_worker; } if (itv->has_cx23415) { IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - itv->dec_mem = ioremap(itv->base_addr + IVTV_DECODER_OFFSET, - IVTV_DECODER_SIZE); + itv->dec_mem = devm_ioremap(&pdev->dev, + itv->base_addr + IVTV_DECODER_OFFSET, + IVTV_DECODER_SIZE); if (!itv->dec_mem) { IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n"); IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n"); IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n"); retval = -ENOMEM; - goto free_mem; + goto free_worker; } } else { @@ -1073,26 +1041,27 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) /* map registers memory */ IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - itv->reg_mem = - ioremap(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); + itv->reg_mem = devm_ioremap(&pdev->dev, + itv->base_addr + IVTV_REG_OFFSET, + IVTV_REG_SIZE); if (!itv->reg_mem) { IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n"); IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n"); IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n"); retval = -ENOMEM; - goto free_io; + goto free_worker; } retval = ivtv_gpio_init(itv); if (retval) - goto free_io; + goto free_worker; /* active i2c */ IVTV_DEBUG_INFO("activating i2c...\n"); if (init_ivtv_i2c(itv)) { IVTV_ERR("Could not initialize i2c\n"); - goto free_io; + goto free_worker; } if (itv->card->hw_all & IVTV_HW_TVEEPROM) { @@ -1277,13 +1246,6 @@ free_irq: free_i2c: v4l2_ctrl_handler_free(&itv->cxhdl.hdl); exit_ivtv_i2c(itv); -free_io: - ivtv_iounmap(itv); -free_mem: - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - if (itv->has_cx23415) - release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); free_worker: kthread_stop(itv->irq_worker_task); err: @@ -1439,14 +1401,7 @@ static void ivtv_remove(struct pci_dev *pdev) exit_ivtv_i2c(itv); free_irq(itv->pdev->irq, (void *)itv); - ivtv_iounmap(itv); - - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - if (itv->has_cx23415) - release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - pci_disable_device(itv->pdev); for (i = 0; i < IVTV_VBI_FRAMES; i++) kfree(itv->vbi.sliced_mpeg_data[i]); diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index 4202c3a47d33..cfa28d035586 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -21,6 +21,7 @@ #include "ivtv-ioctl.h" #include "ivtv-cards.h" #include "ivtv-firmware.h" +#include <linux/lockdep.h> #include <media/v4l2-event.h> #include <media/i2c/saa7115.h> @@ -190,12 +191,27 @@ static void ivtv_update_pgm_info(struct ivtv *itv) itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num; } +static void ivtv_schedule(struct ivtv_stream *s) +{ + struct ivtv *itv = s->itv; + DEFINE_WAIT(wait); + + lockdep_assert_held(&itv->serialize_lock); + + mutex_unlock(&itv->serialize_lock); + prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); + /* New buffers might have become free before we were added to the waitqueue */ + if (!s->q_free.buffers) + schedule(); + finish_wait(&s->waitq, &wait); + mutex_lock(&itv->serialize_lock); +} + static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err) { struct ivtv *itv = s->itv; struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; struct ivtv_buffer *buf; - DEFINE_WAIT(wait); *err = 0; while (1) { @@ -258,13 +274,7 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, } /* wait for more data to arrive */ - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); - /* New buffers might have become available before we were added to the waitqueue */ - if (!s->q_full.buffers) - schedule(); - finish_wait(&s->waitq, &wait); - mutex_lock(&itv->serialize_lock); + ivtv_schedule(s); if (signal_pending(current)) { /* return if a signal was received */ IVTV_DEBUG_INFO("User stopped %s\n", s->name); @@ -533,6 +543,25 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) return 0; } +static int ivtv_schedule_dma(struct ivtv_stream *s) +{ + struct ivtv *itv = s->itv; + int got_sig; + DEFINE_WAIT(wait); + + lockdep_assert_held(&itv->serialize_lock); + + mutex_unlock(&itv->serialize_lock); + prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); + while (!(got_sig = signal_pending(current)) && + test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) + schedule(); + finish_wait(&itv->dma_waitq, &wait); + mutex_lock(&itv->serialize_lock); + + return got_sig; +} + static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) { struct ivtv_open_id *id = fh2id(filp->private_data); @@ -544,7 +573,6 @@ static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t int bytes_written = 0; int mode; int rc; - DEFINE_WAIT(wait); IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name); @@ -618,13 +646,7 @@ retry: break; if (filp->f_flags & O_NONBLOCK) return -EAGAIN; - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); - /* New buffers might have become free before we were added to the waitqueue */ - if (!s->q_free.buffers) - schedule(); - finish_wait(&s->waitq, &wait); - mutex_lock(&itv->serialize_lock); + ivtv_schedule(s); if (signal_pending(current)) { IVTV_DEBUG_INFO("User stopped %s\n", s->name); return -EINTR; @@ -674,20 +696,10 @@ retry: if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) { if (s->q_full.length >= itv->dma_data_req_size) { - int got_sig; - if (mode == OUT_YUV) ivtv_yuv_setup_stream_frame(itv); - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - while (!(got_sig = signal_pending(current)) && - test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { - schedule(); - } - finish_wait(&itv->dma_waitq, &wait); - mutex_lock(&itv->serialize_lock); - if (got_sig) { + if (ivtv_schedule_dma(s)) { IVTV_DEBUG_INFO("User interrupted %s\n", s->name); return -EINTR; } diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c index 99b9f55ca829..f467a00492f4 100644 --- a/drivers/media/pci/ivtv/ivtv-udma.c +++ b/drivers/media/pci/ivtv/ivtv-udma.c @@ -131,6 +131,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, /* Fill SG List with new values */ if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) { + IVTV_DEBUG_WARN("%s: could not allocate bounce buffers for highmem userspace buffers\n", + __func__); unpin_user_pages(dma->map, dma->page_count); dma->page_count = 0; return -ENOMEM; @@ -139,6 +141,12 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, /* Map SG List */ dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist, dma->page_count, DMA_TO_DEVICE); + if (!dma->SG_length) { + IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", __func__); + unpin_user_pages(dma->map, dma->page_count); + dma->page_count = 0; + return -EINVAL; + } /* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1); diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c index 582146f8d70d..2d9274537725 100644 --- a/drivers/media/pci/ivtv/ivtv-yuv.c +++ b/drivers/media/pci/ivtv/ivtv-yuv.c @@ -114,6 +114,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, } dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist, dma->page_count, DMA_TO_DEVICE); + if (!dma->SG_length) { + IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", __func__); + unpin_user_pages(dma->map, dma->page_count); + dma->page_count = 0; + return -EINVAL; + } /* Fill SG Array with new values */ ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size); diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 410477e3e621..90c584cf97c2 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -104,6 +104,7 @@ MODULE_PARM_DESC(osd_xres, "\t\t\tdefault 640"); MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong"); +MODULE_DESCRIPTION("Conexant cx23415 framebuffer support"); MODULE_LICENSE("GPL"); /* --------------------------------------------------------------------- */ @@ -281,10 +282,10 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, /* Map User DMA */ if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) { mutex_unlock(&itv->udma.lock); - IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with pin_user_pages: %d bytes, %d pages returned\n", - size_in_bytes, itv->udma.page_count); + IVTVFB_WARN("%s, Error in ivtv_udma_setup: %d bytes, %d pages returned\n", + __func__, size_in_bytes, itv->udma.page_count); - /* pin_user_pages must have failed completely */ + /* pin_user_pages or DMA must have failed completely */ return -EIO; } diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index c0bd5d7e148b..b85aef4e2b24 100644 --- a/drivers/media/pci/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c @@ -116,7 +116,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) if (stat & MANTIS_INT_RISCI) { dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28; - tasklet_schedule(&mantis->tasklet); + queue_work(system_bh_wq, &mantis->bh_work); } if (stat & MANTIS_INT_I2CDONE) { dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index 906e4500d87d..b44b4cf42f86 100644 --- a/drivers/media/pci/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -125,7 +125,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id) if (stat & MANTIS_INT_RISCI) { dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28; - tasklet_schedule(&mantis->tasklet); + queue_work(system_bh_wq, &mantis->bh_work); } if (stat & MANTIS_INT_I2CDONE) { dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h index d88ac280226c..6e563ecd94e8 100644 --- a/drivers/media/pci/mantis/mantis_common.h +++ b/drivers/media/pci/mantis/mantis_common.h @@ -125,7 +125,7 @@ struct mantis_pci { __le32 *risc_cpu; dma_addr_t risc_dma; - struct tasklet_struct tasklet; + struct work_struct bh_work; spinlock_t intmask_lock; struct i2c_adapter adapter; diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c index 80c843936493..eeb210a2862f 100644 --- a/drivers/media/pci/mantis/mantis_dma.c +++ b/drivers/media/pci/mantis/mantis_dma.c @@ -200,9 +200,9 @@ void mantis_dma_stop(struct mantis_pci *mantis) } -void mantis_dma_xfer(struct tasklet_struct *t) +void mantis_dma_xfer(struct work_struct *t) { - struct mantis_pci *mantis = from_tasklet(mantis, t, tasklet); + struct mantis_pci *mantis = from_work(mantis, t, bh_work); struct mantis_hwconfig *config = mantis->hwconfig; while (mantis->last_block != mantis->busy_block) { diff --git a/drivers/media/pci/mantis/mantis_dma.h b/drivers/media/pci/mantis/mantis_dma.h index 37da982c9c29..5db0d3728f15 100644 --- a/drivers/media/pci/mantis/mantis_dma.h +++ b/drivers/media/pci/mantis/mantis_dma.h @@ -13,6 +13,6 @@ extern int mantis_dma_init(struct mantis_pci *mantis); extern int mantis_dma_exit(struct mantis_pci *mantis); extern void mantis_dma_start(struct mantis_pci *mantis); extern void mantis_dma_stop(struct mantis_pci *mantis); -extern void mantis_dma_xfer(struct tasklet_struct *t); +extern void mantis_dma_xfer(struct work_struct *t); #endif /* __MANTIS_DMA_H */ diff --git a/drivers/media/pci/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c index c7ba4a76e608..398e32f44692 100644 --- a/drivers/media/pci/mantis/mantis_dvb.c +++ b/drivers/media/pci/mantis/mantis_dvb.c @@ -105,7 +105,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (mantis->feeds == 1) { dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); mantis_dma_start(mantis); - tasklet_enable(&mantis->tasklet); + enable_and_queue_work(system_bh_wq, &mantis->bh_work); } return mantis->feeds; @@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) mantis->feeds--; if (mantis->feeds == 0) { dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); - tasklet_disable(&mantis->tasklet); + disable_work_sync(&mantis->bh_work); mantis_dma_stop(mantis); } @@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *mantis) } dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); - tasklet_setup(&mantis->tasklet, mantis_dma_xfer); - tasklet_disable(&mantis->tasklet); + INIT_WORK(&mantis->bh_work, mantis_dma_xfer); + disable_work_sync(&mantis->bh_work); if (mantis->hwconfig) { result = config->frontend_init(mantis, mantis->fe); if (result < 0) { @@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis) /* Error conditions .. */ err5: - tasklet_kill(&mantis->tasklet); + cancel_work_sync(&mantis->bh_work); dvb_net_release(&mantis->dvbnet); if (mantis->fe) { dvb_unregister_frontend(mantis->fe); @@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis) dvb_frontend_detach(mantis->fe); } - tasklet_kill(&mantis->tasklet); + cancel_work_sync(&mantis->bh_work); dvb_net_release(&mantis->dvbnet); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c index 24ec576dc3bf..db6796240bce 100644 --- a/drivers/media/pci/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c @@ -50,9 +50,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); /* nGene interrupt handler **************************************************/ /****************************************************************************/ -static void event_tasklet(struct tasklet_struct *t) +static void event_bh_work(struct work_struct *t) { - struct ngene *dev = from_tasklet(dev, t, event_tasklet); + struct ngene *dev = from_work(dev, t, event_bh_work); while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) { struct EVENT_BUFFER Event = @@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t) } } -static void demux_tasklet(struct tasklet_struct *t) +static void demux_bh_work(struct work_struct *t) { - struct ngene_channel *chan = from_tasklet(chan, t, demux_tasklet); + struct ngene_channel *chan = from_work(chan, t, demux_bh_work); struct device *pdev = &chan->dev->pci_dev->dev; struct SBufferHeader *Cur = chan->nextBuffer; @@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id) dev->EventQueueOverflowFlag = 1; } dev->EventBuffer->EventStatus &= ~0x80; - tasklet_schedule(&dev->event_tasklet); + queue_work(system_bh_wq, &dev->event_bh_work); rc = IRQ_HANDLED; } @@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) ngeneBuffer.SR.Flags & 0xC0) == 0x80) { dev->channel[i].nextBuffer-> ngeneBuffer.SR.Flags |= 0x40; - tasklet_schedule( - &dev->channel[i].demux_tasklet); + queue_work(system_bh_wq, + &dev->channel[i].demux_bh_work); rc = IRQ_HANDLED; } } @@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev) struct device *pdev = &dev->pci_dev->dev; int i; - tasklet_setup(&dev->event_tasklet, event_tasklet); + INIT_WORK(&dev->event_bh_work, event_bh_work); memset_io(dev->iomem + 0xc000, 0x00, 0x220); memset_io(dev->iomem + 0xc400, 0x00, 0x100); @@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan) if (chan->running) set_transfer(chan, 0); - tasklet_kill(&chan->demux_tasklet); + cancel_work_sync(&chan->demux_bh_work); if (chan->ci_dev) { dvb_unregister_device(chan->ci_dev); @@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan) struct ngene_info *ni = dev->card_info; int io = ni->io_type[nr]; - tasklet_setup(&chan->demux_tasklet, demux_tasklet); + INIT_WORK(&chan->demux_bh_work, demux_bh_work); chan->users = 0; chan->type = io; chan->mode = chan->type; /* for now only one mode */ @@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev) struct ngene *dev = pci_get_drvdata(pdev); int i; - tasklet_kill(&dev->event_tasklet); + cancel_work_sync(&dev->event_bh_work); for (i = MAX_STREAM - 1; i >= 0; i--) release_channel(&dev->channel[i]); if (dev->ci.en) diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h index d1d7da84cd9d..9f989420b9e7 100644 --- a/drivers/media/pci/ngene/ngene.h +++ b/drivers/media/pci/ngene/ngene.h @@ -16,6 +16,7 @@ #include <linux/scatterlist.h> #include <linux/dvb/frontend.h> +#include <linux/workqueue.h> #include <media/dmxdev.h> #include <media/dvbdev.h> @@ -621,7 +622,7 @@ struct ngene_channel { int users; struct video_device *v4l_dev; struct dvb_device *ci_dev; - struct tasklet_struct demux_tasklet; + struct work_struct demux_bh_work; struct SBufferHeader *nextBuffer; enum KSSTATE State; @@ -717,7 +718,7 @@ struct ngene { struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE]; int EventQueueOverflowCount; int EventQueueOverflowFlag; - struct tasklet_struct event_tasklet; + struct work_struct event_bh_work; struct EVENT_BUFFER *EventBuffer; int EventQueueWriteIndex; int EventQueueReadIndex; diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index dd2236c5c4a1..f86a44dfe6e3 100644 --- a/drivers/media/pci/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c @@ -1254,5 +1254,6 @@ static void saa7134_alsa_exit(void) /* We initialize this late, to make sure the sound system is up and running */ late_initcall(saa7134_alsa_init); module_exit(saa7134_alsa_exit); +MODULE_DESCRIPTION("Philips SAA7134 DMA audio support"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ricardo Cerqueira"); diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index 9c6cfef03331..6de8a02314af 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -52,6 +52,7 @@ #include "s5h1411.h" MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); +MODULE_DESCRIPTION("DVB/ATSC Support for saa7134 based TV cards"); MODULE_LICENSE("GPL"); static unsigned int antenna_pwr; @@ -466,7 +467,9 @@ static int philips_europa_tuner_sleep(struct dvb_frontend *fe) /* switch the board to analog mode */ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &analog_msg, 1); + if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1) + return -EIO; + return 0; } @@ -1018,7 +1021,9 @@ static int md8800_set_voltage2(struct dvb_frontend *fe, else wbuf[1] = rbuf & 0xef; msg[0].len = 2; - i2c_transfer(&dev->i2c_adap, msg, 1); + if (i2c_transfer(&dev->i2c_adap, msg, 1) != 1) + return -EIO; + return 0; } diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 434fa1ee1c33..bbf480ab31ca 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -19,6 +19,7 @@ /* ------------------------------------------------------------------ */ MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); +MODULE_DESCRIPTION("Philips SAA7134 empress support"); MODULE_LICENSE("GPL"); static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index da83893ffee9..bd37db5ce363 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -516,4 +516,5 @@ static void __exit saa7134_go7007_mod_cleanup(void) module_init(saa7134_go7007_mod_init); module_exit(saa7134_go7007_mod_cleanup); +MODULE_DESCRIPTION("go7007 support for saa7134 based TV cards"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c index 0c300d019d9c..7db6d443fc54 100644 --- a/drivers/media/pci/smipcie/smipcie-main.c +++ b/drivers/media/pci/smipcie/smipcie-main.c @@ -279,10 +279,10 @@ static void smi_port_clearInterrupt(struct smi_port *port) (port->_dmaInterruptCH0 | port->_dmaInterruptCH1)); } -/* tasklet handler: DMA data to dmx.*/ -static void smi_dma_xfer(struct tasklet_struct *t) +/* BH work handler: DMA data to dmx.*/ +static void smi_dma_xfer(struct work_struct *t) { - struct smi_port *port = from_tasklet(port, t, tasklet); + struct smi_port *port = from_work(port, t, bh_work); struct smi_dev *dev = port->dev; u32 intr_status, finishedData, dmaManagement; u8 dmaChan0State, dmaChan1State; @@ -426,8 +426,8 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) } smi_port_disableInterrupt(port); - tasklet_setup(&port->tasklet, smi_dma_xfer); - tasklet_disable(&port->tasklet); + INIT_WORK(&port->bh_work, smi_dma_xfer); + disable_work_sync(&port->bh_work); port->enable = 1; return 0; err: @@ -438,7 +438,7 @@ err: static void smi_port_exit(struct smi_port *port) { smi_port_disableInterrupt(port); - tasklet_kill(&port->tasklet); + cancel_work_sync(&port->bh_work); smi_port_dma_free(port); port->enable = 0; } @@ -452,7 +452,7 @@ static int smi_port_irq(struct smi_port *port, u32 int_status) smi_port_disableInterrupt(port); port->_int_status = int_status; smi_port_clearInterrupt(port); - tasklet_schedule(&port->tasklet); + queue_work(system_bh_wq, &port->bh_work); handled = 1; } return handled; @@ -823,7 +823,7 @@ static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed) smi_port_clearInterrupt(port); smi_port_enableInterrupt(port); smi_write(port->DMA_MANAGEMENT, dmaManagement); - tasklet_enable(&port->tasklet); + enable_and_queue_work(system_bh_wq, &port->bh_work); } return port->users; } @@ -837,7 +837,7 @@ static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (--port->users) return port->users; - tasklet_disable(&port->tasklet); + disable_work_sync(&port->bh_work); smi_port_disableInterrupt(port); smi_clear(port->DMA_MANAGEMENT, 0x30003); return 0; diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h index 2b5e0154814c..98e44edaab9e 100644 --- a/drivers/media/pci/smipcie/smipcie.h +++ b/drivers/media/pci/smipcie/smipcie.h @@ -17,6 +17,7 @@ #include <linux/pci.h> #include <linux/dma-mapping.h> #include <linux/slab.h> +#include <linux/workqueue.h> #include <media/rc-core.h> #include <media/demux.h> @@ -257,7 +258,7 @@ struct smi_port { u32 _dmaInterruptCH0; u32 _dmaInterruptCH1; u32 _int_status; - struct tasklet_struct tasklet; + struct work_struct bh_work; /* dvb */ struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 2e62c938e2cb..69f5e810f9b5 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -36,6 +36,7 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/spinlock.h> +#include <linux/workqueue.h> #include <media/dvb_ca_en50221.h> @@ -54,7 +55,7 @@ struct budget_av { struct video_device vd; int cur_input; int has_saa7113; - struct tasklet_struct ciintf_irq_tasklet; + struct work_struct ciintf_irq_bh_work; int slot_status; struct dvb_ca_en50221 ca; u8 reinitialise_demod:1; diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 76de40e3c802..33f08adf4feb 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/spinlock.h> +#include <linux/workqueue.h> #include <media/rc-core.h> #include "budget.h" @@ -81,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct budget_ci_ir { struct rc_dev *dev; - struct tasklet_struct msp430_irq_tasklet; + struct work_struct msp430_irq_bh_work; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ char phys[32]; int rc5_device; @@ -92,7 +93,7 @@ struct budget_ci_ir { struct budget_ci { struct budget budget; - struct tasklet_struct ciintf_irq_tasklet; + struct work_struct ciintf_irq_bh_work; int slot_status; int ci_irq; struct dvb_ca_en50221 ca; @@ -100,9 +101,9 @@ struct budget_ci { u8 tuner_pll_address; /* used for philips_tdm1316l configs */ }; -static void msp430_ir_interrupt(struct tasklet_struct *t) +static void msp430_ir_interrupt(struct work_struct *t) { - struct budget_ci_ir *ir = from_tasklet(ir, t, msp430_irq_tasklet); + struct budget_ci_ir *ir = from_work(ir, t, msp430_irq_bh_work); struct budget_ci *budget_ci = container_of(ir, typeof(*budget_ci), ir); struct rc_dev *dev = budget_ci->ir.dev; u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; @@ -231,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.dev = dev; - tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt); + INIT_WORK(&budget_ci->ir.msp430_irq_bh_work, msp430_ir_interrupt); SAA7146_IER_ENABLE(saa, MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); @@ -245,7 +246,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) SAA7146_IER_DISABLE(saa, MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); - tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); + cancel_work_sync(&budget_ci->ir.msp430_irq_bh_work); rc_unregister_device(budget_ci->ir.dev); } @@ -349,10 +350,10 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) return 0; } -static void ciintf_interrupt(struct tasklet_struct *t) +static void ciintf_interrupt(struct work_struct *t) { - struct budget_ci *budget_ci = from_tasklet(budget_ci, t, - ciintf_irq_tasklet); + struct budget_ci *budget_ci = from_work(budget_ci, t, + ciintf_irq_bh_work); struct saa7146_dev *saa = budget_ci->budget.dev; unsigned int flags; @@ -491,7 +492,7 @@ static int ciintf_init(struct budget_ci *budget_ci) // Setup CI slot IRQ if (budget_ci->ci_irq) { - tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt); + INIT_WORK(&budget_ci->ciintf_irq_bh_work, ciintf_interrupt); if (budget_ci->slot_status != SLOTSTATUS_NONE) saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); else @@ -530,7 +531,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) if (budget_ci->ci_irq) { SAA7146_IER_DISABLE(saa, MASK_03); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); - tasklet_kill(&budget_ci->ciintf_irq_tasklet); + cancel_work_sync(&budget_ci->ciintf_irq_bh_work); } // reset interface @@ -556,13 +557,13 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 *isr) dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); if (*isr & MASK_06) - tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet); + queue_work(system_bh_wq, &budget_ci->ir.msp430_irq_bh_work); if (*isr & MASK_10) ttpci_budget_irq10_handler(dev, isr); if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq)) - tasklet_schedule(&budget_ci->ciintf_irq_tasklet); + queue_work(system_bh_wq, &budget_ci->ciintf_irq_bh_work); } static u8 philips_su1278_tt_inittab[] = { diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index d33adeca196f..29531d9c9db0 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -172,9 +172,9 @@ static int budget_read_fe_status(struct dvb_frontend *fe, return ret; } -static void vpeirq(struct tasklet_struct *t) +static void vpeirq(struct work_struct *t) { - struct budget *budget = from_tasklet(budget, t, vpe_tasklet); + struct budget *budget = from_work(budget, t, vpe_bh_work); u8 *mem = (u8 *) (budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); @@ -525,7 +525,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, /* upload all */ saa7146_write(dev, GPIO_CTRL, 0x000000); - tasklet_setup(&budget->vpe_tasklet, vpeirq); + INIT_WORK(&budget->vpe_bh_work, vpeirq); /* frontend power on */ if (bi->type != BUDGET_FS_ACTIVY) @@ -565,7 +565,7 @@ int ttpci_budget_deinit(struct budget *budget) budget_unregister(budget); - tasklet_kill(&budget->vpe_tasklet); + cancel_work_sync(&budget->vpe_bh_work); saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); @@ -584,7 +584,7 @@ void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 *isr) dprintk(8, "dev: %p, budget: %p\n", dev, budget); if (*isr & MASK_10) - tasklet_schedule(&budget->vpe_tasklet); + queue_work(system_bh_wq, &budget->vpe_bh_work); } EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); @@ -602,4 +602,5 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) } EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port); +MODULE_DESCRIPTION("base driver for the SAA7146 based Budget DVB cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h index 83ead34dc766..e933764ac4e3 100644 --- a/drivers/media/pci/ttpci/budget.h +++ b/drivers/media/pci/ttpci/budget.h @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include <media/drv-intf/saa7146.h> @@ -54,8 +55,8 @@ struct budget { unsigned char *grabbing; struct saa7146_pgtable pt; - struct tasklet_struct fidb_tasklet; - struct tasklet_struct vpe_tasklet; + struct work_struct fidb_bh_work; + struct work_struct vpe_bh_work; struct dmxdev dmxdev; struct dvb_demux demux; diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c index 560ff1ddcc83..4d33caf83307 100644 --- a/drivers/media/pci/tw5864/tw5864-core.c +++ b/drivers/media/pci/tw5864/tw5864-core.c @@ -144,7 +144,7 @@ static void tw5864_h264_isr(struct tw5864_dev *dev) cur_frame->gop_seqno = input->frame_gop_seqno; dev->h264_buf_w_index = next_frame_index; - tasklet_schedule(&dev->tasklet); + queue_work(system_bh_wq, &dev->bh_work); cur_frame = next_frame; diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c index 8b1aae4b6319..4f35c159efe5 100644 --- a/drivers/media/pci/tw5864/tw5864-video.c +++ b/drivers/media/pci/tw5864/tw5864-video.c @@ -6,6 +6,7 @@ */ #include <linux/module.h> +#include <linux/workqueue.h> #include <media/v4l2-common.h> #include <media/v4l2-event.h> #include <media/videobuf2-dma-contig.h> @@ -175,7 +176,7 @@ static const unsigned int intra4x4_lambda3[] = { static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std); static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std); -static void tw5864_handle_frame_task(struct tasklet_struct *t); +static void tw5864_handle_frame_work(struct work_struct *t); static void tw5864_handle_frame(struct tw5864_h264_frame *frame); static void tw5864_frame_interval_set(struct tw5864_input *input); @@ -1062,7 +1063,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) dev->irqmask |= TW5864_INTR_VLC_DONE | TW5864_INTR_TIMER; tw5864_irqmask_apply(dev); - tasklet_setup(&dev->tasklet, tw5864_handle_frame_task); + INIT_WORK(&dev->bh_work, tw5864_handle_frame_work); for (i = 0; i < TW5864_INPUTS; i++) { dev->inputs[i].root = dev; @@ -1079,7 +1080,7 @@ fini_video_inputs: for (i = last_input_nr_registered; i >= 0; i--) tw5864_video_input_fini(&dev->inputs[i]); - tasklet_kill(&dev->tasklet); + cancel_work_sync(&dev->bh_work); free_dma: for (i = last_dma_allocated; i >= 0; i--) { @@ -1198,7 +1199,7 @@ void tw5864_video_fini(struct tw5864_dev *dev) { int i; - tasklet_kill(&dev->tasklet); + cancel_work_sync(&dev->bh_work); for (i = 0; i < TW5864_INPUTS; i++) tw5864_video_input_fini(&dev->inputs[i]); @@ -1315,9 +1316,9 @@ static int tw5864_is_motion_triggered(struct tw5864_h264_frame *frame) return detected; } -static void tw5864_handle_frame_task(struct tasklet_struct *t) +static void tw5864_handle_frame_work(struct work_struct *t) { - struct tw5864_dev *dev = from_tasklet(dev, t, tasklet); + struct tw5864_dev *dev = from_work(dev, t, bh_work); unsigned long flags; int batch_size = H264_BUF_CNT; diff --git a/drivers/media/pci/tw5864/tw5864.h b/drivers/media/pci/tw5864/tw5864.h index a8b6fbd5b710..2da5f4215fd9 100644 --- a/drivers/media/pci/tw5864/tw5864.h +++ b/drivers/media/pci/tw5864/tw5864.h @@ -12,6 +12,7 @@ #include <linux/mutex.h> #include <linux/io.h> #include <linux/interrupt.h> +#include <linux/workqueue.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> @@ -85,7 +86,7 @@ struct tw5864_input { int nr; /* input number */ struct tw5864_dev *root; struct mutex lock; /* used for vidq and vdev */ - spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */ + spinlock_t slock; /* used for sync between ISR, bh_work & V4L2 API */ struct video_device vdev; struct v4l2_ctrl_handler hdl; struct vb2_queue vidq; @@ -142,7 +143,7 @@ struct tw5864_h264_frame { /* global device status */ struct tw5864_dev { - spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */ + spinlock_t slock; /* used for sync between ISR, bh_work & V4L2 API */ struct v4l2_device v4l2_dev; struct tw5864_input inputs[TW5864_INPUTS]; #define H264_BUF_CNT 4 @@ -150,7 +151,7 @@ struct tw5864_dev { int h264_buf_r_index; int h264_buf_w_index; - struct tasklet_struct tasklet; + struct work_struct bh_work; int encoder_busy; /* Input number to check next for ready raw picture (in RR fashion) */ |