From 48df47f1ea9e518d876e1bf43443328ee0294f1b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 9 Apr 2014 20:16:19 -0700 Subject: [PATCH] 3.4-stable patches added patches: media-dmxdev-remove-dvb_ringbuffer_flush-on-writer-side.patch media-gspca_kinect-add-kinect-for-windows-usb-id.patch media-hdpvr-fix-iteration-over-uninitialized-lists-in-hdpvr_probe.patch media-hdpvr-register-the-video-node-at-the-end-of-probe.patch media-omap_vout-find_vma-needs-mmap_sem-held.patch media-saa7164-fix-return-value-check-in-saa7164_initdev.patch media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch powernow-k6-correctly-initialize-default-parameters.patch powernow-k6-disable-cache-when-changing-frequency.patch powernow-k6-reorder-frequencies.patch --- ...-dvb_ringbuffer_flush-on-writer-side.patch | 59 +++++++ ...kinect-add-kinect-for-windows-usb-id.patch | 35 ++++ ...r-uninitialized-lists-in-hdpvr_probe.patch | 62 +++++++ ...r-the-video-node-at-the-end-of-probe.patch | 52 ++++++ ...ap_vout-find_vma-needs-mmap_sem-held.patch | 66 ++++++++ ...eturn-value-check-in-saa7164_initdev.patch | 40 +++++ ...-field-to-null-if-registration-fails.patch | 83 ++++++++++ ...rectly-initialize-default-parameters.patch | 153 ++++++++++++++++++ ...isable-cache-when-changing-frequency.patch | 144 +++++++++++++++++ .../powernow-k6-reorder-frequencies.patch | 68 ++++++++ queue-3.4/series | 10 ++ 11 files changed, 772 insertions(+) create mode 100644 queue-3.4/media-dmxdev-remove-dvb_ringbuffer_flush-on-writer-side.patch create mode 100644 queue-3.4/media-gspca_kinect-add-kinect-for-windows-usb-id.patch create mode 100644 queue-3.4/media-hdpvr-fix-iteration-over-uninitialized-lists-in-hdpvr_probe.patch create mode 100644 queue-3.4/media-hdpvr-register-the-video-node-at-the-end-of-probe.patch create mode 100644 queue-3.4/media-omap_vout-find_vma-needs-mmap_sem-held.patch create mode 100644 queue-3.4/media-saa7164-fix-return-value-check-in-saa7164_initdev.patch create mode 100644 queue-3.4/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch create mode 100644 queue-3.4/powernow-k6-correctly-initialize-default-parameters.patch create mode 100644 queue-3.4/powernow-k6-disable-cache-when-changing-frequency.patch create mode 100644 queue-3.4/powernow-k6-reorder-frequencies.patch diff --git a/queue-3.4/media-dmxdev-remove-dvb_ringbuffer_flush-on-writer-side.patch b/queue-3.4/media-dmxdev-remove-dvb_ringbuffer_flush-on-writer-side.patch new file mode 100644 index 00000000000..94f081a22da --- /dev/null +++ b/queue-3.4/media-dmxdev-remove-dvb_ringbuffer_flush-on-writer-side.patch @@ -0,0 +1,59 @@ +From 2af951daef68fcb1c6cace0543c420a8c26fe756 Mon Sep 17 00:00:00 2001 +From: Soeren Moch +Date: Wed, 5 Jun 2013 21:26:23 -0300 +Subject: media: dmxdev: remove dvb_ringbuffer_flush() on writer side + +From: Soeren Moch + +commit 414abbd2cd4c2618895f02ed3a76ec6647281436 upstream. + +In dvb_ringbuffer lock-less synchronizationof reader and writer threads is done +with separateread and write pointers. Sincedvb_ringbuffer_flush() modifies the +read pointer, this function must not be called from the writer thread. +This patch removes the dvb_ringbuffer_flush() calls in the dmxdev ringbuffer +write functions, this fixes Oopses "Unable to handle kernel paging request" +I could observe for the call chaindvb_demux_read ->dvb_dmxdev_buffer_read -> +dvb_ringbuffer_read_user -> __copy_to_user (the reader side of the ringbuffer). +The flush calls at the write side are not necessary anyway since ringbuffer_flush +is also called in dvb_dmxdev_buffer_read() when an error condition is set in the +ringbuffer. +This patch should also be applied to stable kernels. + +Signed-off-by: Soeren Moch +Reviewed-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/dvb/dvb-core/dmxdev.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/media/dvb/dvb-core/dmxdev.c ++++ b/drivers/media/dvb/dvb-core/dmxdev.c +@@ -379,10 +379,8 @@ static int dvb_dmxdev_section_callback(c + ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, + buffer2_len); + } +- if (ret < 0) { +- dvb_ringbuffer_flush(&dmxdevfilter->buffer); ++ if (ret < 0) + dmxdevfilter->buffer.error = ret; +- } + if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) + dmxdevfilter->state = DMXDEV_STATE_DONE; + spin_unlock(&dmxdevfilter->dev->lock); +@@ -418,10 +416,8 @@ static int dvb_dmxdev_ts_callback(const + ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); + if (ret == buffer1_len) + ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); +- if (ret < 0) { +- dvb_ringbuffer_flush(buffer); ++ if (ret < 0) + buffer->error = ret; +- } + spin_unlock(&dmxdevfilter->dev->lock); + wake_up(&buffer->queue); + return 0; diff --git a/queue-3.4/media-gspca_kinect-add-kinect-for-windows-usb-id.patch b/queue-3.4/media-gspca_kinect-add-kinect-for-windows-usb-id.patch new file mode 100644 index 00000000000..b1f83ffd11a --- /dev/null +++ b/queue-3.4/media-gspca_kinect-add-kinect-for-windows-usb-id.patch @@ -0,0 +1,35 @@ +From fd61506bd23ffc170dac4ecf401acae8004efceb Mon Sep 17 00:00:00 2001 +From: Jacob Schloss +Date: Sun, 9 Dec 2012 20:18:25 -0300 +Subject: media: gspca_kinect: add Kinect for Windows USB id + +From: Jacob Schloss + +commit 98fd485795db064d0885150e2c0c7f296d8fe06e upstream. + +Add the USB ID for the Kinect for Windows RGB camera so it can be used +with the gspca_kinect driver. + +Signed-off-by: Jacob Schloss +Signed-off-by: Antonio Ospite +Signed-off-by: Hans de Goede +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/gspca/kinect.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/media/video/gspca/kinect.c ++++ b/drivers/media/video/gspca/kinect.c +@@ -390,6 +390,7 @@ static const struct sd_desc sd_desc = { + /* -- module initialisation -- */ + static const struct usb_device_id device_table[] = { + {USB_DEVICE(0x045e, 0x02ae)}, ++ {USB_DEVICE(0x045e, 0x02bf)}, + {} + }; + diff --git a/queue-3.4/media-hdpvr-fix-iteration-over-uninitialized-lists-in-hdpvr_probe.patch b/queue-3.4/media-hdpvr-fix-iteration-over-uninitialized-lists-in-hdpvr_probe.patch new file mode 100644 index 00000000000..b09fd8b8be7 --- /dev/null +++ b/queue-3.4/media-hdpvr-fix-iteration-over-uninitialized-lists-in-hdpvr_probe.patch @@ -0,0 +1,62 @@ +From 9eb9bfa030d8a49d54f0e4ae671e33f406bbbeff Mon Sep 17 00:00:00 2001 +From: Alexey Khoroshilov +Date: Wed, 3 Jul 2013 16:17:34 -0300 +Subject: media: hdpvr: fix iteration over uninitialized lists in hdpvr_probe() + +From: Alexey Khoroshilov + +commit 2e923a0527ac439e135b9961e58d3acd876bba10 upstream. + +free_buff_list and rec_buff_list are initialized in the middle of hdpvr_probe(), +but if something bad happens before that, error handling code calls hdpvr_delete(), +which contains iteration over the lists (via hdpvr_free_buffers()). +The patch moves the lists initialization to the beginning and by the way fixes +goto label in error handling of registering videodev. +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Alexey Khoroshilov +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/hdpvr/hdpvr-core.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/media/video/hdpvr/hdpvr-core.c ++++ b/drivers/media/video/hdpvr/hdpvr-core.c +@@ -309,6 +309,11 @@ static int hdpvr_probe(struct usb_interf + + dev->workqueue = 0; + ++ /* init video transfer queues first of all */ ++ /* to prevent oops in hdpvr_delete() on error paths */ ++ INIT_LIST_HEAD(&dev->free_buff_list); ++ INIT_LIST_HEAD(&dev->rec_buff_list); ++ + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { + err("v4l2_device_register failed"); +@@ -331,10 +336,6 @@ static int hdpvr_probe(struct usb_interf + if (!dev->workqueue) + goto error; + +- /* init video transfer queues */ +- INIT_LIST_HEAD(&dev->free_buff_list); +- INIT_LIST_HEAD(&dev->rec_buff_list); +- + dev->options = hdpvr_default_options; + + if (default_video_input < HDPVR_VIDEO_INPUTS) +@@ -409,7 +410,7 @@ static int hdpvr_probe(struct usb_interf + video_nr[atomic_inc_return(&dev_nr)]); + if (retval < 0) { + v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); +- goto error; ++ goto reg_fail; + } + + /* let the user know what node this device is now attached to */ diff --git a/queue-3.4/media-hdpvr-register-the-video-node-at-the-end-of-probe.patch b/queue-3.4/media-hdpvr-register-the-video-node-at-the-end-of-probe.patch new file mode 100644 index 00000000000..56dd8fd709b --- /dev/null +++ b/queue-3.4/media-hdpvr-register-the-video-node-at-the-end-of-probe.patch @@ -0,0 +1,52 @@ +From 559a2e36f047ac7e1ab27c489322cfd1409dd842 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Tue, 19 Mar 2013 09:34:58 -0300 +Subject: media: hdpvr: register the video node at the end of probe + +From: Hans Verkuil + +commit 280847b532433ffe7a22795f926327805a127162 upstream. + +Video nodes can be used at once after registration, so make sure the full +initialization is done before registering them. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust filename, context] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/hdpvr/hdpvr-core.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/media/video/hdpvr/hdpvr-core.c ++++ b/drivers/media/video/hdpvr/hdpvr-core.c +@@ -385,12 +385,6 @@ static int hdpvr_probe(struct usb_interf + } + mutex_unlock(&dev->io_mutex); + +- if (hdpvr_register_videodev(dev, &interface->dev, +- video_nr[atomic_inc_return(&dev_nr)])) { +- v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); +- goto error; +- } +- + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + retval = hdpvr_register_i2c_adapter(dev); + if (retval < 0) { +@@ -411,6 +405,13 @@ static int hdpvr_probe(struct usb_interf + } + #endif + ++ retval = hdpvr_register_videodev(dev, &interface->dev, ++ video_nr[atomic_inc_return(&dev_nr)]); ++ if (retval < 0) { ++ v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); ++ goto error; ++ } ++ + /* let the user know what node this device is now attached to */ + v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", + video_device_node_name(dev->video_dev)); diff --git a/queue-3.4/media-omap_vout-find_vma-needs-mmap_sem-held.patch b/queue-3.4/media-omap_vout-find_vma-needs-mmap_sem-held.patch new file mode 100644 index 00000000000..fe5562f2b9d --- /dev/null +++ b/queue-3.4/media-omap_vout-find_vma-needs-mmap_sem-held.patch @@ -0,0 +1,66 @@ +From 5a82145cb978983b79993ee1d0b1982f3b80cd9b Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sun, 16 Dec 2012 16:04:46 -0300 +Subject: media: omap_vout: find_vma() needs ->mmap_sem held + +From: Al Viro + +commit 55ee64b30a38d688232e5eb2860467dddc493573 upstream. + +Walking rbtree while it's modified is a Bad Idea(tm); besides, +the result of find_vma() can be freed just as it's getting returned +to caller. Fortunately, it's easy to fix - just take ->mmap_sem a bit +earlier (and don't bother with find_vma() at all if virtp >= PAGE_OFFSET - +in that case we don't even look at its result). + +While we are at it, what prevents VIDIOC_PREPARE_BUF calling +v4l_prepare_buf() -> (e.g) vb2_ioctl_prepare_buf() -> vb2_prepare_buf() -> +__buf_prepare() -> __qbuf_userptr() -> vb2_vmalloc_get_userptr() -> find_vma(), +AFAICS without having taken ->mmap_sem anywhere in process? The code flow +is bloody convoluted and depends on a bunch of things done by initialization, +so I certainly might've missed something... + +Signed-off-by: Al Viro +Cc: Sakari Ailus +Cc: Laurent Pinchart +Cc: Archit Taneja +Cc: Prabhakar Lad +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/omap/omap_vout.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/media/video/omap/omap_vout.c ++++ b/drivers/media/video/omap/omap_vout.c +@@ -206,19 +206,21 @@ static u32 omap_vout_uservirt_to_phys(u3 + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + +- vma = find_vma(mm, virtp); + /* For kernel direct-mapped memory, take the easy way */ +- if (virtp >= PAGE_OFFSET) { +- physp = virt_to_phys((void *) virtp); +- } else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { ++ if (virtp >= PAGE_OFFSET) ++ return virt_to_phys((void *) virtp); ++ ++ down_read(¤t->mm->mmap_sem); ++ vma = find_vma(mm, virtp); ++ if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { + /* this will catch, kernel-allocated, mmaped-to-usermode + addresses */ + physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); ++ up_read(¤t->mm->mmap_sem); + } else { + /* otherwise, use get_user_pages() for general userland pages */ + int res, nr_pages = 1; + struct page *pages; +- down_read(¤t->mm->mmap_sem); + + res = get_user_pages(current, current->mm, virtp, nr_pages, 1, + 0, &pages, NULL); diff --git a/queue-3.4/media-saa7164-fix-return-value-check-in-saa7164_initdev.patch b/queue-3.4/media-saa7164-fix-return-value-check-in-saa7164_initdev.patch new file mode 100644 index 00000000000..d1b311fa98d --- /dev/null +++ b/queue-3.4/media-saa7164-fix-return-value-check-in-saa7164_initdev.patch @@ -0,0 +1,40 @@ +From 47c55eb0a98d1f513f0bc1bc8065c7cc276c3335 Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Fri, 25 Oct 2013 06:34:03 -0300 +Subject: media: saa7164: fix return value check in saa7164_initdev() + +From: Wei Yongjun + +commit 89f4d45b2752df5d222b5f63919ce59e2d8afaf4 upstream. + +In case of error, the function kthread_run() returns ERR_PTR() +and never returns NULL. The NULL test in the return value check +should be replaced with IS_ERR(). + +Signed-off-by: Wei Yongjun +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/saa7164/saa7164-core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/media/video/saa7164/saa7164-core.c ++++ b/drivers/media/video/saa7164/saa7164-core.c +@@ -1386,9 +1386,11 @@ static int __devinit saa7164_initdev(str + if (fw_debug) { + dev->kthread = kthread_run(saa7164_thread_function, dev, + "saa7164 debug"); +- if (!dev->kthread) ++ if (IS_ERR(dev->kthread)) { ++ dev->kthread = NULL; + printk(KERN_ERR "%s() Failed to create " + "debug kernel thread\n", __func__); ++ } + } + + } /* != BOARD_UNKNOWN */ diff --git a/queue-3.4/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch b/queue-3.4/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch new file mode 100644 index 00000000000..538990b0d46 --- /dev/null +++ b/queue-3.4/media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch @@ -0,0 +1,83 @@ +From 754aed1b98d1c1ed2a8eaae2fc933bc9c6a87629 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Sat, 24 Nov 2012 21:35:48 -0300 +Subject: media: v4l: Reset subdev v4l2_dev field to NULL if registration fails + +From: Laurent Pinchart + +commit 317efce991620adc589b3005b9baed433dcb2a56 upstream. + +When subdev registration fails the subdev v4l2_dev field is left to a +non-NULL value. Later calls to v4l2_device_unregister_subdev() will +consider the subdev as registered and will module_put() the subdev +module without any matching module_get(). +Fix this by setting the subdev v4l2_dev field to NULL in +v4l2_device_register_subdev() when the function fails. + +Signed-off-by: Laurent Pinchart +Acked-by: Sylwester Nawrocki +Signed-off-by: Mauro Carvalho Chehab +[bwh: Backported to 3.2: adjust context, filename] +Signed-off-by: Ben Hutchings +Cc: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/video/v4l2-device.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +--- a/drivers/media/video/v4l2-device.c ++++ b/drivers/media/video/v4l2-device.c +@@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v + sd->v4l2_dev = v4l2_dev; + if (sd->internal_ops && sd->internal_ops->registered) { + err = sd->internal_ops->registered(sd); +- if (err) { +- module_put(sd->owner); +- return err; +- } ++ if (err) ++ goto error_module; + } + + /* This just returns 0 if either of the two args is NULL */ + err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler); +- if (err) { +- if (sd->internal_ops && sd->internal_ops->unregistered) +- sd->internal_ops->unregistered(sd); +- module_put(sd->owner); +- return err; +- } ++ if (err) ++ goto error_unregister; + + #if defined(CONFIG_MEDIA_CONTROLLER) + /* Register the entity. */ + if (v4l2_dev->mdev) { + err = media_device_register_entity(v4l2_dev->mdev, entity); +- if (err < 0) { +- if (sd->internal_ops && sd->internal_ops->unregistered) +- sd->internal_ops->unregistered(sd); +- module_put(sd->owner); +- return err; +- } ++ if (err < 0) ++ goto error_unregister; + } + #endif + +@@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v + spin_unlock(&v4l2_dev->lock); + + return 0; ++ ++error_unregister: ++ if (sd->internal_ops && sd->internal_ops->unregistered) ++ sd->internal_ops->unregistered(sd); ++error_module: ++ module_put(sd->owner); ++ sd->v4l2_dev = NULL; ++ return err; + } + EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); + diff --git a/queue-3.4/powernow-k6-correctly-initialize-default-parameters.patch b/queue-3.4/powernow-k6-correctly-initialize-default-parameters.patch new file mode 100644 index 00000000000..fa93fabc60b --- /dev/null +++ b/queue-3.4/powernow-k6-correctly-initialize-default-parameters.patch @@ -0,0 +1,153 @@ +From d82b922a4acc1781d368aceac2f9da43b038cab2 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 11 Dec 2013 19:38:53 -0500 +Subject: powernow-k6: correctly initialize default parameters + +From: Mikulas Patocka + +commit d82b922a4acc1781d368aceac2f9da43b038cab2 upstream. + +The powernow-k6 driver used to read the initial multiplier from the +powernow register. However, there is a problem with this: + +* If there was a frequency transition before, the multiplier read from the + register corresponds to the current multiplier. +* If there was no frequency transition since reset, the field in the + register always reads as zero, regardless of the current multiplier that + is set using switches on the mainboard and that the CPU is running at. + +The zero value corresponds to multiplier 4.5, so as a consequence, the +powernow-k6 driver always assumes multiplier 4.5. + +For example, if we have 550MHz CPU with bus frequency 100MHz and +multiplier 5.5, the powernow-k6 driver thinks that the multiplier is 4.5 +and bus frequency is 122MHz. The powernow-k6 driver then sets the +multiplier to 4.5, underclocking the CPU to 450MHz, but reports the +current frequency as 550MHz. + +There is no reliable way how to read the initial multiplier. I modified +the driver so that it contains a table of known frequencies (based on +parameters of existing CPUs and some common overclocking schemes) and sets +the multiplier according to the frequency. If the frequency is unknown +(because of unusual overclocking or underclocking), the user must supply +the bus speed and maximum multiplier as module parameters. + +This patch should be backported to all stable kernels. If it doesn't +apply cleanly, change it, or ask me to change it. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/cpufreq/powernow-k6.c | 76 +++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 72 insertions(+), 4 deletions(-) + +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -26,6 +26,14 @@ + static unsigned int busfreq; /* FSB, in 10 kHz */ + static unsigned int max_multiplier; + ++static unsigned int param_busfreq = 0; ++static unsigned int param_max_multiplier = 0; ++ ++module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO); ++MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)"); ++ ++module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO); ++MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz"); + + /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ + static struct cpufreq_frequency_table clock_ratio[] = { +@@ -40,6 +48,27 @@ static struct cpufreq_frequency_table cl + {0, CPUFREQ_TABLE_END} + }; + ++static const struct { ++ unsigned freq; ++ unsigned mult; ++} usual_frequency_table[] = { ++ { 400000, 40 }, // 100 * 4 ++ { 450000, 45 }, // 100 * 4.5 ++ { 475000, 50 }, // 95 * 5 ++ { 500000, 50 }, // 100 * 5 ++ { 506250, 45 }, // 112.5 * 4.5 ++ { 533500, 55 }, // 97 * 5.5 ++ { 550000, 55 }, // 100 * 5.5 ++ { 562500, 50 }, // 112.5 * 5 ++ { 570000, 60 }, // 95 * 6 ++ { 600000, 60 }, // 100 * 6 ++ { 618750, 55 }, // 112.5 * 5.5 ++ { 660000, 55 }, // 120 * 5.5 ++ { 675000, 60 }, // 112.5 * 6 ++ { 720000, 60 }, // 120 * 6 ++}; ++ ++#define FREQ_RANGE 3000 + + /** + * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier +@@ -163,18 +192,57 @@ static int powernow_k6_target(struct cpu + return 0; + } + +- + static int powernow_k6_cpu_init(struct cpufreq_policy *policy) + { + unsigned int i, f; + int result; ++ unsigned khz; + + if (policy->cpu != 0) + return -ENODEV; + +- /* get frequencies */ +- max_multiplier = powernow_k6_get_cpu_multiplier(); +- busfreq = cpu_khz / max_multiplier; ++ max_multiplier = 0; ++ khz = cpu_khz; ++ for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) { ++ if (khz >= usual_frequency_table[i].freq - FREQ_RANGE && ++ khz <= usual_frequency_table[i].freq + FREQ_RANGE) { ++ khz = usual_frequency_table[i].freq; ++ max_multiplier = usual_frequency_table[i].mult; ++ break; ++ } ++ } ++ if (param_max_multiplier) { ++ for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { ++ if (clock_ratio[i].index == param_max_multiplier) { ++ max_multiplier = param_max_multiplier; ++ goto have_max_multiplier; ++ } ++ } ++ printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); ++ return -EINVAL; ++ } ++ ++ if (!max_multiplier) { ++ printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz); ++ printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n"); ++ return -EOPNOTSUPP; ++ } ++ ++have_max_multiplier: ++ param_max_multiplier = max_multiplier; ++ ++ if (param_busfreq) { ++ if (param_busfreq >= 50000 && param_busfreq <= 150000) { ++ busfreq = param_busfreq / 10; ++ goto have_busfreq; ++ } ++ printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); ++ return -EINVAL; ++ } ++ ++ busfreq = khz / max_multiplier; ++have_busfreq: ++ param_busfreq = busfreq * 10; + + /* table init */ + for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { diff --git a/queue-3.4/powernow-k6-disable-cache-when-changing-frequency.patch b/queue-3.4/powernow-k6-disable-cache-when-changing-frequency.patch new file mode 100644 index 00000000000..e1963db728c --- /dev/null +++ b/queue-3.4/powernow-k6-disable-cache-when-changing-frequency.patch @@ -0,0 +1,144 @@ +From e20e1d0ac02308e2211306fc67abcd0b2668fb8b Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 11 Dec 2013 19:38:32 -0500 +Subject: powernow-k6: disable cache when changing frequency + +From: Mikulas Patocka + +commit e20e1d0ac02308e2211306fc67abcd0b2668fb8b upstream. + +I found out that a system with k6-3+ processor is unstable during network +server load. The system locks up or the network card stops receiving. The +reason for the instability is the CPU frequency scaling. + +During frequency transition the processor is in "EPM Stop Grant" state. +The documentation says that the processor doesn't respond to inquiry +requests in this state. Consequently, coherency of processor caches and +bus master devices is not maintained, causing the system instability. + +This patch flushes the cache during frequency transition. It fixes the +instability. + +Other minor changes: +* u64 invalue changed to unsigned long because the variable is 32-bit +* move the logic to set the multiplier to a separate function + powernow_k6_set_cpu_multiplier +* preserve lower 5 bits of the powernow port instead of 4 (the voltage + field has 5 bits) +* mask interrupts when reading the multiplier, so that the port is not + open during other activity (running other kernel code with the port open + shouldn't cause any misbehavior, but we should better be safe and keep + the port closed) + +This patch should be backported to all stable kernels. If it doesn't +apply cleanly, change it, or ask me to change it. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpufreq/powernow-k6.c | 56 +++++++++++++++++++++++++++++------------- + 1 file changed, 39 insertions(+), 17 deletions(-) + +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -44,23 +44,58 @@ static struct cpufreq_frequency_table cl + /** + * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier + * +- * Returns the current setting of the frequency multiplier. Core clock ++ * Returns the current setting of the frequency multiplier. Core clock + * speed is frequency of the Front-Side Bus multiplied with this value. + */ + static int powernow_k6_get_cpu_multiplier(void) + { +- u64 invalue = 0; ++ unsigned long invalue = 0; + u32 msrval; + ++ local_irq_disable(); ++ + msrval = POWERNOW_IOPORT + 0x1; + wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ + invalue = inl(POWERNOW_IOPORT + 0x8); + msrval = POWERNOW_IOPORT + 0x0; + wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ + ++ local_irq_enable(); ++ + return clock_ratio[(invalue >> 5)&7].index; + } + ++static void powernow_k6_set_cpu_multiplier(unsigned int best_i) ++{ ++ unsigned long outvalue, invalue; ++ unsigned long msrval; ++ unsigned long cr0; ++ ++ /* we now need to transform best_i to the BVC format, see AMD#23446 */ ++ ++ /* ++ * The processor doesn't respond to inquiry cycles while changing the ++ * frequency, so we must disable cache. ++ */ ++ local_irq_disable(); ++ cr0 = read_cr0(); ++ write_cr0(cr0 | X86_CR0_CD); ++ wbinvd(); ++ ++ outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); ++ ++ msrval = POWERNOW_IOPORT + 0x1; ++ wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ ++ invalue = inl(POWERNOW_IOPORT + 0x8); ++ invalue = invalue & 0x1f; ++ outvalue = outvalue | invalue; ++ outl(outvalue, (POWERNOW_IOPORT + 0x8)); ++ msrval = POWERNOW_IOPORT + 0x0; ++ wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ ++ ++ write_cr0(cr0); ++ local_irq_enable(); ++} + + /** + * powernow_k6_set_state - set the PowerNow! multiplier +@@ -70,8 +105,6 @@ static int powernow_k6_get_cpu_multiplie + */ + static void powernow_k6_set_state(unsigned int best_i) + { +- unsigned long outvalue = 0, invalue = 0; +- unsigned long msrval; + struct cpufreq_freqs freqs; + + if (clock_ratio[best_i].index > max_multiplier) { +@@ -85,18 +118,7 @@ static void powernow_k6_set_state(unsign + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + +- /* we now need to transform best_i to the BVC format, see AMD#23446 */ +- +- outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); +- +- msrval = POWERNOW_IOPORT + 0x1; +- wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ +- invalue = inl(POWERNOW_IOPORT + 0x8); +- invalue = invalue & 0xf; +- outvalue = outvalue | invalue; +- outl(outvalue , (POWERNOW_IOPORT + 0x8)); +- msrval = POWERNOW_IOPORT + 0x0; +- wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ ++ powernow_k6_set_cpu_multiplier(best_i); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + +@@ -164,7 +186,7 @@ static int powernow_k6_cpu_init(struct c + } + + /* cpuinfo and default policy values */ +- policy->cpuinfo.transition_latency = 200000; ++ policy->cpuinfo.transition_latency = 500000; + policy->cur = busfreq * max_multiplier; + + result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); diff --git a/queue-3.4/powernow-k6-reorder-frequencies.patch b/queue-3.4/powernow-k6-reorder-frequencies.patch new file mode 100644 index 00000000000..5466a0fac4a --- /dev/null +++ b/queue-3.4/powernow-k6-reorder-frequencies.patch @@ -0,0 +1,68 @@ +From 22c73795b101597051924556dce019385a1e2fa0 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 11 Dec 2013 19:39:19 -0500 +Subject: powernow-k6: reorder frequencies + +From: Mikulas Patocka + +commit 22c73795b101597051924556dce019385a1e2fa0 upstream. + +This patch reorders reported frequencies from the highest to the lowest, +just like in other frequency drivers. + +Signed-off-by: Mikulas Patocka +Acked-by: Viresh Kumar +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/cpufreq/powernow-k6.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -37,17 +37,20 @@ MODULE_PARM_DESC(bus_frequency, "Bus fre + + /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ + static struct cpufreq_frequency_table clock_ratio[] = { +- {45, /* 000 -> 4.5x */ 0}, ++ {60, /* 110 -> 6.0x */ 0}, ++ {55, /* 011 -> 5.5x */ 0}, + {50, /* 001 -> 5.0x */ 0}, ++ {45, /* 000 -> 4.5x */ 0}, + {40, /* 010 -> 4.0x */ 0}, +- {55, /* 011 -> 5.5x */ 0}, +- {20, /* 100 -> 2.0x */ 0}, +- {30, /* 101 -> 3.0x */ 0}, +- {60, /* 110 -> 6.0x */ 0}, + {35, /* 111 -> 3.5x */ 0}, ++ {30, /* 101 -> 3.0x */ 0}, ++ {20, /* 100 -> 2.0x */ 0}, + {0, CPUFREQ_TABLE_END} + }; + ++static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 }; ++static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 }; ++ + static const struct { + unsigned freq; + unsigned mult; +@@ -91,7 +94,7 @@ static int powernow_k6_get_cpu_multiplie + + local_irq_enable(); + +- return clock_ratio[(invalue >> 5)&7].index; ++ return clock_ratio[register_to_index[(invalue >> 5)&7]].index; + } + + static void powernow_k6_set_cpu_multiplier(unsigned int best_i) +@@ -111,7 +114,7 @@ static void powernow_k6_set_cpu_multipli + write_cr0(cr0 | X86_CR0_CD); + wbinvd(); + +- outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); ++ outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5); + + msrval = POWERNOW_IOPORT + 0x1; + wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ diff --git a/queue-3.4/series b/queue-3.4/series index fa5999b2a9e..f433ba37a56 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -122,3 +122,13 @@ mmc-mxs-mmc-fix-deadlock-caused-by-recursion-loop.patch sb_edac-avoid-overflow-errors-at-memory-size-calculation.patch tg3-skip-powering-down-function-0-on-certain-serdes-devices.patch tg3-add-read-dma-workaround-for-5720.patch +media-gspca_kinect-add-kinect-for-windows-usb-id.patch +media-v4l-reset-subdev-v4l2_dev-field-to-null-if-registration-fails.patch +media-omap_vout-find_vma-needs-mmap_sem-held.patch +media-dmxdev-remove-dvb_ringbuffer_flush-on-writer-side.patch +media-hdpvr-register-the-video-node-at-the-end-of-probe.patch +media-hdpvr-fix-iteration-over-uninitialized-lists-in-hdpvr_probe.patch +media-saa7164-fix-return-value-check-in-saa7164_initdev.patch +powernow-k6-disable-cache-when-changing-frequency.patch +powernow-k6-correctly-initialize-default-parameters.patch +powernow-k6-reorder-frequencies.patch -- 2.47.3