On Mon, 2011-06-13 at 21:02 +0200, Kay Sievers wrote: > We follow GET_EVENT_STATUS_NOTIFICATION now. Can't we always force TUR > when we open() the device from userland? That's what we did in the > past, didn't we? The in-kernel polling would still not need to do > that, and the periodic usespace polling is about to die pretty soon. After the long discussion today between Tejun and me, something like this *could* work. A patch with printk() debug output is below. Every open() from userland does: GET_EVENT_STATUS_NOTIFICATION and TUR. If the both results disagree 8 times in a row, we will only look at the TUR results in the future. With this I get in dmesg: scsi 8:0:0:1: CD-ROM SanDisk U3 Cruzer Micro 8.02 PQ: 0 ANSI: 0 sr1: scsi3-mmc drive: 48x/48x tray sr 8:0:0:1: Attached scsi CD-ROM sr1 sr 8:0:0:1: Attached scsi generic sg3 type 5 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 1 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 2 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 3 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 4 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 5 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 6 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 7 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 8 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 9 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, ignoring all future GET_EVENT_STATUS_NOTIFICATION The in-kernel polling will still create a media change event every poll interval. The rest seems to work as expected. The other properly working devices I tried fail with the very first TUR <-> GET_EVENT check for some reason: scsi 7:0:0:0: CD-ROM TSSTcorp CDDVDW SE-S084B TS01 PQ: 0 ANSI: 0 sr2: scsi3-mmc drive: 8x/24x writer dvd-ram cd/rw xa/form2 cdda tray sr 7:0:0:0: Attached scsi CD-ROM sr2 sr 7:0:0:0: Attached scsi generic sg4 type 5 sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, last_present 1 <-> cd->media_present 1, count 1 sr: GET_EVENT_STATUS_NOTIFICATION == TUR, clear mismatch count 1 Everything thing else seems to work fine. Kay --- diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 4778e27..9023e1d 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -229,6 +229,15 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi, if (!(clearing & DISK_EVENT_MEDIA_CHANGE)) goto skip_tur; + /* + * earlier GET_EVENT_STATUS_NOTIFICATION and TUR did not agree + * for a couple of times in a row, we rely on TUR only for this + * likely broken device, to prevent generating incorrect media + * changed events for every open() + */ + if (cd->ignore_get_event) + events = 0; + /* let's see whether the media is there with TUR */ last_present = cd->media_present; ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); @@ -241,8 +250,22 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi, cd->media_present = scsi_status_is_good(ret) || (scsi_sense_valid(&sshdr) && sshdr.asc != 0x3a); - if (last_present != cd->media_present) + if (last_present != cd->media_present) { events |= DISK_EVENT_MEDIA_CHANGE; + } else if (events & DISK_EVENT_MEDIA_CHANGE) { + cd->tur_mismatch++; + printk("sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, " + "last_present %i <-> cd->media_present %i, count %i\n", last_present, cd->media_present, cd->tur_mismatch); + if (cd->tur_mismatch > 8) { + printk("sr: GET_EVENT_STATUS_NOTIFICATION but TUR unchanged, " + "ignoring all future GET_EVENT_STATUS_NOTIFICATION\n"); + cd->ignore_get_event = true; + } + } else if (cd->tur_mismatch) { + printk("sr: GET_EVENT_STATUS_NOTIFICATION == TUR, " + "clear mismatch count %i\n", cd->tur_mismatch); + cd->tur_mismatch = 0; + } skip_tur: if (cd->device->changed) { events |= DISK_EVENT_MEDIA_CHANGE; diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index e036f1d..94a3215 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -41,6 +41,8 @@ typedef struct scsi_cd { unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ unsigned readcd_cdda:1; /* reading audio data using READ_CD */ unsigned media_present:1; /* media is present */ + unsigned ignore_get_event:1; /* get_event is unreliable, use TUR */ + int tur_mismatch; /* nr of get_event TUR mismatches */ struct cdrom_device_info cdi; /* We hold gendisk and scsi_device references on probe and use * the refs on this kref to decide when to release them */ -- To unsubscribe from this list: send the line "unsubscribe linux-hotplug" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html