Skip to contentSkip to conversation

dc395x: can't write to tape

PATCH In review Andrew Schulman 3 participants 17 messages Jan 6, 2005 – Feb 23, 2005

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

I have a Travan NS-20 tape drive connected to a Tekram DC395UW controller. Both have worked without trouble for years. My kernel is 2.6.7, and I use the dc395x driver (built as a module) from the kernel source.

Since about a month ago, I can't write a tar archive to tape. The operation aborts before completion:

# tar -vv --one-file-system --file=/dev/st0 --create / /boot /home
tar: Removing leading `/' from member names
tar: /dev/st0: Wrote only 0 of 10240 bytes
tar: Error is not recoverable: exiting now

I've cleaned the drive with the approved head cleaner, tried three different tapes, and retensioned each tape before writing. Still no joy. I haven't rebuilt my kernel since the problem started, so it seems likely to be a hardware problem.

/var/log/kern.log says

Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info fld=0x67, 
Current st0: sense = f0  4
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98
Jan  5 22:50:18 helium kernel: Raw sense data:0xf0 0x00 0x04 0x00 0x00 0x00 
0x67 0x0a 0x00 0x00 0x00 0x00 0x80 0x98 0x00 0x00 0x00 0x00
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Current st0: sense 
= 70  4
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98
Jan  5 22:50:18 helium kernel: Raw sense data:0x70 0x00 0x04 0x00 0x00 0x00 
0x00 0x0a 0x00 0x00 0x00 0x00 0x80 0x98 0x00 0x00 0x00 0x00
Jan  5 22:50:18 helium kernel: st0: Error on write filemark.
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info 
fld=0xffffff63, Current st0: sense = f0  4
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98
Jan  5 22:50:18 helium kernel: Raw sense data:0xf0 0x00 0x04 0xff 0xff 0xff 

0x63 0x0a 0x00 0x00 0x00 0x00 0x80 0x98 0x00 0x00 0x00 0x00

Question: from this log output, can anyone tell if my problem is more likely in the controller, or in the tape drive? I realize there's not a lot of data there... unfortunately even that doesn't mean anything to me.

To get more information, I uncommented

#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)

in drivers/scsi/dc395x.c, rebuilt and reinserted the module, and tried to tar again. But this resulted in multi-GB log files, so if there's a smaller subset of debug options that would be useful, please let me know and I'll try again.

I'd like very much to keep using this tape drive for several more years. It's noisy and slow, but 10 GB/tape still isn't bad, and to replace the drive and 6 tapes would cost around $400, even today.

OTOH, SCSI cards are cheap and I wouldn't mind junking my old DC395 if it's at fault.

Thanks in advance for any light you can shed.
Andrew.

#1 lore raw

Hi

Quoted 12 lines · Andrew Schulman

I have a Travan NS-20 tape drive connected to a Tekram DC395UW controller. Both have worked without trouble for years. My kernel is 2.6.7, and I use the dc395x driver (built as a module) from the kernel source.

Since about a month ago, I can't write a tar archive to tape. The operation aborts before completion:

# tar -vv --one-file-system --file=/dev/st0 --create / /boot /home
tar: Removing leading `/' from member names
tar: /dev/st0: Wrote only 0 of 10240 bytes
tar: Error is not recoverable: exiting now
Quoted 8 lines

I've cleaned the drive with the approved head cleaner, tried three different tapes, and retensioned each tape before writing. Still no joy. I haven't rebuilt my kernel since the problem started, so it seems likely to be a hardware problem.

/var/log/kern.log says

Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed

This doesn't look good. However, after a brief look at the code, I cannot say what exactly went wrong there. Jamie?

Quoted 2 lines
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info fld=0x67, 

Current st0: sense = f0 4

Sense key 4 - hardware error.

Quoted 1 line
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98

Additional sense code 0x80 - vendor specific.

So, the sense codes indicate a hardware problem on the tape drive, but the first message might mean a software bug. You don't have highmem on that machine (> 1GB RAM), do you?

Regards
Guennadi

Quoted 34 lines
Jan  5 22:50:18 helium kernel: Raw sense data:0xf0 0x00 0x04 0x00 0x00 0x00 
0x67 0x0a 0x00 0x00 0x00 0x00 0x80 0x98 0x00 0x00 0x00 0x00
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Current st0: sense 
= 70  4
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98
Jan  5 22:50:18 helium kernel: Raw sense data:0x70 0x00 0x04 0x00 0x00 0x00 
0x00 0x0a 0x00 0x00 0x00 0x00 0x80 0x98 0x00 0x00 0x00 0x00
Jan  5 22:50:18 helium kernel: st0: Error on write filemark.
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info 
fld=0xffffff63, Current st0: sense = f0  4
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98
Jan  5 22:50:18 helium kernel: Raw sense data:0xf0 0x00 0x04 0xff 0xff 0xff 

0x63 0x0a 0x00 0x00 0x00 0x00 0x80 0x98 0x00 0x00 0x00 0x00

Question: from this log output, can anyone tell if my problem is more likely in the controller, or in the tape drive? I realize there's not a lot of data there... unfortunately even that doesn't mean anything to me.

To get more information, I uncommented

#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)

in drivers/scsi/dc395x.c, rebuilt and reinserted the module, and tried to tar again. But this resulted in multi-GB log files, so if there's a smaller subset of debug options that would be useful, please let me know and I'll try again.

I'd like very much to keep using this tape drive for several more years. It's noisy and slow, but 10 GB/tape still isn't bad, and to replace the drive and 6 tapes would cost around $400, even today.

OTOH, SCSI cards are cheap and I wouldn't mind junking my old DC395 if it's at fault.

Quoted 7 lines

Thanks in advance for any light you can shed.
Andrew.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

---
Guennadi Liakhovetski

#2 lore raw
Quoted 4 lines
Quoted 1 line
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed

This doesn't look good. However, after a brief look at the code, I cannot say what exactly went wrong there. Jamie?

I didn't mention it before, but I've gotten that particular message for a long time, even when the tape drive used to work. I reported on it several months ago on this list
(http://marc.theaimsgroup.com/?l=linux-scsi&m=108039964822342&w=2) in connection with a balky CD burner, which I've since junked. After some work and upgrading my kernel, I got the CD burner working again, but the flood of sg_to_virt failed messages continued. Jaime finally recommended that I just disable them, which I did until I got rid of the CD burner. Maybe relevant...

Quoted 5 lines
Quoted 2 lines
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info fld=0x67,

Current st0: sense = f0 4

Sense key 4 - hardware error.

Quoted 7 lines
Quoted 1 line
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98

Additional sense code 0x80 - vendor specific.

So, the sense codes indicate a hardware problem on the tape drive, but the first message might mean a software bug. You don't have highmem on that machine (> 1GB RAM), do you?

CONFIG_HIGHMEM4G is enabled in the kernel, and I have 1 GiB of RAM.

Thanks,
Andrew.

#3 lore raw
Quoted 5 lines · Andrew Schulman
Quoted 4 lines
Quoted 1 line
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed

This doesn't look good. However, after a brief look at the code, I cannot say what exactly went wrong there. Jamie?

Quoted 9 lines

I didn't mention it before, but I've gotten that particular message for a long time, even when the tape drive used to work. I reported on it several months ago on this list
(http://marc.theaimsgroup.com/?l=linux-scsi&m=108039964822342&w=2) in connection with a balky CD burner, which I've since junked. After some work and upgrading my kernel, I got the CD burner working again, but the flood of sg_to_virt failed messages continued. Jaime finally recommended that I just disable them, which I did until I got rid of the CD burner. Maybe relevant...

Could you try disabling highmem either try a kernel without highmem support, or boot with mem=900M, or remove a part of your RAM (if you don't have to saw your RAMs for that:-)), maybe, booting with highmem=0, or with nohighio.

Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info fld=0x67,

Current st0: sense = f0 4

Sense key 4 - hardware error.

Quoted 1 line
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98
Quoted 7 lines
Quoted 5 lines

Additional sense code 0x80 - vendor specific.

So, the sense codes indicate a hardware problem on the tape drive, but the first message might mean a software bug. You don't have highmem on that machine (> 1GB RAM), do you?

CONFIG_HIGHMEM4G is enabled in the kernel, and I have 1 GiB of RAM.

Yeah, that should have been >= 1G. So, at least the message could indicate a bug in highmem support in the driver.

Still, your tape problem seems to be unrelated. Do you have a chance to test it in another system / with another controller?

Thanks
Guennadi
---
Guennadi Liakhovetski

#4 lore raw
Quoted 4 lines · Guennadi Liakhovetski
Quoted 1 line · Andrew Schulman
Quoted 1 line
Quoted 1 line
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 2 lines
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info fld=0x67,

Current st0: sense = f0 4

Sense key 4 - hardware error.

Quoted 1 line
Jan  5 22:50:18 helium kernel: ASC=80 ASCQ=98

Additional sense code 0x80 - vendor specific.

Ok. My interpretation of the errors you see is 1) the dc395x driver is buggy for highmem, and 2) your tape drive has a problem. For the first problem I _could_ try to fix it, however, this will take some time. Unless somebody more skilled does it faster and better than I, I will start slowly fixing it, but it will take some time. And, although I do have a dc-315 adapter, I don't have highmem (would just booting with highmem=64M allow me to test it? Oh, I can check it - will just try it and see if I now get the same error messages), so, would be good if you, Andrew, could test my results, when I am ready (could be a couple of months:-))? I'll mail you then.

Thanks
Guennadi
---
Guennadi Liakhovetski

#5 lore raw
In reply to Guennadi Liakhovetski
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
Quoted 2 lines
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt

failed

This doesn't look good. However, after a brief look at the code, I cannot say what exactly went wrong there. Jamie?

Quoted 7 lines
Quoted 2 lines

I didn't mention it before, but I've gotten that particular message for a long time, even when the tape drive used to work.

Could you try disabling highmem either try a kernel without highmem support, or boot with mem=900M, or remove a part of your RAM (if you don't have to saw your RAMs for that:-)), maybe, booting with highmem=0, or with nohighio.

Okay, I finally got to this. Rebooted with mem=900M. Unfortunately tar fails as before:

tar: /dev/st0: Wrote only 0 of 10240 bytes
tar: Error is not recoverable: exiting now

I had rebuilt dc395x with

#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)

uncommented in dc395x.c. Here's what I got:

# tail -40 /var/log/kern.log
Jan 11 06:29:18 helium kernel: dc395x: srb_done: (pid#4596449) <02-0>
Jan 11 06:29:18 helium kernel: dc395x: srb_done: srb=f6aa2eec sg=0(0/1) 
buf=e7c64000 addr=e7c64000
Jan 11 06:29:18 helium kernel: dc395x: srb_done: AUTO_REQSENSE1
Jan 11 06:29:18 helium kernel: dc395x: pci_unmap_srb_sense: buffer=12a69452
Jan 11 06:29:18 helium kernel: dc395x: ReqSense: MEDIUM_ERROR cmnd=0x10 <02-0> 
stat=0 scan=1 sense=0x03 ASC=0x0c ASCQ=0x00 (0x00000000 0x00000000)
Jan 11 06:29:18 helium kernel: dc395x: srb_done: AUTO_REQSENSE2
Jan 11 06:29:18 helium kernel: dc395x: srb_going_remove: (pid#4596449) <02-0> 
srb=f6aa2eec
Jan 11 06:29:18 helium kernel: dc395x: srb_done: (pid#4596449) done 
result=0x08000002
Jan 11 06:29:18 helium kernel: dc395x: srb_free_insert: srb=f6aa2eec
Jan 11 06:29:18 helium kernel: st0: Error with sense data: Current st0: sense 
= 70  3
Jan 11 06:29:18 helium kernel: ASC= c ASCQ= 0
Jan 11 06:29:18 helium kernel: Raw sense data:0x70 0x00 0x03 0x00 0x00 0x00 
0x00 0x0a 0x00 0x00 0x00 0x00 0x0c 0x00 0x00 0x00 0x00 0x00
Jan 11 06:29:18 helium kernel: st0: Error on write filemark.
Jan 11 06:29:18 helium kernel: dc395x: queue_command: (pid#4596450) <02-0> 
cmnd=0x01
Jan 11 06:29:18 helium kernel: dc395x: srb_get_free: srb=f6aa2f2c
Jan 11 06:29:18 helium kernel: dc395x: build_srb: (pid#4596450) <02-0>
Jan 11 06:29:18 helium kernel: dc395x: build_srb: [0] len=0 buf=e7c64000 
use_sg=0 !MAP=277c0000
Jan 11 06:29:18 helium kernel: dc395x: start_scsi: (pid#4596450) <02-0> 
srb=f6aa2f2c
Jan 11 06:29:18 helium kernel: dc395x: srb_going_append: (pid#4596450) <02-0> 
srb=f6aa2f2c
Jan 11 06:29:18 helium kernel: dc395x: queue_command: (pid#4596450) done
Jan 11 06:29:18 helium kernel: dc395x: msgin_phase1: (pid#4596450)
Jan 11 06:29:18 helium kernel: dc395x: msgin_phase0: (pid#4596450)
Jan 11 06:29:18 helium kernel: dc395x: msgin_phase0: (pid#4596450) SAVE 
POINTER rem=0 Ignore
Jan 11 06:29:18 helium kernel: dc395x: msgin_phase1: (pid#4596450)
Jan 11 06:29:18 helium kernel: dc395x: msgin_phase0: (pid#4596450)
Jan 11 06:29:18 helium kernel: dc395x: disconnect: (pid#4596450)
Jan 11 06:30:41 helium kernel: dc395x: reselect: acb=f6aa21e4
Jan 11 06:30:41 helium kernel: dc395x: reselect: select <2>
Jan 11 06:30:41 helium kernel: dc395x: status_phase1: (pid#4596450) <02-0>
Jan 11 06:30:41 helium kernel: dc395x: status_phase0: (pid#4596450) <02-0>
Jan 11 06:30:41 helium kernel: dc395x: disconnect: (pid#4596450)
Jan 11 06:30:41 helium kernel: dc395x: srb_done: (pid#4596450) <02-0>
Jan 11 06:30:41 helium kernel: dc395x: srb_done: srb=f6aa2f2c sg=0(0/0) 
buf=e7c64000 addr=e7c64000
Jan 11 06:30:41 helium kernel: dc395x: srb_going_remove: (pid#4596450) <02-0> 
srb=f6aa2f2c
Jan 11 06:30:41 helium kernel: dc395x: srb_done: (pid#4596450) done 
result=0x00000000
Jan 11 06:30:41 helium kernel: dc395x: srb_free_insert: srb=f6aa2f2c

The log file is 2.8 GB uncompressed after this operation. Let me know if it would be helpful to see more of it and I can post it (or part of it) on my web site for download.

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines
Jan  5 22:50:18 helium kernel: st0: Error with sense data: Info

fld=0x67, Current st0: sense = f0 4

Sense key 4 - hardware error.

I notice that the sense key is 3 this time.

Quoted 2 lines

Still, your tape problem seems to be unrelated. Do you have a chance to test it in another system / with another controller?

Not now, although I may replace the controller just as something to try. That would be much cheaper than a new tape drive.

I have your other suggestions and will get to them as soon as I have time. A.

#6 lore raw
Quoted 8 lines · Andrew Schulman
Quoted 7 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt

failed

Could you try disabling highmem either try a kernel without highmem support, or boot with mem=900M, or remove a part of your RAM (if you don't have to saw your RAMs for that:-)), maybe, booting with highmem=0, or with nohighio.

Quoted 5 lines

Okay, I finally got to this. Rebooted with mem=900M. Unfortunately tar fails as before:

tar: /dev/st0: Wrote only 0 of 10240 bytes
tar: Error is not recoverable: exiting now

I didn't expect disabling highmem to fix _this_ error. But do you still see the "dc395x: sg_update_list: sg_to_virt failed" message with 900M? Perhaps, the most interesting test would be with my patch...

Quoted 6 lines

I had rebuilt dc395x with

#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)

uncommented in dc395x.c. Here's what I got:

Quoted 8 lines
# tail -40 /var/log/kern.log
Jan 11 06:29:18 helium kernel: dc395x: srb_done: (pid#4596449) <02-0>
Jan 11 06:29:18 helium kernel: dc395x: srb_done: srb=f6aa2eec sg=0(0/1) 
buf=e7c64000 addr=e7c64000
Jan 11 06:29:18 helium kernel: dc395x: srb_done: AUTO_REQSENSE1
Jan 11 06:29:18 helium kernel: dc395x: pci_unmap_srb_sense: buffer=12a69452
Jan 11 06:29:18 helium kernel: dc395x: ReqSense: MEDIUM_ERROR cmnd=0x10 <02-0> 
stat=0 scan=1 sense=0x03 ASC=0x0c ASCQ=0x00 (0x00000000 0x00000000)

...well, could you just keep the log for now, maybe we'll have a look at it later, I'd just first try to fix the highmem problem, before trying to figure out what's going on with your tape drive. BTW, when it worked, you already had 1G RAM in the PC, right?

Quoted 1 line

I have your other suggestions and will get to them as soon as I have time.

Thanks
Guennadi

P.S. Please, don't trim the CC list.
---
Guennadi Liakhovetski

#7 lore raw
Quoted 9 lines
Quoted 5 lines

Okay, I finally got to this. Rebooted with mem=900M. Unfortunately tar fails as before:

tar: /dev/st0: Wrote only 0 of 10240 bytes
tar: Error is not recoverable: exiting now

I didn't expect disabling highmem to fix _this_ error. But do you still see the "dc395x: sg_update_list: sg_to_virt failed" message with 900M? Perhaps, the most interesting test would be with my patch...

OK. Yes, with mem=900M, the 'sg_to_virt failed' messages all went away. Will test the patch when I can.

Quoted 4 lines

...well, could you just keep the log for now, maybe we'll have a look at it later, I'd just first try to fix the highmem problem, before trying to figure out what's going on with your tape drive. BTW, when it worked, you already had 1G RAM in the PC, right?

Right.

maintainer
#8 lore raw
In reply to Guennadi Liakhovetski

On Thu, Jan 06, 2005 at 10:48:38PM +0100, Guennadi Liakhovetski wrote:
[...]

Quoted 4 lines
Quoted 1 line
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed

This doesn't look good. However, after a brief look at the code, I cannot say what exactly went wrong there. Jamie?

This messages has been happening in the driver for ever for some people (mos tlikely related to specific devices they are using?). I believe the sg_to_virt thing is trying to convert from the bus address back to the virtual address to be able to recaculate the position for the next transfer after a partial transfer. I've never been able to actually reproduce this specific problem myself.

All the s/g list handling stuff really needs to be re-written. I'm certain that it's not high-mem safe and another rather nasty thing is that it modifies the sg lists after dma mapping them in some situations which isn't really on (and seems to be the cause of the hangs I see when running on sparc64 with some additional patches I have to support big endien machines.)

[...]

Signature · 1 line
 Jamie Lenehan <[email protected]>
#9 lore raw
Quoted 9 lines · Jamie Lenehan

On Thu, Jan 06, 2005 at 10:48:38PM +0100, Guennadi Liakhovetski wrote:
[...]

Quoted 4 lines
Quoted 1 line
Jan  5 22:50:18 helium kernel: dc395x: sg_update_list: sg_to_virt failed

This doesn't look good. However, after a brief look at the code, I cannot say what exactly went wrong there. Jamie?

This messages has been happening in the driver for ever for some people (mos tlikely related to specific devices they are using?). I

I think, the search createria are wrong. Possibly, the following would be better:

Index: drivers/scsi/dc395x.c
===================================================================
RCS file: /usr/src/cvs/linux-2_6/drivers/scsi/dc395x.c,v retrieving revision 1.1.1.4

scsi/dc395x.c +1 -3
diff -u -r1.1.1.4 dc395x.c
@@ -2004,9 +2004,7 @@
 	/* We have to walk the scatterlist to find it */
 	sg = (struct scatterlist *)cmd->request_buffer;
 	while (segment--) {
-		unsigned long mask =
-		    ~((unsigned long)sg->length - 1) & PAGE_MASK;
-		if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
+		if (sg_dma_address(sg) <= psge->address && sg_dma_address(sg) + psge->length > psge->address) {
 			srb->virt_addr = (page_address(sg->page)
 					   + psge->address -
 					   (psge->address & PAGE_MASK));

(untested). Andrew, could you test?

Quoted 4 lines

believe the sg_to_virt thing is trying to convert from the bus address back to the virtual address to be able to recaculate the position for the next transfer after a partial transfer. I've never been able to actually reproduce this specific problem myself.

The driver is full of "hardware bug workarounds". Jamie, are those PIO operations really needed? Do you ever see, that DMA doesn't transfer the last 1-3 bytes of the segment?

Quoted 6 lines

All the s/g list handling stuff really needs to be re-written. I'm certain that it's not high-mem safe and another rather nasty thing is that it modifies the sg lists after dma mapping them in some situations which isn't really on (and seems to be the cause of the hangs I see when running on sparc64 with some additional patches I have to support big endien machines.)

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

Thanks
Guennadi
---
Guennadi Liakhovetski

maintainer
#10 lore raw

On Sun, Jan 09, 2005 at 12:42:26PM +0100, Guennadi Liakhovetski wrote:
[...]

Quoted 3 lines

The driver is full of "hardware bug workarounds". Jamie, are those PIO operations really needed? Do you ever see, that DMA doesn't transfer the last 1-3 bytes of the segment?

What I suspect those workarounds were added for was to handle a driver bug with dealing with WIDE transfers. The dc315 doesn't support WIDE transfers and that's the card I have.

I wouldn't mind removing all the PIO code and disabling support for WIDE devices. It'll simplify various bits of code a lot and mean no longer having to be concered about breaking things for the dc395 when making changes.

[...]

Quoted 2 lines

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

It's on my list of things to do, but I doubt I'll have any time to do anything about in the next few months. So if you have the time and desire please go ahead! I'll can test any changes you make (with a CD-R/W, tape-drive and HDD), although it may take me a week or two to get around to it.

Signature · 1 line
 Jamie Lenehan <[email protected]>
#11 lore raw
Quoted 10 lines · Jamie Lenehan

On Sun, Jan 09, 2005 at 12:42:26PM +0100, Guennadi Liakhovetski wrote:
[...]

Quoted 2 lines

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

It's on my list of things to do, but I doubt I'll have any time to do anything about in the next few months. So if you have the time and desire please go ahead! I'll can test any changes you make (with a CD-R/W, tape-drive and HDD), although it may take me a week or two to get around to it.

Ok, less than 2 weeks and here comes the first attempt. It removes page_to_virt and maps sg lists dynamically. Please, review, test. Slightly tested here - without highmem.

Thanks
Guennadi
---
Guennadi Liakhovetski

drivers/scsi/dc395x.c +35 -13
diff -u a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
@@ -182,7 +182,7 @@
  * cross a page boundy.
  */
 #define SEGMENTX_LEN	(sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-
+#define VIRTX_LEN	(sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
 
 struct SGentry {
 	u32 address;		/* bus! address */
@@ -234,6 +234,7 @@
 	u8 sg_count;			/* No of HW sg entries for this request */
 	u8 sg_index;			/* Index of HW sg entry for this request */
 	u32 total_xfer_length;		/* Total number of bytes remaining to be transfered */
+	void **virt_map;
 	unsigned char *virt_addr;	/* Virtual address of current transfer position */
 
 	/*
@@ -1020,14 +1021,14 @@
 			reqlen, cmd->request_buffer, cmd->use_sg,
 			srb->sg_count);
 
-		srb->virt_addr = page_address(sl->page);
 		for (i = 0; i < srb->sg_count; i++) {
-			u32 busaddr = (u32)sg_dma_address(&sl[i]);
-			u32 seglen = (u32)sl[i].length;
-			sgp[i].address = busaddr;
+			u32 seglen = (u32)sg_dma_len(sl + i);
+			sgp[i].address = (u32)sg_dma_address(sl + i);
 			sgp[i].length = seglen;
 			srb->total_xfer_length += seglen;
+			srb->virt_map[i] = kmap(sl[i].page);
 		}
+		srb->virt_addr = srb->virt_map[0];
 		sgp += srb->sg_count - 1;
 
 		/*
@@ -1964,6 +1965,7 @@
 	int segment = cmd->use_sg;
 	u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
 	struct SGentry *psge = srb->segment_x + srb->sg_index;
+	void **virt = srb->virt_map;
 
 	dprintkdbg(DBG_0,
 		"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2003,16 +2005,16 @@
 
 	/* We have to walk the scatterlist to find it */
 	sg = (struct scatterlist *)cmd->request_buffer;
+	idx = 0;
 	while (segment--) {
 		unsigned long mask =
 		    ~((unsigned long)sg->length - 1) & PAGE_MASK;
 		if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-			srb->virt_addr = (page_address(sg->page)
-					   + psge->address -
-					   (psge->address & PAGE_MASK));
+			srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
 			return;
 		}
 		++sg;
+		++idx;
 	}
 
 	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2138,7 +2140,7 @@
 				DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
 		}
 		/*
-		 * calculate all the residue data that not yet tranfered
+		 * calculate all the residue data that not yet transfered
 		 * SCSI transfer counter + left in SCSI FIFO data
 		 *
 		 * .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3256,6 +3258,7 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	if (cmd->use_sg && dir != PCI_DMA_NONE) {
+		int i;
 		/* unmap DC395x SG list */
 		dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
 			srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3265,6 +3268,8 @@
 		dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
 			cmd->use_sg, cmd->request_buffer);
 		/* unmap the sg segments */
+		for (i = 0; i < srb->sg_count; i++)
+			kunmap(virt_to_page(srb->virt_map[i]));
 		pci_unmap_sg(acb->dev,
 			     (struct scatterlist *)cmd->request_buffer,
 			     cmd->use_sg, dir);
@@ -3311,7 +3316,7 @@
 
 	if (cmd->use_sg) {
 		struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-		ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
+		ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
 	} else {
 		ptr = (struct ScsiInqData *)(cmd->request_buffer);
 	}
@@ -4246,8 +4251,9 @@
 	const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 
 	for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
-		if (acb->srb_array[i].segment_x)
-			kfree(acb->srb_array[i].segment_x);
+		kfree(acb->srb_array[i].segment_x);
+
+	vfree(acb->srb_array[0].virt_map);
 }
 
 
@@ -4263,9 +4269,12 @@
 	int srb_idx = 0;
 	unsigned i = 0;
 	struct SGentry *ptr;
+	void **virt_array;
 
-	for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+	for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
 		acb->srb_array[i].segment_x = NULL;
+		acb->srb_array[i].virt_map = NULL;
+	}
 
 	dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
 	while (pages--) {
@@ -4286,6 +4295,19 @@
 		    ptr + (i * DC395x_MAX_SG_LISTENTRY);
 	else
 		dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+
+	virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
+
+	if (!virt_array) {
+		adapter_sg_tables_free(acb);
+		return 1;
+	}
+
+	for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
+		acb->srb_array[i].virt_map = virt_array;
+		virt_array += DC395x_MAX_SG_LISTENTRY;
+	}
+
 	return 0;
 }
 
#12 lore raw
Quoted 9 lines
Quoted 8 lines
Quoted 2 lines

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

It's on my list of things to do, but I doubt I'll have any time to do anything about in the next few months. So if you have the time and desire please go ahead! I'll can test any changes you make (with a CD-R/W, tape-drive and HDD), although it may take me a week or two to get around to it.

Quoted 3 lines

Ok, less than 2 weeks and here comes the first attempt. It removes page_to_virt and maps sg lists dynamically. Please, review, test. Slightly tested here - without highmem.

Guennadi and Jamie, thanks for your help on this. However, I'm afraid I have to bail out at this point. My tape drive was the only reason I was keeping my old DC395UW controller going, and it has now gone bad. So I've had to yank both the card and tape drive and install a different backup solution. So, I can't test any patches.

Good luck, and my highest regards to both of you for your continuing work on this project. You are making one corner of Linux and open source software work.

Andrew.

#13 lore raw
Quoted 13 lines · Andrew Schulman
Quoted 9 lines
Quoted 8 lines
Quoted 2 lines

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

It's on my list of things to do, but I doubt I'll have any time to do anything about in the next few months. So if you have the time and desire please go ahead! I'll can test any changes you make (with a CD-R/W, tape-drive and HDD), although it may take me a week or two to get around to it.

Quoted 3 lines

Ok, less than 2 weeks and here comes the first attempt. It removes page_to_virt and maps sg lists dynamically. Please, review, test. Slightly tested here - without highmem.

Quoted 5 lines

Guennadi and Jamie, thanks for your help on this. However, I'm afraid I have to bail out at this point. My tape drive was the only reason I was keeping my old DC395UW controller going, and it has now gone bad. So I've had to yank both the card and tape drive and install a different backup solution. So, I can't test any patches.

Thanks for your help.

Guennadi
---
Guennadi Liakhovetski

#14 lore raw

PATCH 1/1 dc395x fix memory mapping (was Re: dc395x: can't write to tape)

In reply to Guennadi Liakhovetski

Hi again

Two weeks since I posted this patch - ping...

Regards
Guennadi

Quoted 163 lines · Guennadi Liakhovetski
Quoted 10 lines · Jamie Lenehan

On Sun, Jan 09, 2005 at 12:42:26PM +0100, Guennadi Liakhovetski wrote:
[...]

Quoted 2 lines

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

It's on my list of things to do, but I doubt I'll have any time to do anything about in the next few months. So if you have the time and desire please go ahead! I'll can test any changes you make (with a CD-R/W, tape-drive and HDD), although it may take me a week or two to get around to it.

Ok, less than 2 weeks and here comes the first attempt. It removes page_to_virt and maps sg lists dynamically. Please, review, test. Slightly tested here - without highmem.

Thanks
Guennadi
---
Guennadi Liakhovetski

diff -u a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c

drivers/scsi/dc395x.c +28 -13
@@ -182,7 +182,7 @@
  * cross a page boundy.
  */
 #define SEGMENTX_LEN	(sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-
+#define VIRTX_LEN	(sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
 
 struct SGentry {
 	u32 address;		/* bus! address */
@@ -234,6 +234,7 @@
 	u8 sg_count;			/* No of HW sg entries for this request */
 	u8 sg_index;			/* Index of HW sg entry for this request */
 	u32 total_xfer_length;		/* Total number of bytes remaining to be transfered */
+	void **virt_map;
 	unsigned char *virt_addr;	/* Virtual address of current transfer position */
 
 	/*
@@ -1020,14 +1021,14 @@
 			reqlen, cmd->request_buffer, cmd->use_sg,
 			srb->sg_count);
 
-		srb->virt_addr = page_address(sl->page);
 		for (i = 0; i < srb->sg_count; i++) {
-			u32 busaddr = (u32)sg_dma_address(&sl[i]);
-			u32 seglen = (u32)sl[i].length;
-			sgp[i].address = busaddr;
+			u32 seglen = (u32)sg_dma_len(sl + i);
+			sgp[i].address = (u32)sg_dma_address(sl + i);
 			sgp[i].length = seglen;
 			srb->total_xfer_length += seglen;
+			srb->virt_map[i] = kmap(sl[i].page);
 		}
+		srb->virt_addr = srb->virt_map[0];
 		sgp += srb->sg_count - 1;
 
 		/*
@@ -1964,6 +1965,7 @@
 	int segment = cmd->use_sg;
 	u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
 	struct SGentry *psge = srb->segment_x + srb->sg_index;
+	void **virt = srb->virt_map;
 
 	dprintkdbg(DBG_0,
 		"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2003,16 +2005,16 @@
 
 	/* We have to walk the scatterlist to find it */
 	sg = (struct scatterlist *)cmd->request_buffer;
+	idx = 0;
 	while (segment--) {
 		unsigned long mask =
 		    ~((unsigned long)sg->length - 1) & PAGE_MASK;
 		if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-			srb->virt_addr = (page_address(sg->page)
-					   + psge->address -
-					   (psge->address & PAGE_MASK));
+			srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
 			return;
 		}
 		++sg;
+		++idx;
 	}
 
 	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2138,7 +2140,7 @@
 				DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
 		}
 		/*
-		 * calculate all the residue data that not yet tranfered
+		 * calculate all the residue data that not yet transfered
 		 * SCSI transfer counter + left in SCSI FIFO data
 		 *
 		 * .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3256,6 +3258,7 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	if (cmd->use_sg && dir != PCI_DMA_NONE) {
+		int i;
 		/* unmap DC395x SG list */
 		dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
 			srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3265,6 +3268,8 @@
 		dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
 			cmd->use_sg, cmd->request_buffer);
 		/* unmap the sg segments */
+		for (i = 0; i < srb->sg_count; i++)
+			kunmap(virt_to_page(srb->virt_map[i]));
 		pci_unmap_sg(acb->dev,
 			     (struct scatterlist *)cmd->request_buffer,
 			     cmd->use_sg, dir);
@@ -3311,7 +3316,7 @@
 
 	if (cmd->use_sg) {
 		struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-		ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
+		ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
 	} else {
 		ptr = (struct ScsiInqData *)(cmd->request_buffer);
 	}
@@ -4246,8 +4251,9 @@
 	const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 
 	for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
-		if (acb->srb_array[i].segment_x)
-			kfree(acb->srb_array[i].segment_x);
+		kfree(acb->srb_array[i].segment_x);
+
+	vfree(acb->srb_array[0].virt_map);
 }
 
 
@@ -4263,9 +4269,12 @@
 	int srb_idx = 0;
 	unsigned i = 0;
 	struct SGentry *ptr;
+	void **virt_array;
 
-	for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+	for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
 		acb->srb_array[i].segment_x = NULL;
+		acb->srb_array[i].virt_map = NULL;
+	}
 
 	dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
 	while (pages--) {
@@ -4286,6 +4295,19 @@
 		    ptr + (i * DC395x_MAX_SG_LISTENTRY);
 	else
 		dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+
+	virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
+
+	if (!virt_array) {
+		adapter_sg_tables_free(acb);
+		return 1;

drivers/scsi/dc395x.c line 4313

Quoted 10 lines
drivers/scsi/dc395x.c +7 -0
+	}
+
+	for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
+		acb->srb_array[i].virt_map = virt_array;
+		virt_array += DC395x_MAX_SG_LISTENTRY;
+	}
+
 	return 0;
 }
 

---
Guennadi Liakhovetski

#15 lore raw

Re: [PATCH] dc395x fix memory mapping (was Re: dc395x: can't write to tape)

Quoted 1 line · Guennadi Liakhovetski

Two weeks since I posted this patch - ping...

...and another two weeks since you, Jamie, replied to me privately. Just wanted to say, it would be good to get this bug fixed for the post-2.6.11 SCSI patch.

Regards
Guennadi

Quoted 171 lines · Guennadi Liakhovetski
Quoted 169 lines · Jamie Lenehan
Quoted 11 lines · Guennadi Liakhovetski

[...]

Quoted 2 lines

I could try to improve the highmem situation / sg-handling. Or do you plan to do it, Jamie?

It's on my list of things to do, but I doubt I'll have any time to do anything about in the next few months. So if you have the time and desire please go ahead! I'll can test any changes you make (with a CD-R/W, tape-drive and HDD), although it may take me a week or two to get around to it.

Ok, less than 2 weeks and here comes the first attempt. It removes page_to_virt and maps sg lists dynamically. Please, review, test. Slightly tested here - without highmem.

Thanks
Guennadi
---
Guennadi Liakhovetski

diff -u a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c

drivers/scsi/dc395x.c +34 -13
@@ -182,7 +182,7 @@
  * cross a page boundy.
  */
 #define SEGMENTX_LEN	(sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-
+#define VIRTX_LEN	(sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
 
 struct SGentry {
 	u32 address;		/* bus! address */
@@ -234,6 +234,7 @@
 	u8 sg_count;			/* No of HW sg entries for this request */
 	u8 sg_index;			/* Index of HW sg entry for this request */
 	u32 total_xfer_length;		/* Total number of bytes remaining to be transfered */
+	void **virt_map;
 	unsigned char *virt_addr;	/* Virtual address of current transfer position */
 
 	/*
@@ -1020,14 +1021,14 @@
 			reqlen, cmd->request_buffer, cmd->use_sg,
 			srb->sg_count);
 
-		srb->virt_addr = page_address(sl->page);
 		for (i = 0; i < srb->sg_count; i++) {
-			u32 busaddr = (u32)sg_dma_address(&sl[i]);
-			u32 seglen = (u32)sl[i].length;
-			sgp[i].address = busaddr;
+			u32 seglen = (u32)sg_dma_len(sl + i);
+			sgp[i].address = (u32)sg_dma_address(sl + i);
 			sgp[i].length = seglen;
 			srb->total_xfer_length += seglen;
+			srb->virt_map[i] = kmap(sl[i].page);
 		}
+		srb->virt_addr = srb->virt_map[0];
 		sgp += srb->sg_count - 1;
 
 		/*
@@ -1964,6 +1965,7 @@
 	int segment = cmd->use_sg;
 	u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
 	struct SGentry *psge = srb->segment_x + srb->sg_index;
+	void **virt = srb->virt_map;
 
 	dprintkdbg(DBG_0,
 		"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2003,16 +2005,16 @@
 
 	/* We have to walk the scatterlist to find it */
 	sg = (struct scatterlist *)cmd->request_buffer;
+	idx = 0;
 	while (segment--) {
 		unsigned long mask =
 		    ~((unsigned long)sg->length - 1) & PAGE_MASK;
 		if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-			srb->virt_addr = (page_address(sg->page)
-					   + psge->address -
-					   (psge->address & PAGE_MASK));
+			srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
 			return;
 		}
 		++sg;
+		++idx;
 	}
 
 	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2138,7 +2140,7 @@
 				DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
 		}
 		/*
-		 * calculate all the residue data that not yet tranfered
+		 * calculate all the residue data that not yet transfered
 		 * SCSI transfer counter + left in SCSI FIFO data
 		 *
 		 * .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3256,6 +3258,7 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	if (cmd->use_sg && dir != PCI_DMA_NONE) {
+		int i;
 		/* unmap DC395x SG list */
 		dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
 			srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3265,6 +3268,8 @@
 		dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
 			cmd->use_sg, cmd->request_buffer);
 		/* unmap the sg segments */
+		for (i = 0; i < srb->sg_count; i++)
+			kunmap(virt_to_page(srb->virt_map[i]));
 		pci_unmap_sg(acb->dev,
 			     (struct scatterlist *)cmd->request_buffer,
 			     cmd->use_sg, dir);
@@ -3311,7 +3316,7 @@
 
 	if (cmd->use_sg) {
 		struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-		ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
+		ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
 	} else {
 		ptr = (struct ScsiInqData *)(cmd->request_buffer);
 	}
@@ -4246,8 +4251,9 @@
 	const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 
 	for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
-		if (acb->srb_array[i].segment_x)
-			kfree(acb->srb_array[i].segment_x);
+		kfree(acb->srb_array[i].segment_x);
+
+	vfree(acb->srb_array[0].virt_map);
 }
 
 
@@ -4263,9 +4269,12 @@
 	int srb_idx = 0;
 	unsigned i = 0;
 	struct SGentry *ptr;
+	void **virt_array;
 
-	for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+	for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
 		acb->srb_array[i].segment_x = NULL;
+		acb->srb_array[i].virt_map = NULL;
+	}
 
 	dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
 	while (pages--) {
@@ -4286,6 +4295,19 @@
 		    ptr + (i * DC395x_MAX_SG_LISTENTRY);
 	else
 		dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+
+	virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
+
+	if (!virt_array) {
+		adapter_sg_tables_free(acb);
+		return 1;
+	}
+
+	for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
+		acb->srb_array[i].virt_map = virt_array;
+		virt_array += DC395x_MAX_SG_LISTENTRY;
+	}
Quoted 10 lines

drivers/scsi/dc395x.c line 4313

Quoted 5 lines
drivers/scsi/dc395x.c +1 -0
+
 	return 0;
 }
 

---
Guennadi Liakhovetski

---
Guennadi Liakhovetski

maintainer
#16 lore raw

Re: [PATCH] dc395x fix memory mapping (was Re: dc395x: can't write to tape)

Quoted 7 lines · Guennadi Liakhovetski
Quoted 1 line · Guennadi Liakhovetski

Two weeks since I posted this patch - ping...

...and another two weeks since you, Jamie, replied to me privately. Just wanted to say, it would be good to get this bug fixed for the post-2.6.11 SCSI patch.

Yep.
I've been rather busy and have not had any time to look at this. The patch looks good and I've had no issues testing it now with highmem enabled on my 4G DAT drive.

I'll submit the patch in a minute.

Thanks.
Jamie.

Signature · 1 line
 Jamie Lenehan <[email protected]>