V4L/DVB (7854): cx18/ivtv: improve and fix out-of-memory handling
- don't show kernel backtrace when the allocation of the buffers fails: the normal ivtv/cx18 messages are clear enough and the backtrace scares users. - fix cleanup after the buffer allocation fails (caused kernel panic). Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
6a4a79355b
commit
3f98387efa
|
@ -805,7 +805,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
free_streams:
|
free_streams:
|
||||||
cx18_streams_cleanup(cx);
|
cx18_streams_cleanup(cx, 1);
|
||||||
free_irq:
|
free_irq:
|
||||||
free_irq(cx->dev->irq, (void *)cx);
|
free_irq(cx->dev->irq, (void *)cx);
|
||||||
free_i2c:
|
free_i2c:
|
||||||
|
@ -908,7 +908,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
|
||||||
|
|
||||||
cx18_halt_firmware(cx);
|
cx18_halt_firmware(cx);
|
||||||
|
|
||||||
cx18_streams_cleanup(cx);
|
cx18_streams_cleanup(cx, 1);
|
||||||
|
|
||||||
exit_cx18_i2c(cx);
|
exit_cx18_i2c(cx);
|
||||||
|
|
||||||
|
|
|
@ -239,12 +239,12 @@ int cx18_stream_alloc(struct cx18_stream *s)
|
||||||
|
|
||||||
/* allocate stream buffers. Initially all buffers are in q_free. */
|
/* allocate stream buffers. Initially all buffers are in q_free. */
|
||||||
for (i = 0; i < s->buffers; i++) {
|
for (i = 0; i < s->buffers; i++) {
|
||||||
struct cx18_buffer *buf =
|
struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer),
|
||||||
kzalloc(sizeof(struct cx18_buffer), GFP_KERNEL);
|
GFP_KERNEL|__GFP_NOWARN);
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
break;
|
break;
|
||||||
buf->buf = kmalloc(s->buf_size, GFP_KERNEL);
|
buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN);
|
||||||
if (buf->buf == NULL) {
|
if (buf->buf == NULL) {
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -218,7 +218,7 @@ int cx18_streams_setup(struct cx18 *cx)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* One or more streams could not be initialized. Clean 'em all up. */
|
/* One or more streams could not be initialized. Clean 'em all up. */
|
||||||
cx18_streams_cleanup(cx);
|
cx18_streams_cleanup(cx, 0);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,12 +296,12 @@ int cx18_streams_register(struct cx18 *cx)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* One or more streams could not be initialized. Clean 'em all up. */
|
/* One or more streams could not be initialized. Clean 'em all up. */
|
||||||
cx18_streams_cleanup(cx);
|
cx18_streams_cleanup(cx, 1);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unregister v4l2 devices */
|
/* Unregister v4l2 devices */
|
||||||
void cx18_streams_cleanup(struct cx18 *cx)
|
void cx18_streams_cleanup(struct cx18 *cx, int unregister)
|
||||||
{
|
{
|
||||||
struct video_device *vdev;
|
struct video_device *vdev;
|
||||||
int type;
|
int type;
|
||||||
|
@ -319,8 +319,11 @@ void cx18_streams_cleanup(struct cx18 *cx)
|
||||||
|
|
||||||
cx18_stream_free(&cx->streams[type]);
|
cx18_stream_free(&cx->streams[type]);
|
||||||
|
|
||||||
/* Unregister device */
|
/* Unregister or release device */
|
||||||
|
if (unregister)
|
||||||
video_unregister_device(vdev);
|
video_unregister_device(vdev);
|
||||||
|
else
|
||||||
|
video_device_release(vdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
u32 cx18_find_handle(struct cx18 *cx);
|
u32 cx18_find_handle(struct cx18 *cx);
|
||||||
int cx18_streams_setup(struct cx18 *cx);
|
int cx18_streams_setup(struct cx18 *cx);
|
||||||
int cx18_streams_register(struct cx18 *cx);
|
int cx18_streams_register(struct cx18 *cx);
|
||||||
void cx18_streams_cleanup(struct cx18 *cx);
|
void cx18_streams_cleanup(struct cx18 *cx, int unregister);
|
||||||
|
|
||||||
/* Capture related */
|
/* Capture related */
|
||||||
int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
|
int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
|
||||||
|
|
|
@ -1232,7 +1232,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
free_streams:
|
free_streams:
|
||||||
ivtv_streams_cleanup(itv);
|
ivtv_streams_cleanup(itv, 1);
|
||||||
free_irq:
|
free_irq:
|
||||||
free_irq(itv->dev->irq, (void *)itv);
|
free_irq(itv->dev->irq, (void *)itv);
|
||||||
free_i2c:
|
free_i2c:
|
||||||
|
@ -1377,7 +1377,7 @@ static void ivtv_remove(struct pci_dev *pci_dev)
|
||||||
flush_workqueue(itv->irq_work_queues);
|
flush_workqueue(itv->irq_work_queues);
|
||||||
destroy_workqueue(itv->irq_work_queues);
|
destroy_workqueue(itv->irq_work_queues);
|
||||||
|
|
||||||
ivtv_streams_cleanup(itv);
|
ivtv_streams_cleanup(itv, 1);
|
||||||
ivtv_udma_free(itv);
|
ivtv_udma_free(itv);
|
||||||
|
|
||||||
exit_ivtv_i2c(itv);
|
exit_ivtv_i2c(itv);
|
||||||
|
|
|
@ -203,14 +203,14 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
|
||||||
s->dma != PCI_DMA_NONE ? "DMA " : "",
|
s->dma != PCI_DMA_NONE ? "DMA " : "",
|
||||||
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
|
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
|
||||||
|
|
||||||
s->sg_pending = kzalloc(SGsize, GFP_KERNEL);
|
s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
|
||||||
if (s->sg_pending == NULL) {
|
if (s->sg_pending == NULL) {
|
||||||
IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
|
IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
s->sg_pending_size = 0;
|
s->sg_pending_size = 0;
|
||||||
|
|
||||||
s->sg_processing = kzalloc(SGsize, GFP_KERNEL);
|
s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
|
||||||
if (s->sg_processing == NULL) {
|
if (s->sg_processing == NULL) {
|
||||||
IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
|
IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
|
||||||
kfree(s->sg_pending);
|
kfree(s->sg_pending);
|
||||||
|
@ -219,7 +219,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
|
||||||
}
|
}
|
||||||
s->sg_processing_size = 0;
|
s->sg_processing_size = 0;
|
||||||
|
|
||||||
s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), GFP_KERNEL);
|
s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element),
|
||||||
|
GFP_KERNEL|__GFP_NOWARN);
|
||||||
if (s->sg_dma == NULL) {
|
if (s->sg_dma == NULL) {
|
||||||
IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
|
IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
|
||||||
kfree(s->sg_pending);
|
kfree(s->sg_pending);
|
||||||
|
@ -235,11 +236,12 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
|
||||||
|
|
||||||
/* allocate stream buffers. Initially all buffers are in q_free. */
|
/* allocate stream buffers. Initially all buffers are in q_free. */
|
||||||
for (i = 0; i < s->buffers; i++) {
|
for (i = 0; i < s->buffers; i++) {
|
||||||
struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), GFP_KERNEL);
|
struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer),
|
||||||
|
GFP_KERNEL|__GFP_NOWARN);
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
break;
|
break;
|
||||||
buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL);
|
buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN);
|
||||||
if (buf->buf == NULL) {
|
if (buf->buf == NULL) {
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -244,7 +244,7 @@ int ivtv_streams_setup(struct ivtv *itv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* One or more streams could not be initialized. Clean 'em all up. */
|
/* One or more streams could not be initialized. Clean 'em all up. */
|
||||||
ivtv_streams_cleanup(itv);
|
ivtv_streams_cleanup(itv, 0);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,12 +304,12 @@ int ivtv_streams_register(struct ivtv *itv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* One or more streams could not be initialized. Clean 'em all up. */
|
/* One or more streams could not be initialized. Clean 'em all up. */
|
||||||
ivtv_streams_cleanup(itv);
|
ivtv_streams_cleanup(itv, 1);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unregister v4l2 devices */
|
/* Unregister v4l2 devices */
|
||||||
void ivtv_streams_cleanup(struct ivtv *itv)
|
void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
|
@ -322,8 +322,11 @@ void ivtv_streams_cleanup(struct ivtv *itv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ivtv_stream_free(&itv->streams[type]);
|
ivtv_stream_free(&itv->streams[type]);
|
||||||
/* Unregister device */
|
/* Unregister or release device */
|
||||||
|
if (unregister)
|
||||||
video_unregister_device(vdev);
|
video_unregister_device(vdev);
|
||||||
|
else
|
||||||
|
video_device_release(vdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
int ivtv_streams_setup(struct ivtv *itv);
|
int ivtv_streams_setup(struct ivtv *itv);
|
||||||
int ivtv_streams_register(struct ivtv *itv);
|
int ivtv_streams_register(struct ivtv *itv);
|
||||||
void ivtv_streams_cleanup(struct ivtv *itv);
|
void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
|
||||||
|
|
||||||
/* Capture related */
|
/* Capture related */
|
||||||
int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
|
int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
|
||||||
|
|
|
@ -908,7 +908,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
|
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
|
||||||
yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL);
|
yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
|
||||||
if (yi->blanking_ptr) {
|
if (yi->blanking_ptr) {
|
||||||
yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
|
yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -948,7 +948,8 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the pseudo palette */
|
/* Allocate the pseudo palette */
|
||||||
oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
|
oi->ivtvfb_info.pseudo_palette =
|
||||||
|
kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
|
||||||
|
|
||||||
if (!oi->ivtvfb_info.pseudo_palette) {
|
if (!oi->ivtvfb_info.pseudo_palette) {
|
||||||
IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
|
IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
|
||||||
|
@ -1056,7 +1057,8 @@ static int ivtvfb_init_card(struct ivtv *itv)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC);
|
itv->osd_info = kzalloc(sizeof(struct osd_info),
|
||||||
|
GFP_ATOMIC|__GFP_NOWARN);
|
||||||
if (itv->osd_info == NULL) {
|
if (itv->osd_info == NULL) {
|
||||||
IVTVFB_ERR("Failed to allocate memory for osd_info\n");
|
IVTVFB_ERR("Failed to allocate memory for osd_info\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
Loading…
Reference in New Issue