Commit 3f98387e authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

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: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 6a4a7935
...@@ -805,7 +805,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 */
video_unregister_device(vdev); if (unregister)
video_unregister_device(vdev);
else
video_device_release(vdev);
} }
} }
......
...@@ -24,7 +24,7 @@ ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 */
video_unregister_device(vdev); if (unregister)
video_unregister_device(vdev);
else
video_device_release(vdev);
} }
} }
......
...@@ -23,7 +23,7 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment