* [00/20] 2.6.27.40-stable review @ 2009-12-06 23:37 ` Greg KH 2009-12-06 23:30 ` [01/20] ALSA: AACI: fix AC97 multiple-open bug Greg KH ` (19 more replies) 0 siblings, 20 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:37 UTC (permalink / raw) To: linux-kernel, stable; +Cc: stable-review, torvalds, akpm, alan This is the start of the stable review cycle for the 2.6.27.40 release. There are 20 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it. Responses should be made by Tuesday Dec 8, 20:00:00 UTC. Anything received after that time might be too late. The whole patch series can be found in one patch at: kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.40-rc1.gz and the diffstat can be found below. thanks, greg k-h Makefile | 2 +- arch/x86/kernel/acpi/processor.c | 3 +- drivers/dca/dca-core.c | 51 ++++++++++----- drivers/hwmon/it87.c | 2 +- drivers/isdn/hisax/hfc_usb.c | 4 +- drivers/media/common/tuners/tda18271-fe.c | 8 +- drivers/media/dvb/frontends/dib7000p.c | 5 ++ drivers/media/video/em28xx/em28xx-audio.c | 5 ++ drivers/media/video/s2255drv.c | 5 -- drivers/misc/thinkpad_acpi.c | 2 +- drivers/scsi/gdth.c | 2 +- drivers/usb/host/ohci-hcd.c | 5 ++ drivers/usb/host/ohci-pci.c | 20 ++++++ drivers/usb/host/ohci-q.c | 18 ++++-- drivers/usb/host/ohci.h | 9 +++ drivers/usb/serial/aircable.c | 5 +- drivers/usb/serial/belkin_sa.c | 7 +- drivers/usb/serial/cp2101.c | 6 +- drivers/usb/serial/cyberjack.c | 20 +++++-- drivers/usb/serial/cypress_m8.c | 11 ++-- drivers/usb/serial/digi_acceleport.c | 20 +++++-- drivers/usb/serial/empeg.c | 8 --- drivers/usb/serial/ftdi_sio.c | 14 ---- drivers/usb/serial/garmin_gps.c | 16 ++++- drivers/usb/serial/generic.c | 9 ++- drivers/usb/serial/io_edgeport.c | 29 ++++++--- drivers/usb/serial/io_tables.h | 12 +++- drivers/usb/serial/io_ti.c | 22 +++++-- drivers/usb/serial/ipaq.c | 7 -- drivers/usb/serial/iuu_phoenix.c | 6 +- drivers/usb/serial/keyspan.c | 13 ++++- drivers/usb/serial/keyspan.h | 12 +++- drivers/usb/serial/keyspan_pda.c | 4 +- drivers/usb/serial/kl5kusb105.c | 39 +++++++----- drivers/usb/serial/kobil_sct.c | 12 +--- drivers/usb/serial/mct_u232.c | 13 ++--- drivers/usb/serial/mos7720.c | 9 +-- drivers/usb/serial/mos7840.c | 48 ++++++++++++--- drivers/usb/serial/omninet.c | 19 +++++- drivers/usb/serial/option.c | 97 ++++++++++++++++++++++++++--- drivers/usb/serial/oti6858.c | 7 +- drivers/usb/serial/pl2303.c | 5 +- drivers/usb/serial/sierra.c | 28 +++++++- drivers/usb/serial/spcp8x5.c | 5 +- drivers/usb/serial/ti_usb_3410_5052.c | 10 +-- drivers/usb/serial/usb-serial.c | 29 ++++----- drivers/usb/serial/visor.c | 13 ++--- drivers/usb/serial/whiteheat.c | 6 +- fs/fuse/dir.c | 3 + fs/fuse/file.c | 3 +- fs/jffs2/read.c | 9 ++- include/linux/usb/serial.h | 12 +++- sound/arm/aaci.c | 6 ++- sound/usb/usbaudio.h | 2 +- 54 files changed, 493 insertions(+), 244 deletions(-) ^ permalink raw reply [flat|nested] 21+ messages in thread
* [01/20] ALSA: AACI: fix AC97 multiple-open bug 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [02/20] ALSA: AACI: fix recording bug Greg KH ` (18 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Russell King, Takashi Iwai [-- Attachment #1: alsa-aaci-fix-ac97-multiple-open-bug.patch --] [-- Type: text/plain, Size: 761 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Russell King <rmk+kernel@arm.linux.org.uk> commit 4acd57c3de62374fe5bb52e5cd24538190f4eab2 upstream. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- sound/arm/aaci.c | 4 ++++ 1 file changed, 4 insertions(+) --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -504,6 +504,10 @@ static int aaci_pcm_hw_params(struct snd int err; aaci_pcm_hw_free(substream); + if (aacirun->pcm_open) { + snd_ac97_pcm_close(aacirun->pcm); + aacirun->pcm_open = 0; + } err = devdma_hw_alloc(NULL, substream, params_buffer_bytes(params)); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [02/20] ALSA: AACI: fix recording bug 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH 2009-12-06 23:30 ` [01/20] ALSA: AACI: fix AC97 multiple-open bug Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [03/20] ALSA: usb-audio: fix combine_word problem Greg KH ` (17 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Russell King, Takashi Iwai [-- Attachment #1: alsa-aaci-fix-recording-bug.patch --] [-- Type: text/plain, Size: 895 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Russell King <rmk+kernel@arm.linux.org.uk> commit 8ee763b9c82c6ca0a59a7271ce4fa29d7baf5c09 upstream. pcm->r[1].slots is the double rate slot information, not the capture information. For capture, 'pcm' will already be the capture ac97 pcm structure. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- sound/arm/aaci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -521,7 +521,7 @@ static int aaci_pcm_hw_params(struct snd else err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), params_channels(params), - aacirun->pcm->r[1].slots); + aacirun->pcm->r[0].slots); if (err) goto out; ^ permalink raw reply [flat|nested] 21+ messages in thread
* [03/20] ALSA: usb-audio: fix combine_word problem 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH 2009-12-06 23:30 ` [01/20] ALSA: AACI: fix AC97 multiple-open bug Greg KH 2009-12-06 23:30 ` [02/20] ALSA: AACI: fix recording bug Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [04/20] [SCSI] gdth: Prevent negative offsets in ioctl CVE-2009-3080 Greg KH ` (16 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Julian Anastasov, Takashi Iwai [-- Attachment #1: alsa-usb-audio-fix-combine_word-problem.patch --] [-- Type: text/plain, Size: 1418 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Julian Anastasov <ja@ssi.bg> commit f495088210c8b9e20791d995a8210170c68d2deb upstream. Fix combine_word problem where first octet is not read properly. The only affected place seems to be the INPUT_TERMINAL type. Before now, sound controls can be created with the output terminal's name which is a fallback mechanism used only for unknown input terminal types. For example, Line can wrongly appear as Speaker. After the change it should appear as Line. The side effect of this change can be that users can expect the wrong control name in their scripts or programs while now we return the correct one. Probably, these defines should use get_unaligned_le16 and friends. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- sound/usb/usbaudio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -209,7 +209,7 @@ struct snd_usb_midi_endpoint_info { /* */ -#define combine_word(s) ((*s) | ((unsigned int)(s)[1] << 8)) +#define combine_word(s) ((*(s)) | ((unsigned int)(s)[1] << 8)) #define combine_triple(s) (combine_word(s) | ((unsigned int)(s)[2] << 16)) #define combine_quad(s) (combine_triple(s) | ((unsigned int)(s)[3] << 24)) ^ permalink raw reply [flat|nested] 21+ messages in thread
* [04/20] [SCSI] gdth: Prevent negative offsets in ioctl CVE-2009-3080 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (2 preceding siblings ...) 2009-12-06 23:30 ` [03/20] ALSA: usb-audio: fix combine_word problem Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [05/20] jffs2: Fix memory corruption in jffs2_read_inode_range() Greg KH ` (15 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Dave Jones, James Bottomley [-- Attachment #1: gdth-prevent-negative-offsets-in-ioctl-cve-2009-3080.patch --] [-- Type: text/plain, Size: 869 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Dave Jones <davej@redhat.com> commit 690e744869f3262855b83b4fb59199cf142765b0 upstream. A negative offset could be used to index before the event buffer and lead to a security breach. Signed-off-by: Dave Jones <davej@redhat.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/scsi/gdth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -2912,7 +2912,7 @@ static int gdth_read_event(gdth_ha_str * eindex = handle; estr->event_source = 0; - if (eindex >= MAX_EVENTS) { + if (eindex < 0 || eindex >= MAX_EVENTS) { spin_unlock_irqrestore(&ha->smp_lock, flags); return eindex; } ^ permalink raw reply [flat|nested] 21+ messages in thread
* [05/20] jffs2: Fix memory corruption in jffs2_read_inode_range() 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (3 preceding siblings ...) 2009-12-06 23:30 ` [04/20] [SCSI] gdth: Prevent negative offsets in ioctl CVE-2009-3080 Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [06/20] V4L/DVB (13079): dib0700: fixed xc2028 firmware loading kernel oops Greg KH ` (14 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable; +Cc: stable-review, torvalds, akpm, alan, David Woodhouse [-- Attachment #1: jffs2-fix-memory-corruption-in-jffs2_read_inode_range.patch --] [-- Type: text/plain, Size: 3523 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: David Woodhouse <dwmw2@infradead.org> commit 199bc9ff5ca5e4b3bcaff8927b2983c65f34c263 upstream. In 2.6.23 kernel, commit a32ea1e1f925399e0d81ca3f7394a44a6dafa12c ("Fix read/truncate race") fixed a race in the generic code, and as a side effect, now do_generic_file_read() can ask us to readpage() past the i_size. This seems to be correctly handled by the block routines (e.g. block_read_full_page() fills the page with zeroes in case if somebody is trying to read past the last inode's block). JFFS2 doesn't handle this; it assumes that it won't be asked to read pages which don't exist -- and thus that there will be at least _one_ valid 'frag' on the page it's being asked to read. It will fill any holes with the following memset: memset(buf, 0, min(end, frag->ofs + frag->size) - offset); When the 'closest smaller match' returned by jffs2_lookup_node_frag() is actually on a previous page and ends before 'offset', that results in: memset(buf, 0, <huge unsigned negative>); Hopefully, in most cases the corruption is fatal, and quickly causing random oopses, like this: root@10.0.0.4:~/ltp-fs-20090531# ./testcases/kernel/fs/ftest/ftest01 Unable to handle kernel paging request for data at address 0x00000008 Faulting instruction address: 0xc01cd980 Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c01cd980] rb_insert_color+0x38/0x184 LR [c0043978] enqueue_hrtimer+0x88/0xc4 Call Trace: [c6c63b60] [c004f9a8] tick_sched_timer+0xa0/0xe4 (unreliable) [c6c63b80] [c0043978] enqueue_hrtimer+0x88/0xc4 [c6c63b90] [c0043a48] __run_hrtimer+0x94/0xbc [c6c63bb0] [c0044628] hrtimer_interrupt+0x140/0x2b8 [c6c63c10] [c000f8e8] timer_interrupt+0x13c/0x254 [c6c63c30] [c001352c] ret_from_except+0x0/0x14 --- Exception: 901 at memset+0x38/0x5c LR = jffs2_read_inode_range+0x144/0x17c [c6c63cf0] [00000000] (null) (unreliable) This patch fixes the issue, plus fixes all LTP tests on NAND/UBI with JFFS2 filesystem that were failing since 2.6.23 (seems like the bug above also broke the truncation). Reported-By: Anton Vorontsov <avorontsov@ru.mvista.com> Tested-By: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/jffs2/read.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -164,12 +164,15 @@ int jffs2_read_inode_range(struct jffs2_ /* XXX FIXME: Where a single physical node actually shows up in two frags, we read it twice. Don't do that. */ - /* Now we're pointing at the first frag which overlaps our page */ + /* Now we're pointing at the first frag which overlaps our page + * (or perhaps is before it, if we've been asked to read off the + * end of the file). */ while(offset < end) { D2(printk(KERN_DEBUG "jffs2_read_inode_range: offset %d, end %d\n", offset, end)); - if (unlikely(!frag || frag->ofs > offset)) { + if (unlikely(!frag || frag->ofs > offset || + frag->ofs + frag->size <= offset)) { uint32_t holesize = end - offset; - if (frag) { + if (frag && frag->ofs > offset) { D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); holesize = min(holesize, frag->ofs - offset); } ^ permalink raw reply [flat|nested] 21+ messages in thread
* [06/20] V4L/DVB (13079): dib0700: fixed xc2028 firmware loading kernel oops 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (4 preceding siblings ...) 2009-12-06 23:30 ` [05/20] jffs2: Fix memory corruption in jffs2_read_inode_range() Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [07/20] V4L/DVB (13107): tda18271: fix overflow in FM radio frequency calculation Greg KH ` (13 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Martin Samek, Devin Heitmueller, Mauro Carvalho Chehab [-- Attachment #1: v4l-dvb-13079-dib0700-fixed-xc2028-firmware-loading-kernel-oops.patch --] [-- Type: text/plain, Size: 1510 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Martin Samek <martin@marsark.sytes.net> commit 7646b9de26c54cf4bc9c446d7ada9f91ece31e0a upstream. Fixing kernel oops when driver attemps to load xc2028 firmware. Note by djh: the patch contribute by Martin is a port of a fix I made during the PCTV 340e development. It's a temporary workaround that fixes a regression (an OOPS condition) and the real fix should be in the code that manages the i2c master on the dib7000p. But this fix does address the immmediate regression and should be merged upstream until we do a cleaner fix. Signed-off-by: Martin Samek <martin@marsark.sytes.net> Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/media/dvb/frontends/dib7000p.c | 5 +++++ 1 file changed, 5 insertions(+) --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -1343,6 +1343,11 @@ struct dvb_frontend * dib7000p_attach(st if (dib7000p_identify(st) != 0) goto error; + /* FIXME: make sure the dev.parent field is initialized, or else + request_firmware() will hit an OOPS (this should be moved somewhere + more common) */ + st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; + dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); dib7000p_demod_reset(st); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [07/20] V4L/DVB (13107): tda18271: fix overflow in FM radio frequency calculation 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (5 preceding siblings ...) 2009-12-06 23:30 ` [06/20] V4L/DVB (13079): dib0700: fixed xc2028 firmware loading kernel oops Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [08/20] V4L/DVB (13109): tda18271: fix signedness issue in tda18271_rf_tracking_filters_init Greg KH ` (12 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Henk Vergonet, Michael Krufky, Mauro Carvalho Chehab [-- Attachment #1: v4l-dvb-13107-tda18271-fix-overflow-in-fm-radio-frequency-calculation.patch --] [-- Type: text/plain, Size: 1400 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Michael Krufky <mkrufky@kernellabs.com> commit 4d8317876d5f53ef792e90f89d8f162d7bca5c81 upstream. Multiplication by 62500 causes an overflow in the 32 bit freq variable, which is later divided by 1000 when using FM radio. This patch prevents the overflow by scaling the frequency value correctly upfront. Thanks to Henk Vergonet for spotting the problem and providing a preliminary patch, which this changeset was based upon. Cc: Henk Vergonet <Henk.Vergonet@gmail.com> Signed-off-by: Michael Krufky <mkrufky@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/media/common/tuners/tda18271-fe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -927,12 +927,12 @@ static int tda18271_set_analog_params(st struct tda18271_std_map_item *map; char *mode; int ret; - u32 freq = params->frequency * 62500; + u32 freq = params->frequency * 125 * + ((params->mode == V4L2_TUNER_RADIO) ? 1 : 1000) / 2; priv->mode = TDA18271_ANALOG; if (params->mode == V4L2_TUNER_RADIO) { - freq = freq / 1000; map = &std_map->fm_radio; mode = "fm"; } else if (params->std & V4L2_STD_MN) { ^ permalink raw reply [flat|nested] 21+ messages in thread
* [08/20] V4L/DVB (13109): tda18271: fix signedness issue in tda18271_rf_tracking_filters_init 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (6 preceding siblings ...) 2009-12-06 23:30 ` [07/20] V4L/DVB (13107): tda18271: fix overflow in FM radio frequency calculation Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [09/20] V4L/DVB (13190): em28xx: fix panic that can occur when starting audio streaming Greg KH ` (11 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Seth Barry, Michael Krufky, Mauro Carvalho Chehab [-- Attachment #1: v4l-dvb-13109-tda18271-fix-signedness-issue-in-tda18271_rf_tracking_filters_init.patch --] [-- Type: text/plain, Size: 2997 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Seth Barry <seth@cyberseth.com> commit a57c1dcb93e43357ed3f666e5a2b5d5071dd3930 upstream. While having tda18271 module set with debug=17 (cal & info prints) and cal=0 (delay calibration process until first use) - I discovered that during the calibration process, if the frequency test for 69750000 returned a bcal of 0 (see tda18721-fe.c in tda18271_powerscan func) that the tuner wouldn't be able to pickup any of the frequencies in the range (all the other frequencies bands returned bcal=1). I spent some time going over the code and the NXP's tda18271 spec (ver.4 of it i think) and adding a lot of debug prints and walking/stepping through the calibration process. I found that when the powerscan fails to find a frequency, the rf calibration is not run and the default value is supposed to be used in its place (pulled from the RF_CAL_map table) - but something was getting goofed up there. Now, my c coding skills are very rusty, but i think root of the problem is a signedness issue with the math operation for calculating the rf_a1 and rf_a2 values in tda18271_rf_tracking_filters_init func, which results in values like 20648 for rf_a1 (when it should probably have a value like 0, or so slightly negative that it should be zero - this bad value for rf_a1 would in turn makes the approx calc within tda18271c2_rf_tracking_filters_correction go out of whack). The simplest solution i found was to explicitly convert the signedness of the denominator to avoid the implicit conversion. The values placed into the u32 rf_freq array should never exceed about 900mhz, so i think the s32 max value shouldn't be an issue in this case. I've tested it out a little, and even when i get a bcal=0 with the modified code, the default calibration value gets used, rf_a1 is zero, and the tuner seems to lock on the stream and mythtv seems to play it fine. Signed-off-by: Seth Barry <seth@cyberseth.com> Signed-off-by: Michael Krufky <mkrufky@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/media/common/tuners/tda18271-fe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -595,13 +595,13 @@ static int tda18271_rf_tracking_filters_ case RF2: map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] - prog_cal[RF1] + prog_tab[RF1]) / - ((rf_freq[RF2] - rf_freq[RF1]) / 1000); + (s32)((rf_freq[RF2] - rf_freq[RF1]) / 1000); map[i].rf2 = rf_freq[RF2] / 1000; break; case RF3: map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] - prog_cal[RF2] + prog_tab[RF2]) / - ((rf_freq[RF3] - rf_freq[RF2]) / 1000); + (s32)((rf_freq[RF3] - rf_freq[RF2]) / 1000); map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; map[i].rf3 = rf_freq[RF3] / 1000; break; ^ permalink raw reply [flat|nested] 21+ messages in thread
* [09/20] V4L/DVB (13190): em28xx: fix panic that can occur when starting audio streaming 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (7 preceding siblings ...) 2009-12-06 23:30 ` [08/20] V4L/DVB (13109): tda18271: fix signedness issue in tda18271_rf_tracking_filters_init Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [10/20] V4L/DVB (13230): s2255drv: Dont conditionalize video buffer completion on waiting processes Greg KH ` (10 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Devin Heitmueller, Mauro Carvalho Chehab [-- Attachment #1: v4l-dvb-13190-em28xx-fix-panic-that-can-occur-when-starting-audio-streaming.patch --] [-- Type: text/plain, Size: 1270 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Devin Heitmueller <dheitmueller@kernellabs.com> commit 96fbf771d86a90ff006bc62ca4d4de6474b3de31 upstream. Because the counters were not reset when starting up streaming, they would be reused from the previous run. This can result in cases such that when the second instance of streaming starts up, the "cnt" variable in em28xx_audio_isocirq() can end up being negative, resulting in attempting to write to memory before the start of runtime->dma_area (as well as having a negative number of bytes to copy). Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/media/video/em28xx/em28xx-audio.c | 5 +++++ 1 file changed, 5 insertions(+) --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -365,6 +365,11 @@ static int snd_em28xx_hw_capture_free(st static int snd_em28xx_prepare(struct snd_pcm_substream *substream) { + struct em28xx *dev = snd_pcm_substream_chip(substream); + + dev->adev.hwptr_done_capture = 0; + dev->adev.capture_transfer_done = 0; + return 0; } ^ permalink raw reply [flat|nested] 21+ messages in thread
* [10/20] V4L/DVB (13230): s2255drv: Dont conditionalize video buffer completion on waiting processes 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (8 preceding siblings ...) 2009-12-06 23:30 ` [09/20] V4L/DVB (13190): em28xx: fix panic that can occur when starting audio streaming Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [11/20] [CPUFREQ] Enable ACPI PDC handshake for VIA/Centaur CPUs Greg KH ` (9 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Mike Isely, Mauro Carvalho Chehab [-- Attachment #1: v4l-dvb-13230-s2255drv-don-t-conditionalize-video-buffer-completion-on-waiting-processes.patch --] [-- Type: text/plain, Size: 1920 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Mike Isely <isely@pobox.com> commit 1f95725755ab67f3198df3b5bf7517f926f310ca upstream. The s2255 driver had logic which aborted processing of a video frame if there was no process waiting on the video buffer in question. That simply doesn't work when the application is doing things in an asynchronous manner. If the application went to the trouble to queue the buffer in the first place, then the driver should always attempt to complete it - even if the application at that moment has its attention turned elsewhere. Applications which always blocked waiting for I/O on the capture device would not have been affected by this. Applications which *mostly* blocked waiting for I/O on the capture device probably only would have been somewhat affected (frame lossage, at a rate which goes up as the application blocks less). Applications which never blocked on the capture device (e.g. polling only) however would never have been able to receive any video frames, since in that case this "is anyone waiting on this?" check on the buffer never would have evalutated true. This patch just deletes that harmful check against the buffer's wait queue. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/media/video/s2255drv.c | 5 ----- 1 file changed, 5 deletions(-) --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -578,11 +578,6 @@ static int s2255_got_frame(struct s2255_ buf = list_entry(dma_q->active.next, struct s2255_buffer, vb.queue); - if (!waitqueue_active(&buf->vb.done)) { - /* no one active */ - rc = -1; - goto unlock; - } list_del(&buf->vb.queue); do_gettimeofday(&buf->vb.ts); dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [11/20] [CPUFREQ] Enable ACPI PDC handshake for VIA/Centaur CPUs 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (9 preceding siblings ...) 2009-12-06 23:30 ` [10/20] V4L/DVB (13230): s2255drv: Dont conditionalize video buffer completion on waiting processes Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [12/20] fuse: reject O_DIRECT flag also in fuse_create Greg KH ` (8 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Harald Welte, Dave Jones [-- Attachment #1: enable-acpi-pdc-handshake-for-via-centaur-cpus.patch --] [-- Type: text/plain, Size: 1547 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Harald Welte <HaraldWelte@viatech.com> commit d77b81974521c82fa6fda38dfff1b491dcc62a32 upstream. In commit 0de51088e6a82bc8413d3ca9e28bbca2788b5b53, we introduced the use of acpi-cpufreq on VIA/Centaur CPU's by removing a vendor check for VENDOR_INTEL. However, as it turns out, at least the Nano CPU's also need the PDC (processor driver capabilities) handshake in order to activate the methods required for acpi-cpufreq. Since arch_acpi_processor_init_pdc() contains another vendor check for Intel, the PDC is not initialized on VIA CPU's. The resulting behavior of a current mainline kernel on such systems is: acpi-cpufreq loads and it indicates CPU frequency changes. However, the CPU stays at a single frequency This trivial patch ensures that init_intel_pdc() is called on Intel and VIA/Centaur CPU's alike. Signed-off-by: Harald Welte <HaraldWelte@viatech.com> Signed-off-by: Dave Jones <davej@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- arch/x86/kernel/acpi/processor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -78,7 +78,8 @@ void arch_acpi_processor_init_pdc(struct struct cpuinfo_x86 *c = &cpu_data(pr->id); pr->pdc = NULL; - if (c->x86_vendor == X86_VENDOR_INTEL) + if (c->x86_vendor == X86_VENDOR_INTEL || + c->x86_vendor == X86_VENDOR_CENTAUR) init_intel_pdc(pr, c); return; ^ permalink raw reply [flat|nested] 21+ messages in thread
* [12/20] fuse: reject O_DIRECT flag also in fuse_create 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (10 preceding siblings ...) 2009-12-06 23:30 ` [11/20] [CPUFREQ] Enable ACPI PDC handshake for VIA/Centaur CPUs Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [13/20] fuse: prevent fuse_put_request on invalid pointer Greg KH ` (7 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Csaba Henk, Miklos Szeredi, Harshavardhana [-- Attachment #1: fuse-reject-o_direct-flag-also-in-fuse_create.patch --] [-- Type: text/plain, Size: 1188 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Csaba Henk <csaba@gluster.com> commit 1b7323965a8c6eee9dc4e345a7ae4bff1dc93149 upstream. The comment in fuse_open about O_DIRECT: "VFS checks this, but only _after_ ->open()" also holds for fuse_create, however, the same kind of check was missing there. As an impact of this bug, open(newfile, O_RDWR|O_CREAT|O_DIRECT) fails, but a stub newfile will remain if the fuse server handled the implied FUSE_CREATE request appropriately. Other impact: in the above situation ima_file_free() will complain to open/free imbalance if CONFIG_IMA is set. Signed-off-by: Csaba Henk <csaba@gluster.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Cc: Harshavardhana <harsha@gluster.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/fuse/dir.c | 3 +++ 1 file changed, 3 insertions(+) --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -398,6 +398,9 @@ static int fuse_create_open(struct inode if (fc->no_create) return -ENOSYS; + if (flags & O_DIRECT) + return -EINVAL; + forget_req = fuse_get_req(fc); if (IS_ERR(forget_req)) return PTR_ERR(forget_req); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [13/20] fuse: prevent fuse_put_request on invalid pointer 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (11 preceding siblings ...) 2009-12-06 23:30 ` [12/20] fuse: reject O_DIRECT flag also in fuse_create Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [14/20] isdn: hfc_usb: Fix read buffer overflow Greg KH ` (6 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Anand V. Avati, Miklos Szeredi [-- Attachment #1: fuse-prevent-fuse_put_request-on-invalid-pointer.patch --] [-- Type: text/plain, Size: 908 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Anand V. Avati <avati@gluster.com> commit f60311d5f7670d9539b424e4ed8b5c0872fc9e83 upstream. fuse_direct_io() has a loop where requests are allocated in each iteration. if allocation fails, the loop is broken out and follows into an unconditional fuse_put_request() on that invalid pointer. Signed-off-by: Anand V. Avati <avati@gluster.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- fs/fuse/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1005,7 +1005,8 @@ static ssize_t fuse_direct_io(struct fil break; } } - fuse_put_request(fc, req); + if (!IS_ERR(req)) + fuse_put_request(fc, req); if (res > 0) { if (write) fuse_write_update_size(inode, pos); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [14/20] isdn: hfc_usb: Fix read buffer overflow 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (12 preceding siblings ...) 2009-12-06 23:30 ` [13/20] fuse: prevent fuse_put_request on invalid pointer Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [15/20] thinkpad-acpi: fix sign of ERESTARTSYS return Greg KH ` (5 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Roel Kluin, Karsten Keil, David S. Miller [-- Attachment #1: isdn-hfc_usb-fix-read-buffer-overflow.patch --] [-- Type: text/plain, Size: 1039 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Roel Kluin <roel.kluin@gmail.com> commit 286e633ef0ff5bb63c07b4516665da8004966fec upstream. Check whether index is within bounds before testing the element. Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Cc: Karsten Keil <isdn@linux-pingi.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/isdn/hisax/hfc_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -818,8 +818,8 @@ collect_rx_frame(usb_fifo * fifo, __u8 * } /* we have a complete hdlc packet */ if (finish) { - if ((!fifo->skbuff->data[fifo->skbuff->len - 1]) - && (fifo->skbuff->len > 3)) { + if (fifo->skbuff->len > 3 && + !fifo->skbuff->data[fifo->skbuff->len - 1]) { if (fifon == HFCUSB_D_RX) { DBG(HFCUSB_DBG_DCHANNEL, ^ permalink raw reply [flat|nested] 21+ messages in thread
* [15/20] thinkpad-acpi: fix sign of ERESTARTSYS return 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (13 preceding siblings ...) 2009-12-06 23:30 ` [14/20] isdn: hfc_usb: Fix read buffer overflow Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [16/20] USB: ohci: quirk AMD prefetch for USB 1.1 ISO transfer Greg KH ` (4 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Roel Kluin, Henrique de Moraes Holschuh, Len Brown [-- Attachment #1: thinkpad-acpi-fix-sign-of-erestartsys-return.patch --] [-- Type: text/plain, Size: 974 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Roel Kluin <roel.kluin@gmail.com> commit 80a8d1228e90349b4514e8c925c061fa5cbcea75 upstream. The returned error should be negative Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/misc/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -5042,7 +5042,7 @@ static int brightness_write(char *buf) * Doing it this way makes the syscall restartable in case of EINTR */ rc = brightness_set(level); - return (rc == -EINTR)? ERESTARTSYS : rc; + return (rc == -EINTR)? -ERESTARTSYS : rc; } static struct ibm_struct brightness_driver_data = { ^ permalink raw reply [flat|nested] 21+ messages in thread
* [16/20] USB: ohci: quirk AMD prefetch for USB 1.1 ISO transfer 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (14 preceding siblings ...) 2009-12-06 23:30 ` [15/20] thinkpad-acpi: fix sign of ERESTARTSYS return Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [17/20] USB: suspend/resume support for option driver Greg KH ` (3 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Libin Yang, David Brownell, Alan Stern [-- Attachment #1: usb-ohci-quirk-amd-prefetch-for-usb-1.1-iso-transfer.patch --] [-- Type: text/plain, Size: 4542 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Libin Yang <libin.yang@amd.com> commit a1f17a872bc7b1cb7efdd5486a2963e88a536e61 upstream. The following patch in the driver is required to avoid USB 1.1 device failures that may occur due to requests from USB OHCI controllers may be overwritten if the latency for any pending request by the USB controller is very long (in the range of milliseconds). Signed-off-by: Libin Yang <libin.yang@amd.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/usb/host/ohci-hcd.c | 5 +++++ drivers/usb/host/ohci-pci.c | 20 ++++++++++++++++++++ drivers/usb/host/ohci-q.c | 18 ++++++++++++------ drivers/usb/host/ohci.h | 9 +++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -89,6 +89,7 @@ static int ohci_restart (struct ohci_hcd #ifdef CONFIG_PCI static void quirk_amd_pll(int state); static void amd_iso_dev_put(void); +static void sb800_prefetch(struct ohci_hcd *ohci, int on); #else static inline void quirk_amd_pll(int state) { @@ -98,6 +99,10 @@ static inline void amd_iso_dev_put(void) { return; } +static inline void sb800_prefetch(struct ohci_hcd *ohci, int on) +{ + return; +} #endif --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -177,6 +177,13 @@ static int ohci_quirk_amd700(struct usb_ return 0; pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + + /* SB800 needs pre-fetch fix */ + if ((rev >= 0x40) && (rev <= 0x4f)) { + ohci->flags |= OHCI_QUIRK_AMD_PREFETCH; + ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); + } + if ((rev > 0x3b) || (rev < 0x30)) { pci_dev_put(amd_smbus_dev); amd_smbus_dev = NULL; @@ -262,6 +269,19 @@ static void amd_iso_dev_put(void) } +static void sb800_prefetch(struct ohci_hcd *ohci, int on) +{ + struct pci_dev *pdev; + u16 misc; + + pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); + pci_read_config_word(pdev, 0x50, &misc); + if (on == 0) + pci_write_config_word(pdev, 0x50, misc & 0xfcff); + else + pci_write_config_word(pdev, 0x50, misc | 0x0300); +} + /* List of quirks for OHCI */ static const struct pci_device_id ohci_pci_quirks[] = { { --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -49,9 +49,12 @@ __acquires(ohci->lock) switch (usb_pipetype (urb->pipe)) { case PIPE_ISOCHRONOUS: ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--; - if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0 - && quirk_amdiso(ohci)) - quirk_amd_pll(1); + if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) { + if (quirk_amdiso(ohci)) + quirk_amd_pll(1); + if (quirk_amdprefetch(ohci)) + sb800_prefetch(ohci, 0); + } break; case PIPE_INTERRUPT: ohci_to_hcd(ohci)->self.bandwidth_int_reqs--; @@ -680,9 +683,12 @@ static void td_submit_urb ( data + urb->iso_frame_desc [cnt].offset, urb->iso_frame_desc [cnt].length, urb, cnt); } - if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0 - && quirk_amdiso(ohci)) - quirk_amd_pll(0); + if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) { + if (quirk_amdiso(ohci)) + quirk_amd_pll(0); + if (quirk_amdprefetch(ohci)) + sb800_prefetch(ohci, 1); + } periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; break; --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -402,6 +402,7 @@ struct ohci_hcd { #define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */ #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ +#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ // there are also chip quirks/bugs in init logic struct work_struct nec_work; /* Worker for NEC quirk */ @@ -433,6 +434,10 @@ static inline int quirk_amdiso(struct oh { return ohci->flags & OHCI_QUIRK_AMD_ISO; } +static inline int quirk_amdprefetch(struct ohci_hcd *ohci) +{ + return ohci->flags & OHCI_QUIRK_AMD_PREFETCH; +} #else static inline int quirk_nec(struct ohci_hcd *ohci) { @@ -446,6 +451,10 @@ static inline int quirk_amdiso(struct oh { return 0; } +static inline int quirk_amdprefetch(struct ohci_hcd *ohci) +{ + return 0; +} #endif /* convert between an hcd pointer and the corresponding ohci_hcd */ ^ permalink raw reply [flat|nested] 21+ messages in thread
* [17/20] USB: suspend/resume support for option driver 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (15 preceding siblings ...) 2009-12-06 23:30 ` [16/20] USB: ohci: quirk AMD prefetch for USB 1.1 ISO transfer Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [18/20] USB: usb-serial: replace shutdown with disconnect, release Greg KH ` (2 subsequent siblings) 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Oliver Neukum, Matthias Urlichs [-- Attachment #1: usb-suspend-resume-support-for-option-driver.patch --] [-- Type: text/plain, Size: 4891 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Oliver Neukum <oliver@neukum.org> commit 4901b2c34ecb6fc45909228ad269c8126efe4401 upstream. This patch implements suspend and resume methods for the option driver. With my hardware I can even suspend the system and keep up a connection for a short time. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-Off-By: Matthias Urlichs <smurf@smurf.noris.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/usb/serial/option.c | 86 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 6 deletions(-) --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -62,6 +62,8 @@ static int option_tiocmget(struct tty_s static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); +static int option_suspend(struct usb_serial *serial, pm_message_t message); +static int option_resume(struct usb_serial *serial); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -511,6 +513,8 @@ static struct usb_driver option_driver = .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, .id_table = option_ids, .no_dynamic_id = 1, }; @@ -539,6 +543,8 @@ static struct usb_serial_driver option_1 .attach = option_startup, .shutdown = option_shutdown, .read_int_callback = option_instat_callback, + .suspend = option_suspend, + .resume = option_resume, }; static int debug; @@ -809,10 +815,10 @@ static void option_instat_callback(struc req_pkt->bRequestType, req_pkt->bRequest); } } else - dbg("%s: error %d", __func__, status); + err("%s: error %d", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ - if (status != -ESHUTDOWN) { + if (status != -ESHUTDOWN && status != -ENOENT) { urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) @@ -831,7 +837,6 @@ static int option_write_room(struct tty_ portdata = usb_get_serial_port_data(port); - for (i = 0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && !test_bit(i, &portdata->out_busy)) @@ -1090,14 +1095,12 @@ bail_out_error: return 1; } -static void option_shutdown(struct usb_serial *serial) +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct option_port_private *portdata; - dbg("%s", __func__); - /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -1107,6 +1110,17 @@ static void option_shutdown(struct usb_s for (j = 0; j < N_OUT_URB; j++) usb_kill_urb(portdata->out_urbs[j]); } +} + +static void option_shutdown(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct option_port_private *portdata; + + dbg("%s", __func__); + + stop_read_write_urbs(serial); /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { @@ -1137,6 +1151,66 @@ static void option_shutdown(struct usb_s } } +static int option_suspend(struct usb_serial *serial, pm_message_t message) +{ + dbg("%s entered", __func__); + stop_read_write_urbs(serial); + + return 0; +} + +static int option_resume(struct usb_serial *serial) +{ + int err, i, j; + struct usb_serial_port *port; + struct urb *urb; + struct option_port_private *portdata; + + dbg("%s entered", __func__); + /* get the interrupt URBs resubmitted unconditionally */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + if (!port->interrupt_in_urb) { + dbg("%s: No interrupt URB for port %d\n", __func__, i); + continue; + } + port->interrupt_in_urb->dev = serial->dev; + err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); + dbg("Submitted interrupt URB for port %d (result %d)", i, err); + if (err < 0) { + err("%s: Error %d for interrupt URB of port%d", + __func__, err, i); + return err; + } + } + + for (i = 0; i < serial->num_ports; i++) { + /* walk all ports */ + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + mutex_lock(&port->mutex); + + /* skip closed ports */ + if (!port->port.count) { + mutex_unlock(&port->mutex); + continue; + } + + for (j = 0; j < N_IN_URB; j++) { + urb = portdata->in_urbs[j]; + err = usb_submit_urb(urb, GFP_NOIO); + if (err < 0) { + mutex_unlock(&port->mutex); + err("%s: Error %d for bulk URB %d", + __func__, err, i); + return err; + } + } + mutex_unlock(&port->mutex); + } + return 0; +} + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [18/20] USB: usb-serial: replace shutdown with disconnect, release 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (16 preceding siblings ...) 2009-12-06 23:30 ` [17/20] USB: suspend/resume support for option driver Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [19/20] dca: redesign locks to fix deadlocks Greg KH 2009-12-06 23:30 ` [20/20] hwmon: (it87) Fix VID reading on IT8718F Greg KH 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable, Greg KH Cc: stable-review, torvalds, akpm, alan, Rory Filer, USB list, Alan Stern [-- Attachment #1: usb-usb-serial-replace-shutdown-with-disconnect-release.patch --] [-- Type: text/plain, Size: 49423 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ This is commit f9c99bb8b3a1ec81af68d484a551307326c2e933 back-ported to 2.6.27.39. This patch (as1254-2) splits up the shutdown method of usb_serial_driver into a disconnect and a release method. The problem is that the usb-serial core was calling shutdown during disconnect handling, but drivers didn't expect it to be called until after all the open file references had been closed. The result was an oops when the close method tried to use memory that had been deallocated by shutdown. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Tested-by: Rory Filer <rfiler@SierraWireless.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/usb/serial/aircable.c | 5 +-- drivers/usb/serial/belkin_sa.c | 7 ++-- drivers/usb/serial/cp2101.c | 6 ++-- drivers/usb/serial/cyberjack.c | 20 ++++++++++---- drivers/usb/serial/cypress_m8.c | 11 +++---- drivers/usb/serial/digi_acceleport.c | 20 ++++++++++---- drivers/usb/serial/empeg.c | 8 ----- drivers/usb/serial/ftdi_sio.c | 14 --------- drivers/usb/serial/garmin_gps.c | 16 +++++++++-- drivers/usb/serial/generic.c | 9 ++++-- drivers/usb/serial/io_edgeport.c | 29 ++++++++++++++------ drivers/usb/serial/io_tables.h | 12 +++++--- drivers/usb/serial/io_ti.c | 22 ++++++++++++--- drivers/usb/serial/ipaq.c | 7 ---- drivers/usb/serial/iuu_phoenix.c | 6 ++-- drivers/usb/serial/keyspan.c | 13 ++++++++- drivers/usb/serial/keyspan.h | 12 +++++--- drivers/usb/serial/keyspan_pda.c | 4 +- drivers/usb/serial/kl5kusb105.c | 39 +++++++++++++++------------ drivers/usb/serial/kobil_sct.c | 12 ++------ drivers/usb/serial/mct_u232.c | 13 +++------ drivers/usb/serial/mos7720.c | 9 ++---- drivers/usb/serial/mos7840.c | 48 ++++++++++++++++++++++++++++------ drivers/usb/serial/omninet.c | 19 ++++++++++--- drivers/usb/serial/option.c | 17 ++++++++---- drivers/usb/serial/oti6858.c | 7 ++-- drivers/usb/serial/pl2303.c | 5 +-- drivers/usb/serial/sierra.c | 28 +++++++++++++++++-- drivers/usb/serial/spcp8x5.c | 5 +-- drivers/usb/serial/ti_usb_3410_5052.c | 10 ++----- drivers/usb/serial/usb-serial.c | 29 +++++++++----------- drivers/usb/serial/visor.c | 13 +++------ drivers/usb/serial/whiteheat.c | 6 ++-- include/linux/usb/serial.h | 12 +++++--- 34 files changed, 298 insertions(+), 195 deletions(-) --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -362,7 +362,7 @@ static int aircable_attach(struct usb_se return 0; } -static void aircable_shutdown(struct usb_serial *serial) +static void aircable_release(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; @@ -373,7 +373,6 @@ static void aircable_shutdown(struct usb if (priv) { serial_buf_free(priv->tx_buf); serial_buf_free(priv->rx_buf); - usb_set_serial_port_data(port, NULL); kfree(priv); } } @@ -598,7 +597,7 @@ static struct usb_serial_driver aircable .num_ports = 1, .attach = aircable_attach, .probe = aircable_probe, - .shutdown = aircable_shutdown, + .release = aircable_release, .write = aircable_write, .write_room = aircable_write_room, .write_bulk_callback = aircable_write_bulk_callback, --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -90,7 +90,7 @@ static int debug; /* function prototypes for a Belkin USB Serial Adapter F5U103 */ static int belkin_sa_startup(struct usb_serial *serial); -static void belkin_sa_shutdown(struct usb_serial *serial); +static void belkin_sa_release(struct usb_serial *serial); static int belkin_sa_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void belkin_sa_close(struct tty_struct *tty, @@ -143,7 +143,7 @@ static struct usb_serial_driver belkin_d .tiocmget = belkin_sa_tiocmget, .tiocmset = belkin_sa_tiocmset, .attach = belkin_sa_startup, - .shutdown = belkin_sa_shutdown, + .release = belkin_sa_release, }; @@ -198,14 +198,13 @@ static int belkin_sa_startup(struct usb_ } -static void belkin_sa_shutdown(struct usb_serial *serial) +static void belkin_sa_release(struct usb_serial *serial) { struct belkin_sa_private *priv; int i; dbg("%s", __func__); - /* stop reads and writes on all ports */ for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ priv = usb_get_serial_port_data(serial->port[i]); --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -50,7 +50,7 @@ static int cp2101_tiocmset(struct tty_st unsigned int, unsigned int); static void cp2101_break_ctl(struct tty_struct *, int); static int cp2101_startup(struct usb_serial *); -static void cp2101_shutdown(struct usb_serial *); +static void cp2101_disconnect(struct usb_serial *); static int debug; @@ -125,7 +125,7 @@ static struct usb_serial_driver cp2101_d .tiocmget = cp2101_tiocmget, .tiocmset = cp2101_tiocmset, .attach = cp2101_startup, - .shutdown = cp2101_shutdown, + .disconnect = cp2101_disconnect, }; /* Config request types */ @@ -727,7 +727,7 @@ static int cp2101_startup(struct usb_ser return 0; } -static void cp2101_shutdown(struct usb_serial *serial) +static void cp2101_disconnect(struct usb_serial *serial) { int i; --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -58,7 +58,8 @@ static int debug; /* Function prototypes */ static int cyberjack_startup(struct usb_serial *serial); -static void cyberjack_shutdown(struct usb_serial *serial); +static void cyberjack_disconnect(struct usb_serial *serial); +static void cyberjack_release(struct usb_serial *serial); static int cyberjack_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void cyberjack_close(struct tty_struct *tty, @@ -95,7 +96,8 @@ static struct usb_serial_driver cyberjac .id_table = id_table, .num_ports = 1, .attach = cyberjack_startup, - .shutdown = cyberjack_shutdown, + .disconnect = cyberjack_disconnect, + .release = cyberjack_release, .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, @@ -148,17 +150,25 @@ static int cyberjack_startup(struct usb_ return 0; } -static void cyberjack_shutdown(struct usb_serial *serial) +static void cyberjack_disconnect(struct usb_serial *serial) { int i; dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) usb_kill_urb(serial->port[i]->interrupt_in_urb); +} + +static void cyberjack_release(struct usb_serial *serial) +{ + int i; + + dbg("%s", __func__); + + for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); } } --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -171,7 +171,7 @@ struct cypress_buf { static int cypress_earthmate_startup(struct usb_serial *serial); static int cypress_hidcom_startup(struct usb_serial *serial); static int cypress_ca42v2_startup(struct usb_serial *serial); -static void cypress_shutdown(struct usb_serial *serial); +static void cypress_release(struct usb_serial *serial); static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void cypress_close(struct tty_struct *tty, @@ -215,7 +215,7 @@ static struct usb_serial_driver cypress_ .id_table = id_table_earthmate, .num_ports = 1, .attach = cypress_earthmate_startup, - .shutdown = cypress_shutdown, + .release = cypress_release, .open = cypress_open, .close = cypress_close, .write = cypress_write, @@ -241,7 +241,7 @@ static struct usb_serial_driver cypress_ .id_table = id_table_cyphidcomrs232, .num_ports = 1, .attach = cypress_hidcom_startup, - .shutdown = cypress_shutdown, + .release = cypress_release, .open = cypress_open, .close = cypress_close, .write = cypress_write, @@ -267,7 +267,7 @@ static struct usb_serial_driver cypress_ .id_table = id_table_nokiaca42v2, .num_ports = 1, .attach = cypress_ca42v2_startup, - .shutdown = cypress_shutdown, + .release = cypress_release, .open = cypress_open, .close = cypress_close, .write = cypress_write, @@ -612,7 +612,7 @@ static int cypress_ca42v2_startup(struct } /* cypress_ca42v2_startup */ -static void cypress_shutdown(struct usb_serial *serial) +static void cypress_release(struct usb_serial *serial) { struct cypress_private *priv; @@ -625,7 +625,6 @@ static void cypress_shutdown(struct usb_ if (priv) { cypress_buf_free(priv->buf); kfree(priv); - usb_set_serial_port_data(serial->port[0], NULL); } } --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -460,7 +460,8 @@ static void digi_close(struct tty_struct struct file *filp); static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); -static void digi_shutdown(struct usb_serial *serial); +static void digi_disconnect(struct usb_serial *serial); +static void digi_release(struct usb_serial *serial); static void digi_read_bulk_callback(struct urb *urb); static int digi_read_inb_callback(struct urb *urb); static int digi_read_oob_callback(struct urb *urb); @@ -522,7 +523,8 @@ static struct usb_serial_driver digi_acc .tiocmget = digi_tiocmget, .tiocmset = digi_tiocmset, .attach = digi_startup, - .shutdown = digi_shutdown, + .disconnect = digi_disconnect, + .release = digi_release, }; static struct usb_serial_driver digi_acceleport_4_device = { @@ -548,7 +550,8 @@ static struct usb_serial_driver digi_acc .tiocmget = digi_tiocmget, .tiocmset = digi_tiocmset, .attach = digi_startup, - .shutdown = digi_shutdown, + .disconnect = digi_disconnect, + .release = digi_release, }; @@ -1586,16 +1589,23 @@ static int digi_startup(struct usb_seria } -static void digi_shutdown(struct usb_serial *serial) +static void digi_disconnect(struct usb_serial *serial) { int i; - dbg("digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt()); + dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt()); /* stop reads and writes on all ports */ for (i = 0; i < serial->type->num_ports + 1; i++) { usb_kill_urb(serial->port[i]->read_urb); usb_kill_urb(serial->port[i]->write_urb); } +} + + +static void digi_release(struct usb_serial *serial) +{ + int i; + dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt()); /* free the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -92,7 +92,6 @@ static int empeg_chars_in_buffer(struct static void empeg_throttle(struct tty_struct *tty); static void empeg_unthrottle(struct tty_struct *tty); static int empeg_startup(struct usb_serial *serial); -static void empeg_shutdown(struct usb_serial *serial); static void empeg_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); static void empeg_write_bulk_callback(struct urb *urb); @@ -126,7 +125,6 @@ static struct usb_serial_driver empeg_de .throttle = empeg_throttle, .unthrottle = empeg_unthrottle, .attach = empeg_startup, - .shutdown = empeg_shutdown, .set_termios = empeg_set_termios, .write = empeg_write, .write_room = empeg_write_room, @@ -429,12 +427,6 @@ static int empeg_startup(struct usb_ser } -static void empeg_shutdown(struct usb_serial *serial) -{ - dbg("%s", __func__); -} - - static void empeg_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -708,7 +708,6 @@ static const char *ftdi_chip_name[] = { /* function prototypes for a FTDI serial converter */ static int ftdi_sio_probe(struct usb_serial *serial, const struct usb_device_id *id); -static void ftdi_shutdown(struct usb_serial *serial); static int ftdi_sio_port_probe(struct usb_serial_port *port); static int ftdi_sio_port_remove(struct usb_serial_port *port); static int ftdi_open(struct tty_struct *tty, @@ -764,7 +763,6 @@ static struct usb_serial_driver ftdi_sio .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, .break_ctl = ftdi_break_ctl, - .shutdown = ftdi_shutdown, }; @@ -1442,18 +1440,6 @@ static int ftdi_mtxorb_hack_setup(struct return 0; } -/* ftdi_shutdown is called from usbserial:usb_serial_disconnect - * it is called when the usb device is disconnected - * - * usbserial:usb_serial_disconnect - * calls __serial_close for each open of the port - * shutdown is called then (ie ftdi_shutdown) - */ -static void ftdi_shutdown(struct usb_serial *serial) -{ - dbg("%s", __func__); -} - static int ftdi_sio_port_remove(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1527,7 +1527,7 @@ static int garmin_attach(struct usb_seri } -static void garmin_shutdown(struct usb_serial *serial) +static void garmin_disconnect(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); @@ -1536,8 +1536,17 @@ static void garmin_shutdown(struct usb_s usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); +} + + +static void garmin_release(struct usb_serial *serial) +{ + struct usb_serial_port *port = serial->port[0]; + struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); + + dbg("%s", __func__); + kfree(garmin_data_p); - usb_set_serial_port_data(port, NULL); } @@ -1556,7 +1565,8 @@ static struct usb_serial_driver garmin_d .throttle = garmin_throttle, .unthrottle = garmin_unthrottle, .attach = garmin_attach, - .shutdown = garmin_shutdown, + .disconnect = garmin_disconnect, + .release = garmin_release, .write = garmin_write, .write_room = garmin_write_room, .write_bulk_callback = garmin_write_bulk_callback, --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -63,7 +63,8 @@ struct usb_serial_driver usb_serial_gene .id_table = generic_device_ids, .usb_driver = &generic_driver, .num_ports = 1, - .shutdown = usb_serial_generic_shutdown, + .disconnect = usb_serial_generic_disconnect, + .release = usb_serial_generic_release, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, .resume = usb_serial_generic_resume, @@ -419,7 +420,7 @@ void usb_serial_generic_unthrottle(struc } } -void usb_serial_generic_shutdown(struct usb_serial *serial) +void usb_serial_generic_disconnect(struct usb_serial *serial) { int i; @@ -430,3 +431,7 @@ void usb_serial_generic_shutdown(struct generic_cleanup(serial->port[i]); } +void usb_serial_generic_release(struct usb_serial *serial) +{ + dbg("%s", __func__); +} --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -225,7 +225,8 @@ static int edge_tiocmget(struct tty_str static int edge_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int edge_startup(struct usb_serial *serial); -static void edge_shutdown(struct usb_serial *serial); +static void edge_disconnect(struct usb_serial *serial); +static void edge_release(struct usb_serial *serial); #include "io_tables.h" /* all of the devices that this driver supports */ @@ -3178,21 +3179,16 @@ static int edge_startup(struct usb_seria /**************************************************************************** - * edge_shutdown + * edge_disconnect * This function is called whenever the device is removed from the usb bus. ****************************************************************************/ -static void edge_shutdown(struct usb_serial *serial) +static void edge_disconnect(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - int i; dbg("%s", __func__); /* stop reads and writes on all ports */ - for (i = 0; i < serial->num_ports; ++i) { - kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); - } /* free up our endpoint stuff */ if (edge_serial->is_epic) { usb_kill_urb(edge_serial->interrupt_read_urb); @@ -3203,9 +3199,24 @@ static void edge_shutdown(struct usb_ser usb_free_urb(edge_serial->read_urb); kfree(edge_serial->bulk_in_buffer); } +} + + +/**************************************************************************** + * edge_release + * This function is called when the device structure is deallocated. + ****************************************************************************/ +static void edge_release(struct usb_serial *serial) +{ + struct edgeport_serial *edge_serial = usb_get_serial_data(serial); + int i; + + dbg("%s", __func__); + + for (i = 0; i < serial->num_ports; ++i) + kfree(usb_get_serial_port_data(serial->port[i])); kfree(edge_serial); - usb_set_serial_data(serial, NULL); } --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -117,7 +117,8 @@ static struct usb_serial_driver edgeport .throttle = edge_throttle, .unthrottle = edge_unthrottle, .attach = edge_startup, - .shutdown = edge_shutdown, + .disconnect = edge_disconnect, + .release = edge_release, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -145,7 +146,8 @@ static struct usb_serial_driver edgeport .throttle = edge_throttle, .unthrottle = edge_unthrottle, .attach = edge_startup, - .shutdown = edge_shutdown, + .disconnect = edge_disconnect, + .release = edge_release, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -173,7 +175,8 @@ static struct usb_serial_driver edgeport .throttle = edge_throttle, .unthrottle = edge_unthrottle, .attach = edge_startup, - .shutdown = edge_shutdown, + .disconnect = edge_disconnect, + .release = edge_release, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -200,7 +203,8 @@ static struct usb_serial_driver epic_dev .throttle = edge_throttle, .unthrottle = edge_unthrottle, .attach = edge_startup, - .shutdown = edge_shutdown, + .disconnect = edge_disconnect, + .release = edge_release, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2652,7 +2652,7 @@ cleanup: return -ENOMEM; } -static void edge_shutdown(struct usb_serial *serial) +static void edge_disconnect(struct usb_serial *serial) { int i; struct edgeport_port *edge_port; @@ -2662,12 +2662,22 @@ static void edge_shutdown(struct usb_ser for (i = 0; i < serial->num_ports; ++i) { edge_port = usb_get_serial_port_data(serial->port[i]); edge_remove_sysfs_attrs(edge_port->port); + } +} + +static void edge_release(struct usb_serial *serial) +{ + int i; + struct edgeport_port *edge_port; + + dbg("%s", __func__); + + for (i = 0; i < serial->num_ports; ++i) { + edge_port = usb_get_serial_port_data(serial->port[i]); edge_buf_free(edge_port->ep_out_buf); kfree(edge_port); - usb_set_serial_port_data(serial->port[i], NULL); } kfree(usb_get_serial_data(serial)); - usb_set_serial_data(serial, NULL); } @@ -2904,7 +2914,8 @@ static struct usb_serial_driver edgeport .throttle = edge_throttle, .unthrottle = edge_unthrottle, .attach = edge_startup, - .shutdown = edge_shutdown, + .disconnect = edge_disconnect, + .release = edge_release, .port_probe = edge_create_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, @@ -2933,7 +2944,8 @@ static struct usb_serial_driver edgeport .throttle = edge_throttle, .unthrottle = edge_unthrottle, .attach = edge_startup, - .shutdown = edge_shutdown, + .disconnect = edge_disconnect, + .release = edge_release, .port_probe = edge_create_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -79,7 +79,6 @@ static int ipaq_open(struct tty_struct static void ipaq_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static int ipaq_startup(struct usb_serial *serial); -static void ipaq_shutdown(struct usb_serial *serial); static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int ipaq_write_bulk(struct usb_serial_port *port, @@ -581,7 +580,6 @@ static struct usb_serial_driver ipaq_dev .open = ipaq_open, .close = ipaq_close, .attach = ipaq_startup, - .shutdown = ipaq_shutdown, .write = ipaq_write, .write_room = ipaq_write_room, .chars_in_buffer = ipaq_chars_in_buffer, @@ -957,11 +955,6 @@ static int ipaq_startup(struct usb_seria return usb_reset_configuration(serial->dev); } -static void ipaq_shutdown(struct usb_serial *serial) -{ - dbg("%s", __func__); -} - static int __init ipaq_init(void) { int retval; --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -122,8 +122,8 @@ static int iuu_startup(struct usb_serial return 0; } -/* Shutdown function */ -static void iuu_shutdown(struct usb_serial *serial) +/* Release function */ +static void iuu_release(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); @@ -1171,7 +1171,7 @@ static struct usb_serial_driver iuu_devi .tiocmget = iuu_tiocmget, .tiocmset = iuu_tiocmset, .attach = iuu_startup, - .shutdown = iuu_shutdown, + .release = iuu_release, }; static int __init iuu_init(void) --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2678,7 +2678,7 @@ static int keyspan_startup(struct usb_se return 0; } -static void keyspan_shutdown(struct usb_serial *serial) +static void keyspan_disconnect(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; @@ -2718,6 +2718,17 @@ static void keyspan_shutdown(struct usb_ usb_free_urb(p_priv->out_urbs[j]); } } +} + +static void keyspan_release(struct usb_serial *serial) +{ + int i; + struct usb_serial_port *port; + struct keyspan_serial_private *s_priv; + + dbg("%s", __func__); + + s_priv = usb_get_serial_data(serial); /* dbg("Freeing serial->private."); */ kfree(s_priv); --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,7 +42,8 @@ static void keyspan_close (struct tty_s struct usb_serial_port *port, struct file *filp); static int keyspan_startup (struct usb_serial *serial); -static void keyspan_shutdown (struct usb_serial *serial); +static void keyspan_disconnect (struct usb_serial *serial); +static void keyspan_release (struct usb_serial *serial); static int keyspan_write_room (struct tty_struct *tty); static int keyspan_write (struct tty_struct *tty, @@ -569,7 +570,8 @@ static struct usb_serial_driver keyspan_ .tiocmget = keyspan_tiocmget, .tiocmset = keyspan_tiocmset, .attach = keyspan_startup, - .shutdown = keyspan_shutdown, + .disconnect = keyspan_disconnect, + .release = keyspan_release, }; static struct usb_serial_driver keyspan_2port_device = { @@ -589,7 +591,8 @@ static struct usb_serial_driver keyspan_ .tiocmget = keyspan_tiocmget, .tiocmset = keyspan_tiocmset, .attach = keyspan_startup, - .shutdown = keyspan_shutdown, + .disconnect = keyspan_disconnect, + .release = keyspan_release, }; static struct usb_serial_driver keyspan_4port_device = { @@ -609,7 +612,8 @@ static struct usb_serial_driver keyspan_ .tiocmget = keyspan_tiocmget, .tiocmset = keyspan_tiocmset, .attach = keyspan_startup, - .shutdown = keyspan_shutdown, + .disconnect = keyspan_disconnect, + .release = keyspan_release, }; #endif --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -789,7 +789,7 @@ static int keyspan_pda_startup(struct us return 0; } -static void keyspan_pda_shutdown(struct usb_serial *serial) +static void keyspan_pda_release(struct usb_serial *serial) { dbg("%s", __func__); @@ -847,7 +847,7 @@ static struct usb_serial_driver keyspan_ .tiocmget = keyspan_pda_tiocmget, .tiocmset = keyspan_pda_tiocmset, .attach = keyspan_pda_startup, - .shutdown = keyspan_pda_shutdown, + .release = keyspan_pda_release, }; --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -73,7 +73,8 @@ static int debug; * Function prototypes */ static int klsi_105_startup(struct usb_serial *serial); -static void klsi_105_shutdown(struct usb_serial *serial); +static void klsi_105_disconnect(struct usb_serial *serial); +static void klsi_105_release(struct usb_serial *serial); static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void klsi_105_close(struct tty_struct *tty, @@ -132,7 +133,8 @@ static struct usb_serial_driver kl5kusb1 .tiocmget = klsi_105_tiocmget, .tiocmset = klsi_105_tiocmset, .attach = klsi_105_startup, - .shutdown = klsi_105_shutdown, + .disconnect = klsi_105_disconnect, + .release = klsi_105_release, .throttle = klsi_105_throttle, .unthrottle = klsi_105_unthrottle, }; @@ -314,7 +316,7 @@ err_cleanup: } /* klsi_105_startup */ -static void klsi_105_shutdown(struct usb_serial *serial) +static void klsi_105_disconnect(struct usb_serial *serial) { int i; @@ -324,33 +326,36 @@ static void klsi_105_shutdown(struct usb for (i = 0; i < serial->num_ports; ++i) { struct klsi_105_private *priv = usb_get_serial_port_data(serial->port[i]); - unsigned long flags; if (priv) { /* kill our write urb pool */ int j; struct urb **write_urbs = priv->write_urb_pool; - spin_lock_irqsave(&priv->lock, flags); for (j = 0; j < NUM_URBS; j++) { if (write_urbs[j]) { - /* FIXME - uncomment the following - * usb_kill_urb call when the host - * controllers get fixed to set - * urb->dev = NULL after the urb is - * finished. Otherwise this call - * oopses. */ - /* usb_kill_urb(write_urbs[j]); */ - kfree(write_urbs[j]->transfer_buffer); + usb_kill_urb(write_urbs[j]); usb_free_urb(write_urbs[j]); } } - spin_unlock_irqrestore(&priv->lock, flags); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); } } -} /* klsi_105_shutdown */ +} /* klsi_105_disconnect */ + + +static void klsi_105_release(struct usb_serial *serial) +{ + int i; + + dbg("%s", __func__); + + for (i = 0; i < serial->num_ports; ++i) { + struct klsi_105_private *priv = + usb_get_serial_port_data(serial->port[i]); + + kfree(priv); + } +} /* klsi_105_release */ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -69,7 +69,7 @@ static int debug; /* Function prototypes */ static int kobil_startup(struct usb_serial *serial); -static void kobil_shutdown(struct usb_serial *serial); +static void kobil_release(struct usb_serial *serial); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port, @@ -118,7 +118,7 @@ static struct usb_serial_driver kobil_de .id_table = id_table, .num_ports = 1, .attach = kobil_startup, - .shutdown = kobil_shutdown, + .release = kobil_release, .ioctl = kobil_ioctl, .set_termios = kobil_set_termios, .tiocmget = kobil_tiocmget, @@ -202,17 +202,13 @@ static int kobil_startup(struct usb_seri } -static void kobil_shutdown(struct usb_serial *serial) +static void kobil_release(struct usb_serial *serial) { int i; dbg("%s - port %d", __func__, serial->port[0]->number); - for (i = 0; i < serial->num_ports; ++i) { - while (serial->port[i]->port.count > 0) - kobil_close(NULL, serial->port[i], NULL); + for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); - } } --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -92,7 +92,7 @@ static int debug; * Function prototypes */ static int mct_u232_startup(struct usb_serial *serial); -static void mct_u232_shutdown(struct usb_serial *serial); +static void mct_u232_release(struct usb_serial *serial); static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void mct_u232_close(struct tty_struct *tty, @@ -148,7 +148,7 @@ static struct usb_serial_driver mct_u232 .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, .attach = mct_u232_startup, - .shutdown = mct_u232_shutdown, + .release = mct_u232_release, }; @@ -401,7 +401,7 @@ static int mct_u232_startup(struct usb_s } /* mct_u232_startup */ -static void mct_u232_shutdown(struct usb_serial *serial) +static void mct_u232_release(struct usb_serial *serial) { struct mct_u232_private *priv; int i; @@ -411,12 +411,9 @@ static void mct_u232_shutdown(struct usb for (i = 0; i < serial->num_ports; ++i) { /* My special items, the standard routines free my urbs */ priv = usb_get_serial_port_data(serial->port[i]); - if (priv) { - usb_set_serial_port_data(serial->port[i], NULL); - kfree(priv); - } + kfree(priv); } -} /* mct_u232_shutdown */ +} /* mct_u232_release */ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1547,19 +1547,16 @@ static int mos7720_startup(struct usb_se return 0; } -static void mos7720_shutdown(struct usb_serial *serial) +static void mos7720_release(struct usb_serial *serial) { int i; /* free private structure allocated for serial port */ - for (i = 0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); - } /* free private structure allocated for serial device */ kfree(usb_get_serial_data(serial)); - usb_set_serial_data(serial, NULL); } static struct usb_driver usb_driver = { @@ -1584,7 +1581,7 @@ static struct usb_serial_driver moschip7 .throttle = mos7720_throttle, .unthrottle = mos7720_unthrottle, .attach = mos7720_startup, - .shutdown = mos7720_shutdown, + .release = mos7720_release, .ioctl = mos7720_ioctl, .set_termios = mos7720_set_termios, .write = mos7720_write, --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2643,16 +2643,16 @@ error: } /**************************************************************************** - * mos7840_shutdown + * mos7840_disconnect * This function is called whenever the device is removed from the usb bus. ****************************************************************************/ -static void mos7840_shutdown(struct usb_serial *serial) +static void mos7840_disconnect(struct usb_serial *serial) { int i; unsigned long flags; struct moschip_port *mos7840_port; - dbg("%s \n", " shutdown :entering.........."); + dbg("%s\n", " disconnect :entering.........."); if (!serial) { dbg("%s", "Invalid Handler \n"); @@ -2670,10 +2670,41 @@ static void mos7840_shutdown(struct usb_ mos7840_port->zombie = 1; spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); usb_kill_urb(mos7840_port->control_urb); - kfree(mos7840_port->ctrl_buf); - kfree(mos7840_port->dr); - kfree(mos7840_port); - mos7840_set_port_private(serial->port[i], NULL); + } + + dbg("%s\n", "Thank u ::"); + +} + +/**************************************************************************** + * mos7840_release + * This function is called when the usb_serial structure is freed. + ****************************************************************************/ + +static void mos7840_release(struct usb_serial *serial) +{ + int i; + struct moschip_port *mos7840_port; + dbg("%s\n", " release :entering.........."); + + if (!serial) { + dbg("%s", "Invalid Handler"); + return; + } + + /* check for the ports to be closed,close the ports and disconnect */ + + /* free private structure allocated for serial port * + * stop reads and writes on all ports */ + + for (i = 0; i < serial->num_ports; ++i) { + mos7840_port = mos7840_get_port_private(serial->port[i]); + dbg("mos7840_port %d = %p", i, mos7840_port); + if (mos7840_port) { + kfree(mos7840_port->ctrl_buf); + kfree(mos7840_port->dr); + kfree(mos7840_port); + } } dbg("%s\n", "Thank u :: "); @@ -2714,7 +2745,8 @@ static struct usb_serial_driver moschip7 .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, .attach = mos7840_startup, - .shutdown = mos7840_shutdown, + .disconnect = mos7840_disconnect, + .release = mos7840_release, .read_bulk_callback = mos7840_bulk_in_callback, .read_int_callback = mos7840_interrupt_callback, }; --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -73,7 +73,8 @@ static void omninet_write_bulk_callback( static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room(struct tty_struct *tty); -static void omninet_shutdown(struct usb_serial *serial); +static void omninet_disconnect(struct usb_serial *serial); +static void omninet_release(struct usb_serial *serial); static int omninet_attach(struct usb_serial *serial); static struct usb_device_id id_table[] = { @@ -109,7 +110,8 @@ static struct usb_serial_driver zyxel_om .write_room = omninet_write_room, .read_bulk_callback = omninet_read_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback, - .shutdown = omninet_shutdown, + .disconnect = omninet_disconnect, + .release = omninet_release, }; @@ -342,13 +344,22 @@ static void omninet_write_bulk_callback( } -static void omninet_shutdown(struct usb_serial *serial) +static void omninet_disconnect(struct usb_serial *serial) { struct usb_serial_port *wport = serial->port[1]; - struct usb_serial_port *port = serial->port[0]; + dbg("%s", __func__); usb_kill_urb(wport->write_urb); +} + + +static void omninet_release(struct usb_serial *serial) +{ + struct usb_serial_port *port = serial->port[0]; + + dbg("%s", __func__); + kfree(usb_get_serial_port_data(port)); } --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -48,7 +48,8 @@ static int option_open(struct tty_struc static void option_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static int option_startup(struct usb_serial *serial); -static void option_shutdown(struct usb_serial *serial); +static void option_disconnect(struct usb_serial *serial); +static void option_release(struct usb_serial *serial); static int option_write_room(struct tty_struct *tty); static void option_instat_callback(struct urb *urb); @@ -541,7 +542,8 @@ static struct usb_serial_driver option_1 .tiocmget = option_tiocmget, .tiocmset = option_tiocmset, .attach = option_startup, - .shutdown = option_shutdown, + .disconnect = option_disconnect, + .release = option_release, .read_int_callback = option_instat_callback, .suspend = option_suspend, .resume = option_resume, @@ -1112,7 +1114,14 @@ static void stop_read_write_urbs(struct } } -static void option_shutdown(struct usb_serial *serial) +static void option_disconnect(struct usb_serial *serial) +{ + dbg("%s", __func__); + + stop_read_write_urbs(serial); +} + +static void option_release(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; @@ -1120,8 +1129,6 @@ static void option_shutdown(struct usb_s dbg("%s", __func__); - stop_read_write_urbs(serial); - /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -160,7 +160,7 @@ static int oti6858_tiocmget(struct tty_s static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int oti6858_startup(struct usb_serial *serial); -static void oti6858_shutdown(struct usb_serial *serial); +static void oti6858_release(struct usb_serial *serial); /* functions operating on buffers */ static struct oti6858_buf *oti6858_buf_alloc(unsigned int size); @@ -195,7 +195,7 @@ static struct usb_serial_driver oti6858_ .write_room = oti6858_write_room, .chars_in_buffer = oti6858_chars_in_buffer, .attach = oti6858_startup, - .shutdown = oti6858_shutdown, + .release = oti6858_release, }; struct oti6858_private { @@ -833,7 +833,7 @@ static int oti6858_ioctl(struct tty_stru } -static void oti6858_shutdown(struct usb_serial *serial) +static void oti6858_release(struct usb_serial *serial) { struct oti6858_private *priv; int i; @@ -845,7 +845,6 @@ static void oti6858_shutdown(struct usb_ if (priv) { oti6858_buf_free(priv->buf); kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); } } } --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -905,7 +905,7 @@ static void pl2303_break_ctl(struct tty_ dbg("%s - error sending break = %d", __func__, result); } -static void pl2303_shutdown(struct usb_serial *serial) +static void pl2303_release(struct usb_serial *serial) { int i; struct pl2303_private *priv; @@ -917,7 +917,6 @@ static void pl2303_shutdown(struct usb_s if (priv) { pl2303_buf_free(priv->buf); kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); } } } @@ -1145,7 +1144,7 @@ static struct usb_serial_driver pl2303_d .write_room = pl2303_write_room, .chars_in_buffer = pl2303_chars_in_buffer, .attach = pl2303_startup, - .shutdown = pl2303_shutdown, + .release = pl2303_release, }; static int __init pl2303_init(void) --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -677,7 +677,7 @@ static int sierra_startup(struct usb_ser return 0; } -static void sierra_shutdown(struct usb_serial *serial) +static void sierra_disconnect(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; @@ -696,10 +696,29 @@ static void sierra_shutdown(struct usb_s for (j = 0; j < N_IN_URB; j++) { usb_kill_urb(portdata->in_urbs[j]); usb_free_urb(portdata->in_urbs[j]); - kfree(portdata->in_buffer[j]); } + } +} + +static void sierra_release(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct sierra_port_private *portdata; + + dev_dbg(&serial->dev->dev, "%s\n", __func__); + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (!port) + continue; + portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; + + for (j = 0; j < N_IN_URB; j++) + kfree(portdata->in_buffer[j]); kfree(portdata); - usb_set_serial_port_data(port, NULL); } } @@ -721,7 +740,8 @@ static struct usb_serial_driver sierra_d .tiocmget = sierra_tiocmget, .tiocmset = sierra_tiocmset, .attach = sierra_startup, - .shutdown = sierra_shutdown, + .disconnect = sierra_disconnect, + .release = sierra_release, .read_int_callback = sierra_instat_callback, }; --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -356,7 +356,7 @@ cleanup: } /* call when the device plug out. free all the memory alloced by probe */ -static void spcp8x5_shutdown(struct usb_serial *serial) +static void spcp8x5_release(struct usb_serial *serial) { int i; struct spcp8x5_private *priv; @@ -366,7 +366,6 @@ static void spcp8x5_shutdown(struct usb_ if (priv) { free_ringbuf(priv->buf); kfree(priv); - usb_set_serial_port_data(serial->port[i] , NULL); } } } @@ -1041,7 +1040,7 @@ static struct usb_serial_driver spcp8x5_ .write_bulk_callback = spcp8x5_write_bulk_callback, .chars_in_buffer = spcp8x5_chars_in_buffer, .attach = spcp8x5_startup, - .shutdown = spcp8x5_shutdown, + .release = spcp8x5_release, }; static int __init spcp8x5_init(void) --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -148,7 +148,7 @@ struct ti_device { /* Function Declarations */ static int ti_startup(struct usb_serial *serial); -static void ti_shutdown(struct usb_serial *serial); +static void ti_release(struct usb_serial *serial); static int ti_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *file); static void ti_close(struct tty_struct *tty, struct usb_serial_port *port, @@ -271,7 +271,7 @@ static struct usb_serial_driver ti_1port .id_table = ti_id_table_3410, .num_ports = 1, .attach = ti_startup, - .shutdown = ti_shutdown, + .release = ti_release, .open = ti_open, .close = ti_close, .write = ti_write, @@ -299,7 +299,7 @@ static struct usb_serial_driver ti_2port .id_table = ti_id_table_5052, .num_ports = 2, .attach = ti_startup, - .shutdown = ti_shutdown, + .release = ti_release, .open = ti_open, .close = ti_close, .write = ti_write, @@ -506,7 +506,7 @@ free_tdev: } -static void ti_shutdown(struct usb_serial *serial) +static void ti_release(struct usb_serial *serial) { int i; struct ti_device *tdev = usb_get_serial_data(serial); @@ -519,12 +519,10 @@ static void ti_shutdown(struct usb_seria if (tport) { ti_buf_free(tport->tp_write_buf); kfree(tport); - usb_set_serial_port_data(serial->port[i], NULL); } } kfree(tdev); - usb_set_serial_data(serial, NULL); } --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -140,6 +140,14 @@ static void destroy_serial(struct kref * if (serial->minor != SERIAL_TTY_NO_MINOR) return_serial(serial); + serial->type->release(serial); + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (port) + put_device(&port->dev); + } + /* If this is a "fake" port, we have to clean it up here, as it will * not get cleaned up in port_release() as it was never registered with * the driver core */ @@ -147,9 +155,8 @@ static void destroy_serial(struct kref * for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { port = serial->port[i]; - if (!port) - continue; - port_free(port); + if (port) + port_free(port); } } @@ -1061,10 +1068,6 @@ void usb_serial_disconnect(struct usb_in serial->disconnected = 1; mutex_unlock(&serial->disc_mutex); - /* Unfortunately, many of the sub-drivers expect the port structures - * to exist when their shutdown method is called, so we have to go - * through this awkward two-step unregistration procedure. - */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) { @@ -1075,14 +1078,7 @@ void usb_serial_disconnect(struct usb_in device_del(&port->dev); } } - serial->type->shutdown(serial); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (port) { - put_device(&port->dev); - serial->port[i] = NULL; - } - } + serial->type->disconnect(serial); /* let the last holder of this object * cause it to be cleaned up */ @@ -1246,7 +1242,8 @@ static void fixup_generic(struct usb_ser set_to_generic_if_null(device, chars_in_buffer); set_to_generic_if_null(device, read_bulk_callback); set_to_generic_if_null(device, write_bulk_callback); - set_to_generic_if_null(device, shutdown); + set_to_generic_if_null(device, disconnect); + set_to_generic_if_null(device, release); set_to_generic_if_null(device, resume); } --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -48,7 +48,7 @@ static void visor_unthrottle(struct tty_ static int visor_probe(struct usb_serial *serial, const struct usb_device_id *id); static int visor_calc_num_ports(struct usb_serial *serial); -static void visor_shutdown(struct usb_serial *serial); +static void visor_release(struct usb_serial *serial); static void visor_write_bulk_callback(struct urb *urb); static void visor_read_bulk_callback(struct urb *urb); static void visor_read_int_callback(struct urb *urb); @@ -203,7 +203,7 @@ static struct usb_serial_driver handspri .attach = treo_attach, .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, - .shutdown = visor_shutdown, + .release = visor_release, .write = visor_write, .write_room = visor_write_room, .write_bulk_callback = visor_write_bulk_callback, @@ -228,7 +228,7 @@ static struct usb_serial_driver clie_5_d .attach = clie_5_attach, .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, - .shutdown = visor_shutdown, + .release = visor_release, .write = visor_write, .write_room = visor_write_room, .write_bulk_callback = visor_write_bulk_callback, @@ -916,7 +916,7 @@ static int clie_5_attach(struct usb_seri return generic_startup(serial); } -static void visor_shutdown(struct usb_serial *serial) +static void visor_release(struct usb_serial *serial) { struct visor_private *priv; int i; @@ -925,10 +925,7 @@ static void visor_shutdown(struct usb_se for (i = 0; i < serial->num_ports; i++) { priv = usb_get_serial_port_data(serial->port[i]); - if (priv) { - usb_set_serial_port_data(serial->port[i], NULL); - kfree(priv); - } + kfree(priv); } } --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -144,7 +144,7 @@ static int whiteheat_firmware_attach(st /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_attach(struct usb_serial *serial); -static void whiteheat_shutdown(struct usb_serial *serial); +static void whiteheat_release(struct usb_serial *serial); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void whiteheat_close(struct tty_struct *tty, @@ -190,7 +190,7 @@ static struct usb_serial_driver whitehea .id_table = id_table_std, .num_ports = 4, .attach = whiteheat_attach, - .shutdown = whiteheat_shutdown, + .release = whiteheat_release, .open = whiteheat_open, .close = whiteheat_close, .write = whiteheat_write, @@ -600,7 +600,7 @@ no_command_buffer: } -static void whiteheat_shutdown(struct usb_serial *serial) +static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; struct usb_serial_port *port; --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -177,8 +177,10 @@ static inline void usb_set_serial_data(s * This will be called when the struct usb_serial structure is fully set * set up. Do any local initialization of the device, or any private * memory structure allocation at this point in time. - * @shutdown: pointer to the driver's shutdown function. This will be - * called when the device is removed from the system. + * @disconnect: pointer to the driver's disconnect function. This will be + * called when the device is unplugged or unbound from the driver. + * @release: pointer to the driver's release function. This will be called + * when the usb_serial data structure is about to be destroyed. * @usb_driver: pointer to the struct usb_driver that controls this * device. This is necessary to allow dynamic ids to be added to * the driver from sysfs. @@ -208,7 +210,8 @@ struct usb_serial_driver { int (*attach)(struct usb_serial *serial); int (*calc_num_ports) (struct usb_serial *serial); - void (*shutdown)(struct usb_serial *serial); + void (*disconnect)(struct usb_serial *serial); + void (*release)(struct usb_serial *serial); int (*port_probe)(struct usb_serial_port *port); int (*port_remove)(struct usb_serial_port *port); @@ -288,7 +291,8 @@ extern void usb_serial_generic_read_bulk extern void usb_serial_generic_write_bulk_callback(struct urb *urb); extern void usb_serial_generic_throttle(struct tty_struct *tty); extern void usb_serial_generic_unthrottle(struct tty_struct *tty); -extern void usb_serial_generic_shutdown(struct usb_serial *serial); +extern void usb_serial_generic_disconnect(struct usb_serial *serial); +extern void usb_serial_generic_release(struct usb_serial *serial); extern int usb_serial_generic_register(int debug); extern void usb_serial_generic_deregister(void); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [19/20] dca: redesign locks to fix deadlocks 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (17 preceding siblings ...) 2009-12-06 23:30 ` [18/20] USB: usb-serial: replace shutdown with disconnect, release Greg KH @ 2009-12-06 23:30 ` Greg KH 2009-12-06 23:30 ` [20/20] hwmon: (it87) Fix VID reading on IT8718F Greg KH 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Maciej Sosnowski, Jeff Kirsher, David S. Miller [-- Attachment #1: dca-redesign-locks-to-fix-deadlocks.patch --] [-- Type: text/plain, Size: 4160 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Maciej Sosnowski <maciej.sosnowski@intel.com> commit eb4400e3a040b90a3ad805b01fcbc99a5f615c8f upstream. Change spin_locks to irqsave to prevent dead-locks. Protect adding and deleting to/from dca_providers list. Drop the lock during dca_sysfs_add_req() and dca_sysfs_remove_req() calls as they might sleep (use GFP_KERNEL allocation). Signed-off-by: Maciej Sosnowski <maciej.sosnowski@intel.com> Acked-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/dca/dca-core.c | 51 +++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -28,7 +28,7 @@ #include <linux/device.h> #include <linux/dca.h> -#define DCA_VERSION "1.4" +#define DCA_VERSION "1.8" MODULE_VERSION(DCA_VERSION); MODULE_LICENSE("GPL"); @@ -60,16 +60,17 @@ int dca_add_requester(struct device *dev { struct dca_provider *dca; int err, slot = -ENODEV; + unsigned long flags; if (!dev) return -EFAULT; - spin_lock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); /* check if the requester has not been added already */ dca = dca_find_provider_by_dev(dev); if (dca) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return -EEXIST; } @@ -78,19 +79,21 @@ int dca_add_requester(struct device *dev if (slot >= 0) break; } - if (slot < 0) { - spin_unlock(&dca_lock); + + spin_unlock_irqrestore(&dca_lock, flags); + + if (slot < 0) return slot; - } err = dca_sysfs_add_req(dca, dev, slot); if (err) { - dca->ops->remove_requester(dca, dev); - spin_unlock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); + if (dca == dca_find_provider_by_dev(dev)) + dca->ops->remove_requester(dca, dev); + spin_unlock_irqrestore(&dca_lock, flags); return err; } - spin_unlock(&dca_lock); return 0; } EXPORT_SYMBOL_GPL(dca_add_requester); @@ -103,25 +106,25 @@ int dca_remove_requester(struct device * { struct dca_provider *dca; int slot; + unsigned long flags; if (!dev) return -EFAULT; - spin_lock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); dca = dca_find_provider_by_dev(dev); if (!dca) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } slot = dca->ops->remove_requester(dca, dev); - if (slot < 0) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); + + if (slot < 0) return slot; - } dca_sysfs_remove_req(dca, slot); - spin_unlock(&dca_lock); return 0; } EXPORT_SYMBOL_GPL(dca_remove_requester); @@ -135,17 +138,18 @@ u8 dca_common_get_tag(struct device *dev { struct dca_provider *dca; u8 tag; + unsigned long flags; - spin_lock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); dca = dca_find_provider_by_dev(dev); if (!dca) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } tag = dca->ops->get_tag(dca, dev, cpu); - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return tag; } @@ -217,11 +221,16 @@ static BLOCKING_NOTIFIER_HEAD(dca_provid int register_dca_provider(struct dca_provider *dca, struct device *dev) { int err; + unsigned long flags; err = dca_sysfs_add_provider(dca, dev); if (err) return err; + + spin_lock_irqsave(&dca_lock, flags); list_add(&dca->node, &dca_providers); + spin_unlock_irqrestore(&dca_lock, flags); + blocking_notifier_call_chain(&dca_provider_chain, DCA_PROVIDER_ADD, NULL); return 0; @@ -234,9 +243,15 @@ EXPORT_SYMBOL_GPL(register_dca_provider) */ void unregister_dca_provider(struct dca_provider *dca) { + unsigned long flags; + blocking_notifier_call_chain(&dca_provider_chain, DCA_PROVIDER_REMOVE, NULL); + + spin_lock_irqsave(&dca_lock, flags); list_del(&dca->node); + spin_unlock_irqrestore(&dca_lock, flags); + dca_sysfs_remove_provider(dca); } EXPORT_SYMBOL_GPL(unregister_dca_provider); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [20/20] hwmon: (it87) Fix VID reading on IT8718F 2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH ` (18 preceding siblings ...) 2009-12-06 23:30 ` [19/20] dca: redesign locks to fix deadlocks Greg KH @ 2009-12-06 23:30 ` Greg KH 19 siblings, 0 replies; 21+ messages in thread From: Greg KH @ 2009-12-06 23:30 UTC (permalink / raw) To: linux-kernel, stable Cc: stable-review, torvalds, akpm, alan, Willy Tarreau, Jean Delvare [-- Attachment #1: hwmon-it87-fix-vid-reading-on-it8718f.patch --] [-- Type: text/plain, Size: 852 bytes --] 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Jean Delvare <khali@linux-fr.org> commit 371dc4a6d8c3c74a9a1c74b87c2affb3fcef6500 upstream Comparing apples to bananas doesn't seem right. The bug has been there since support for the IT8718F was added, so VID never worked for this chip. Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/hwmon/it87.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -1017,7 +1017,7 @@ static int __init it87_find(unsigned sho int reg; superio_select(GPIO); - if (chip_type == it8718) + if (sio_data->type == it8718) sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); reg = superio_inb(IT87_SIO_PINX2_REG); ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2009-12-06 23:42 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20091206233032.387950574@mini.kroah.org>
2009-12-06 23:37 ` [00/20] 2.6.27.40-stable review Greg KH
2009-12-06 23:30 ` [01/20] ALSA: AACI: fix AC97 multiple-open bug Greg KH
2009-12-06 23:30 ` [02/20] ALSA: AACI: fix recording bug Greg KH
2009-12-06 23:30 ` [03/20] ALSA: usb-audio: fix combine_word problem Greg KH
2009-12-06 23:30 ` [04/20] [SCSI] gdth: Prevent negative offsets in ioctl CVE-2009-3080 Greg KH
2009-12-06 23:30 ` [05/20] jffs2: Fix memory corruption in jffs2_read_inode_range() Greg KH
2009-12-06 23:30 ` [06/20] V4L/DVB (13079): dib0700: fixed xc2028 firmware loading kernel oops Greg KH
2009-12-06 23:30 ` [07/20] V4L/DVB (13107): tda18271: fix overflow in FM radio frequency calculation Greg KH
2009-12-06 23:30 ` [08/20] V4L/DVB (13109): tda18271: fix signedness issue in tda18271_rf_tracking_filters_init Greg KH
2009-12-06 23:30 ` [09/20] V4L/DVB (13190): em28xx: fix panic that can occur when starting audio streaming Greg KH
2009-12-06 23:30 ` [10/20] V4L/DVB (13230): s2255drv: Dont conditionalize video buffer completion on waiting processes Greg KH
2009-12-06 23:30 ` [11/20] [CPUFREQ] Enable ACPI PDC handshake for VIA/Centaur CPUs Greg KH
2009-12-06 23:30 ` [12/20] fuse: reject O_DIRECT flag also in fuse_create Greg KH
2009-12-06 23:30 ` [13/20] fuse: prevent fuse_put_request on invalid pointer Greg KH
2009-12-06 23:30 ` [14/20] isdn: hfc_usb: Fix read buffer overflow Greg KH
2009-12-06 23:30 ` [15/20] thinkpad-acpi: fix sign of ERESTARTSYS return Greg KH
2009-12-06 23:30 ` [16/20] USB: ohci: quirk AMD prefetch for USB 1.1 ISO transfer Greg KH
2009-12-06 23:30 ` [17/20] USB: suspend/resume support for option driver Greg KH
2009-12-06 23:30 ` [18/20] USB: usb-serial: replace shutdown with disconnect, release Greg KH
2009-12-06 23:30 ` [19/20] dca: redesign locks to fix deadlocks Greg KH
2009-12-06 23:30 ` [20/20] hwmon: (it87) Fix VID reading on IT8718F Greg KH
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox