2015-11-18 08:46:21

by Finn Thain

[permalink] [raw]
Subject: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


Like my previous work on the NCR5380 drivers, this patch series has bug
fixes, code cleanup and modernization. These drivers suffer from mistakes,
poor style and neglect and this long series addresses the worst of it,
covering all ten wrapper drivers and both of the core driver forks. The
combined size of the drivers is reduced by about 750 LoC.

This series continues to reduce divergence between the two core driver
forks, often by copying a bug fix from one to the other. Most patches are
larger for having to keep the two forks in sync. Making the same change to
both is churn if one of them is to be removed but neither can be as yet.
By the end of this series the diff between the two forks is minimal, so it
becomes clear what caused the fork and what can be done about it.

This patch series did benefit from scripts/checkpatch.pl but not too much.
Decades ago, these drivers started out with 4-space tabs and if the 80
column limit were to be strictly enforced now, it would require adding new
functions and shortening identifiers. I would defer this sort of activity
until after the fork has been resolved.

I have compile-tested all patches to all NCR5380 drivers (x86, ARM, m68k)
and regression tested mac_scsi and dmx3191d modules on suitable hardware.
Testing the mac_scsi and dmx3191d modules provides only limited coverage.
It would be good to see some testing of ISA cards and Sun 3 and Atari
hardware too (I don't have any).

---
drivers/scsi/Kconfig | 17
drivers/scsi/NCR5380.c | 2871 +++++++++++++++++++------------------------
drivers/scsi/NCR5380.h | 72 -
drivers/scsi/arm/cumana_1.c | 30
drivers/scsi/arm/oak.c | 26
drivers/scsi/atari_NCR5380.c | 2295 +++++++++++++++-------------------
drivers/scsi/atari_scsi.c | 102 -
drivers/scsi/dmx3191d.c | 32
drivers/scsi/dtc.c | 114 -
drivers/scsi/dtc.h | 45
drivers/scsi/g_NCR5380.c | 178 +-
drivers/scsi/g_NCR5380.h | 56
drivers/scsi/mac_scsi.c | 116 -
drivers/scsi/pas16.c | 115 -
drivers/scsi/pas16.h | 40
drivers/scsi/sun3_scsi.c | 141 --
drivers/scsi/t128.c | 101 -
drivers/scsi/t128.h | 39
18 files changed, 2815 insertions(+), 3575 deletions(-)




2015-11-18 11:35:24

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Wednesday 18 November 2015, Finn Thain wrote:
> Like my previous work on the NCR5380 drivers, this patch series has bug
> fixes, code cleanup and modernization. These drivers suffer from mistakes,
> poor style and neglect and this long series addresses the worst of it,
> covering all ten wrapper drivers and both of the core driver forks. The
> combined size of the drivers is reduced by about 750 LoC.
>
> This series continues to reduce divergence between the two core driver
> forks, often by copying a bug fix from one to the other. Most patches are
> larger for having to keep the two forks in sync. Making the same change to
> both is churn if one of them is to be removed but neither can be as yet.
> By the end of this series the diff between the two forks is minimal, so it
> becomes clear what caused the fork and what can be done about it.
>
> This patch series did benefit from scripts/checkpatch.pl but not too much.
> Decades ago, these drivers started out with 4-space tabs and if the 80
> column limit were to be strictly enforced now, it would require adding new
> functions and shortening identifiers. I would defer this sort of activity
> until after the fork has been resolved.
>
> I have compile-tested all patches to all NCR5380 drivers (x86, ARM, m68k)
> and regression tested mac_scsi and dmx3191d modules on suitable hardware.
> Testing the mac_scsi and dmx3191d modules provides only limited coverage.
> It would be good to see some testing of ISA cards and Sun 3 and Atari
> hardware too (I don't have any).

I have some NCR5380 ISA cards and can test them.

--
Ondrej Zary

2015-11-19 02:25:21

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Wed, 18 Nov 2015, Ondrej Zary wrote:

> On Wednesday 18 November 2015, Finn Thain wrote:
>
> > Like my previous work on the NCR5380 drivers, this patch series has
> > bug fixes, code cleanup and modernization. These drivers suffer from
> > mistakes, poor style and neglect and this long series addresses the
> > worst of it, covering all ten wrapper drivers and both of the core
> > driver forks. The combined size of the drivers is reduced by about 750
> > LoC.
> >
> > This series continues to reduce divergence between the two core driver
> > forks, often by copying a bug fix from one to the other. Most patches
> > are larger for having to keep the two forks in sync. Making the same
> > change to both is churn if one of them is to be removed but neither
> > can be as yet. By the end of this series the diff between the two
> > forks is minimal, so it becomes clear what caused the fork and what
> > can be done about it.
> >
> > This patch series did benefit from scripts/checkpatch.pl but not too
> > much. Decades ago, these drivers started out with 4-space tabs and if
> > the 80 column limit were to be strictly enforced now, it would require
> > adding new functions and shortening identifiers. I would defer this
> > sort of activity until after the fork has been resolved.
> >
> > I have compile-tested all patches to all NCR5380 drivers (x86, ARM,
> > m68k) and regression tested mac_scsi and dmx3191d modules on suitable
> > hardware. Testing the mac_scsi and dmx3191d modules provides only
> > limited coverage. It would be good to see some testing of ISA cards
> > and Sun 3 and Atari hardware too (I don't have any).
>
> I have some NCR5380 ISA cards and can test them.
>

Thanks Ondrej. I've no idea which ISA drivers are presently working in
mainline. Finding regressions may be more difficult than usual ;-)

Michael, Sam: only atari_scsi and sun3_scsi implement DMA support, so some
testing of either driver would be helpful.

--

2015-11-19 02:52:59

by Michael Schmitz

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

Hi Finn,

>>>
>>> I have compile-tested all patches to all NCR5380 drivers (x86, ARM,
>>> m68k) and regression tested mac_scsi and dmx3191d modules on suitable
>>> hardware. Testing the mac_scsi and dmx3191d modules provides only
>>> limited coverage. It would be good to see some testing of ISA cards
>>> and Sun 3 and Atari hardware too (I don't have any).
>>
>> I have some NCR5380 ISA cards and can test them.
>>
>
> Thanks Ondrej. I've no idea which ISA drivers are presently working in
> mainline. Finding regressions may be more difficult than usual ;-)
>
> Michael, Sam: only atari_scsi and sun3_scsi implement DMA support, so some
> testing of either driver would be helpful.

One way or another, I'll test this series or get someone to test a
kernel I built.

Cheers,

Michael


2015-11-19 07:48:28

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Thursday 19 November 2015, Finn Thain wrote:
> On Wed, 18 Nov 2015, Ondrej Zary wrote:
> > On Wednesday 18 November 2015, Finn Thain wrote:
> > > Like my previous work on the NCR5380 drivers, this patch series has
> > > bug fixes, code cleanup and modernization. These drivers suffer from
> > > mistakes, poor style and neglect and this long series addresses the
> > > worst of it, covering all ten wrapper drivers and both of the core
> > > driver forks. The combined size of the drivers is reduced by about 750
> > > LoC.
> > >
> > > This series continues to reduce divergence between the two core driver
> > > forks, often by copying a bug fix from one to the other. Most patches
> > > are larger for having to keep the two forks in sync. Making the same
> > > change to both is churn if one of them is to be removed but neither
> > > can be as yet. By the end of this series the diff between the two
> > > forks is minimal, so it becomes clear what caused the fork and what
> > > can be done about it.
> > >
> > > This patch series did benefit from scripts/checkpatch.pl but not too
> > > much. Decades ago, these drivers started out with 4-space tabs and if
> > > the 80 column limit were to be strictly enforced now, it would require
> > > adding new functions and shortening identifiers. I would defer this
> > > sort of activity until after the fork has been resolved.
> > >
> > > I have compile-tested all patches to all NCR5380 drivers (x86, ARM,
> > > m68k) and regression tested mac_scsi and dmx3191d modules on suitable
> > > hardware. Testing the mac_scsi and dmx3191d modules provides only
> > > limited coverage. It would be good to see some testing of ISA cards
> > > and Sun 3 and Atari hardware too (I don't have any).
> >
> > I have some NCR5380 ISA cards and can test them.
>
> Thanks Ondrej. I've no idea which ISA drivers are presently working in
> mainline. Finding regressions may be more difficult than usual ;-)

I remember that at least one of them never worked in Linux - HP C2502 card
with 53C400A chip with no jumpers (magic-numbers-based configuration).

The memory-mapped Canon FG2-5202 (53C400) did not work properly either.

At least DTCT-436P used to work.

--
Ondrej Zary

2015-11-19 22:51:18

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers



On Thursday 19 November 2015 03:24:56 Finn Thain wrote:
> On Wed, 18 Nov 2015, Ondrej Zary wrote:
> > On Wednesday 18 November 2015, Finn Thain wrote:
> > > Like my previous work on the NCR5380 drivers, this patch series has
> > > bug fixes, code cleanup and modernization. These drivers suffer from
> > > mistakes, poor style and neglect and this long series addresses the
> > > worst of it, covering all ten wrapper drivers and both of the core
> > > driver forks. The combined size of the drivers is reduced by about 750
> > > LoC.
> > >
> > > This series continues to reduce divergence between the two core driver
> > > forks, often by copying a bug fix from one to the other. Most patches
> > > are larger for having to keep the two forks in sync. Making the same
> > > change to both is churn if one of them is to be removed but neither
> > > can be as yet. By the end of this series the diff between the two
> > > forks is minimal, so it becomes clear what caused the fork and what
> > > can be done about it.
> > >
> > > This patch series did benefit from scripts/checkpatch.pl but not too
> > > much. Decades ago, these drivers started out with 4-space tabs and if
> > > the 80 column limit were to be strictly enforced now, it would require
> > > adding new functions and shortening identifiers. I would defer this
> > > sort of activity until after the fork has been resolved.
> > >
> > > I have compile-tested all patches to all NCR5380 drivers (x86, ARM,
> > > m68k) and regression tested mac_scsi and dmx3191d modules on suitable
> > > hardware. Testing the mac_scsi and dmx3191d modules provides only
> > > limited coverage. It would be good to see some testing of ISA cards
> > > and Sun 3 and Atari hardware too (I don't have any).
> >
> > I have some NCR5380 ISA cards and can test them.
>
> Thanks Ondrej. I've no idea which ISA drivers are presently working in
> mainline. Finding regressions may be more difficult than usual ;-)

You're right... looks very broken:

[ 62.577194] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA
NCR53C400 }
[ 62.796635] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
[ 63.878494] sd 2:0:0:0: Attached scsi generic sg1 type 0
[ 95.848260] sd 2:0:0:0: aborting command

And the system hangs completely.

It's much better with your patches, but still not great :)

[ 93.963264] pnp 01:01.00: [io 0x0240-0x025f]
[ 93.963493] pnp 01:01.00: [irq 5]
[ 93.965768] pnp 01:01.00: activated
[ 93.977147] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 93.987527] scsi host2: rejecting message
[ 93.987647] Synchronous Data Transfer Request period = 100 ns offset = 12
[ 94.001219] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
[ 113.000794] sd 2:0:0:0: Attached scsi generic sg1 type 0
[ 144.852432] sd 2:0:0:0: [sdb] Unit Not Ready
[ 144.852574] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
[ 144.852713] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
[ 240.108292] INFO: task modprobe:1957 blocked for more than 120 seconds.
[ 240.108418] Not tainted 4.3.0-rc1+ #74
[ 240.108501] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 240.108597] modprobe D 0000001a 0 1957 1950 0x00000000
[ 240.108790] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
[ 240.109246] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
[ 240.109699] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
[ 240.110156] Call Trace:
[ 240.110295] [<c139c504>] ? schedule+0x5b/0x67
[ 240.110430] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 240.110569] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 240.110699] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 240.110824] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 240.110948] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 240.111068] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 240.852458] sd 2:0:0:0: [sdb] Read Capacity(10) failed: Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
[ 240.852620] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
[ 240.852760] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
[ 272.852471] sd 2:0:0:0: [sdb] Write Protect is off
[ 272.852614] sd 2:0:0:0: [sdb] Mode Sense: 00 00 00 00
[ 304.084452] sd 2:0:0:0: [sdb] Asking for cache data failed
[ 304.084592] sd 2:0:0:0: [sdb] Assuming drive cache: write through
[ 360.108284] INFO: task modprobe:1957 blocked for more than 120 seconds.
[ 360.108409] Not tainted 4.3.0-rc1+ #74
[ 360.108492] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 360.108591] modprobe D 0000001a 0 1957 1950 0x00000000
[ 360.108787] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
[ 360.109248] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
[ 360.109703] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
[ 360.110158] Call Trace:
[ 360.110296] [<c139c504>] ? schedule+0x5b/0x67
[ 360.110430] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 360.110568] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 360.110699] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 360.110823] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 360.110945] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 360.111065] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 431.060488] sd 2:0:0:0: [sdb] Read Capacity(10) failed: Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
[ 431.060650] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
[ 431.060791] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
[ 480.108282] INFO: task modprobe:1957 blocked for more than 120 seconds.
[ 480.108405] Not tainted 4.3.0-rc1+ #74
[ 480.108488] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 480.108585] modprobe D 0000001a 0 1957 1950 0x00000000
[ 480.108779] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
[ 480.109236] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
[ 480.109689] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
[ 480.110145] Call Trace:
[ 480.110282] [<c139c504>] ? schedule+0x5b/0x67
[ 480.110417] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 480.110556] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 480.110685] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 480.110810] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 480.110932] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 480.111052] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 495.062082] sd 2:0:0:0: [sdb] Attached SCSI disk

--
Ondrej Zary

2015-11-20 01:41:43

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Thu, 19 Nov 2015, Ondrej Zary wrote:

> On Thursday 19 November 2015 03:24:56 Finn Thain wrote:
>
> > On Wed, 18 Nov 2015, Ondrej Zary wrote:
> >
> > >
> > > I have some NCR5380 ISA cards and can test them.
> >
> > Thanks Ondrej. I've no idea which ISA drivers are presently working in
> > mainline. Finding regressions may be more difficult than usual ;-)
>
> You're right... looks very broken:
>
> [ 62.577194] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
> sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA
> NCR53C400 }
> [ 62.796635] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
> [ 63.878494] sd 2:0:0:0: Attached scsi generic sg1 type 0
> [ 95.848260] sd 2:0:0:0: aborting command
>
> And the system hangs completely.
>

Yes. That was the usual failure mode. The old EH abort routine is fatal.
Up until I disabled PDMA by default for mac_scsi (in v3.19), that driver
would do the same thing.

> It's much better with your patches, but still not great :)
>

Pleased to hear it :)

> [ 93.963264] pnp 01:01.00: [io 0x0240-0x025f]
> [ 93.963493] pnp 01:01.00: [irq 5]
> [ 93.965768] pnp 01:01.00: activated
> [ 93.977147] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
> sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 93.987527] scsi host2: rejecting message
> [ 93.987647] Synchronous Data Transfer Request period = 100 ns offset = 12
> [ 94.001219] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
> [ 113.000794] sd 2:0:0:0: Attached scsi generic sg1 type 0

I'd be interested to know what commands were in play in that 19 second
interval. Might need to use scsi_logging_level to figure that out.

My tests involved 3 different scsi targets (two disks and a CD-ROM) but
none of these send a SDTR. Your log says the driver correctly rejected the
SDTR message but that doesn't mean the target actually went to MSG IN
phase and got the message. Do you have any older targets you can test?

> [ 144.852432] sd 2:0:0:0: [sdb] Unit Not Ready
> [ 144.852574] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
> [ 144.852713] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure

AFAIK, the target should not have to abort any commands. Moreover, the
target should never experience a select/reselect failure, because you have
irq == 0 (see above) and that implies that the target is never permitted
the disconnect privilege.

> [ 240.108292] INFO: task modprobe:1957 blocked for more than 120 seconds.
> [ 240.108418] Not tainted 4.3.0-rc1+ #74

Why not use v4.3?

> [ 240.108501] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 240.108597] modprobe D 0000001a 0 1957 1950 0x00000000
> [ 240.108790] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
> [ 240.109246] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
> [ 240.109699] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
> [ 240.110156] Call Trace:
> [ 240.110295] [<c139c504>] ? schedule+0x5b/0x67
> [ 240.110430] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 240.110569] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 240.110699] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 240.110824] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 240.110948] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 240.111068] [<c139e2c0>] ? sysenter_do_call+0x12/0x12

Not sure what module was being probed here. I presume it was g_NCR5380 or
g_NCR5380_mmio. Neither of these calls 'scsi_scan_host'. I'm not sure what
the implications are (?)

> [ 240.852458] sd 2:0:0:0: [sdb] Read Capacity(10) failed: Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> [ 240.852620] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
> [ 240.852760] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
> [ 272.852471] sd 2:0:0:0: [sdb] Write Protect is off
> [ 272.852614] sd 2:0:0:0: [sdb] Mode Sense: 00 00 00 00
> [ 304.084452] sd 2:0:0:0: [sdb] Asking for cache data failed
> [ 304.084592] sd 2:0:0:0: [sdb] Assuming drive cache: write through

This looks like nonsense to me ... I don't think the target actually
aborted the reselection phase of a read capacity command. I'm out of ideas
here. Can anyone else make sense of this?

> [ 360.108284] INFO: task modprobe:1957 blocked for more than 120 seconds.
> [ 360.108409] Not tainted 4.3.0-rc1+ #74
> [ 360.108492] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 360.108591] modprobe D 0000001a 0 1957 1950 0x00000000
> [ 360.108787] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
> [ 360.109248] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
> [ 360.109703] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
> [ 360.110158] Call Trace:
> [ 360.110296] [<c139c504>] ? schedule+0x5b/0x67
> [ 360.110430] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 360.110568] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 360.110699] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 360.110823] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 360.110945] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 360.111065] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> [ 431.060488] sd 2:0:0:0: [sdb] Read Capacity(10) failed: Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> [ 431.060650] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
> [ 431.060791] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
> [ 480.108282] INFO: task modprobe:1957 blocked for more than 120 seconds.
> [ 480.108405] Not tainted 4.3.0-rc1+ #74
> [ 480.108488] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 480.108585] modprobe D 0000001a 0 1957 1950 0x00000000
> [ 480.108779] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
> [ 480.109236] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
> [ 480.109689] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
> [ 480.110145] Call Trace:
> [ 480.110282] [<c139c504>] ? schedule+0x5b/0x67
> [ 480.110417] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 480.110556] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 480.110685] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 480.110810] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 480.110932] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 480.111052] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> [ 495.062082] sd 2:0:0:0: [sdb] Attached SCSI disk
>
>

--

2015-11-20 07:21:33

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Fri, 20 Nov 2015, I wrote:

> On Thu, 19 Nov 2015, Ondrej Zary wrote:
>
> > [ 240.108501] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 240.108597] modprobe D 0000001a 0 1957 1950 0x00000000
> > [ 240.108790] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
> > [ 240.109246] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
> > [ 240.109699] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
> > [ 240.110156] Call Trace:
> > [ 240.110295] [<c139c504>] ? schedule+0x5b/0x67
> > [ 240.110430] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> > [ 240.110569] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> > [ 240.110699] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> > [ 240.110824] [<c107ddb5>] ? load_module+0x14de/0x18ca
> > [ 240.110948] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> > [ 240.111068] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
>
> Not sure what module was being probed here. I presume it was g_NCR5380
> or g_NCR5380_mmio. Neither of these calls 'scsi_scan_host'. I'm not sure
> what the implications are (?)

Nevermind. The call is in scsi_module.c.

--

2015-11-20 07:34:16

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Fri, Nov 20, 2015 at 06:21:06PM +1100, Finn Thain wrote:
> > Not sure what module was being probed here. I presume it was g_NCR5380
> > or g_NCR5380_mmio. Neither of these calls 'scsi_scan_host'. I'm not sure
> > what the implications are (?)
>
> Nevermind. The call is in scsi_module.c.

Which, btw really need to go away. If you want to resurrect the
ISA drivers they need to be converted to proper probing.

2015-11-20 07:35:28

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Friday 20 November 2015, Finn Thain wrote:
>
> On Thu, 19 Nov 2015, Ondrej Zary wrote:
>
> > On Thursday 19 November 2015 03:24:56 Finn Thain wrote:
> >
> > > On Wed, 18 Nov 2015, Ondrej Zary wrote:
> > >
> > > >
> > > > I have some NCR5380 ISA cards and can test them.
> > >
> > > Thanks Ondrej. I've no idea which ISA drivers are presently working in
> > > mainline. Finding regressions may be more difficult than usual ;-)
> >
> > You're right... looks very broken:
> >
> > [ 62.577194] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
> > sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA
> > NCR53C400 }
> > [ 62.796635] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
> > [ 63.878494] sd 2:0:0:0: Attached scsi generic sg1 type 0
> > [ 95.848260] sd 2:0:0:0: aborting command
> >
> > And the system hangs completely.
> >
>
> Yes. That was the usual failure mode. The old EH abort routine is fatal.
> Up until I disabled PDMA by default for mac_scsi (in v3.19), that driver
> would do the same thing.
>
> > It's much better with your patches, but still not great :)
> >
>
> Pleased to hear it :)
>
> > [ 93.963264] pnp 01:01.00: [io 0x0240-0x025f]
> > [ 93.963493] pnp 01:01.00: [irq 5]
> > [ 93.965768] pnp 01:01.00: activated
> > [ 93.977147] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
> > sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> > [ 93.987527] scsi host2: rejecting message
> > [ 93.987647] Synchronous Data Transfer Request period = 100 ns offset = 12
> > [ 94.001219] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
> > [ 113.000794] sd 2:0:0:0: Attached scsi generic sg1 type 0
>
> I'd be interested to know what commands were in play in that 19 second
> interval. Might need to use scsi_logging_level to figure that out.
>
> My tests involved 3 different scsi targets (two disks and a CD-ROM) but
> none of these send a SDTR. Your log says the driver correctly rejected the
> SDTR message but that doesn't mean the target actually went to MSG IN
> phase and got the message. Do you have any older targets you can test?

Yes, I have some older disks too and also CD-ROMs. This one was just handy in
an external enclosure (the card has only an external DB25 connector). It can
be opened easily so I'll test the other devices too.

> > [ 144.852432] sd 2:0:0:0: [sdb] Unit Not Ready
> > [ 144.852574] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
> > [ 144.852713] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
>
> AFAIK, the target should not have to abort any commands. Moreover, the
> target should never experience a select/reselect failure, because you have
> irq == 0 (see above) and that implies that the target is never permitted
> the disconnect privilege.
>
> > [ 240.108292] INFO: task modprobe:1957 blocked for more than 120 seconds.
> > [ 240.108418] Not tainted 4.3.0-rc1+ #74
>
> Why not use v4.3?

I had that already built so just quickly applied the patches and tested. I have
to update the git tree anyway as ACPI is broken.

> > [ 240.108501] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 240.108597] modprobe D 0000001a 0 1957 1950 0x00000000
> > [ 240.108790] ce0fad00 00000086 53881781 0000001a c1525f88 4edbe39c 0000001a 04ac33e5
> > [ 240.109246] 00000000 ccd54000 ffffffff ffffffff d204b280 c139c504 00000000 c104416d
> > [ 240.109699] 00000000 ce0fad00 c1054a45 c151fd8c c151fd8c d204b280 00000000 ccd6d100
> > [ 240.110156] Call Trace:
> > [ 240.110295] [<c139c504>] ? schedule+0x5b/0x67
> > [ 240.110430] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> > [ 240.110569] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> > [ 240.110699] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> > [ 240.110824] [<c107ddb5>] ? load_module+0x14de/0x18ca
> > [ 240.110948] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> > [ 240.111068] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
>
> Not sure what module was being probed here. I presume it was g_NCR5380 or
> g_NCR5380_mmio. Neither of these calls 'scsi_scan_host'. I'm not sure what
> the implications are (?)

It was g_NCR5380 (DTCT-436P card).

> > [ 240.852458] sd 2:0:0:0: [sdb] Read Capacity(10) failed: Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> > [ 240.852620] sd 2:0:0:0: [sdb] Sense Key : Aborted Command [current]
> > [ 240.852760] sd 2:0:0:0: [sdb] Add. Sense: Select or reselect failure
> > [ 272.852471] sd 2:0:0:0: [sdb] Write Protect is off
> > [ 272.852614] sd 2:0:0:0: [sdb] Mode Sense: 00 00 00 00
> > [ 304.084452] sd 2:0:0:0: [sdb] Asking for cache data failed
> > [ 304.084592] sd 2:0:0:0: [sdb] Assuming drive cache: write through
>
> This looks like nonsense to me ... I don't think the target actually
> aborted the reselection phase of a read capacity command. I'm out of ideas
> here. Can anyone else make sense of this?


--
Ondrej Zary

2015-11-20 08:19:46

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Thu, 19 Nov 2015, Christoph Hellwig wrote:

> On Fri, Nov 20, 2015 at 06:21:06PM +1100, Finn Thain wrote:
>
> > > Not sure what module was being probed here. I presume it was
> > > g_NCR5380 or g_NCR5380_mmio. Neither of these calls
> > > 'scsi_scan_host'. I'm not sure what the implications are (?)
> >
> > Nevermind. The call is in scsi_module.c.
>
> Which, btw really need to go away. If you want to resurrect the
> ISA drivers they need to be converted to proper probing.

Yes. I didn't do that conversion because I don't have ISA hardware and I
don't understand ISA probing.

The present patch set doesn't seek to resurrect the ISA drivers. But I am
trying to avoid regressions.

I have mixed feelings about the ISA drivers. ISA DMA support complicates
things (it was never completed) and DMA seems to be the main obstacle to
merging the two core driver forks.

--

2015-11-20 09:16:43

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Friday 20 November 2015, Finn Thain wrote:
>
> On Thu, 19 Nov 2015, Christoph Hellwig wrote:
>
> > On Fri, Nov 20, 2015 at 06:21:06PM +1100, Finn Thain wrote:
> >
> > > > Not sure what module was being probed here. I presume it was
> > > > g_NCR5380 or g_NCR5380_mmio. Neither of these calls
> > > > 'scsi_scan_host'. I'm not sure what the implications are (?)
> > >
> > > Nevermind. The call is in scsi_module.c.
> >
> > Which, btw really need to go away. If you want to resurrect the
> > ISA drivers they need to be converted to proper probing.
>
> Yes. I didn't do that conversion because I don't have ISA hardware and I
> don't understand ISA probing.
>
> The present patch set doesn't seek to resurrect the ISA drivers. But I am
> trying to avoid regressions.
>
> I have mixed feelings about the ISA drivers. ISA DMA support complicates
> things (it was never completed) and DMA seems to be the main obstacle to
> merging the two core driver forks.

IIRC, my ISA cards can't do DMA either.

--
Ondrej Zary

2015-11-20 10:01:08

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Fri, Nov 20, 2015 at 07:19:21PM +1100, Finn Thain wrote:
> Yes. I didn't do that conversion because I don't have ISA hardware and I
> don't understand ISA probing.
>
> The present patch set doesn't seek to resurrect the ISA drivers. But I am
> trying to avoid regressions.
>
> I have mixed feelings about the ISA drivers. ISA DMA support complicates
> things (it was never completed) and DMA seems to be the main obstacle to
> merging the two core driver forks.

I'd love to be able to get rid of the ISA drivers to be honest. Given
that they appear to be gravely broken before your cleanups this might
be an opportunity to get rid of them.

2015-11-20 10:53:32

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Fri, 20 Nov 2015, Christoph Hellwig wrote:

> On Fri, Nov 20, 2015 at 07:19:21PM +1100, Finn Thain wrote:
>
> > Yes. I didn't do that conversion because I don't have ISA hardware and
> > I don't understand ISA probing.
> >
> > The present patch set doesn't seek to resurrect the ISA drivers. But I
> > am trying to avoid regressions.
> >
> > I have mixed feelings about the ISA drivers. ISA DMA support
> > complicates things (it was never completed) and DMA seems to be the
> > main obstacle to merging the two core driver forks.
>
> I'd love to be able to get rid of the ISA drivers to be honest.

Is that because of their use of scsi_module.c or their general decrepitude
or something else?

> Given that they appear to be gravely broken before your cleanups this
> might be an opportunity to get rid of them.

At this stage, that's unclear (to me). It could be that g_NCR5380.c is not
broken. It could be that the core driver can't handle certain targets. I
think we need to do more testing.

--

2015-11-20 11:40:15

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Friday 20 November 2015, Finn Thain wrote:
>
> On Fri, 20 Nov 2015, Christoph Hellwig wrote:
>
> > On Fri, Nov 20, 2015 at 07:19:21PM +1100, Finn Thain wrote:
> >
> > > Yes. I didn't do that conversion because I don't have ISA hardware and
> > > I don't understand ISA probing.
> > >
> > > The present patch set doesn't seek to resurrect the ISA drivers. But I
> > > am trying to avoid regressions.
> > >
> > > I have mixed feelings about the ISA drivers. ISA DMA support
> > > complicates things (it was never completed) and DMA seems to be the
> > > main obstacle to merging the two core driver forks.
> >
> > I'd love to be able to get rid of the ISA drivers to be honest.
>
> Is that because of their use of scsi_module.c or their general decrepitude
> or something else?

scsi_module.c usage shouldn't be hard to fix. I can do that after finding a working setup.

> > Given that they appear to be gravely broken before your cleanups this
> > might be an opportunity to get rid of them.
>
> At this stage, that's unclear (to me). It could be that g_NCR5380.c is not
> broken. It could be that the core driver can't handle certain targets. I
> think we need to do more testing.

Maybe I was just unlucky and tested a drive that never worked with this driver.

Working ISA means more testing possibilities. It's much easier to get an ISA card than a Sun or Atari. Also faster CPU (such as 1 GHz P3) means quicker testing.

--
Ondrej Zary

2015-11-20 11:45:24

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Fri, Nov 20, 2015 at 12:40:03PM +0100, Ondrej Zary wrote:
> > > I'd love to be able to get rid of the ISA drivers to be honest.
> >
> > Is that because of their use of scsi_module.c or their general decrepitude
> > or something else?
>
> scsi_module.c usage shouldn't be hard to fix. I can do that after finding a working setup.

It's the general state of them.

>
> > > Given that they appear to be gravely broken before your cleanups this
> > > might be an opportunity to get rid of them.
> >
> > At this stage, that's unclear (to me). It could be that g_NCR5380.c is not
> > broken. It could be that the core driver can't handle certain targets. I
> > think we need to do more testing.
>
> Maybe I was just unlucky and tested a drive that never worked with this driver.
>
> Working ISA means more testing possibilities. It's much easier to get an ISA card than a Sun or Atari. Also faster CPU (such as 1 GHz P3) means quicker testing.


Well, if you volunteer to bring the NCR5380 ISA drivers up to date and
maintain them it's obvuously fine to keep them around.

I'm more worried about all the unmaintained ISA drivers in horrible
shape.

2015-11-20 12:23:20

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Fri, Nov 20, 2015 at 12:40 PM, Ondrej Zary
<[email protected]> wrote:
> Working ISA means more testing possibilities. It's much easier to get an ISA card than a Sun or Atari. Also faster CPU (such as 1 GHz P3) means quicker testing.

Faster PCs without ISA slots? ;-)

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2015-11-20 12:46:32

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Friday 20 November 2015, Geert Uytterhoeven wrote:
> On Fri, Nov 20, 2015 at 12:40 PM, Ondrej Zary
> <[email protected]> wrote:
> > Working ISA means more testing possibilities. It's much easier to get an ISA card than a Sun or Atari. Also faster CPU (such as 1 GHz P3) means quicker testing.
>
> Faster PCs without ISA slots? ;-)

Faster but not too fast, you have to be careful :)
There are many boards for Pentium 3 or Ahlon XP CPUs with ISA slots.

--
Ondrej Zary

2015-11-20 18:29:35

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Friday 20 November 2015 02:41:19 Finn Thain wrote:
>
> On Thu, 19 Nov 2015, Ondrej Zary wrote:
>
> > On Thursday 19 November 2015 03:24:56 Finn Thain wrote:
> >
> > > On Wed, 18 Nov 2015, Ondrej Zary wrote:
> > >
> > > >
> > > > I have some NCR5380 ISA cards and can test them.
> > >
> > > Thanks Ondrej. I've no idea which ISA drivers are presently working in
> > > mainline. Finding regressions may be more difficult than usual ;-)
> >
> > You're right... looks very broken:
> >
> > [ 62.577194] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
> > sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA
> > NCR53C400 }
> > [ 62.796635] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
> > [ 63.878494] sd 2:0:0:0: Attached scsi generic sg1 type 0
> > [ 95.848260] sd 2:0:0:0: aborting command
> >
> > And the system hangs completely.
> >
>
> Yes. That was the usual failure mode. The old EH abort routine is fatal.
> Up until I disabled PDMA by default for mac_scsi (in v3.19), that driver
> would do the same thing.
>
> > It's much better with your patches, but still not great :)
> >
>
> Pleased to hear it :)
>
> > [ 93.963264] pnp 01:01.00: [io 0x0240-0x025f]
> > [ 93.963493] pnp 01:01.00: [irq 5]
> > [ 93.965768] pnp 01:01.00: activated
> > [ 93.977147] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2,
> > sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> > [ 93.987527] scsi host2: rejecting message
> > [ 93.987647] Synchronous Data Transfer Request period = 100 ns offset = 12
> > [ 94.001219] scsi 2:0:0:0: Direct-Access IBM 0663 e PQ: 0 ANSI: 2
> > [ 113.000794] sd 2:0:0:0: Attached scsi generic sg1 type 0
>
> I'd be interested to know what commands were in play in that 19 second
> interval. Might need to use scsi_logging_level to figure that out.
>
> My tests involved 3 different scsi targets (two disks and a CD-ROM) but
> none of these send a SDTR. Your log says the driver correctly rejected the
> SDTR message but that doesn't mean the target actually went to MSG IN
> phase and got the message. Do you have any older targets you can test?

Another disk, without patches:

[ 84.481582] pnp 01:01.00: activated
[ 84.489650] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
[ 84.953332] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 86.786475] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 86.793753] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 86.998555] sd 2:0:1:0: [sdb] Write Protect is off
[ 87.406068] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 118.888271] sd 2:0:1:0: [sdb] aborting command
[ 118.888738] sd 2:0:1:0: [sdb] aborting command

With patches:

[ 258.473748] pnp 01:01.00: activated
[ 258.483592] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 261.347632] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 275.560451] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 275.632519] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 275.635533] sd 2:0:1:0: [sdb] Write Protect is off
[ 275.642315] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 469.076347] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
[ 469.076613] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
[ 469.076851] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
[ 469.077086] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 02 00
[ 469.077306] blk_update_request: I/O error, dev sdb, sector 2
[ 469.077522] Buffer I/O error on dev sdb, logical block 1, async page read
[ 480.108255] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
[ 480.109773] Not tainted 4.3.0-rc1+ #74
[ 480.109973] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 480.110179] kworker/u2:2 D 00000040 0 60 2 0x00000000
[ 480.110671] Workqueue: events_unbound async_run_entry_fn
[ 480.110999] cf9e8780 00000046 2eff25f7 00000040 c117f111 2ee82733 00000040 0016fec4
[ 480.112390] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
[ 480.113661] 00000040 cfaa5cfc c106f460 00161108 00000000 0000c648 2106dcce 00000040
[ 480.114893] Call Trace:
[ 480.115124] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
[ 480.115344] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
[ 480.115564] [<c139c504>] ? schedule+0x5b/0x67
[ 480.115794] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
[ 480.116007] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
[ 480.116406] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
[ 480.116636] [<c106fae7>] ? ktime_get+0x38/0x48
[ 480.116843] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
[ 480.117062] [<c139c7f3>] ? bit_wait_io+0x21/0x26
[ 480.117256] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
[ 480.117486] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
[ 480.117704] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
[ 480.117942] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
[ 480.118151] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
[ 480.118373] [<c10ae0e1>] ? do_read_cache_page+0x8e/0x116
[ 480.118587] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
[ 480.118809] [<c10ae192>] ? read_cache_page+0x14/0x18
[ 480.119008] [<c1189b0e>] ? read_dev_sector+0x25/0x57
[ 480.119222] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
[ 480.119438] [<c119a3f1>] ? vsnprintf+0x78/0x25d
[ 480.119671] [<c119a614>] ? snprintf+0x16/0x18
[ 480.119874] [<c118a7ea>] ? check_partition+0xd7/0x165
[ 480.120253] [<c118a067>] ? rescan_partitions+0x95/0x283
[ 480.120443] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
[ 480.120693] [<c139cbc6>] ? mutex_lock+0x9/0x21
[ 480.120915] [<c1100046>] ? __blkdev_get+0x155/0x2f6
[ 480.121133] [<c110032f>] ? blkdev_get+0x148/0x258
[ 480.121350] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
[ 480.121570] [<c10ff106>] ? bdget+0xdc/0xe6
[ 480.121761] [<c118854f>] ? add_disk+0x221/0x368
[ 480.121996] [<c126321a>] ? sd_probe_async+0xed/0x157
[ 480.122214] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
[ 480.122437] [<c103f060>] ? process_one_work+0x130/0x21f
[ 480.122639] [<c103f2f6>] ? worker_thread+0x18a/0x247
[ 480.122854] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
[ 480.123069] [<c1042c46>] ? kthread+0x7c/0x81
[ 480.123288] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
[ 480.123493] [<c1042bca>] ? kthread_parkme+0x11/0x11
[ 480.123733] INFO: task modprobe:1977 blocked for more than 120 seconds.
[ 480.123919] Not tainted 4.3.0-rc1+ #74
[ 480.124239] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 480.124410] modprobe D 00000040 0 1977 1969 0x00000000
[ 480.124864] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
[ 480.126123] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
[ 480.127354] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
[ 480.128746] Call Trace:
[ 480.128961] [<c139c504>] ? schedule+0x5b/0x67
[ 480.129202] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 480.129449] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 480.129667] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 480.129899] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 480.130119] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 480.130346] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 502.100317] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
[ 502.100578] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
[ 502.100818] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
[ 502.101057] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 04 00 00 02 00
[ 502.101279] blk_update_request: I/O error, dev sdb, sector 4
[ 502.101495] Buffer I/O error on dev sdb, logical block 2, async page read
[ 600.128255] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
[ 600.128486] Not tainted 4.3.0-rc1+ #74
[ 600.128687] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 600.128891] kworker/u2:2 D 00000040 0 60 2 0x00000000
[ 600.129381] Workqueue: events_unbound async_run_entry_fn
[ 600.129709] cf9e8780 00000046 2eff25f7 00000040 c117f111 2ee82733 00000040 0016fec4
[ 600.130941] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
[ 600.132342] 00000040 cfaa5cfc c106f460 00161108 00000000 0000c648 2106dcce 00000040
[ 600.133613] Call Trace:
[ 600.133821] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
[ 600.134065] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
[ 600.134283] [<c139c504>] ? schedule+0x5b/0x67
[ 600.134509] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
[ 600.134723] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
[ 600.134948] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
[ 600.135154] [<c106fae7>] ? ktime_get+0x38/0x48
[ 600.135377] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
[ 600.135576] [<c139c7f3>] ? bit_wait_io+0x21/0x26
[ 600.135788] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
[ 600.136000] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
[ 600.136399] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
[ 600.136607] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
[ 600.136838] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
[ 600.137044] [<c10ae0e1>] ? do_read_cache_page+0x8e/0x116
[ 600.137276] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
[ 600.137481] [<c10ae192>] ? read_cache_page+0x14/0x18
[ 600.137699] [<c1189b0e>] ? read_dev_sector+0x25/0x57
[ 600.137901] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
[ 600.138131] [<c119a3f1>] ? vsnprintf+0x78/0x25d
[ 600.138329] [<c119a614>] ? snprintf+0x16/0x18
[ 600.138544] [<c118a7ea>] ? check_partition+0xd7/0x165
[ 600.138738] [<c118a067>] ? rescan_partitions+0x95/0x283
[ 600.138962] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
[ 600.139189] [<c139cbc6>] ? mutex_lock+0x9/0x21
[ 600.139427] [<c1100046>] ? __blkdev_get+0x155/0x2f6
[ 600.139632] [<c110032f>] ? blkdev_get+0x148/0x258
[ 600.139865] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
[ 600.140263] [<c10ff106>] ? bdget+0xdc/0xe6
[ 600.140448] [<c118854f>] ? add_disk+0x221/0x368
[ 600.140689] [<c126321a>] ? sd_probe_async+0xed/0x157
[ 600.140908] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
[ 600.141133] [<c103f060>] ? process_one_work+0x130/0x21f
[ 600.141336] [<c103f2f6>] ? worker_thread+0x18a/0x247
[ 600.141552] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
[ 600.141764] [<c1042c46>] ? kthread+0x7c/0x81
[ 600.141982] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
[ 600.142186] [<c1042bca>] ? kthread_parkme+0x11/0x11
[ 600.142426] INFO: task modprobe:1977 blocked for more than 120 seconds.
[ 600.142612] Not tainted 4.3.0-rc1+ #74
[ 600.142787] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 600.142991] modprobe D 00000040 0 1977 1969 0x00000000
[ 600.143444] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
[ 600.144819] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
[ 600.146052] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
[ 600.147279] Call Trace:
[ 600.147489] [<c139c504>] ? schedule+0x5b/0x67
[ 600.147729] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 600.147992] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 600.148390] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 600.148627] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 600.148846] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 600.149073] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 662.100333] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
[ 662.100598] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
[ 662.100838] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
[ 662.101076] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 06 00 00 02 00
[ 662.101297] blk_update_request: I/O error, dev sdb, sector 6
[ 662.101512] Buffer I/O error on dev sdb, logical block 3, async page read
[ 720.148270] INFO: task modprobe:1977 blocked for more than 120 seconds.
[ 720.148499] Not tainted 4.3.0-rc1+ #74
[ 720.148699] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 720.148903] modprobe D 00000040 0 1977 1969 0x00000000
[ 720.149360] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
[ 720.150615] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
[ 720.151836] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
[ 720.153221] Call Trace:
[ 720.153465] [<c139c504>] ? schedule+0x5b/0x67
[ 720.153689] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 720.153931] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 720.154149] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 720.154379] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 720.154593] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 720.154820] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 781.025039] systemd-logind[1942]: New session c2 of user rainbow.
[ 840.152254] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
[ 840.152486] Not tainted 4.3.0-rc1+ #74
[ 840.152693] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 840.152903] kworker/u2:2 D 0000009a 0 60 2 0x00000000
[ 840.153399] Workqueue: events_unbound async_run_entry_fn
[ 840.153730] cf9e8780 00000046 2860b1ff 0000009a c117f111 284404dd 0000009a 001cad22
[ 840.156408] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
[ 840.157689] 0000009a cfaa5c64 c106f460 00161e18 00000000 00013d94 006b70ce 0000009a
[ 840.158925] Call Trace:
[ 840.159158] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
[ 840.159379] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
[ 840.159600] [<c139c504>] ? schedule+0x5b/0x67
[ 840.159834] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
[ 840.160052] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
[ 840.160446] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
[ 840.160677] [<c106fae7>] ? ktime_get+0x38/0x48
[ 840.160884] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
[ 840.161105] [<c139c7f3>] ? bit_wait_io+0x21/0x26
[ 840.161306] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
[ 840.161541] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
[ 840.161767] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
[ 840.161997] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
[ 840.162206] [<c10ae14f>] ? do_read_cache_page+0xfc/0x116
[ 840.162445] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
[ 840.162651] [<c10ae192>] ? read_cache_page+0x14/0x18
[ 840.162872] [<c1189b0e>] ? read_dev_sector+0x25/0x57
[ 840.163073] [<c118e22f>] ? read_lba+0x94/0x10b
[ 840.163289] [<c118e7eb>] ? efi_partition+0xbc/0x451
[ 840.163506] [<c10b5c33>] ? put_page+0x16/0x24
[ 840.163732] [<c10ad39d>] ? wait_on_page_read+0x26/0x2a
[ 840.163968] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
[ 840.164348] [<c10ae192>] ? read_cache_page+0x14/0x18
[ 840.164541] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
[ 840.164777] [<c119a3f1>] ? vsnprintf+0x78/0x25d
[ 840.164977] [<c119a614>] ? snprintf+0x16/0x18
[ 840.165187] [<c118a7ea>] ? check_partition+0xd7/0x165
[ 840.165382] [<c118a067>] ? rescan_partitions+0x95/0x283
[ 840.165603] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
[ 840.165829] [<c139cbc6>] ? mutex_lock+0x9/0x21
[ 840.166066] [<c1100046>] ? __blkdev_get+0x155/0x2f6
[ 840.166270] [<c110032f>] ? blkdev_get+0x148/0x258
[ 840.166501] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
[ 840.166707] [<c10ff106>] ? bdget+0xdc/0xe6
[ 840.166914] [<c118854f>] ? add_disk+0x221/0x368
[ 840.167134] [<c126321a>] ? sd_probe_async+0xed/0x157
[ 840.167372] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
[ 840.167582] [<c103f060>] ? process_one_work+0x130/0x21f
[ 840.167802] [<c103f2f6>] ? worker_thread+0x18a/0x247
[ 840.168006] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
[ 840.168416] [<c1042c46>] ? kthread+0x7c/0x81
[ 840.168642] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
[ 840.168847] [<c1042bca>] ? kthread_parkme+0x11/0x11
[ 840.169094] INFO: task modprobe:1977 blocked for more than 120 seconds.
[ 840.169281] Not tainted 4.3.0-rc1+ #74
[ 840.169454] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 840.169659] modprobe D 00000040 0 1977 1969 0x00000000
[ 840.170114] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
[ 840.171368] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
[ 840.172741] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
[ 840.173986] Call Trace:
[ 840.174200] [<c139c504>] ? schedule+0x5b/0x67
[ 840.174443] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
[ 840.174689] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
[ 840.174910] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
[ 840.175141] [<c107ddb5>] ? load_module+0x14de/0x18ca
[ 840.175359] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
[ 840.175607] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
[ 856.020359] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
[ 856.020623] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
[ 856.020862] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
[ 856.021101] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 02 00
[ 856.021324] blk_update_request: I/O error, dev sdb, sector 2
[ 856.021539] Buffer I/O error on dev sdb, logical block 1, async page read
[ 857.025325] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_ABORT driverbyte=DRIVER_OK
[ 857.025596] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 04 00 00 02 00
[ 857.025830] blk_update_request: I/O error, dev sdb, sector 4
[ 857.026043] Buffer I/O error on dev sdb, logical block 2, async page read


And a CD-ROM, first without patches:
[ 655.929795] pnp 01:01.00: activated
[ 655.939503] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
[ 656.441943] scsi 2:0:2:0: CD-ROM SONY CD-ROM CDU-55S 1.0t PQ: 0 ANSI: 2
[ 657.829087] scsi 2:0:2:0: Attached scsi generic sg1 type 5
[ 658.325517] sr 2:0:2:0: [sr0] scsi-1 drive
[ 658.325731] cdrom: Uniform CD-ROM driver Revision: 3.20

Modprobe succeeded but mount resulted in this & hang:
[ 694.056266] sr 2:0:2:0: [sr0] aborting command

Then with patches:

[ 109.753273] pnp 01:01.00: activated
[ 109.763039] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 115.456294] scsi 2:0:2:0: CD-ROM SONY CD-ROM CDU-55S 1.0t PQ: 0 ANSI: 2
[ 126.823400] scsi 2:0:2:0: Attached scsi generic sg1 type 5
[ 126.909680] sr 2:0:2:0: [sr0] scsi-1 drive
[ 126.909888] cdrom: Uniform CD-ROM driver Revision: 3.20

Modprobe succeeded but mount failed after some time with this:
[ 1005.149546] sr 2:0:2:0: [sr0] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[ 1005.149764] sr 2:0:2:0: [sr0] Sense Key : Illegal Request [current]
[ 1005.149992] sr 2:0:2:0: [sr0] Add. Sense: Logical block address out of range
[ 1005.150222] sr 2:0:2:0: [sr0] CDB: Read(10) 28 00 00 05 7a 94 00 00 02 00
[ 1005.150433] blk_update_request: critical target error, dev sr0, sector 1436240
[ 1005.154101] sr 2:0:2:0: [sr0] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[ 1005.154309] sr 2:0:2:0: [sr0] Sense Key : Illegal Request [current]
[ 1005.154533] sr 2:0:2:0: [sr0] Add. Sense: Logical block address out of range
[ 1005.156209] sr 2:0:2:0: [sr0] CDB: Read(10) 28 00 00 05 7a 94 00 00 02 00
[ 1005.156404] blk_update_request: critical target error, dev sr0, sector 1436240
[ 1005.156607] Buffer I/O error on dev sr0, logical block 179530, async page read

mount: unknown filesystem type 'iso9660'

--
Ondrej Zary

2015-11-21 01:59:36

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


Hi Ondrej,

On Fri, 20 Nov 2015, Ondrej Zary wrote:

> On Friday 20 November 2015 02:41:19 Finn Thain wrote:
> >
> >
> > My tests involved 3 different scsi targets (two disks and a CD-ROM)
> > but none of these send a SDTR. Your log says the driver correctly
> > rejected the SDTR message but that doesn't mean the target actually
> > went to MSG IN phase and got the message. Do you have any older
> > targets you can test?
>
> Another disk, without patches:
>
> [ 84.481582] pnp 01:01.00: activated
> [ 84.489650] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> [ 84.953332] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 86.786475] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 86.793753] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 86.998555] sd 2:0:1:0: [sdb] Write Protect is off
> [ 87.406068] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 118.888271] sd 2:0:1:0: [sdb] aborting command
> [ 118.888738] sd 2:0:1:0: [sdb] aborting command
>
> With patches:
>
> [ 258.473748] pnp 01:01.00: activated
> [ 258.483592] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 261.347632] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 275.560451] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 275.632519] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 275.635533] sd 2:0:1:0: [sdb] Write Protect is off
> [ 275.642315] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 469.076347] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> [ 469.076613] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> [ 469.076851] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> [ 469.077086] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 02 00
> [ 469.077306] blk_update_request: I/O error, dev sdb, sector 2
> [ 469.077522] Buffer I/O error on dev sdb, logical block 1, async page read
> [ 480.108255] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
> [ 480.109773] Not tainted 4.3.0-rc1+ #74
> [ 480.109973] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 480.110179] kworker/u2:2 D 00000040 0 60 2 0x00000000
> [ 480.110671] Workqueue: events_unbound async_run_entry_fn
> [ 480.110999] cf9e8780 00000046 2eff25f7 00000040 c117f111 2ee82733 00000040 0016fec4
> [ 480.112390] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
> [ 480.113661] 00000040 cfaa5cfc c106f460 00161108 00000000 0000c648 2106dcce 00000040
> [ 480.114893] Call Trace:
> [ 480.115124] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
> [ 480.115344] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> [ 480.115564] [<c139c504>] ? schedule+0x5b/0x67
> [ 480.115794] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
> [ 480.116007] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
> [ 480.116406] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> [ 480.116636] [<c106fae7>] ? ktime_get+0x38/0x48
> [ 480.116843] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
> [ 480.117062] [<c139c7f3>] ? bit_wait_io+0x21/0x26
> [ 480.117256] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
> [ 480.117486] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> [ 480.117704] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
> [ 480.117942] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
> [ 480.118151] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
> [ 480.118373] [<c10ae0e1>] ? do_read_cache_page+0x8e/0x116
> [ 480.118587] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> [ 480.118809] [<c10ae192>] ? read_cache_page+0x14/0x18
> [ 480.119008] [<c1189b0e>] ? read_dev_sector+0x25/0x57
> [ 480.119222] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
> [ 480.119438] [<c119a3f1>] ? vsnprintf+0x78/0x25d
> [ 480.119671] [<c119a614>] ? snprintf+0x16/0x18
> [ 480.119874] [<c118a7ea>] ? check_partition+0xd7/0x165
> [ 480.120253] [<c118a067>] ? rescan_partitions+0x95/0x283
> [ 480.120443] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
> [ 480.120693] [<c139cbc6>] ? mutex_lock+0x9/0x21
> [ 480.120915] [<c1100046>] ? __blkdev_get+0x155/0x2f6
> [ 480.121133] [<c110032f>] ? blkdev_get+0x148/0x258
> [ 480.121350] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
> [ 480.121570] [<c10ff106>] ? bdget+0xdc/0xe6
> [ 480.121761] [<c118854f>] ? add_disk+0x221/0x368
> [ 480.121996] [<c126321a>] ? sd_probe_async+0xed/0x157
> [ 480.122214] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
> [ 480.122437] [<c103f060>] ? process_one_work+0x130/0x21f
> [ 480.122639] [<c103f2f6>] ? worker_thread+0x18a/0x247
> [ 480.122854] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
> [ 480.123069] [<c1042c46>] ? kthread+0x7c/0x81
> [ 480.123288] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
> [ 480.123493] [<c1042bca>] ? kthread_parkme+0x11/0x11
> [ 480.123733] INFO: task modprobe:1977 blocked for more than 120 seconds.
> [ 480.123919] Not tainted 4.3.0-rc1+ #74
> [ 480.124239] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 480.124410] modprobe D 00000040 0 1977 1969 0x00000000
> [ 480.124864] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> [ 480.126123] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> [ 480.127354] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> [ 480.128746] Call Trace:
> [ 480.128961] [<c139c504>] ? schedule+0x5b/0x67
> [ 480.129202] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 480.129449] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 480.129667] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 480.129899] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 480.130119] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 480.130346] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> [ 502.100317] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> [ 502.100578] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> [ 502.100818] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> [ 502.101057] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 04 00 00 02 00
> [ 502.101279] blk_update_request: I/O error, dev sdb, sector 4
> [ 502.101495] Buffer I/O error on dev sdb, logical block 2, async page read
> [ 600.128255] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
> [ 600.128486] Not tainted 4.3.0-rc1+ #74
> [ 600.128687] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 600.128891] kworker/u2:2 D 00000040 0 60 2 0x00000000
> [ 600.129381] Workqueue: events_unbound async_run_entry_fn
> [ 600.129709] cf9e8780 00000046 2eff25f7 00000040 c117f111 2ee82733 00000040 0016fec4
> [ 600.130941] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
> [ 600.132342] 00000040 cfaa5cfc c106f460 00161108 00000000 0000c648 2106dcce 00000040
> [ 600.133613] Call Trace:
> [ 600.133821] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
> [ 600.134065] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> [ 600.134283] [<c139c504>] ? schedule+0x5b/0x67
> [ 600.134509] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
> [ 600.134723] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
> [ 600.134948] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> [ 600.135154] [<c106fae7>] ? ktime_get+0x38/0x48
> [ 600.135377] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
> [ 600.135576] [<c139c7f3>] ? bit_wait_io+0x21/0x26
> [ 600.135788] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
> [ 600.136000] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> [ 600.136399] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
> [ 600.136607] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
> [ 600.136838] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
> [ 600.137044] [<c10ae0e1>] ? do_read_cache_page+0x8e/0x116
> [ 600.137276] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> [ 600.137481] [<c10ae192>] ? read_cache_page+0x14/0x18
> [ 600.137699] [<c1189b0e>] ? read_dev_sector+0x25/0x57
> [ 600.137901] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
> [ 600.138131] [<c119a3f1>] ? vsnprintf+0x78/0x25d
> [ 600.138329] [<c119a614>] ? snprintf+0x16/0x18
> [ 600.138544] [<c118a7ea>] ? check_partition+0xd7/0x165
> [ 600.138738] [<c118a067>] ? rescan_partitions+0x95/0x283
> [ 600.138962] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
> [ 600.139189] [<c139cbc6>] ? mutex_lock+0x9/0x21
> [ 600.139427] [<c1100046>] ? __blkdev_get+0x155/0x2f6
> [ 600.139632] [<c110032f>] ? blkdev_get+0x148/0x258
> [ 600.139865] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
> [ 600.140263] [<c10ff106>] ? bdget+0xdc/0xe6
> [ 600.140448] [<c118854f>] ? add_disk+0x221/0x368
> [ 600.140689] [<c126321a>] ? sd_probe_async+0xed/0x157
> [ 600.140908] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
> [ 600.141133] [<c103f060>] ? process_one_work+0x130/0x21f
> [ 600.141336] [<c103f2f6>] ? worker_thread+0x18a/0x247
> [ 600.141552] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
> [ 600.141764] [<c1042c46>] ? kthread+0x7c/0x81
> [ 600.141982] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
> [ 600.142186] [<c1042bca>] ? kthread_parkme+0x11/0x11
> [ 600.142426] INFO: task modprobe:1977 blocked for more than 120 seconds.
> [ 600.142612] Not tainted 4.3.0-rc1+ #74
> [ 600.142787] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 600.142991] modprobe D 00000040 0 1977 1969 0x00000000
> [ 600.143444] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> [ 600.144819] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> [ 600.146052] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> [ 600.147279] Call Trace:
> [ 600.147489] [<c139c504>] ? schedule+0x5b/0x67
> [ 600.147729] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 600.147992] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 600.148390] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 600.148627] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 600.148846] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 600.149073] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> [ 662.100333] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> [ 662.100598] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> [ 662.100838] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> [ 662.101076] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 06 00 00 02 00
> [ 662.101297] blk_update_request: I/O error, dev sdb, sector 6
> [ 662.101512] Buffer I/O error on dev sdb, logical block 3, async page read
> [ 720.148270] INFO: task modprobe:1977 blocked for more than 120 seconds.
> [ 720.148499] Not tainted 4.3.0-rc1+ #74
> [ 720.148699] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 720.148903] modprobe D 00000040 0 1977 1969 0x00000000
> [ 720.149360] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> [ 720.150615] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> [ 720.151836] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> [ 720.153221] Call Trace:
> [ 720.153465] [<c139c504>] ? schedule+0x5b/0x67
> [ 720.153689] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 720.153931] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 720.154149] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 720.154379] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 720.154593] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 720.154820] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> [ 781.025039] systemd-logind[1942]: New session c2 of user rainbow.
> [ 840.152254] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
> [ 840.152486] Not tainted 4.3.0-rc1+ #74
> [ 840.152693] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 840.152903] kworker/u2:2 D 0000009a 0 60 2 0x00000000
> [ 840.153399] Workqueue: events_unbound async_run_entry_fn
> [ 840.153730] cf9e8780 00000046 2860b1ff 0000009a c117f111 284404dd 0000009a 001cad22
> [ 840.156408] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
> [ 840.157689] 0000009a cfaa5c64 c106f460 00161e18 00000000 00013d94 006b70ce 0000009a
> [ 840.158925] Call Trace:
> [ 840.159158] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
> [ 840.159379] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> [ 840.159600] [<c139c504>] ? schedule+0x5b/0x67
> [ 840.159834] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
> [ 840.160052] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
> [ 840.160446] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> [ 840.160677] [<c106fae7>] ? ktime_get+0x38/0x48
> [ 840.160884] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
> [ 840.161105] [<c139c7f3>] ? bit_wait_io+0x21/0x26
> [ 840.161306] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
> [ 840.161541] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
> [ 840.161767] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
> [ 840.161997] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
> [ 840.162206] [<c10ae14f>] ? do_read_cache_page+0xfc/0x116
> [ 840.162445] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> [ 840.162651] [<c10ae192>] ? read_cache_page+0x14/0x18
> [ 840.162872] [<c1189b0e>] ? read_dev_sector+0x25/0x57
> [ 840.163073] [<c118e22f>] ? read_lba+0x94/0x10b
> [ 840.163289] [<c118e7eb>] ? efi_partition+0xbc/0x451
> [ 840.163506] [<c10b5c33>] ? put_page+0x16/0x24
> [ 840.163732] [<c10ad39d>] ? wait_on_page_read+0x26/0x2a
> [ 840.163968] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> [ 840.164348] [<c10ae192>] ? read_cache_page+0x14/0x18
> [ 840.164541] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
> [ 840.164777] [<c119a3f1>] ? vsnprintf+0x78/0x25d
> [ 840.164977] [<c119a614>] ? snprintf+0x16/0x18
> [ 840.165187] [<c118a7ea>] ? check_partition+0xd7/0x165
> [ 840.165382] [<c118a067>] ? rescan_partitions+0x95/0x283
> [ 840.165603] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
> [ 840.165829] [<c139cbc6>] ? mutex_lock+0x9/0x21
> [ 840.166066] [<c1100046>] ? __blkdev_get+0x155/0x2f6
> [ 840.166270] [<c110032f>] ? blkdev_get+0x148/0x258
> [ 840.166501] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
> [ 840.166707] [<c10ff106>] ? bdget+0xdc/0xe6
> [ 840.166914] [<c118854f>] ? add_disk+0x221/0x368
> [ 840.167134] [<c126321a>] ? sd_probe_async+0xed/0x157
> [ 840.167372] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
> [ 840.167582] [<c103f060>] ? process_one_work+0x130/0x21f
> [ 840.167802] [<c103f2f6>] ? worker_thread+0x18a/0x247
> [ 840.168006] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
> [ 840.168416] [<c1042c46>] ? kthread+0x7c/0x81
> [ 840.168642] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
> [ 840.168847] [<c1042bca>] ? kthread_parkme+0x11/0x11
> [ 840.169094] INFO: task modprobe:1977 blocked for more than 120 seconds.
> [ 840.169281] Not tainted 4.3.0-rc1+ #74
> [ 840.169454] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 840.169659] modprobe D 00000040 0 1977 1969 0x00000000
> [ 840.170114] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> [ 840.171368] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> [ 840.172741] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> [ 840.173986] Call Trace:
> [ 840.174200] [<c139c504>] ? schedule+0x5b/0x67
> [ 840.174443] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> [ 840.174689] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> [ 840.174910] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> [ 840.175141] [<c107ddb5>] ? load_module+0x14de/0x18ca
> [ 840.175359] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> [ 840.175607] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> [ 856.020359] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> [ 856.020623] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> [ 856.020862] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> [ 856.021101] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 02 00
> [ 856.021324] blk_update_request: I/O error, dev sdb, sector 2
> [ 856.021539] Buffer I/O error on dev sdb, logical block 1, async page read
> [ 857.025325] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_ABORT driverbyte=DRIVER_OK
> [ 857.025596] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 04 00 00 02 00
> [ 857.025830] blk_update_request: I/O error, dev sdb, sector 4
> [ 857.026043] Buffer I/O error on dev sdb, logical block 2, async page read
>
>
> And a CD-ROM, first without patches:
> [ 655.929795] pnp 01:01.00: activated
> [ 655.939503] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> [ 656.441943] scsi 2:0:2:0: CD-ROM SONY CD-ROM CDU-55S 1.0t PQ: 0 ANSI: 2
> [ 657.829087] scsi 2:0:2:0: Attached scsi generic sg1 type 5
> [ 658.325517] sr 2:0:2:0: [sr0] scsi-1 drive
> [ 658.325731] cdrom: Uniform CD-ROM driver Revision: 3.20
>
> Modprobe succeeded but mount resulted in this & hang:
> [ 694.056266] sr 2:0:2:0: [sr0] aborting command
>
> Then with patches:
>
> [ 109.753273] pnp 01:01.00: activated
> [ 109.763039] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 115.456294] scsi 2:0:2:0: CD-ROM SONY CD-ROM CDU-55S 1.0t PQ: 0 ANSI: 2
> [ 126.823400] scsi 2:0:2:0: Attached scsi generic sg1 type 5
> [ 126.909680] sr 2:0:2:0: [sr0] scsi-1 drive
> [ 126.909888] cdrom: Uniform CD-ROM driver Revision: 3.20
>
> Modprobe succeeded but mount failed after some time with this:
> [ 1005.149546] sr 2:0:2:0: [sr0] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> [ 1005.149764] sr 2:0:2:0: [sr0] Sense Key : Illegal Request [current]
> [ 1005.149992] sr 2:0:2:0: [sr0] Add. Sense: Logical block address out of range
> [ 1005.150222] sr 2:0:2:0: [sr0] CDB: Read(10) 28 00 00 05 7a 94 00 00 02 00
> [ 1005.150433] blk_update_request: critical target error, dev sr0, sector 1436240
> [ 1005.154101] sr 2:0:2:0: [sr0] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> [ 1005.154309] sr 2:0:2:0: [sr0] Sense Key : Illegal Request [current]
> [ 1005.154533] sr 2:0:2:0: [sr0] Add. Sense: Logical block address out of range
> [ 1005.156209] sr 2:0:2:0: [sr0] CDB: Read(10) 28 00 00 05 7a 94 00 00 02 00
> [ 1005.156404] blk_update_request: critical target error, dev sr0, sector 1436240
> [ 1005.156607] Buffer I/O error on dev sr0, logical block 179530, async page read
>
> mount: unknown filesystem type 'iso9660'
>
>

Thanks for these test results! It looks like READ(10) commands don't work.
I don't know the cause of the failures but it appears to be an old bug.
Did you find any regression?

I gather that your setup here is a QUANTUM LP240S target with Domex 3181
(DTC-436) card and g_NCR5380 module. I've been testing a similar setup:
QUANTUM LPS540S target with a Domex 3191D (DTC-536) card and dmx3191d
module. In both setups PIO is used exclusively, no IRQ is used, and
FLAG_DTC3181E is set. I didn't see any issues in my tests, so your results
are surprising.

Let me know off-list if you want any help to debug this. Unfortunately,
Domex Technology Corporation in Taiwan never responded to my requests for
data on the DTC-536 device so there's probably no point in asking them for
data on the DTC-436 device either.

--

2015-11-21 13:02:19

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Saturday 21 November 2015 02:58:57 Finn Thain wrote:
>
> Hi Ondrej,
>
> On Fri, 20 Nov 2015, Ondrej Zary wrote:
>
> > On Friday 20 November 2015 02:41:19 Finn Thain wrote:
> > >
> > >
> > > My tests involved 3 different scsi targets (two disks and a CD-ROM)
> > > but none of these send a SDTR. Your log says the driver correctly
> > > rejected the SDTR message but that doesn't mean the target actually
> > > went to MSG IN phase and got the message. Do you have any older
> > > targets you can test?
> >
> > Another disk, without patches:
> >
> > [ 84.481582] pnp 01:01.00: activated
> > [ 84.489650] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> > [ 84.953332] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> > [ 86.786475] sd 2:0:1:0: Attached scsi generic sg1 type 0
> > [ 86.793753] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> > [ 86.998555] sd 2:0:1:0: [sdb] Write Protect is off
> > [ 87.406068] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> > [ 118.888271] sd 2:0:1:0: [sdb] aborting command
> > [ 118.888738] sd 2:0:1:0: [sdb] aborting command
> >
> > With patches:
> >
> > [ 258.473748] pnp 01:01.00: activated
> > [ 258.483592] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> > [ 261.347632] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> > [ 275.560451] sd 2:0:1:0: Attached scsi generic sg1 type 0
> > [ 275.632519] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> > [ 275.635533] sd 2:0:1:0: [sdb] Write Protect is off
> > [ 275.642315] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> > [ 469.076347] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> > [ 469.076613] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> > [ 469.076851] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> > [ 469.077086] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 02 00
> > [ 469.077306] blk_update_request: I/O error, dev sdb, sector 2
> > [ 469.077522] Buffer I/O error on dev sdb, logical block 1, async page read
> > [ 480.108255] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
> > [ 480.109773] Not tainted 4.3.0-rc1+ #74
> > [ 480.109973] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 480.110179] kworker/u2:2 D 00000040 0 60 2 0x00000000
> > [ 480.110671] Workqueue: events_unbound async_run_entry_fn
> > [ 480.110999] cf9e8780 00000046 2eff25f7 00000040 c117f111 2ee82733 00000040 0016fec4
> > [ 480.112390] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
> > [ 480.113661] 00000040 cfaa5cfc c106f460 00161108 00000000 0000c648 2106dcce 00000040
> > [ 480.114893] Call Trace:
> > [ 480.115124] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
> > [ 480.115344] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> > [ 480.115564] [<c139c504>] ? schedule+0x5b/0x67
> > [ 480.115794] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
> > [ 480.116007] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
> > [ 480.116406] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> > [ 480.116636] [<c106fae7>] ? ktime_get+0x38/0x48
> > [ 480.116843] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
> > [ 480.117062] [<c139c7f3>] ? bit_wait_io+0x21/0x26
> > [ 480.117256] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
> > [ 480.117486] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> > [ 480.117704] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
> > [ 480.117942] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
> > [ 480.118151] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
> > [ 480.118373] [<c10ae0e1>] ? do_read_cache_page+0x8e/0x116
> > [ 480.118587] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> > [ 480.118809] [<c10ae192>] ? read_cache_page+0x14/0x18
> > [ 480.119008] [<c1189b0e>] ? read_dev_sector+0x25/0x57
> > [ 480.119222] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
> > [ 480.119438] [<c119a3f1>] ? vsnprintf+0x78/0x25d
> > [ 480.119671] [<c119a614>] ? snprintf+0x16/0x18
> > [ 480.119874] [<c118a7ea>] ? check_partition+0xd7/0x165
> > [ 480.120253] [<c118a067>] ? rescan_partitions+0x95/0x283
> > [ 480.120443] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
> > [ 480.120693] [<c139cbc6>] ? mutex_lock+0x9/0x21
> > [ 480.120915] [<c1100046>] ? __blkdev_get+0x155/0x2f6
> > [ 480.121133] [<c110032f>] ? blkdev_get+0x148/0x258
> > [ 480.121350] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
> > [ 480.121570] [<c10ff106>] ? bdget+0xdc/0xe6
> > [ 480.121761] [<c118854f>] ? add_disk+0x221/0x368
> > [ 480.121996] [<c126321a>] ? sd_probe_async+0xed/0x157
> > [ 480.122214] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
> > [ 480.122437] [<c103f060>] ? process_one_work+0x130/0x21f
> > [ 480.122639] [<c103f2f6>] ? worker_thread+0x18a/0x247
> > [ 480.122854] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
> > [ 480.123069] [<c1042c46>] ? kthread+0x7c/0x81
> > [ 480.123288] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
> > [ 480.123493] [<c1042bca>] ? kthread_parkme+0x11/0x11
> > [ 480.123733] INFO: task modprobe:1977 blocked for more than 120 seconds.
> > [ 480.123919] Not tainted 4.3.0-rc1+ #74
> > [ 480.124239] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 480.124410] modprobe D 00000040 0 1977 1969 0x00000000
> > [ 480.124864] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> > [ 480.126123] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> > [ 480.127354] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> > [ 480.128746] Call Trace:
> > [ 480.128961] [<c139c504>] ? schedule+0x5b/0x67
> > [ 480.129202] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> > [ 480.129449] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> > [ 480.129667] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> > [ 480.129899] [<c107ddb5>] ? load_module+0x14de/0x18ca
> > [ 480.130119] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> > [ 480.130346] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> > [ 502.100317] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> > [ 502.100578] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> > [ 502.100818] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> > [ 502.101057] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 04 00 00 02 00
> > [ 502.101279] blk_update_request: I/O error, dev sdb, sector 4
> > [ 502.101495] Buffer I/O error on dev sdb, logical block 2, async page read
> > [ 600.128255] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
> > [ 600.128486] Not tainted 4.3.0-rc1+ #74
> > [ 600.128687] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 600.128891] kworker/u2:2 D 00000040 0 60 2 0x00000000
> > [ 600.129381] Workqueue: events_unbound async_run_entry_fn
> > [ 600.129709] cf9e8780 00000046 2eff25f7 00000040 c117f111 2ee82733 00000040 0016fec4
> > [ 600.130941] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
> > [ 600.132342] 00000040 cfaa5cfc c106f460 00161108 00000000 0000c648 2106dcce 00000040
> > [ 600.133613] Call Trace:
> > [ 600.133821] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
> > [ 600.134065] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> > [ 600.134283] [<c139c504>] ? schedule+0x5b/0x67
> > [ 600.134509] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
> > [ 600.134723] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
> > [ 600.134948] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> > [ 600.135154] [<c106fae7>] ? ktime_get+0x38/0x48
> > [ 600.135377] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
> > [ 600.135576] [<c139c7f3>] ? bit_wait_io+0x21/0x26
> > [ 600.135788] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
> > [ 600.136000] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> > [ 600.136399] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
> > [ 600.136607] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
> > [ 600.136838] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
> > [ 600.137044] [<c10ae0e1>] ? do_read_cache_page+0x8e/0x116
> > [ 600.137276] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> > [ 600.137481] [<c10ae192>] ? read_cache_page+0x14/0x18
> > [ 600.137699] [<c1189b0e>] ? read_dev_sector+0x25/0x57
> > [ 600.137901] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
> > [ 600.138131] [<c119a3f1>] ? vsnprintf+0x78/0x25d
> > [ 600.138329] [<c119a614>] ? snprintf+0x16/0x18
> > [ 600.138544] [<c118a7ea>] ? check_partition+0xd7/0x165
> > [ 600.138738] [<c118a067>] ? rescan_partitions+0x95/0x283
> > [ 600.138962] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
> > [ 600.139189] [<c139cbc6>] ? mutex_lock+0x9/0x21
> > [ 600.139427] [<c1100046>] ? __blkdev_get+0x155/0x2f6
> > [ 600.139632] [<c110032f>] ? blkdev_get+0x148/0x258
> > [ 600.139865] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
> > [ 600.140263] [<c10ff106>] ? bdget+0xdc/0xe6
> > [ 600.140448] [<c118854f>] ? add_disk+0x221/0x368
> > [ 600.140689] [<c126321a>] ? sd_probe_async+0xed/0x157
> > [ 600.140908] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
> > [ 600.141133] [<c103f060>] ? process_one_work+0x130/0x21f
> > [ 600.141336] [<c103f2f6>] ? worker_thread+0x18a/0x247
> > [ 600.141552] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
> > [ 600.141764] [<c1042c46>] ? kthread+0x7c/0x81
> > [ 600.141982] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
> > [ 600.142186] [<c1042bca>] ? kthread_parkme+0x11/0x11
> > [ 600.142426] INFO: task modprobe:1977 blocked for more than 120 seconds.
> > [ 600.142612] Not tainted 4.3.0-rc1+ #74
> > [ 600.142787] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 600.142991] modprobe D 00000040 0 1977 1969 0x00000000
> > [ 600.143444] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> > [ 600.144819] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> > [ 600.146052] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> > [ 600.147279] Call Trace:
> > [ 600.147489] [<c139c504>] ? schedule+0x5b/0x67
> > [ 600.147729] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> > [ 600.147992] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> > [ 600.148390] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> > [ 600.148627] [<c107ddb5>] ? load_module+0x14de/0x18ca
> > [ 600.148846] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> > [ 600.149073] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> > [ 662.100333] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> > [ 662.100598] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> > [ 662.100838] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> > [ 662.101076] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 06 00 00 02 00
> > [ 662.101297] blk_update_request: I/O error, dev sdb, sector 6
> > [ 662.101512] Buffer I/O error on dev sdb, logical block 3, async page read
> > [ 720.148270] INFO: task modprobe:1977 blocked for more than 120 seconds.
> > [ 720.148499] Not tainted 4.3.0-rc1+ #74
> > [ 720.148699] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 720.148903] modprobe D 00000040 0 1977 1969 0x00000000
> > [ 720.149360] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> > [ 720.150615] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> > [ 720.151836] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> > [ 720.153221] Call Trace:
> > [ 720.153465] [<c139c504>] ? schedule+0x5b/0x67
> > [ 720.153689] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> > [ 720.153931] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> > [ 720.154149] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> > [ 720.154379] [<c107ddb5>] ? load_module+0x14de/0x18ca
> > [ 720.154593] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> > [ 720.154820] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> > [ 781.025039] systemd-logind[1942]: New session c2 of user rainbow.
> > [ 840.152254] INFO: task kworker/u2:2:60 blocked for more than 120 seconds.
> > [ 840.152486] Not tainted 4.3.0-rc1+ #74
> > [ 840.152693] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 840.152903] kworker/u2:2 D 0000009a 0 60 2 0x00000000
> > [ 840.153399] Workqueue: events_unbound async_run_entry_fn
> > [ 840.153730] cf9e8780 00000046 2860b1ff 0000009a c117f111 284404dd 0000009a 001cad22
> > [ 840.156408] 00000000 cfaa6000 00000000 7fffffff c139c7d2 c139c504 7fffffff c139d9d3
> > [ 840.157689] 0000009a cfaa5c64 c106f460 00161e18 00000000 00013d94 006b70ce 0000009a
> > [ 840.158925] Call Trace:
> > [ 840.159158] [<c117f111>] ? blk_queue_bio+0x1e8/0x1fb
> > [ 840.159379] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> > [ 840.159600] [<c139c504>] ? schedule+0x5b/0x67
> > [ 840.159834] [<c139d9d3>] ? schedule_timeout+0x13/0xc5
> > [ 840.160052] [<c106f460>] ? timekeeping_get_ns+0x10/0x69
> > [ 840.160446] [<c139c7d2>] ? bit_wait_io_timeout+0x3d/0x3d
> > [ 840.160677] [<c106fae7>] ? ktime_get+0x38/0x48
> > [ 840.160884] [<c139bf83>] ? io_schedule_timeout+0x83/0xd7
> > [ 840.161105] [<c139c7f3>] ? bit_wait_io+0x21/0x26
> > [ 840.161306] [<c139c697>] ? __wait_on_bit+0x2f/0x5a
> > [ 840.161541] [<c10ad361>] ? wait_on_page_bit+0x57/0x5e
> > [ 840.161767] [<c1054a98>] ? wake_atomic_t_function+0x2a/0x2a
> > [ 840.161997] [<c10ad386>] ? wait_on_page_read+0xf/0x2a
> > [ 840.162206] [<c10ae14f>] ? do_read_cache_page+0xfc/0x116
> > [ 840.162445] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> > [ 840.162651] [<c10ae192>] ? read_cache_page+0x14/0x18
> > [ 840.162872] [<c1189b0e>] ? read_dev_sector+0x25/0x57
> > [ 840.163073] [<c118e22f>] ? read_lba+0x94/0x10b
> > [ 840.163289] [<c118e7eb>] ? efi_partition+0xbc/0x451
> > [ 840.163506] [<c10b5c33>] ? put_page+0x16/0x24
> > [ 840.163732] [<c10ad39d>] ? wait_on_page_read+0x26/0x2a
> > [ 840.163968] [<c10ff1eb>] ? blkdev_readpages+0x15/0x15
> > [ 840.164348] [<c10ae192>] ? read_cache_page+0x14/0x18
> > [ 840.164541] [<c118a8a8>] ? adfspart_check_ICS+0x30/0x1ac
> > [ 840.164777] [<c119a3f1>] ? vsnprintf+0x78/0x25d
> > [ 840.164977] [<c119a614>] ? snprintf+0x16/0x18
> > [ 840.165187] [<c118a7ea>] ? check_partition+0xd7/0x165
> > [ 840.165382] [<c118a067>] ? rescan_partitions+0x95/0x283
> > [ 840.165603] [<c1254b50>] ? scsi_block_when_processing_errors+0x13/0xae
> > [ 840.165829] [<c139cbc6>] ? mutex_lock+0x9/0x21
> > [ 840.166066] [<c1100046>] ? __blkdev_get+0x155/0x2f6
> > [ 840.166270] [<c110032f>] ? blkdev_get+0x148/0x258
> > [ 840.166501] [<c10ec747>] ? unlock_new_inode+0x36/0x3c
> > [ 840.166707] [<c10ff106>] ? bdget+0xdc/0xe6
> > [ 840.166914] [<c118854f>] ? add_disk+0x221/0x368
> > [ 840.167134] [<c126321a>] ? sd_probe_async+0xed/0x157
> > [ 840.167372] [<c10443a0>] ? async_run_entry_fn+0x2c/0xad
> > [ 840.167582] [<c103f060>] ? process_one_work+0x130/0x21f
> > [ 840.167802] [<c103f2f6>] ? worker_thread+0x18a/0x247
> > [ 840.168006] [<c103f16c>] ? process_scheduled_works+0x1d/0x1d
> > [ 840.168416] [<c1042c46>] ? kthread+0x7c/0x81
> > [ 840.168642] [<c139e201>] ? ret_from_kernel_thread+0x21/0x30
> > [ 840.168847] [<c1042bca>] ? kthread_parkme+0x11/0x11
> > [ 840.169094] INFO: task modprobe:1977 blocked for more than 120 seconds.
> > [ 840.169281] Not tainted 4.3.0-rc1+ #74
> > [ 840.169454] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > [ 840.169659] modprobe D 00000040 0 1977 1969 0x00000000
> > [ 840.170114] cfb20000 00000086 29042653 00000040 c1525f88 28a83a17 00000040 005bec3c
> > [ 840.171368] 00000000 ccdd0000 ffffffff ffffffff d2057280 c139c504 00000000 c104416d
> > [ 840.172741] 00000000 cfb20000 c1054a45 c151fd8c c151fd8c d2057280 00000000 ccd621f0
> > [ 840.173986] Call Trace:
> > [ 840.174200] [<c139c504>] ? schedule+0x5b/0x67
> > [ 840.174443] [<c104416d>] ? async_synchronize_cookie_domain+0x73/0x9f
> > [ 840.174689] [<c1054a45>] ? abort_exclusive_wait+0x6e/0x6e
> > [ 840.174910] [<c10ac9bc>] ? do_init_module+0xa4/0x1a3
> > [ 840.175141] [<c107ddb5>] ? load_module+0x14de/0x18ca
> > [ 840.175359] [<c107e2a0>] ? SyS_finit_module+0x47/0x56
> > [ 840.175607] [<c139e2c0>] ? sysenter_do_call+0x12/0x12
> > [ 856.020359] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_SENSE
> > [ 856.020623] sd 2:0:1:0: [sdb] Sense Key : Aborted Command [current]
> > [ 856.020862] sd 2:0:1:0: [sdb] Add. Sense: No additional sense information
> > [ 856.021101] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 02 00
> > [ 856.021324] blk_update_request: I/O error, dev sdb, sector 2
> > [ 856.021539] Buffer I/O error on dev sdb, logical block 1, async page read
> > [ 857.025325] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_ABORT driverbyte=DRIVER_OK
> > [ 857.025596] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 04 00 00 02 00
> > [ 857.025830] blk_update_request: I/O error, dev sdb, sector 4
> > [ 857.026043] Buffer I/O error on dev sdb, logical block 2, async page read
> >
> >
> > And a CD-ROM, first without patches:
> > [ 655.929795] pnp 01:01.00: activated
> > [ 655.939503] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> > [ 656.441943] scsi 2:0:2:0: CD-ROM SONY CD-ROM CDU-55S 1.0t PQ: 0 ANSI: 2
> > [ 657.829087] scsi 2:0:2:0: Attached scsi generic sg1 type 5
> > [ 658.325517] sr 2:0:2:0: [sr0] scsi-1 drive
> > [ 658.325731] cdrom: Uniform CD-ROM driver Revision: 3.20
> >
> > Modprobe succeeded but mount resulted in this & hang:
> > [ 694.056266] sr 2:0:2:0: [sr0] aborting command
> >
> > Then with patches:
> >
> > [ 109.753273] pnp 01:01.00: activated
> > [ 109.763039] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { DTC3181E NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> > [ 115.456294] scsi 2:0:2:0: CD-ROM SONY CD-ROM CDU-55S 1.0t PQ: 0 ANSI: 2
> > [ 126.823400] scsi 2:0:2:0: Attached scsi generic sg1 type 5
> > [ 126.909680] sr 2:0:2:0: [sr0] scsi-1 drive
> > [ 126.909888] cdrom: Uniform CD-ROM driver Revision: 3.20
> >
> > Modprobe succeeded but mount failed after some time with this:
> > [ 1005.149546] sr 2:0:2:0: [sr0] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> > [ 1005.149764] sr 2:0:2:0: [sr0] Sense Key : Illegal Request [current]
> > [ 1005.149992] sr 2:0:2:0: [sr0] Add. Sense: Logical block address out of range
> > [ 1005.150222] sr 2:0:2:0: [sr0] CDB: Read(10) 28 00 00 05 7a 94 00 00 02 00
> > [ 1005.150433] blk_update_request: critical target error, dev sr0, sector 1436240
> > [ 1005.154101] sr 2:0:2:0: [sr0] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> > [ 1005.154309] sr 2:0:2:0: [sr0] Sense Key : Illegal Request [current]
> > [ 1005.154533] sr 2:0:2:0: [sr0] Add. Sense: Logical block address out of range
> > [ 1005.156209] sr 2:0:2:0: [sr0] CDB: Read(10) 28 00 00 05 7a 94 00 00 02 00
> > [ 1005.156404] blk_update_request: critical target error, dev sr0, sector 1436240
> > [ 1005.156607] Buffer I/O error on dev sr0, logical block 179530, async page read
> >
> > mount: unknown filesystem type 'iso9660'
> >
> >
>
> Thanks for these test results! It looks like READ(10) commands don't work.
> I don't know the cause of the failures but it appears to be an old bug.
> Did you find any regression?
>
> I gather that your setup here is a QUANTUM LP240S target with Domex 3181
> (DTC-436) card and g_NCR5380 module. I've been testing a similar setup:
> QUANTUM LPS540S target with a Domex 3191D (DTC-536) card and dmx3191d
> module. In both setups PIO is used exclusively, no IRQ is used, and
> FLAG_DTC3181E is set. I didn't see any issues in my tests, so your results
> are surprising.

I agree that the results are surprising. Even tried 2.4 kernels (Debian 3.1)
and even 2.2 (Debian 3.0) and nothing worked.
HW is fine - the drive is accessible in Windows 98 (with Domex driver
installed).

Now testing the Canon FG2-5202 controller - a simple 8-bit ISA card with only
two chips: NCR 53C400 and 74LS245. It's memory mapped, IRQ hardwired to 7.

# modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1

[ 1245.919223] scsi2 : interrupts not enabled. for better interactive performance,
[ 1245.919326] scsi2 : please jumper the board for a free IRQ.
[ 1245.919389] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
[ 1246.376738] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 1248.202198] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 1248.420856] 53C400r: no 53C80 gated irq after transfer
[ 1248.420948] 53C400r: no end dma signal
[ 1248.422459] sd 2:0:1:0: [sdb] Sector size 0 reported, assuming 512.

Seems that the PSEUDO_DMA is broken. After adding FLAG_NO_PSEUDO_DMA:

# modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1

[ 67.974362] scsi2 : interrupts not enabled. for better interactive performance,
[ 67.974463] scsi2 : please jumper the board for a free IRQ.
[ 67.974526] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
[ 68.432728] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 70.258258] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 70.277265] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 70.482252] sd 2:0:1:0: [sdb] Write Protect is off
[ 70.482335] sd 2:0:1:0: [sdb] Mode Sense: 8b 00 00 08
[ 70.889646] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 73.159513] sdb: sdb1
[ 74.617099] sd 2:0:1:0: [sdb] Attached SCSI disk

Yeah, first success! I can even mount the filesystem, although it takes ages
(a minute) and these messages:
[ 160.872074] sd 2:0:1:0: [sdb] aborting command
[ 161.816083] sd 2:0:1:0: [sdb] aborting command

# hdparm -t --direct /dev/sdb

/dev/sdb:
[ 244.840075] sd 2:0:1:0: [sdb] aborting command
[ 248.824078] sd 2:0:1:0: [sdb] aborting command
[ 293.864069] sd 2:0:1:0: [sdb] aborting command
[ 297.824075] sd 2:0:1:0: [sdb] aborting command
[ 319.765020] blk_update_request: critical target error, dev sdb, sector 0
[ 319.972994] blk_update_request: critical target error, dev sdb, sector 0
Timing O_DIRECT disk reads: 2 MB in 105.26 seconds = 19.46 kB/sec



With your patches (and adding FLAG_NO_PSEUDO_DMA), modprobe is slower but
mount faster (4 seconds) and then works better:

# modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1

[ 130.126185] scsi2 : interrupts not enabled. for better interactive performance,
[ 130.126284] scsi2 : please jumper the board for a free IRQ.
[ 130.126347] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 145.221755] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 220.629912] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 220.651400] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 220.654061] sd 2:0:1:0: [sdb] Write Protect is off
[ 220.659344] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 220.732415] sdb: sdb1
[ 220.749760] sd 2:0:1:0: [sdb] Attached SCSI disk

# hdparm -t --direct /dev/sdb

/dev/sdb:
Timing O_DIRECT disk reads: 2 MB in 18.25 seconds = 112.20 kB/sec



IRQ seems to work too, although driver always shows "irq 0":

# modprobe g_NCR5380_mmio ncr_irq=7 ncr_addr=0xd8000 ncr_53c400=1

[ 117.263062] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 132.357474] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 207.765080] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 207.783415] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 207.786167] sd 2:0:1:0: [sdb] Write Protect is off
[ 207.790260] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 207.859669] sdb: sdb1
[ 207.876556] sd 2:0:1:0: [sdb] Attached SCSI disk

# hdparm -t --direct /dev/sdb

/dev/sdb:
Timing O_DIRECT disk reads: 2 MB in 18.30 seconds = 111.94 kB/sec

# mount /dev/sdb1 /mnt
# umount /mnt
# head /proc/interrupts
CPU0
0: 44793 XT-PIC timer
1: 9 XT-PIC i8042
2: 0 XT-PIC cascade
7: 86 XT-PIC NCR5380
8: 1 XT-PIC rtc0
9: 0 XT-PIC uhci_hcd:usb1, uhci_hcd:usb2
10: 1179 XT-PIC eth0
12: 136 XT-PIC i8042
14: 3411 XT-PIC pata_via

--
Ondrej Zary

2015-11-21 23:08:04

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Saturday 21 November 2015 14:01:39 Ondrej Zary wrote:
> On Saturday 21 November 2015 02:58:57 Finn Thain wrote:
> >
> > Hi Ondrej,
> >
> > On Fri, 20 Nov 2015, Ondrej Zary wrote:
> >
> > > On Friday 20 November 2015 02:41:19 Finn Thain wrote:
> > > >
> > > >
> > > > My tests involved 3 different scsi targets (two disks and a CD-ROM)
> > > > but none of these send a SDTR. Your log says the driver correctly
> > > > rejected the SDTR message but that doesn't mean the target actually
> > > > went to MSG IN phase and got the message. Do you have any older
> > > > targets you can test?
> > >

[...]

> > >
> >
> > Thanks for these test results! It looks like READ(10) commands don't work.
> > I don't know the cause of the failures but it appears to be an old bug.
> > Did you find any regression?
> >
> > I gather that your setup here is a QUANTUM LP240S target with Domex 3181
> > (DTC-436) card and g_NCR5380 module. I've been testing a similar setup:
> > QUANTUM LPS540S target with a Domex 3191D (DTC-536) card and dmx3191d
> > module. In both setups PIO is used exclusively, no IRQ is used, and
> > FLAG_DTC3181E is set. I didn't see any issues in my tests, so your results
> > are surprising.
>
> I agree that the results are surprising. Even tried 2.4 kernels (Debian 3.1)
> and even 2.2 (Debian 3.0) and nothing worked.
> HW is fine - the drive is accessible in Windows 98 (with Domex driver
> installed).
>
> Now testing the Canon FG2-5202 controller - a simple 8-bit ISA card with only
> two chips: NCR 53C400 and 74LS245. It's memory mapped, IRQ hardwired to 7.
>
> # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 1245.919223] scsi2 : interrupts not enabled. for better interactive performance,
> [ 1245.919326] scsi2 : please jumper the board for a free IRQ.
> [ 1245.919389] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> [ 1246.376738] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 1248.202198] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 1248.420856] 53C400r: no 53C80 gated irq after transfer
> [ 1248.420948] 53C400r: no end dma signal
> [ 1248.422459] sd 2:0:1:0: [sdb] Sector size 0 reported, assuming 512.
>
> Seems that the PSEUDO_DMA is broken. After adding FLAG_NO_PSEUDO_DMA:
>
> # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 67.974362] scsi2 : interrupts not enabled. for better interactive performance,
> [ 67.974463] scsi2 : please jumper the board for a free IRQ.
> [ 67.974526] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> [ 68.432728] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 70.258258] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 70.277265] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 70.482252] sd 2:0:1:0: [sdb] Write Protect is off
> [ 70.482335] sd 2:0:1:0: [sdb] Mode Sense: 8b 00 00 08
> [ 70.889646] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 73.159513] sdb: sdb1
> [ 74.617099] sd 2:0:1:0: [sdb] Attached SCSI disk
>
> Yeah, first success! I can even mount the filesystem, although it takes ages
> (a minute) and these messages:
> [ 160.872074] sd 2:0:1:0: [sdb] aborting command
> [ 161.816083] sd 2:0:1:0: [sdb] aborting command
>
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> [ 244.840075] sd 2:0:1:0: [sdb] aborting command
> [ 248.824078] sd 2:0:1:0: [sdb] aborting command
> [ 293.864069] sd 2:0:1:0: [sdb] aborting command
> [ 297.824075] sd 2:0:1:0: [sdb] aborting command
> [ 319.765020] blk_update_request: critical target error, dev sdb, sector 0
> [ 319.972994] blk_update_request: critical target error, dev sdb, sector 0
> Timing O_DIRECT disk reads: 2 MB in 105.26 seconds = 19.46 kB/sec
>
>
>
> With your patches (and adding FLAG_NO_PSEUDO_DMA), modprobe is slower but
> mount faster (4 seconds) and then works better:
>
> # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 130.126185] scsi2 : interrupts not enabled. for better interactive performance,
> [ 130.126284] scsi2 : please jumper the board for a free IRQ.
> [ 130.126347] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 145.221755] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 220.629912] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 220.651400] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 220.654061] sd 2:0:1:0: [sdb] Write Protect is off
> [ 220.659344] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 220.732415] sdb: sdb1
> [ 220.749760] sd 2:0:1:0: [sdb] Attached SCSI disk
>
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 2 MB in 18.25 seconds = 112.20 kB/sec
>
>
>
> IRQ seems to work too, although driver always shows "irq 0":
>
> # modprobe g_NCR5380_mmio ncr_irq=7 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 117.263062] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 132.357474] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 207.765080] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 207.783415] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 207.786167] sd 2:0:1:0: [sdb] Write Protect is off
> [ 207.790260] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 207.859669] sdb: sdb1
> [ 207.876556] sd 2:0:1:0: [sdb] Attached SCSI disk
>
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 2 MB in 18.30 seconds = 111.94 kB/sec
>
> # mount /dev/sdb1 /mnt
> # umount /mnt
> # head /proc/interrupts
> CPU0
> 0: 44793 XT-PIC timer
> 1: 9 XT-PIC i8042
> 2: 0 XT-PIC cascade
> 7: 86 XT-PIC NCR5380
> 8: 1 XT-PIC rtc0
> 9: 0 XT-PIC uhci_hcd:usb1, uhci_hcd:usb2
> 10: 1179 XT-PIC eth0
> 12: 136 XT-PIC i8042
> 14: 3411 XT-PIC pata_via
>

Even the HP C2502 (that never worked) works now. It's 8-bit card based on
NCR 53C400A (there are also 74ALS245 and 3 PALCE chips).
Configuration is by using magic numbers, wrote a simple userspace enabler:

#include <stdio.h>
#include <sys/io.h>

const unsigned short io_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350 };

/* IRQs: 2,3,4,5,7 */
void configure_hp400a(int idx, unsigned char irq) {
unsigned char b = 0;

outb(0x0f, 0x779);
outb(0x22, 0x379);
outb(0xf0, 0x379);
outb(0x20, 0x379);
outb(0x80, 0x379);
if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
irq = 0;
if (idx >= 0 && idx <= 7)
b = 0x80 | idx | (irq << 4);
outb(b, 0x379);
}

int main(void) {
if (iopl(3)) {
perror("iopl");
return 1;
}

configure_hp400a(0, 7);

return 0;
}

And now:
# modprobe g_NCR5380 ncr_irq=255 ncr_addr=0x280 ncr_53c400a=1

[ 79.051669] scsi2 : interrupts not enabled. for better interactive performance,
[ 79.051770] scsi2 : please jumper the board for a free IRQ.
[ 79.051833] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x280, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 95.390329] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 177.022776] sd 2:0:1:0: Attached scsi generic sg1 type 0
[ 177.041505] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 177.044491] sd 2:0:1:0: [sdb] Write Protect is off
[ 177.049605] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 177.129093] sdb: sdb1
[ 177.145439] sd 2:0:1:0: [sdb] Attached SCSI disk

# hdparm -t --direct /dev/sdb

/dev/sdb:
Timing O_DIRECT disk reads: 2 MB in 21.38 seconds = 95.77 kB/sec

Seems to work without IRQ.
With IRQ is enabled, no interrupts are shown in /proc/interrupts.

--
Ondrej Zary

2015-11-21 23:33:02

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Sat, 21 Nov 2015, Ondrej Zary wrote:

> On Saturday 21 November 2015 02:58:57 Finn Thain wrote:
>
> >
> > I gather that your setup here is a QUANTUM LP240S target with Domex
> > 3181 (DTC-436) card and g_NCR5380 module. I've been testing a similar
> > setup: QUANTUM LPS540S target with a Domex 3191D (DTC-536) card and
> > dmx3191d module. In both setups PIO is used exclusively, no IRQ is
> > used, and FLAG_DTC3181E is set. I didn't see any issues in my tests,
> > so your results are surprising.
>
> I agree that the results are surprising. Even tried 2.4 kernels (Debian
> 3.1) and even 2.2 (Debian 3.0) and nothing worked. HW is fine - the
> drive is accessible in Windows 98 (with Domex driver installed).

That's good to know (and very thorough).

>
> Now testing the Canon FG2-5202 controller - a simple 8-bit ISA card with
> only two chips: NCR 53C400 and 74LS245. It's memory mapped, IRQ
> hardwired to 7.
>
> # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 1245.919223] scsi2 : interrupts not enabled. for better interactive performance,
> [ 1245.919326] scsi2 : please jumper the board for a free IRQ.
> [ 1245.919389] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> [ 1246.376738] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 1248.202198] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 1248.420856] 53C400r: no 53C80 gated irq after transfer
> [ 1248.420948] 53C400r: no end dma signal
> [ 1248.422459] sd 2:0:1:0: [sdb] Sector size 0 reported, assuming 512.
>
> Seems that the PSEUDO_DMA is broken.

That's been my experience with mac_scsi also (going back 10 years). I'm
told that it used to work in v2.2. PIO was always usable though hopelessly
slow.

I haven't yet done any work on the PDMA problem with mac_scsi because
crashing bugs and the forked core driver seemed to be the more pressing
problems. And resolving the fork has implications for all of the DMA
variations anyway.

> After adding FLAG_NO_PSEUDO_DMA:
>
> # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 67.974362] scsi2 : interrupts not enabled. for better interactive performance,
> [ 67.974463] scsi2 : please jumper the board for a free IRQ.
> [ 67.974526] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 NO_PSEUDO_DMA }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> [ 68.432728] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 70.258258] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 70.277265] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 70.482252] sd 2:0:1:0: [sdb] Write Protect is off
> [ 70.482335] sd 2:0:1:0: [sdb] Mode Sense: 8b 00 00 08
> [ 70.889646] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 73.159513] sdb: sdb1
> [ 74.617099] sd 2:0:1:0: [sdb] Attached SCSI disk
>
> Yeah, first success! I can even mount the filesystem, although it takes ages
> (a minute) and these messages:
> [ 160.872074] sd 2:0:1:0: [sdb] aborting command
> [ 161.816083] sd 2:0:1:0: [sdb] aborting command
>
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> [ 244.840075] sd 2:0:1:0: [sdb] aborting command
> [ 248.824078] sd 2:0:1:0: [sdb] aborting command
> [ 293.864069] sd 2:0:1:0: [sdb] aborting command
> [ 297.824075] sd 2:0:1:0: [sdb] aborting command
> [ 319.765020] blk_update_request: critical target error, dev sdb, sector 0
> [ 319.972994] blk_update_request: critical target error, dev sdb, sector 0
> Timing O_DIRECT disk reads: 2 MB in 105.26 seconds = 19.46 kB/sec
>
>
>
> With your patches (and adding FLAG_NO_PSEUDO_DMA), modprobe is slower but
> mount faster (4 seconds) and then works better:
>
> # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 130.126185] scsi2 : interrupts not enabled. for better interactive performance,
> [ 130.126284] scsi2 : please jumper the board for a free IRQ.
> [ 130.126347] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 145.221755] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 220.629912] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 220.651400] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 220.654061] sd 2:0:1:0: [sdb] Write Protect is off
> [ 220.659344] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 220.732415] sdb: sdb1
> [ 220.749760] sd 2:0:1:0: [sdb] Attached SCSI disk
>
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 2 MB in 18.25 seconds = 112.20 kB/sec
>
>
>
> IRQ seems to work too, although driver always shows "irq 0":

Your right, there's a superficial bug there that affects the banner in the
log. But it doesn't affect behaviour (the IRQ should still work). It isn't
a new bug.

>
> # modprobe g_NCR5380_mmio ncr_irq=7 ncr_addr=0xd8000 ncr_53c400=1
>
> [ 117.263062] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_PSEUDO_DMA }, options { AUTOPROBE_IRQ PSEUDO_DMA }
> [ 132.357474] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> [ 207.765080] sd 2:0:1:0: Attached scsi generic sg1 type 0
> [ 207.783415] sd 2:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
> [ 207.786167] sd 2:0:1:0: [sdb] Write Protect is off
> [ 207.790260] sd 2:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [ 207.859669] sdb: sdb1
> [ 207.876556] sd 2:0:1:0: [sdb] Attached SCSI disk
>
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 2 MB in 18.30 seconds = 111.94 kB/sec
>
> # mount /dev/sdb1 /mnt
> # umount /mnt
> # head /proc/interrupts
> CPU0
> 0: 44793 XT-PIC timer
> 1: 9 XT-PIC i8042
> 2: 0 XT-PIC cascade
> 7: 86 XT-PIC NCR5380
> 8: 1 XT-PIC rtc0
> 9: 0 XT-PIC uhci_hcd:usb1, uhci_hcd:usb2
> 10: 1179 XT-PIC eth0
> 12: 136 XT-PIC i8042
> 14: 3411 XT-PIC pata_via
>

Nice! Thanks for your perseverance. It is gratifying to see it working.

--

2015-11-23 22:55:23

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Sunday 22 November 2015 00:32:31 Finn Thain wrote:
>
> On Sat, 21 Nov 2015, Ondrej Zary wrote:
>
> > On Saturday 21 November 2015 02:58:57 Finn Thain wrote:
> >
> > >
> > > I gather that your setup here is a QUANTUM LP240S target with Domex
> > > 3181 (DTC-436) card and g_NCR5380 module. I've been testing a similar
> > > setup: QUANTUM LPS540S target with a Domex 3191D (DTC-536) card and
> > > dmx3191d module. In both setups PIO is used exclusively, no IRQ is
> > > used, and FLAG_DTC3181E is set. I didn't see any issues in my tests,
> > > so your results are surprising.
> >
> > I agree that the results are surprising. Even tried 2.4 kernels (Debian
> > 3.1) and even 2.2 (Debian 3.0) and nothing worked. HW is fine - the
> > drive is accessible in Windows 98 (with Domex driver installed).
>
> That's good to know (and very thorough).
>
> >
> > Now testing the Canon FG2-5202 controller - a simple 8-bit ISA card with
> > only two chips: NCR 53C400 and 74LS245. It's memory mapped, IRQ
> > hardwired to 7.
> >
> > # modprobe g_NCR5380_mmio ncr_irq=255 ncr_addr=0xd8000 ncr_53c400=1
> >
> > [ 1245.919223] scsi2 : interrupts not enabled. for better interactive performance,
> > [ 1245.919326] scsi2 : please jumper the board for a free IRQ.
> > [ 1245.919389] scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NCR53C400 }, USLEEP_POLL 3, USLEEP_WAITLONG 1250, options { AUTOPROBE_IRQ PSEUDO_DMA NCR53C400 }
> > [ 1246.376738] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
> > [ 1248.202198] sd 2:0:1:0: Attached scsi generic sg1 type 0
> > [ 1248.420856] 53C400r: no 53C80 gated irq after transfer
> > [ 1248.420948] 53C400r: no end dma signal
> > [ 1248.422459] sd 2:0:1:0: [sdb] Sector size 0 reported, assuming 512.
> >
> > Seems that the PSEUDO_DMA is broken.
>
> That's been my experience with mac_scsi also (going back 10 years). I'm
> told that it used to work in v2.2. PIO was always usable though hopelessly
> slow.
>
> I haven't yet done any work on the PDMA problem with mac_scsi because
> crashing bugs and the forked core driver seemed to be the more pressing
> problems. And resolving the fork has implications for all of the DMA
> variations anyway.

PDMA seems to be broken in multiple ways. NCR5380_pread cannot process less
than 128 bytes. In fact, 53C400 datasheet says that it's HW limitation:
non-modulo-128-byte transfers should use PIO.

Adding
transfersize = round_down(transfersize, 128);
to generic_NCR5380_dma_xfer_len() improves the situation a bit.

After modprobe, some small reads (8, 4, 24 and 64 bytes) are done using PIO,
then eight 512-byte reads using PDMA and then it fails on a 254-byte read.
First 128 bytes are read using PDMA and the next PDMA operation hangs waiting
forever for the host buffer to be ready.

--
Ondrej Zary

2015-11-24 01:22:01

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Mon, 23 Nov 2015, Ondrej Zary wrote:

>
> PDMA seems to be broken in multiple ways. NCR5380_pread cannot process
> less than 128 bytes. In fact, 53C400 datasheet says that it's HW
> limitation: non-modulo-128-byte transfers should use PIO.
>
> Adding
> transfersize = round_down(transfersize, 128);
> to generic_NCR5380_dma_xfer_len() improves the situation a bit.
>
> After modprobe, some small reads (8, 4, 24 and 64 bytes) are done using
> PIO, then eight 512-byte reads using PDMA and then it fails on a
> 254-byte read. First 128 bytes are read using PDMA and the next PDMA
> operation hangs waiting forever for the host buffer to be ready.
>

A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't see how
that is possible given round_down(126, 128) == 0. Was this the actual
'len' argument to NCR5380_pread() in g_NCR5380.c?

BTW, I presume that FLAG_NO_DMA_FIXUPS was set (which is the case if you
pass ncr_53c400=1 option with modprobe). Otherwise you could see PDMA IO
sizes like 127 etc.

--

2015-11-24 08:05:02

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Tuesday 24 November 2015, Finn Thain wrote:
>
> On Mon, 23 Nov 2015, Ondrej Zary wrote:
>
> >
> > PDMA seems to be broken in multiple ways. NCR5380_pread cannot process
> > less than 128 bytes. In fact, 53C400 datasheet says that it's HW
> > limitation: non-modulo-128-byte transfers should use PIO.
> >
> > Adding
> > transfersize = round_down(transfersize, 128);
> > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> >
> > After modprobe, some small reads (8, 4, 24 and 64 bytes) are done using
> > PIO, then eight 512-byte reads using PDMA and then it fails on a
> > 254-byte read. First 128 bytes are read using PDMA and the next PDMA
> > operation hangs waiting forever for the host buffer to be ready.
> >
>
> A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't see how
> that is possible given round_down(126, 128) == 0. Was this the actual
> 'len' argument to NCR5380_pread() in g_NCR5380.c?

No 126-byte PDMA. The 126 bytes were probably lost (or mixed with the next
read?). The next read was also 254 bytes so another 128-byte PDMA transfer.

Then modified NCR5380_information_transfer() to transfer the remaining data
(126 bytes in this case) using PIO. It did not help, the next PDMA transfer
failed too.

> BTW, I presume that FLAG_NO_DMA_FIXUPS was set (which is the case if you
> pass ncr_53c400=1 option with modprobe). Otherwise you could see PDMA IO
> sizes like 127 etc.

Yes, the flag was set.

--
Ondrej Zary

2015-11-24 09:14:04

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Tue, 24 Nov 2015, Ondrej Zary wrote:

> On Tuesday 24 November 2015, Finn Thain wrote:
> >
> > On Mon, 23 Nov 2015, Ondrej Zary wrote:
> >
> > >
> > > PDMA seems to be broken in multiple ways. NCR5380_pread cannot
> > > process less than 128 bytes. In fact, 53C400 datasheet says that
> > > it's HW limitation: non-modulo-128-byte transfers should use PIO.
> > >
> > > Adding
> > > transfersize = round_down(transfersize, 128);
> > > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> > >
> > > After modprobe, some small reads (8, 4, 24 and 64 bytes) are done
> > > using PIO, then eight 512-byte reads using PDMA and then it fails on
> > > a 254-byte read. First 128 bytes are read using PDMA and the next
> > > PDMA operation hangs waiting forever for the host buffer to be
> > > ready.
> > >
> >
> > A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't see
> > how that is possible given round_down(126, 128) == 0. Was this the
> > actual 'len' argument to NCR5380_pread() in g_NCR5380.c?
>
> No 126-byte PDMA. The 126 bytes were probably lost (or mixed with the
> next read?).

When you said, the "PDMA operation hangs waiting forever", I figured that
you had hit an infinite loop in NCR5380_pread()... but now I'm lost.

My main concern here is to confirm that I didn't break anything e.g. with
patch 24 or 41. It would be nice to know that this hang is not the result
of a new bug.

> The next read was also 254 bytes so another 128-byte PDMA transfer.
>
> Then modified NCR5380_information_transfer() to transfer the remaining
> data (126 bytes in this case) using PIO. It did not help, the next PDMA
> transfer failed too.
>

AFAICT, no change to NCR5380_information_transfer() should be needed. It
was always meant to cope with the need to split a transfer between (P)DMA
and PIO.

If the target is expecting the remaining 126 bytes, it will keep the bus
in DATA OUT phase, and the next iteration of the loop
while ((cmd = hostdata->connected)) { }
will call NCR5380_transfer_pio() for the remaining bytes. If the target
never asserts REQ, that transfer will never happen, but then the command
should timeout and get aborted, to handle the possibility that a "PDMA
operation hangs waiting forever".

A protocol analyzer would be useful to debug this. I get a lot of value
from a bus terminator block that has LEDs for the various control signals.
Failing that, you might need to place,
#define NDEBUG (NDEBUG_INFORMATION | NDEBUG_HANDSHAKE | NDEBUG_PIO | NDEBUG_DMA | NDEBUG_MAIN)
at the top of g_NCR5380.c.

--

2015-11-24 12:03:25

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Tuesday 24 November 2015, Finn Thain wrote:
>
> On Tue, 24 Nov 2015, Ondrej Zary wrote:
>
> > On Tuesday 24 November 2015, Finn Thain wrote:
> > >
> > > On Mon, 23 Nov 2015, Ondrej Zary wrote:
> > >
> > > >
> > > > PDMA seems to be broken in multiple ways. NCR5380_pread cannot
> > > > process less than 128 bytes. In fact, 53C400 datasheet says that
> > > > it's HW limitation: non-modulo-128-byte transfers should use PIO.
> > > >
> > > > Adding
> > > > transfersize = round_down(transfersize, 128);
> > > > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> > > >
> > > > After modprobe, some small reads (8, 4, 24 and 64 bytes) are done
> > > > using PIO, then eight 512-byte reads using PDMA and then it fails on
> > > > a 254-byte read. First 128 bytes are read using PDMA and the next
> > > > PDMA operation hangs waiting forever for the host buffer to be
> > > > ready.
> > > >
> > >
> > > A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't see
> > > how that is possible given round_down(126, 128) == 0. Was this the
> > > actual 'len' argument to NCR5380_pread() in g_NCR5380.c?
> >
> > No 126-byte PDMA. The 126 bytes were probably lost (or mixed with the
> > next read?).
>
> When you said, the "PDMA operation hangs waiting forever", I figured that
> you had hit an infinite loop in NCR5380_pread()... but now I'm lost.

The first 128-byte PDMA ended successfully (ignoring what happened to the
remaining 126 bytes), then a next request for 254 bytes came. This resulted
in a new 128-byte PDMA and that hanged (in one of its possibly infinite loops
without a timeout).

> My main concern here is to confirm that I didn't break anything e.g. with
> patch 24 or 41. It would be nice to know that this hang is not the result
> of a new bug.

PDMA was already broken before so it's hard to tell. I can try to modify
the unpatched driver to see if PDMA is broken the same way.

> > The next read was also 254 bytes so another 128-byte PDMA transfer.
> >
> > Then modified NCR5380_information_transfer() to transfer the remaining
> > data (126 bytes in this case) using PIO. It did not help, the next PDMA
> > transfer failed too.
> >
>
> AFAICT, no change to NCR5380_information_transfer() should be needed. It
> was always meant to cope with the need to split a transfer between (P)DMA
> and PIO.
>
> If the target is expecting the remaining 126 bytes, it will keep the bus
> in DATA OUT phase, and the next iteration of the loop
> while ((cmd = hostdata->connected)) { }
> will call NCR5380_transfer_pio() for the remaining bytes. If the target
> never asserts REQ, that transfer will never happen, but then the command
> should timeout and get aborted, to handle the possibility that a "PDMA
> operation hangs waiting forever".

Thanks for explanation.

> A protocol analyzer would be useful to debug this. I get a lot of value
> from a bus terminator block that has LEDs for the various control signals.
> Failing that, you might need to place,
> #define NDEBUG (NDEBUG_INFORMATION | NDEBUG_HANDSHAKE | NDEBUG_PIO | NDEBUG_DMA | NDEBUG_MAIN)
> at the top of g_NCR5380.c.


--
Ondrej Zary

2015-11-24 18:04:37

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Tuesday 24 November 2015 13:03:17 Ondrej Zary wrote:
> On Tuesday 24 November 2015, Finn Thain wrote:
> >
> > On Tue, 24 Nov 2015, Ondrej Zary wrote:
> >
> > > On Tuesday 24 November 2015, Finn Thain wrote:
> > > >
> > > > On Mon, 23 Nov 2015, Ondrej Zary wrote:
> > > >
> > > > >
> > > > > PDMA seems to be broken in multiple ways. NCR5380_pread cannot
> > > > > process less than 128 bytes. In fact, 53C400 datasheet says that
> > > > > it's HW limitation: non-modulo-128-byte transfers should use PIO.
> > > > >
> > > > > Adding
> > > > > transfersize = round_down(transfersize, 128);
> > > > > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> > > > >
> > > > > After modprobe, some small reads (8, 4, 24 and 64 bytes) are done
> > > > > using PIO, then eight 512-byte reads using PDMA and then it fails on
> > > > > a 254-byte read. First 128 bytes are read using PDMA and the next
> > > > > PDMA operation hangs waiting forever for the host buffer to be
> > > > > ready.
> > > > >
> > > >
> > > > A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't see
> > > > how that is possible given round_down(126, 128) == 0. Was this the
> > > > actual 'len' argument to NCR5380_pread() in g_NCR5380.c?
> > >
> > > No 126-byte PDMA. The 126 bytes were probably lost (or mixed with the
> > > next read?).
> >
> > When you said, the "PDMA operation hangs waiting forever", I figured that
> > you had hit an infinite loop in NCR5380_pread()... but now I'm lost.
>
> The first 128-byte PDMA ended successfully (ignoring what happened to the
> remaining 126 bytes), then a next request for 254 bytes came. This resulted
> in a new 128-byte PDMA and that hanged (in one of its possibly infinite loops
> without a timeout).
>
> > My main concern here is to confirm that I didn't break anything e.g. with
> > patch 24 or 41. It would be nice to know that this hang is not the result
> > of a new bug.
>
> PDMA was already broken before so it's hard to tell. I can try to modify
> the unpatched driver to see if PDMA is broken the same way.

Just tested the driver without your patches and it's broken exactly the same
way.

--
Ondrej Zary

2015-11-24 21:40:40

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Tuesday 24 November 2015 10:13:17 Finn Thain wrote:
>
> On Tue, 24 Nov 2015, Ondrej Zary wrote:
>
> > On Tuesday 24 November 2015, Finn Thain wrote:
> > >
> > > On Mon, 23 Nov 2015, Ondrej Zary wrote:
> > >
> > > >
> > > > PDMA seems to be broken in multiple ways. NCR5380_pread cannot
> > > > process less than 128 bytes. In fact, 53C400 datasheet says that
> > > > it's HW limitation: non-modulo-128-byte transfers should use PIO.
> > > >
> > > > Adding
> > > > transfersize = round_down(transfersize, 128);
> > > > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> > > >
> > > > After modprobe, some small reads (8, 4, 24 and 64 bytes) are done
> > > > using PIO, then eight 512-byte reads using PDMA and then it fails on
> > > > a 254-byte read. First 128 bytes are read using PDMA and the next
> > > > PDMA operation hangs waiting forever for the host buffer to be
> > > > ready.
> > > >
> > >
> > > A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't see
> > > how that is possible given round_down(126, 128) == 0. Was this the
> > > actual 'len' argument to NCR5380_pread() in g_NCR5380.c?
> >
> > No 126-byte PDMA. The 126 bytes were probably lost (or mixed with the
> > next read?).
>
> When you said, the "PDMA operation hangs waiting forever", I figured that
> you had hit an infinite loop in NCR5380_pread()... but now I'm lost.
>
> My main concern here is to confirm that I didn't break anything e.g. with
> patch 24 or 41. It would be nice to know that this hang is not the result
> of a new bug.
>
> > The next read was also 254 bytes so another 128-byte PDMA transfer.
> >
> > Then modified NCR5380_information_transfer() to transfer the remaining
> > data (126 bytes in this case) using PIO. It did not help, the next PDMA
> > transfer failed too.
> >
>
> AFAICT, no change to NCR5380_information_transfer() should be needed. It
> was always meant to cope with the need to split a transfer between (P)DMA
> and PIO.

Instead of fixing split transfers, simply forced everything non-modulo-128 to
PIO:
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -703,6 +703,10 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd)
!(cmd->SCp.this_residual % transfersize))
transfersize = 32 * 1024;

+ /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */
+ if (transfersize % 128)
+ transfersize = 0;
+
return transfersize;
}

It seems to work and greatly improves performance:
# hdparm -t --direct /dev/sdb

/dev/sdb:
Timing O_DIRECT disk reads: 4 MB in 4.84 seconds = 846.15 kB/sec

--
Ondrej Zary

2015-11-25 02:11:04

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Tue, 24 Nov 2015, Ondrej Zary wrote:

> On Tuesday 24 November 2015 10:13:17 Finn Thain wrote:
> >
> > On Tue, 24 Nov 2015, Ondrej Zary wrote:
> >
> > > On Tuesday 24 November 2015, Finn Thain wrote:
> > > >
> > > > On Mon, 23 Nov 2015, Ondrej Zary wrote:
> > > >
> > > > >
> > > > > PDMA seems to be broken in multiple ways. NCR5380_pread cannot
> > > > > process less than 128 bytes. In fact, 53C400 datasheet says that
> > > > > it's HW limitation: non-modulo-128-byte transfers should use
> > > > > PIO.
> > > > >
> > > > > Adding
> > > > > transfersize = round_down(transfersize, 128);
> > > > > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> > > > >
> > > > > After modprobe, some small reads (8, 4, 24 and 64 bytes) are
> > > > > done using PIO, then eight 512-byte reads using PDMA and then it
> > > > > fails on a 254-byte read. First 128 bytes are read using PDMA
> > > > > and the next PDMA operation hangs waiting forever for the host
> > > > > buffer to be ready.
> > > > >
> > > >
> > > > A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't
> > > > see how that is possible given round_down(126, 128) == 0. Was this
> > > > the actual 'len' argument to NCR5380_pread() in g_NCR5380.c?
> > >
> > > No 126-byte PDMA. The 126 bytes were probably lost (or mixed with
> > > the next read?).
> > [...]
> > > The next read was also 254 bytes so another 128-byte PDMA transfer.
> > >
> > > Then modified NCR5380_information_transfer() to transfer the
> > > remaining data (126 bytes in this case) using PIO. It did not help,
> > > the next PDMA transfer failed too.
> > >
> >
> > AFAICT, no change to NCR5380_information_transfer() should be needed.
> > It was always meant to cope with the need to split a transfer between
> > (P)DMA and PIO.
>
> Instead of fixing split transfers, simply forced everything
> non-modulo-128 to PIO:

The need to split a transfer arises from early chip errata relating to DMA
and the workarounds for them (see the comments in the source). That's why
I believe that the driver was meant to be cope with this. But I don't have
any experimental evidence for it.

I'm almost certain that these errata aren't applicable to your hardware.
So I don't have any reason to think that your card will allow part of a
transfer to be performed with PDMA and the rest with PIO. So I don't
really object to the patch.

But I don't understand the need for it either: I have no idea what state
the driver, chip and scsi bus were in when the 126-byte PIO transfer
failed. If the PIO transfer didn't succeed then the entire command should
have failed.

> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -703,6 +703,10 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd)
> !(cmd->SCp.this_residual % transfersize))
> transfersize = 32 * 1024;
>
> + /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */

Do you have a download link for this datasheet?

> + if (transfersize % 128)
> + transfersize = 0;
> +
> return transfersize;
> }
>
> It seems to work and greatly improves performance:
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 4 MB in 4.84 seconds = 846.15 kB/sec
>

Sounds about right...

--

2015-11-25 09:05:35

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Wednesday 25 November 2015, Finn Thain wrote:
>
> On Tue, 24 Nov 2015, Ondrej Zary wrote:
>
> > On Tuesday 24 November 2015 10:13:17 Finn Thain wrote:
> > >
> > > On Tue, 24 Nov 2015, Ondrej Zary wrote:
> > >
> > > > On Tuesday 24 November 2015, Finn Thain wrote:
> > > > >
> > > > > On Mon, 23 Nov 2015, Ondrej Zary wrote:
> > > > >
> > > > > >
> > > > > > PDMA seems to be broken in multiple ways. NCR5380_pread cannot
> > > > > > process less than 128 bytes. In fact, 53C400 datasheet says that
> > > > > > it's HW limitation: non-modulo-128-byte transfers should use
> > > > > > PIO.
> > > > > >
> > > > > > Adding
> > > > > > transfersize = round_down(transfersize, 128);
> > > > > > to generic_NCR5380_dma_xfer_len() improves the situation a bit.
> > > > > >
> > > > > > After modprobe, some small reads (8, 4, 24 and 64 bytes) are
> > > > > > done using PIO, then eight 512-byte reads using PDMA and then it
> > > > > > fails on a 254-byte read. First 128 bytes are read using PDMA
> > > > > > and the next PDMA operation hangs waiting forever for the host
> > > > > > buffer to be ready.
> > > > > >
> > > > >
> > > > > A 128-byte PDMA receive followed by 126-byte PDMA receive? I don't
> > > > > see how that is possible given round_down(126, 128) == 0. Was this
> > > > > the actual 'len' argument to NCR5380_pread() in g_NCR5380.c?
> > > >
> > > > No 126-byte PDMA. The 126 bytes were probably lost (or mixed with
> > > > the next read?).
> > > [...]
> > > > The next read was also 254 bytes so another 128-byte PDMA transfer.
> > > >
> > > > Then modified NCR5380_information_transfer() to transfer the
> > > > remaining data (126 bytes in this case) using PIO. It did not help,
> > > > the next PDMA transfer failed too.
> > > >
> > >
> > > AFAICT, no change to NCR5380_information_transfer() should be needed.
> > > It was always meant to cope with the need to split a transfer between
> > > (P)DMA and PIO.
> >
> > Instead of fixing split transfers, simply forced everything
> > non-modulo-128 to PIO:
>
> The need to split a transfer arises from early chip errata relating to DMA
> and the workarounds for them (see the comments in the source). That's why
> I believe that the driver was meant to be cope with this. But I don't have
> any experimental evidence for it.
>
> I'm almost certain that these errata aren't applicable to your hardware.
> So I don't have any reason to think that your card will allow part of a
> transfer to be performed with PDMA and the rest with PIO. So I don't
> really object to the patch.
>
> But I don't understand the need for it either: I have no idea what state
> the driver, chip and scsi bus were in when the 126-byte PIO transfer
> failed. If the PIO transfer didn't succeed then the entire command should
> have failed.

The patch was just a quick hack to confirm that PDMA is not completely broken.
Now we know that it mostly works so I can investigate the partial PIO problem.

> > --- a/drivers/scsi/g_NCR5380.c
> > +++ b/drivers/scsi/g_NCR5380.c
> > @@ -703,6 +703,10 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd)
> > !(cmd->SCp.this_residual % transfersize))
> > transfersize = 32 * 1024;
> >
> > + /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */
>
> Do you have a download link for this datasheet?

http://bitsavers.trailing-edge.com/pdf/ncr/scsi/NCR_53C400.pdf

53C400A datasheet would be great too but haven't found any.
I think that PDMA should work with 53C400A too but seems that the driver was
never able to do it.

Although there is code for port-mapped transfer in NCR5380_pread(),
NCR53C400_register_offset is defined to 0 in the port-mapped case. The C400_
register offsets are thus defined with negative offset:

#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8
#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7
#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6
#define C400_HOST_BUFFER NCR53C400_register_offset-4

This is probably OK for a port-mapped 53C400 (such card must have some glue
decoding logic as the 53C400 chip itself can do memory-mapping only) because:

/*
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
*/
if (overrides[current_override].board == BOARD_NCR53C400)
instance->io_port += 8;

This means that on a 53C400, first 5380 register will be at base+8 and first
C400_ register at base.

But on a 53C400A, the 5380 registers are mapped on the base address so the
C400_ registers would be below the base, which is obviously wrong. I hope that
PDMA will work if I fix the C400_ registers mapping.

> > + if (transfersize % 128)
> > + transfersize = 0;
> > +
> > return transfersize;
> > }
> >
> > It seems to work and greatly improves performance:
> > # hdparm -t --direct /dev/sdb
> >
> > /dev/sdb:
> > Timing O_DIRECT disk reads: 4 MB in 4.84 seconds = 846.15 kB/sec
> >
>
> Sounds about right...
>

--
Ondrej Zary

2015-11-25 11:50:44

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers


On Wed, 25 Nov 2015, Ondrej Zary wrote:

> On Wednesday 25 November 2015, Finn Thain wrote:
> >
> > On Tue, 24 Nov 2015, Ondrej Zary wrote:
> >
> > > Instead of fixing split transfers, simply forced everything
> > > non-modulo-128 to PIO:
> >
> > [...]
> > I don't have any reason to think that your card will allow part of
> > a transfer to be performed with PDMA and the rest with PIO. So I don't
> > really object to the patch.
> >

>From looking at the datasheet, I think your patch is correct.

Your patch needs to be applied after mine, so if you will sign-off, I'll
include it in the series with your Signed-off-by and "From:" header.

> > But I don't understand the need for it either: I have no idea what
> > state the driver, chip and scsi bus were in when the 126-byte PIO
> > transfer failed. If the PIO transfer didn't succeed then the entire
> > command should have failed.
>
> The patch was just a quick hack to confirm that PDMA is not completely
> broken.
> Now we know that it mostly works so I can investigate the partial PIO
> problem.
>

There may not be any problem to investigate. Because this 53C80 core is
embedded in other logic, it's hard to say whether or not the partial PIO
algorithm could be expected to work at all.

Besides, the DMA errata don't apply to this core. And large transfers will
always be divisible by 128 bytes so there's very little to be gained.

> [...]
>
> 53C400A datasheet would be great too but haven't found any.

I don't have one either.

--

2015-11-25 21:35:04

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH 72/71] ncr5380: Fix pseudo-DMA

Pseudo-DMA (PDMA) has been broken for ages, resulting in hangs on
53C400-based cards.

According to 53C400 datasheet, PDMA transfer length must be a multiple
of 128. Check if that's true and use PIO if it's not.

This makes PDMA work on 53C400 (Canon FG2-5202).

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 0daffe2..a9a237f 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -703,6 +703,10 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd)
!(cmd->SCp.this_residual % transfersize))
transfersize = 32 * 1024;

+ /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */
+ if (transfersize % 128)
+ transfersize = 0;
+
return transfersize;
}

--
Ondrej Zary

2015-11-25 23:01:35

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 00/71] More fixes, cleanup and modernization for NCR5380 drivers

On Wednesday 25 November 2015 10:04:10 Ondrej Zary wrote:
> I think that PDMA should work with 53C400A too but seems that the driver was
> never able to do it.
>
> Although there is code for port-mapped transfer in NCR5380_pread(),
> NCR53C400_register_offset is defined to 0 in the port-mapped case. The C400_
> register offsets are thus defined with negative offset:
>
> #define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8
> #define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7
> #define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6
> #define C400_HOST_BUFFER NCR53C400_register_offset-4
>
> This is probably OK for a port-mapped 53C400 (such card must have some glue
> decoding logic as the 53C400 chip itself can do memory-mapping only) because:
>
> /*
> * On NCR53C400 boards, NCR5380 registers are mapped 8 past
> * the base address.
> */
> if (overrides[current_override].board == BOARD_NCR53C400)
> instance->io_port += 8;
>
> This means that on a 53C400, first 5380 register will be at base+8 and first
> C400_ register at base.
>
> But on a 53C400A, the 5380 registers are mapped on the base address so the
> C400_ registers would be below the base, which is obviously wrong. I hope that
> PDMA will work if I fix the C400_ registers mapping.

A quick hack (breaks other chips, needs more work for proper mapping on all
chips):

--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -163,7 +163,7 @@
/* Write any value to this register to start an ini mode DMA receive */
#define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */

-#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
+#define C400_CONTROL_STATUS_REG 9 /* rw */

#define CSR_RESET 0x80 /* wo Resets 53c400 */
#define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
@@ -182,13 +182,13 @@
#endif

/* Number of 128-byte blocks to be transferred */
-#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
+#define C400_BLOCK_COUNTER_REG 10 /* rw */

/* Resume transfer after disconnect */
-#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
+#define C400_RESUME_TRANSFER_REG 11 /* wo */

/* Access to host buffer stack */
-#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
+#define C400_HOST_BUFFER 8 /* rw */


/* Note : PHASE_* macros are based on the values of the STATUS register */
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -323,7 +323,10 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
#endif
break;
case BOARD_NCR53C400A:
+ flags = FLAG_NO_DMA_FIXUP;
+#ifndef PSEUDO_DMA
flags = FLAG_NO_PSEUDO_DMA;
+#endif
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
@@ -414,7 +417,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (NCR5380_init(instance, flags))
goto out_unregister;

- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400 ||
+ overrides[current_override].board == BOARD_NCR53C400A)
NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);

NCR5380_maybe_reset_bus(instance);


And PDMA works on I/O mapped 53C400A (HP C2502)!

# modprobe g_NCR5380 ncr_irq=7 ncr_addr=0x280 ncr_53c400a=1
[ 1799.939856] scsi host4: Generic NCR5380/NCR53C400 SCSI, io_port 0x280, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { NO_DMA_FIXUP }, options { AUTOPROBE_IRQ PSEUDO_DMA }
[ 1816.277018] scsi 4:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS
[ 1897.899648] sd 4:0:1:0: Attached scsi generic sg1 type 0
[ 1897.917842] sd 4:0:1:0: [sdb] 479350 512-byte logical blocks: (245 MB/234 MiB)
[ 1897.920872] sd 4:0:1:0: [sdb] Write Protect is off
[ 1897.924744] sd 4:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1897.967857] sdb: sdb1
[ 1897.993822] sd 4:0:1:0: [sdb] Attached SCSI disk


Nice performance improvement (although it's slower than the memory-mapped
53C400):
# hdparm -t --direct /dev/sdb

/dev/sdb:
Timing O_DIRECT disk reads: 2 MB in 3.99 seconds = 513.57 kB/sec


And it even fixed the IRQ:
# head /proc/interrupts
CPU0
0: 151228 XT-PIC timer
1: 9 XT-PIC i8042
2: 0 XT-PIC cascade
7: 115 XT-PIC NCR5380
8: 1 XT-PIC rtc0
9: 0 XT-PIC uhci_hcd:usb1, uhci_hcd:usb2
10: 3256 XT-PIC eth0
12: 136 XT-PIC i8042
14: 3833 XT-PIC pata_via


--
Ondrej Zary

2015-11-29 09:40:16

by Ondrej Zary

[permalink] [raw]
Subject: [RFC PATCH 73/71] ncr5380: Use runtime register mapping

Convert compile-time C400_ register mapping to runtime mapping.
This removes the weird negative register offsets and allows adding
additional mappings.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/NCR5380.h | 13 +---------
drivers/scsi/g_NCR5380.c | 61 ++++++++++++++++++++++++++--------------------
drivers/scsi/g_NCR5380.h | 12 ++++++---
3 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 36779df..0d8ec43 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -163,8 +163,7 @@
/* Write any value to this register to start an ini mode DMA receive */
#define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */

-#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
-
+/* C400_CONTROL_STATUS_REG */
#define CSR_RESET 0x80 /* wo Resets 53c400 */
#define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
@@ -181,16 +180,6 @@
#define CSR_BASE CSR_53C80_INTR
#endif

-/* Number of 128-byte blocks to be transferred */
-#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
-
-/* Resume transfer after disconnect */
-#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
-
-/* Access to host buffer stack */
-#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
-
-
/* Note : PHASE_* macros are based on the values of the STATUS register */
#define PHASE_MASK (SR_MSG | SR_CD | SR_IO)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index a9a237f..ce444da 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -253,6 +253,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
};
int flags;
struct Scsi_Host *instance;
+ struct NCR5380_hostdata *hostdata;
#ifdef SCSI_G_NCR5380_MEM
unsigned long base;
void __iomem *iomem;
@@ -395,6 +396,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL)
goto out_release;
+ hostdata = shost_priv(instance);

#ifndef SCSI_G_NCR5380_MEM
instance->io_port = overrides[current_override].NCR5380_map_name;
@@ -404,18 +406,27 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
*/
- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400) {
instance->io_port += 8;
+ hostdata->c400_ctl_status = 0;
+ hostdata->c400_blk_cnt = 1;
+ hostdata->c400_host_buf = 4;
+ }
#else
instance->base = overrides[current_override].NCR5380_map_name;
- ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
+ hostdata->iomem = iomem;
+ if (overrides[current_override].board == BOARD_NCR53C400) {
+ hostdata->c400_ctl_status = 0x100;
+ hostdata->c400_blk_cnt = 0x101;
+ hostdata->c400_host_buf = 0x104;
+ }
#endif

if (NCR5380_init(instance, flags))
goto out_unregister;

if (overrides[current_override].board == BOARD_NCR53C400)
- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);

@@ -523,30 +534,28 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,

static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
{
-#ifdef SCSI_G_NCR5380_MEM
struct NCR5380_hostdata *hostdata = shost_priv(instance);
-#endif
int blocks = len / 128;
int start = 0;
int bl;

- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
- NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
+ NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
- if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
+ if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
break;
}
- if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
+ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);

#ifndef SCSI_G_NCR5380_MEM
{
int i;
for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
+ dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -558,7 +567,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
}

if (blocks) {
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
{
// FIXME - no timeout
}
@@ -567,7 +576,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
{
int i;
for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
+ dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -578,7 +587,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
blocks--;
}

- if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
+ if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
printk("53C400r: no 53C80 gated irq after transfer");

#if 0
@@ -586,7 +595,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
* DON'T DO THIS - THEY NEVER ARRIVE!
*/
printk("53C400r: Waiting for 53C80 registers\n");
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
;
#endif
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
@@ -607,31 +616,29 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,

static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
{
-#ifdef SCSI_G_NCR5380_MEM
struct NCR5380_hostdata *hostdata = shost_priv(instance);
-#endif
int blocks = len / 128;
int start = 0;
int bl;
int i;

- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
- NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
+ NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
- if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
+ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}

- if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
+ if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
break;
}
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
{
for (i = 0; i < 128; i++)
- NCR5380_write(C400_HOST_BUFFER, src[start + i]);
+ NCR5380_write(hostdata->c400_host_buf, src[start + i]);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -642,13 +649,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
blocks--;
}
if (blocks) {
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout

#ifndef SCSI_G_NCR5380_MEM
{
for (i = 0; i < 128; i++)
- NCR5380_write(C400_HOST_BUFFER, src[start + i]);
+ NCR5380_write(hostdata->c400_host_buf, src[start + i]);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -661,7 +668,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,

#if 0
printk("53C400w: waiting for registers to be available\n");
- THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
+ THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
printk("53C400w: Got em\n");
#endif

@@ -669,7 +676,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
; // FIXME - no timeout

/*
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index fd201e9..633edd0 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -29,7 +29,6 @@

#define NCR5380_map_type int
#define NCR5380_map_name port
-#define NCR53C400_register_offset 0

#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR5380_region_size 16
@@ -42,7 +41,10 @@
#define NCR5380_write(reg, value) \
outb(value, instance->io_port + (reg))

-#define NCR5380_implementation_fields /* none */
+#define NCR5380_implementation_fields \
+ int c400_ctl_status;\
+ int c400_blk_cnt;\
+ int c400_host_buf;

#else
/* therefore SCSI_G_NCR5380_MEM */
@@ -50,7 +52,6 @@

#define NCR5380_map_type unsigned long
#define NCR5380_map_name base
-#define NCR53C400_register_offset 0x108
#define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900
#define NCR5380_region_size 0x3a00
@@ -63,7 +64,10 @@
NCR53C400_mem_base + (reg))

#define NCR5380_implementation_fields \
- void __iomem *iomem;
+ void __iomem *iomem;\
+ int c400_ctl_status;\
+ int c400_blk_cnt;\
+ int c400_host_buf;

#endif

--
Ondrej Zary

2015-11-29 09:39:57

by Ondrej Zary

[permalink] [raw]
Subject: [RFC PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A

Add I/O register mapping for NCR53C400A and enable PDMA mode to
improve performance and fix non-working IRQ.

Tested with HP C2502 (and user-space enabler).

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index ce444da..c3abe48 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -324,7 +324,10 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
#endif
break;
case BOARD_NCR53C400A:
+ flags = FLAG_NO_DMA_FIXUP;
+#ifndef PSEUDO_DMA
flags = FLAG_NO_PSEUDO_DMA;
+#endif
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
@@ -412,6 +415,11 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
}
+ if (overrides[current_override].board == BOARD_NCR53C400A) {
+ hostdata->c400_ctl_status = 9;
+ hostdata->c400_blk_cnt = 10;
+ hostdata->c400_host_buf = 8;
+ }
#else
instance->base = overrides[current_override].NCR5380_map_name;
hostdata->iomem = iomem;
@@ -425,7 +433,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (NCR5380_init(instance, flags))
goto out_unregister;

- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400 ||
+ overrides[current_override].board == BOARD_NCR53C400A)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
--
Ondrej Zary

2015-11-29 10:01:20

by Ondrej Zary

[permalink] [raw]
Subject: [RFC PATCH 75/71] ncr5380: Remove FLAG_DTC3181E

The FLAG_DTC3181E is used to activate a work-around for arbitration lost
condition that these chips see when ICR is written during arbitration.

Move the ICR write (to set SEL and BSY) after the arbitration loss check
and remove FLAG_DTC3181E.

Signed-off-by: Ondrej Zary <[email protected]>
---
Weird, we now have two consecutive checks for ICR_ARBITRATION_LOST and
do different things when they fail...

drivers/scsi/NCR5380.c | 23 +++++++++--------------
drivers/scsi/NCR5380.h | 1 -
drivers/scsi/atari_NCR5380.c | 23 +++++++++--------------
drivers/scsi/dmx3191d.c | 2 +-
drivers/scsi/g_NCR5380.c | 2 +-
5 files changed, 20 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index acb359a..b617f99 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -482,14 +482,13 @@ static void prepare_info(struct Scsi_Host *instance)
"base 0x%lx, irq %d, "
"can_queue %d, cmd_per_lun %d, "
"sg_tablesize %d, this_id %d, "
- "flags { %s%s%s%s}, "
+ "flags { %s%s%s}, "
"options { %s} ",
instance->hostt->name, instance->io_port, instance->n_io_port,
instance->base, instance->irq,
instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
hostdata->flags & FLAG_NO_DMA_FIXUP ? "NO_DMA_FIXUP " : "",
- hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "",
hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
#ifdef AUTOPROBE_IRQ
@@ -1078,18 +1077,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
goto out;
}

- /* After/during arbitration, BSY should be asserted.
- * IBM DPES-31080 Version S31Q works now
- * Tnx to [email protected] for finding this! (Roman)
- */
- NCR5380_write(INITIATOR_COMMAND_REG,
- ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
-
- /* RvC: DTC3181E has some trouble with this so we simply removed it.
- * Seems to work with only Mustek scanner attached.
- */
- if (!(hostdata->flags & FLAG_DTC3181E) &&
- (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
+ if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) {
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
dsprintk(NDEBUG_ARBITRATION, instance, "arbitration lost, negating SEL\n");
@@ -1097,6 +1085,13 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
goto out;
}

+ /* After/during arbitration, BSY should be asserted.
+ * IBM DPES-31080 Version S31Q works now
+ * Tnx to [email protected] for finding this! (Roman)
+ */
+ NCR5380_write(INITIATOR_COMMAND_REG,
+ ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
+
/*
* Again, bus clear + bus settle time is 1.2us, however, this is
* a minimum so we'll udelay ceil(1.2)
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 0d8ec43..5092580 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -222,7 +222,6 @@

#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
-#define FLAG_DTC3181E 16 /* DTC3181E */
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
#define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index d04374d..7640110 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -586,13 +586,12 @@ static void prepare_info(struct Scsi_Host *instance)
"base 0x%lx, irq %d, "
"can_queue %d, cmd_per_lun %d, "
"sg_tablesize %d, this_id %d, "
- "flags { %s%s%s}, "
+ "flags { %s%s}, "
"options { %s} ",
instance->hostt->name, instance->io_port, instance->n_io_port,
instance->base, instance->irq,
instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
- hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "",
hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "",
hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
#ifdef DIFFERENTIAL
@@ -1279,18 +1278,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
goto out;
}

- /* After/during arbitration, BSY should be asserted.
- * IBM DPES-31080 Version S31Q works now
- * Tnx to [email protected] for finding this! (Roman)
- */
- NCR5380_write(INITIATOR_COMMAND_REG,
- ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
-
- /* RvC: DTC3181E has some trouble with this so we simply removed it.
- * Seems to work with only Mustek scanner attached.
- */
- if (!(hostdata->flags & FLAG_DTC3181E) &&
- (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
+ if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) {
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
dsprintk(NDEBUG_ARBITRATION, instance, "arbitration lost, negating SEL\n");
@@ -1298,6 +1286,13 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
goto out;
}

+ /* After/during arbitration, BSY should be asserted.
+ * IBM DPES-31080 Version S31Q works now
+ * Tnx to [email protected] for finding this! (Roman)
+ */
+ NCR5380_write(INITIATOR_COMMAND_REG,
+ ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
+
/*
* Again, bus clear + bus settle time is 1.2us, however, this is
* a minimum so we'll udelay ceil(1.2)
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 3c60dfb..ddb4e61 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -92,7 +92,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
*/
shost->irq = NO_IRQ;

- error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
+ error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA);
if (error)
goto out_host_put;

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index c3abe48..fae4332 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -331,7 +331,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
- flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E;
+ flags = FLAG_NO_PSEUDO_DMA;
ports = dtc_3181e_ports;
break;
}
--
Ondrej Zary

2015-11-30 04:57:11

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 75/71] ncr5380: Remove FLAG_DTC3181E


On Sun, 29 Nov 2015, Ondrej Zary wrote:

> The FLAG_DTC3181E is used to activate a work-around for arbitration lost
> condition that these chips see when ICR is written during arbitration.
>
> Move the ICR write (to set SEL and BSY) after the arbitration loss check
> and remove FLAG_DTC3181E.

The first test for ICR_ARBITRATION_LOST happens after the required
arbitration delay, 2.4 us. The second test for ICR_ARBITRATION_LOST
happens after ICR_ASSERT_SEL.

This second test seems to be pointless. It comes from the flow chart in
the NCR datasheet (see download link in patch 17). The spec does not
require this test but some 5380 devices may do. Who knows? It's almost
impossible to be sure, because it would mean losing a race with another
bus device right at the end of the arbitration delay (and we extend that
delay to 3 us anyway).

Certainly one can find other datasheets with sample code and flow charts
that don't do this second check. The reason is that ICR_ARBITRATION_LOST
can be triggered when SEL is asserted by any device, so it may be
triggered after we've won arbitration (because we then set ICR_ASSERT_SEL
ourselves in order to enter selection phase).

>
> ... Weird, we now have two consecutive checks for ICR_ARBITRATION_LOST
> and do different things when they fail...

They do different things because the second exit has to cleanup after the
ICR write.

I agree that it would be nice to remove the DTC3181E special case. It
would mean replacing patch 49.

The patch below is another version of your patch 75. It really needs to be
tested on all kinds of 5380 device, and if possible with a contested bus
(which would imply diconnection privileges, for which the driver still
requires that the chip has a working irq).

Index: linux/drivers/scsi/NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/NCR5380.c 2015-11-30 15:34:39.000000000 +1100
+++ linux/drivers/scsi/NCR5380.c 2015-11-30 15:34:39.000000000 +1100
@@ -482,14 +482,13 @@ static void prepare_info(struct Scsi_Hos
"base 0x%lx, irq %d, "
"can_queue %d, cmd_per_lun %d, "
"sg_tablesize %d, this_id %d, "
- "flags { %s%s%s%s}, "
+ "flags { %s%s%s}, "
"options { %s} ",
instance->hostt->name, instance->io_port, instance->n_io_port,
instance->base, instance->irq,
instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
hostdata->flags & FLAG_NO_DMA_FIXUP ? "NO_DMA_FIXUP " : "",
- hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "",
hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
#ifdef AUTOPROBE_IRQ
@@ -1085,18 +1084,6 @@ static struct scsi_cmnd *NCR5380_select(
NCR5380_write(INITIATOR_COMMAND_REG,
ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);

- /* RvC: DTC3181E has some trouble with this so we simply removed it.
- * Seems to work with only Mustek scanner attached.
- */
- if (!(hostdata->flags & FLAG_DTC3181E) &&
- (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- dsprintk(NDEBUG_ARBITRATION, instance, "arbitration lost, negating SEL\n");
- spin_lock_irq(&hostdata->lock);
- goto out;
- }
-
/*
* Again, bus clear + bus settle time is 1.2us, however, this is
* a minimum so we'll udelay ceil(1.2)
Index: linux/drivers/scsi/NCR5380.h
===================================================================
--- linux.orig/drivers/scsi/NCR5380.h 2015-11-30 15:34:36.000000000 +1100
+++ linux/drivers/scsi/NCR5380.h 2015-11-30 15:34:39.000000000 +1100
@@ -233,7 +233,6 @@

#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
-#define FLAG_DTC3181E 16 /* DTC3181E */
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
#define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */
Index: linux/drivers/scsi/atari_NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/atari_NCR5380.c 2015-11-30 15:34:39.000000000 +1100
+++ linux/drivers/scsi/atari_NCR5380.c 2015-11-30 15:34:39.000000000 +1100
@@ -586,13 +586,12 @@ static void prepare_info(struct Scsi_Hos
"base 0x%lx, irq %d, "
"can_queue %d, cmd_per_lun %d, "
"sg_tablesize %d, this_id %d, "
- "flags { %s%s%s}, "
+ "flags { %s%s}, "
"options { %s} ",
instance->hostt->name, instance->io_port, instance->n_io_port,
instance->base, instance->irq,
instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
- hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "",
hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "",
hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
#ifdef DIFFERENTIAL
@@ -1286,18 +1285,6 @@ static struct scsi_cmnd *NCR5380_select(
NCR5380_write(INITIATOR_COMMAND_REG,
ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);

- /* RvC: DTC3181E has some trouble with this so we simply removed it.
- * Seems to work with only Mustek scanner attached.
- */
- if (!(hostdata->flags & FLAG_DTC3181E) &&
- (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- dsprintk(NDEBUG_ARBITRATION, instance, "arbitration lost, negating SEL\n");
- spin_lock_irq(&hostdata->lock);
- goto out;
- }
-
/*
* Again, bus clear + bus settle time is 1.2us, however, this is
* a minimum so we'll udelay ceil(1.2)
Index: linux/drivers/scsi/g_NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/g_NCR5380.c 2015-11-30 15:34:39.000000000 +1100
+++ linux/drivers/scsi/g_NCR5380.c 2015-11-30 15:34:39.000000000 +1100
@@ -326,7 +326,7 @@ static int __init generic_NCR5380_detect
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
- flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E;
+ flags = FLAG_NO_PSEUDO_DMA;
ports = dtc_3181e_ports;
break;
}
Index: linux/drivers/scsi/dmx3191d.c
===================================================================
--- linux.orig/drivers/scsi/dmx3191d.c 2015-11-30 15:34:35.000000000 +1100
+++ linux/drivers/scsi/dmx3191d.c 2015-11-30 15:34:39.000000000 +1100
@@ -92,7 +92,7 @@ static int dmx3191d_probe_one(struct pci
*/
shost->irq = NO_IRQ;

- error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
+ error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA);
if (error)
goto out_host_put;

2015-11-30 11:50:37

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 73/71] ncr5380: Use runtime register mapping


On Sun, 29 Nov 2015, Ondrej Zary wrote:

> Convert compile-time C400_ register mapping to runtime mapping.
> This removes the weird negative register offsets and allows adding
> additional mappings.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/NCR5380.h | 13 +---------
> drivers/scsi/g_NCR5380.c | 61 ++++++++++++++++++++++++++--------------------
> drivers/scsi/g_NCR5380.h | 12 ++++++---
> 3 files changed, 43 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
> index 36779df..0d8ec43 100644
> --- a/drivers/scsi/NCR5380.h
> +++ b/drivers/scsi/NCR5380.h
> @@ -163,8 +163,7 @@
> /* Write any value to this register to start an ini mode DMA receive */
> #define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */
>
> -#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
> -
> +/* C400_CONTROL_STATUS_REG */

That symbol is removed by this patch. No need for abbreviations. How about

/* NCR 53C400 and 53C400A Control Status Register bits: */

> #define CSR_RESET 0x80 /* wo Resets 53c400 */
> #define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
> #define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
> @@ -181,16 +180,6 @@
> #define CSR_BASE CSR_53C80_INTR
> #endif
>
> -/* Number of 128-byte blocks to be transferred */
> -#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
> -
> -/* Resume transfer after disconnect */
> -#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
> -
> -/* Access to host buffer stack */
> -#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
> -
> -
> /* Note : PHASE_* macros are based on the values of the STATUS register */
> #define PHASE_MASK (SR_MSG | SR_CD | SR_IO)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index a9a237f..ce444da 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -253,6 +253,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> };
> int flags;
> struct Scsi_Host *instance;
> + struct NCR5380_hostdata *hostdata;
> #ifdef SCSI_G_NCR5380_MEM
> unsigned long base;
> void __iomem *iomem;
> @@ -395,6 +396,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
> if (instance == NULL)
> goto out_release;
> + hostdata = shost_priv(instance);
>
> #ifndef SCSI_G_NCR5380_MEM
> instance->io_port = overrides[current_override].NCR5380_map_name;
> @@ -404,18 +406,27 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> * On NCR53C400 boards, NCR5380 registers are mapped 8 past
> * the base address.
> */
> - if (overrides[current_override].board == BOARD_NCR53C400)
> + if (overrides[current_override].board == BOARD_NCR53C400) {
> instance->io_port += 8;
> + hostdata->c400_ctl_status = 0;
> + hostdata->c400_blk_cnt = 1;
> + hostdata->c400_host_buf = 4;
> + }
> #else
> instance->base = overrides[current_override].NCR5380_map_name;
> - ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
> + hostdata->iomem = iomem;
> + if (overrides[current_override].board == BOARD_NCR53C400) {
> + hostdata->c400_ctl_status = 0x100;
> + hostdata->c400_blk_cnt = 0x101;
> + hostdata->c400_host_buf = 0x104;
> + }
> #endif
>
> if (NCR5380_init(instance, flags))
> goto out_unregister;
>
> if (overrides[current_override].board == BOARD_NCR53C400)
> - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
> + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
>
> @@ -523,30 +534,28 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
>
> static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
> {
> -#ifdef SCSI_G_NCR5380_MEM
> struct NCR5380_hostdata *hostdata = shost_priv(instance);
> -#endif
> int blocks = len / 128;
> int start = 0;
> int bl;
>
> - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
> - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
> + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
> + NCR5380_write(hostdata->c400_blk_cnt, blocks);
> while (1) {
> - if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
> + if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
> break;
> }
> - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
> + if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
> printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
> return -1;
> }
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);
>
> #ifndef SCSI_G_NCR5380_MEM
> {
> int i;
> for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
> + dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> }
> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -558,7 +567,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> }
>
> if (blocks) {
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> {
> // FIXME - no timeout
> }
> @@ -567,7 +576,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> {
> int i;
> for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
> + dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> }
> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -578,7 +587,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> blocks--;
> }
>
> - if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
> + if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> printk("53C400r: no 53C80 gated irq after transfer");
>
> #if 0
> @@ -586,7 +595,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> * DON'T DO THIS - THEY NEVER ARRIVE!
> */
> printk("53C400r: Waiting for 53C80 registers\n");
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
> ;
> #endif
> if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
> @@ -607,31 +616,29 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
>
> static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
> {
> -#ifdef SCSI_G_NCR5380_MEM
> struct NCR5380_hostdata *hostdata = shost_priv(instance);
> -#endif
> int blocks = len / 128;
> int start = 0;
> int bl;
> int i;
>
> - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
> - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
> + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
> + NCR5380_write(hostdata->c400_blk_cnt, blocks);
> while (1) {
> - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
> + if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
> printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
> return -1;
> }
>
> - if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
> + if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
> break;
> }
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - timeout
> #ifndef SCSI_G_NCR5380_MEM
> {
> for (i = 0; i < 128; i++)
> - NCR5380_write(C400_HOST_BUFFER, src[start + i]);
> + NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> }
> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -642,13 +649,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> blocks--;
> }
> if (blocks) {
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - no timeout
>
> #ifndef SCSI_G_NCR5380_MEM
> {
> for (i = 0; i < 128; i++)
> - NCR5380_write(C400_HOST_BUFFER, src[start + i]);
> + NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> }
> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -661,7 +668,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
>
> #if 0
> printk("53C400w: waiting for registers to be available\n");
> - THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
> + THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
> printk("53C400w: Got em\n");
> #endif
>
> @@ -669,7 +676,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> /* All documentation says to check for this. Maybe my hardware is too
> * fast. Waiting for it seems to work fine! KLL
> */
> - while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
> + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> ; // FIXME - no timeout
>
> /*
> diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> index fd201e9..633edd0 100644
> --- a/drivers/scsi/g_NCR5380.h
> +++ b/drivers/scsi/g_NCR5380.h
> @@ -29,7 +29,6 @@
>
> #define NCR5380_map_type int
> #define NCR5380_map_name port
> -#define NCR53C400_register_offset 0
>
> #ifdef CONFIG_SCSI_GENERIC_NCR53C400
> #define NCR5380_region_size 16
> @@ -42,7 +41,10 @@
> #define NCR5380_write(reg, value) \
> outb(value, instance->io_port + (reg))
>
> -#define NCR5380_implementation_fields /* none */
> +#define NCR5380_implementation_fields \
> + int c400_ctl_status;\
> + int c400_blk_cnt;\
> + int c400_host_buf;
>
> #else
> /* therefore SCSI_G_NCR5380_MEM */

A space before the backslash would be more consistent.

> @@ -50,7 +52,6 @@
>
> #define NCR5380_map_type unsigned long
> #define NCR5380_map_name base
> -#define NCR53C400_register_offset 0x108
> #define NCR53C400_mem_base 0x3880
> #define NCR53C400_host_buffer 0x3900
> #define NCR5380_region_size 0x3a00
> @@ -63,7 +64,10 @@
> NCR53C400_mem_base + (reg))
>
> #define NCR5380_implementation_fields \
> - void __iomem *iomem;
> + void __iomem *iomem;\
> + int c400_ctl_status;\
> + int c400_blk_cnt;\
> + int c400_host_buf;
>
> #endif
>

Same here.

--

2015-11-30 11:52:43

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A


On Sun, 29 Nov 2015, Ondrej Zary wrote:

> Add I/O register mapping for NCR53C400A and enable PDMA mode to
> improve performance and fix non-working IRQ.
>
> Tested with HP C2502 (and user-space enabler).
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index ce444da..c3abe48 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -324,7 +324,10 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> #endif
> break;
> case BOARD_NCR53C400A:
> + flags = FLAG_NO_DMA_FIXUP;
> +#ifndef PSEUDO_DMA
> flags = FLAG_NO_PSEUDO_DMA;
> +#endif

FLAG_NO_PSEUDO_DMA is not tested unless defined(PSEUDO_DMA), so it
shouldn't be set here. I know I made the same mistake in patch 8; it will
be fixed in the next submission.

--

> ports = ncr_53c400a_ports;
> break;
> case BOARD_DTC3181E:
> @@ -412,6 +415,11 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> hostdata->c400_blk_cnt = 1;
> hostdata->c400_host_buf = 4;
> }
> + if (overrides[current_override].board == BOARD_NCR53C400A) {
> + hostdata->c400_ctl_status = 9;
> + hostdata->c400_blk_cnt = 10;
> + hostdata->c400_host_buf = 8;
> + }
> #else
> instance->base = overrides[current_override].NCR5380_map_name;
> hostdata->iomem = iomem;
> @@ -425,7 +433,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> if (NCR5380_init(instance, flags))
> goto out_unregister;
>
> - if (overrides[current_override].board == BOARD_NCR53C400)
> + if (overrides[current_override].board == BOARD_NCR53C400 ||
> + overrides[current_override].board == BOARD_NCR53C400A)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
>

2015-11-30 12:04:30

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A


On Sun, 29 Nov 2015, Ondrej Zary wrote:

> Add I/O register mapping for NCR53C400A and enable PDMA mode to
> improve performance and fix non-working IRQ.
>

Is CONFIG_SCSI_GENERIC_NCR53C400 is still needed? Can the driver be fully
configured at runtime now?

> Tested with HP C2502 (and user-space enabler).
>

It would be nice if the enabler was documented.
Documentation/scsi/g_NCR5380.txt might be a good place for that. That file
could perhaps be updated (?) Certainly obsolete and misleading information
should be removed if you see any.

--

2015-11-30 13:40:18

by Ondrej Zary

[permalink] [raw]
Subject: Re: [RFC PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A

On Monday 30 November 2015, Finn Thain wrote:
>
> On Sun, 29 Nov 2015, Ondrej Zary wrote:
>
> > Add I/O register mapping for NCR53C400A and enable PDMA mode to
> > improve performance and fix non-working IRQ.
> >
>
> Is CONFIG_SCSI_GENERIC_NCR53C400 is still needed? Can the driver be fully
> configured at runtime now?

Things depending on CONFIG_SCSI_GENERIC_NCR53C400:

#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define PSEUDO_DMA
#endif

Defining PSEUDO_DMA should not break anything, just makes code bigger a bit. We can probably just define it always in g_NCR5380.c.


This looks weird. I don't have any card with a BIOS to test.
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define BIOSPARAM
#define NCR5380_BIOSPARAM generic_NCR5380_biosparam
#else
#define NCR5380_BIOSPARAM NULL
#endif


This looks very wrong and should be done at runtime:
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR5380_region_size 16
#else
#define NCR5380_region_size 8
#endif


> > Tested with HP C2502 (and user-space enabler).
> >
>
> It would be nice if the enabler was documented.
> Documentation/scsi/g_NCR5380.txt might be a good place for that. That file
> could perhaps be updated (?) Certainly obsolete and misleading information
> should be removed if you see any.

I'll integrate the enabler into the driver. It's like "wakeup sequence for the NCR53C400A and DTC3181E */" in g_NCR5380.c, only the magic numbers are different.

--
Ondrej Zary

2015-12-03 23:03:18

by Ondrej Zary

[permalink] [raw]
Subject: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips

Add I/O register mapping for DTC chips and enable PDMA mode.

These chips have 16-bit wide HOST BUFFER register (counter register at
offset 0x0d increments by 2 on each HOST BUFFER read).

Large PIO transfers crash at least the DTCT-436P chip (all reads result
in 0xFF) so this patch actually makes it work.

The chip also crashes when we bang the C400 host status register too
heavily after PDMA write - a small udelay is needed.

Signed-off-by: Ondrej Zary <[email protected]>
---
# hdparm -t --direct /dev/sdb

/dev/sdb:
Timing O_DIRECT disk reads: 4 MB in 3.78 seconds = 1.06 MB/sec


drivers/scsi/NCR5380.h | 1 +
drivers/scsi/g_NCR5380.c | 47 +++++++++++++++++++++++-----------------------
2 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 5092580..e3b8149 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -222,6 +222,7 @@

#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
+#define FLAG_16BIT 16 /* 16-bit PDMA */
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
#define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index fae4332..04f6c29 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -331,7 +331,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
- flags = FLAG_NO_PSEUDO_DMA;
+ flags = FLAG_NO_DMA_FIXUP | FLAG_16BIT;
ports = dtc_3181e_ports;
break;
}
@@ -415,7 +415,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
}
- if (overrides[current_override].board == BOARD_NCR53C400A) {
+ if (overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_DTC3181E) {
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
hostdata->c400_host_buf = 8;
@@ -434,7 +435,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
goto out_unregister;

if (overrides[current_override].board == BOARD_NCR53C400 ||
- overrides[current_override].board == BOARD_NCR53C400A)
+ overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_DTC3181E)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
@@ -561,11 +563,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);

#ifndef SCSI_G_NCR5380_MEM
- {
- int i;
- for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
- }
+ if (hostdata->flags & FLAG_16BIT)
+ insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start,
@@ -582,11 +583,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
}

#ifndef SCSI_G_NCR5380_MEM
- {
- int i;
- for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
- }
+ if (hostdata->flags & FLAG_16BIT)
+ insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start,
@@ -645,10 +645,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
- {
- for (i = 0; i < 128; i++)
- NCR5380_write(hostdata->c400_host_buf, src[start + i]);
- }
+ if (hostdata->flags & FLAG_16BIT)
+ outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
@@ -660,12 +660,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
if (blocks) {
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout
-
#ifndef SCSI_G_NCR5380_MEM
- {
- for (i = 0; i < 128; i++)
- NCR5380_write(hostdata->c400_host_buf, src[start + i]);
- }
+ if (hostdata->flags & FLAG_16BIT)
+ outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
@@ -685,8 +684,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
+ udelay(4); /* DTC436 chip hangs without this */
; // FIXME - no timeout
+ }

/*
* I know. i is certainly != 0 here but the loop is new. See previous
--
Ondrej Zary

2015-12-03 23:03:17

by Ondrej Zary

[permalink] [raw]
Subject: [RFC PATCH 77/71] ncr5380: Fix wait for 53C80 registers registers after PDMA

The check for 53C80 registers accessibility was commented out because
it was broken (inverted). Fix and enable it.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 35 +++++++----------------------------
1 file changed, 7 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 04f6c29..c5cd490 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -599,14 +599,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
printk("53C400r: no 53C80 gated irq after transfer");

-#if 0
- /*
- * DON'T DO THIS - THEY NEVER ARRIVE!
- */
- printk("53C400r: Waiting for 53C80 registers\n");
- while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
+ /* wait for 53C80 registers to be available */
+ while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
;
-#endif
+
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
printk(KERN_ERR "53C400r: no end dma signal\n");

@@ -674,36 +670,19 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
blocks--;
}

-#if 0
- printk("53C400w: waiting for registers to be available\n");
- THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
- printk("53C400w: Got em\n");
-#endif
-
- /* Let's wait for this instead - could be ugly */
- /* All documentation says to check for this. Maybe my hardware is too
- * fast. Waiting for it seems to work fine! KLL
- */
while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
udelay(4); /* DTC436 chip hangs without this */
; // FIXME - no timeout
}

- /*
- * I know. i is certainly != 0 here but the loop is new. See previous
- * comment.
- */
- if (i) {
- if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
- printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i);
- } else
- printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n");
+ /* wait for 53C80 registers to be available */
+ while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
+ ;

-#if 0
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
printk(KERN_ERR "53C400w: no end dma signal\n");
}
-#endif
+
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
; // TIMEOUT
return 0;
--
Ondrej Zary

2015-12-04 00:13:22

by Julian Calaby

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips

Hi Finn, Ondrej,

One small question:

On Fri, Dec 4, 2015 at 10:03 AM, Ondrej Zary <[email protected]> wrote:
> Add I/O register mapping for DTC chips and enable PDMA mode.
>
> These chips have 16-bit wide HOST BUFFER register (counter register at
> offset 0x0d increments by 2 on each HOST BUFFER read).
>
> Large PIO transfers crash at least the DTCT-436P chip (all reads result
> in 0xFF) so this patch actually makes it work.
>
> The chip also crashes when we bang the C400 host status register too
> heavily after PDMA write - a small udelay is needed.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 4 MB in 3.78 seconds = 1.06 MB/sec
>
>
> drivers/scsi/NCR5380.h | 1 +
> drivers/scsi/g_NCR5380.c | 47 +++++++++++++++++++++++-----------------------
> 2 files changed, 25 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index fae4332..04f6c29 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -415,7 +415,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> hostdata->c400_blk_cnt = 1;
> hostdata->c400_host_buf = 4;
> }
> - if (overrides[current_override].board == BOARD_NCR53C400A) {
> + if (overrides[current_override].board == BOARD_NCR53C400A ||
> + overrides[current_override].board == BOARD_DTC3181E) {

These if statements are starting to get a bit long, would it make
sense to replace them with a flag or equivalent?

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/

2015-12-04 08:38:15

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips


On Fri, 4 Dec 2015, Julian Calaby wrote:

> > - if (overrides[current_override].board == BOARD_NCR53C400A) {
> > + if (overrides[current_override].board == BOARD_NCR53C400A ||
> > + overrides[current_override].board == BOARD_DTC3181E) {
>
> These if statements are starting to get a bit long, would it make
> sense to replace them with a flag or equivalent?

To what end? Shorter lines? As in,

if (board_is_ncr53c400a || board_is_dtc3181e) {
/* ... */
}

I suppose that could be an improvement if new flags would entirely replace
the override.board struct member and the existing switch statement,

switch (overrides[current_override].board) {
/* ... */
}

Or maybe you meant testing a new flag something like this,

if (hostdata->ncr53c400_compatible) {
/* ... */
}

If your concern is the Don't Repeat Yourself rule, I'm not sure that new
flag would get tested more than once (?) And it would still have to be
assigned using an "objectionably" long expression, e.g.

hostdata->ncr53c400_compatible =
overrides[current_override].board == BOARD_NCR53C400 ||
overrides[current_override].board == BOARD_NCR53C400A ||
overrides[current_override].board == BOARD_DTC3181E;

Rather than add new flags, perhaps a 'switch' statement instead of an 'if'
statement would be shorter (if the size of the expression is the problem).

--

2015-12-04 09:08:41

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips


On Fri, 4 Dec 2015, Ondrej Zary wrote:

> Add I/O register mapping for DTC chips and enable PDMA mode.
>
> These chips have 16-bit wide HOST BUFFER register (counter register at
> offset 0x0d increments by 2 on each HOST BUFFER read).
>
> Large PIO transfers crash at least the DTCT-436P chip (all reads result
> in 0xFF) so this patch actually makes it work.
>
> The chip also crashes when we bang the C400 host status register too
> heavily after PDMA write - a small udelay is needed.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> # hdparm -t --direct /dev/sdb
>
> /dev/sdb:
> Timing O_DIRECT disk reads: 4 MB in 3.78 seconds = 1.06 MB/sec
>
>
> drivers/scsi/NCR5380.h | 1 +
> drivers/scsi/g_NCR5380.c | 47 +++++++++++++++++++++++-----------------------
> 2 files changed, 25 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
> index 5092580..e3b8149 100644
> --- a/drivers/scsi/NCR5380.h
> +++ b/drivers/scsi/NCR5380.h
> @@ -222,6 +222,7 @@
>
> #define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */
> #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
> +#define FLAG_16BIT 16 /* 16-bit PDMA */

Can we give this a better name? FLAG_16BIT could be taken to mean "16-bit
ISA card" but do we really want a flag for that? How about
FLAG_16BIT_BUF_REG or FLAG_WORD_IO_BUF?

All active flags appear in the console log, thanks to prepare_info(). It
might be helpful to include this one; FLAG_DTC3181E is likely to
disappear.

--

> #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
> #define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
> #define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index fae4332..04f6c29 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -331,7 +331,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> ports = ncr_53c400a_ports;
> break;
> case BOARD_DTC3181E:
> - flags = FLAG_NO_PSEUDO_DMA;
> + flags = FLAG_NO_DMA_FIXUP | FLAG_16BIT;
> ports = dtc_3181e_ports;
> break;
> }
> @@ -415,7 +415,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> hostdata->c400_blk_cnt = 1;
> hostdata->c400_host_buf = 4;
> }
> - if (overrides[current_override].board == BOARD_NCR53C400A) {
> + if (overrides[current_override].board == BOARD_NCR53C400A ||
> + overrides[current_override].board == BOARD_DTC3181E) {
> hostdata->c400_ctl_status = 9;
> hostdata->c400_blk_cnt = 10;
> hostdata->c400_host_buf = 8;
> @@ -434,7 +435,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> goto out_unregister;
>
> if (overrides[current_override].board == BOARD_NCR53C400 ||
> - overrides[current_override].board == BOARD_NCR53C400A)
> + overrides[current_override].board == BOARD_NCR53C400A ||
> + overrides[current_override].board == BOARD_DTC3181E)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
> @@ -561,11 +563,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);
>
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - int i;
> - for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> - }
> + if (hostdata->flags & FLAG_16BIT)
> + insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
> + else
> + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_fromio(dst + start,
> @@ -582,11 +583,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> }
>
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - int i;
> - for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> - }
> + if (hostdata->flags & FLAG_16BIT)
> + insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
> + else
> + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_fromio(dst + start,
> @@ -645,10 +645,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - timeout
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - for (i = 0; i < 128; i++)
> - NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> - }
> + if (hostdata->flags & FLAG_16BIT)
> + outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
> + else
> + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
> @@ -660,12 +660,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> if (blocks) {
> while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - no timeout
> -
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - for (i = 0; i < 128; i++)
> - NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> - }
> + if (hostdata->flags & FLAG_16BIT)
> + outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
> + else
> + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
> @@ -685,8 +684,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> /* All documentation says to check for this. Maybe my hardware is too
> * fast. Waiting for it seems to work fine! KLL
> */
> - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
> + udelay(4); /* DTC436 chip hangs without this */
> ; // FIXME - no timeout
> + }
>
> /*
> * I know. i is certainly != 0 here but the loop is new. See previous
>

2015-12-04 09:20:29

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips


On Fri, 4 Dec 2015, Ondrej Zary wrote:

> @@ -685,8 +684,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> /* All documentation says to check for this. Maybe my hardware is too
> * fast. Waiting for it seems to work fine! KLL
> */
> - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
> + udelay(4); /* DTC436 chip hangs without this */
> ; // FIXME - no timeout
> + }
>
> /*
> * I know. i is certainly != 0 here but the loop is new. See previous
>

Given that you've added braces, the redundant semicolon can be removed.

--

2015-12-04 09:32:43

by Ondrej Zary

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips

On Friday 04 December 2015, Finn Thain wrote:
>
> On Fri, 4 Dec 2015, Ondrej Zary wrote:
>
> > Add I/O register mapping for DTC chips and enable PDMA mode.
> >
> > These chips have 16-bit wide HOST BUFFER register (counter register at
> > offset 0x0d increments by 2 on each HOST BUFFER read).
> >
> > Large PIO transfers crash at least the DTCT-436P chip (all reads result
> > in 0xFF) so this patch actually makes it work.
> >
> > The chip also crashes when we bang the C400 host status register too
> > heavily after PDMA write - a small udelay is needed.
> >
> > Signed-off-by: Ondrej Zary <[email protected]>
> > ---
> > # hdparm -t --direct /dev/sdb
> >
> > /dev/sdb:
> > Timing O_DIRECT disk reads: 4 MB in 3.78 seconds = 1.06 MB/sec
> >
> >
> > drivers/scsi/NCR5380.h | 1 +
> > drivers/scsi/g_NCR5380.c | 47 +++++++++++++++++++++++-----------------------
> > 2 files changed, 25 insertions(+), 23 deletions(-)
> >
> > diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
> > index 5092580..e3b8149 100644
> > --- a/drivers/scsi/NCR5380.h
> > +++ b/drivers/scsi/NCR5380.h
> > @@ -222,6 +222,7 @@
> >
> > #define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */
> > #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
> > +#define FLAG_16BIT 16 /* 16-bit PDMA */
>
> Can we give this a better name? FLAG_16BIT could be taken to mean "16-bit
> ISA card" but do we really want a flag for that? How about
> FLAG_16BIT_BUF_REG or FLAG_WORD_IO_BUF?
>
> All active flags appear in the console log, thanks to prepare_info(). It
> might be helpful to include this one; FLAG_DTC3181E is likely to
> disappear.

Thinking more about this, we can probably detect the host buffer register
width instead of adding another flag. Read the counter, then read once from
the host buffer and read the counter again to see if it increments by 1 or 2.
Or maybe even 4 for PCI cards.

--
Ondrej Zary

2015-12-04 21:01:12

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH 73/71] ncr5380: Use runtime register mapping

Convert compile-time C400_ register mapping to runtime mapping.
This removes the weird negative register offsets and allows adding
additional mappings.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/NCR5380.h | 13 +---------
drivers/scsi/g_NCR5380.c | 61 ++++++++++++++++++++++++++--------------------
drivers/scsi/g_NCR5380.h | 12 ++++++---
3 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 36779df..923db6c 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -163,8 +163,7 @@
/* Write any value to this register to start an ini mode DMA receive */
#define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */

-#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
-
+/* NCR 53C400(A) Control Status Register bits: */
#define CSR_RESET 0x80 /* wo Resets 53c400 */
#define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
@@ -181,16 +180,6 @@
#define CSR_BASE CSR_53C80_INTR
#endif

-/* Number of 128-byte blocks to be transferred */
-#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
-
-/* Resume transfer after disconnect */
-#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
-
-/* Access to host buffer stack */
-#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
-
-
/* Note : PHASE_* macros are based on the values of the STATUS register */
#define PHASE_MASK (SR_MSG | SR_CD | SR_IO)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index a9a237f..ce444da 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -253,6 +253,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
};
int flags;
struct Scsi_Host *instance;
+ struct NCR5380_hostdata *hostdata;
#ifdef SCSI_G_NCR5380_MEM
unsigned long base;
void __iomem *iomem;
@@ -395,6 +396,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL)
goto out_release;
+ hostdata = shost_priv(instance);

#ifndef SCSI_G_NCR5380_MEM
instance->io_port = overrides[current_override].NCR5380_map_name;
@@ -404,18 +406,27 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
*/
- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400) {
instance->io_port += 8;
+ hostdata->c400_ctl_status = 0;
+ hostdata->c400_blk_cnt = 1;
+ hostdata->c400_host_buf = 4;
+ }
#else
instance->base = overrides[current_override].NCR5380_map_name;
- ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
+ hostdata->iomem = iomem;
+ if (overrides[current_override].board == BOARD_NCR53C400) {
+ hostdata->c400_ctl_status = 0x100;
+ hostdata->c400_blk_cnt = 0x101;
+ hostdata->c400_host_buf = 0x104;
+ }
#endif

if (NCR5380_init(instance, flags))
goto out_unregister;

if (overrides[current_override].board == BOARD_NCR53C400)
- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);

@@ -523,30 +534,28 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,

static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
{
-#ifdef SCSI_G_NCR5380_MEM
struct NCR5380_hostdata *hostdata = shost_priv(instance);
-#endif
int blocks = len / 128;
int start = 0;
int bl;

- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
- NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
+ NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
- if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
+ if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
break;
}
- if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
+ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);

#ifndef SCSI_G_NCR5380_MEM
{
int i;
for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
+ dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -558,7 +567,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
}

if (blocks) {
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
{
// FIXME - no timeout
}
@@ -567,7 +576,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
{
int i;
for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
+ dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -578,7 +587,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
blocks--;
}

- if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
+ if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
printk("53C400r: no 53C80 gated irq after transfer");

#if 0
@@ -586,7 +595,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
* DON'T DO THIS - THEY NEVER ARRIVE!
*/
printk("53C400r: Waiting for 53C80 registers\n");
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
;
#endif
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
@@ -607,31 +616,29 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,

static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
{
-#ifdef SCSI_G_NCR5380_MEM
struct NCR5380_hostdata *hostdata = shost_priv(instance);
-#endif
int blocks = len / 128;
int start = 0;
int bl;
int i;

- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
- NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
+ NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
- if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
+ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}

- if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
+ if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
break;
}
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
{
for (i = 0; i < 128; i++)
- NCR5380_write(C400_HOST_BUFFER, src[start + i]);
+ NCR5380_write(hostdata->c400_host_buf, src[start + i]);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -642,13 +649,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
blocks--;
}
if (blocks) {
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout

#ifndef SCSI_G_NCR5380_MEM
{
for (i = 0; i < 128; i++)
- NCR5380_write(C400_HOST_BUFFER, src[start + i]);
+ NCR5380_write(hostdata->c400_host_buf, src[start + i]);
}
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -661,7 +668,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,

#if 0
printk("53C400w: waiting for registers to be available\n");
- THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
+ THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
printk("53C400w: Got em\n");
#endif

@@ -669,7 +676,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
; // FIXME - no timeout

/*
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index fd201e9..c5e57b7 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -29,7 +29,6 @@

#define NCR5380_map_type int
#define NCR5380_map_name port
-#define NCR53C400_register_offset 0

#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR5380_region_size 16
@@ -42,7 +41,10 @@
#define NCR5380_write(reg, value) \
outb(value, instance->io_port + (reg))

-#define NCR5380_implementation_fields /* none */
+#define NCR5380_implementation_fields \
+ int c400_ctl_status; \
+ int c400_blk_cnt; \
+ int c400_host_buf;

#else
/* therefore SCSI_G_NCR5380_MEM */
@@ -50,7 +52,6 @@

#define NCR5380_map_type unsigned long
#define NCR5380_map_name base
-#define NCR53C400_register_offset 0x108
#define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900
#define NCR5380_region_size 0x3a00
@@ -63,7 +64,10 @@
NCR53C400_mem_base + (reg))

#define NCR5380_implementation_fields \
- void __iomem *iomem;
+ void __iomem *iomem; \
+ int c400_ctl_status; \
+ int c400_blk_cnt; \
+ int c400_host_buf;

#endif

--
Ondrej Zary

2015-12-04 21:02:14

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A

Add I/O register mapping for NCR53C400A and enable PDMA mode to
improve performance and fix non-working IRQ.

Tested with HP C2502 (and user-space enabler).

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index ce444da..cd483c6 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
#endif
break;
case BOARD_NCR53C400A:
- flags = FLAG_NO_PSEUDO_DMA;
+ flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
@@ -412,6 +412,11 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
}
+ if (overrides[current_override].board == BOARD_NCR53C400A) {
+ hostdata->c400_ctl_status = 9;
+ hostdata->c400_blk_cnt = 10;
+ hostdata->c400_host_buf = 8;
+ }
#else
instance->base = overrides[current_override].NCR5380_map_name;
hostdata->iomem = iomem;
@@ -425,7 +430,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (NCR5380_init(instance, flags))
goto out_unregister;

- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400 ||
+ overrides[current_override].board == BOARD_NCR53C400A)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
--
Ondrej Zary

2015-12-04 21:17:49

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH 76/71] ncr5380: Enable PDMA for DTC chips

Add I/O register mapping for DTC chips and enable PDMA mode.

These chips have 16-bit wide HOST BUFFER register (counter register at
offset 0x0d increments by 2 on each HOST BUFFER read). Detect it
automatically.

Large PIO transfers crash at least the DTCT-436P chip (all reads result
in 0xFF) so this patch actually makes it work.

The chip also crashes when we bang the C400 host status register too
heavily after PDMA write - a small udelay is needed.

Tested on DTCT-436P and verified that it does not break 53C400A.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 59 ++++++++++++++++++++++++++++------------------
drivers/scsi/g_NCR5380.h | 4 +++-
2 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 85da3c2..9816b81 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
- flags = FLAG_NO_PSEUDO_DMA;
+ flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
break;
}
@@ -412,10 +412,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
}
- if (overrides[current_override].board == BOARD_NCR53C400A) {
+ if (overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_DTC3181E) {
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
hostdata->c400_host_buf = 8;
+ hostdata->c400_host_idx = 13;
}
#else
instance->base = overrides[current_override].NCR5380_map_name;
@@ -430,8 +432,20 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (NCR5380_init(instance, flags))
goto out_unregister;

+#ifndef SCSI_G_NCR5380_MEM
+ /* read initial value of index register */
+ i = NCR5380_read(hostdata->c400_host_idx);
+ /* read something from host buffer */
+ NCR5380_read(hostdata->c400_host_buf);
+ /* I/O width = index register increment */
+ hostdata->io_width = NCR5380_read(hostdata->c400_host_idx) - i;
+ if (hostdata->io_width < 0)
+ hostdata->io_width += 128;
+#endif
+
if (overrides[current_override].board == BOARD_NCR53C400 ||
- overrides[current_override].board == BOARD_NCR53C400A)
+ overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_DTC3181E)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
@@ -558,11 +572,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);

#ifndef SCSI_G_NCR5380_MEM
- {
- int i;
- for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
- }
+ if (hostdata->io_width == 2)
+ insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start,
@@ -579,11 +592,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
}

#ifndef SCSI_G_NCR5380_MEM
- {
- int i;
- for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
- }
+ if (hostdata->io_width == 2)
+ insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start,
@@ -642,10 +654,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
- {
- for (i = 0; i < 128; i++)
- NCR5380_write(hostdata->c400_host_buf, src[start + i]);
- }
+ if (hostdata->io_width == 2)
+ outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
@@ -657,12 +669,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
if (blocks) {
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout
-
#ifndef SCSI_G_NCR5380_MEM
- {
- for (i = 0; i < 128; i++)
- NCR5380_write(hostdata->c400_host_buf, src[start + i]);
- }
+ if (hostdata->io_width == 2)
+ outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
@@ -682,8 +693,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
+ udelay(4); /* DTC436 chip hangs without this */
; // FIXME - no timeout
+ }

/*
* I know. i is certainly != 0 here but the loop is new. See previous
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index c5e57b7..b3936aa 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -44,7 +44,9 @@
#define NCR5380_implementation_fields \
int c400_ctl_status; \
int c400_blk_cnt; \
- int c400_host_buf;
+ int c400_host_buf; \
+ int c400_host_idx; \
+ int io_width;

#else
/* therefore SCSI_G_NCR5380_MEM */
--
Ondrej Zary

2015-12-05 01:32:38

by Julian Calaby

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips

Hi Finn,

On Fri, Dec 4, 2015 at 7:38 PM, Finn Thain <[email protected]> wrote:
>
> On Fri, 4 Dec 2015, Julian Calaby wrote:
>
>> > - if (overrides[current_override].board == BOARD_NCR53C400A) {
>> > + if (overrides[current_override].board == BOARD_NCR53C400A ||
>> > + overrides[current_override].board == BOARD_DTC3181E) {
>>
>> These if statements are starting to get a bit long, would it make
>> sense to replace them with a flag or equivalent?
>
> To what end? Shorter lines? As in,

Pretty much, each expression is quite long and they seem to be growing
fairly rapidly as you and Ondrej discover similar boards.

>
> if (board_is_ncr53c400a || board_is_dtc3181e) {
> /* ... */
> }
>
> I suppose that could be an improvement if new flags would entirely replace
> the override.board struct member and the existing switch statement,
>
> switch (overrides[current_override].board) {
> /* ... */
> }
>
> Or maybe you meant testing a new flag something like this,
>
> if (hostdata->ncr53c400_compatible) {
> /* ... */
> }
>
> If your concern is the Don't Repeat Yourself rule, I'm not sure that new
> flag would get tested more than once (?) And it would still have to be
> assigned using an "objectionably" long expression, e.g.
>
> hostdata->ncr53c400_compatible =
> overrides[current_override].board == BOARD_NCR53C400 ||
> overrides[current_override].board == BOARD_NCR53C400A ||
> overrides[current_override].board == BOARD_DTC3181E;
>
> Rather than add new flags, perhaps a 'switch' statement instead of an 'if'
> statement would be shorter (if the size of the expression is the problem).

I think switch statements would be cleaner in this particular
instance. I was thinking something like:

if (somthing->flags & NCR53C400_COMPATIBLE) {
/* ... */
}

but if it's only ever going to be used once, then it's pretty
pointless and switch statements are cleaner.

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/

2015-12-05 02:12:25

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips


On Sat, 5 Dec 2015, Julian Calaby wrote:

> Hi Finn,
>
> On Fri, Dec 4, 2015 at 7:38 PM, Finn Thain <[email protected]> wrote:
> >
> > On Fri, 4 Dec 2015, Julian Calaby wrote:
> >
> >> > - if (overrides[current_override].board == BOARD_NCR53C400A) {
> >> > + if (overrides[current_override].board == BOARD_NCR53C400A ||
> >> > + overrides[current_override].board == BOARD_DTC3181E) {
> >>
> >> These if statements are starting to get a bit long, would it make
> >> sense to replace them with a flag or equivalent?
> >
> > To what end? Shorter lines? As in,
>
> Pretty much, each expression is quite long and they seem to be growing
> fairly rapidly as you and Ondrej discover similar boards.

Each BOARD_* macro actually refers to a whole category of devices. No new
boards, devices or categories of devices have been discovered.

Ondrej is enabling and/or fixing PDMA functionality for three existing
device categories, for which the driver already has a nominally compatible
PDMA implementation.

--

2015-12-05 02:38:25

by Julian Calaby

[permalink] [raw]
Subject: Re: [RFC PATCH 76/71] ncr5380: Enable PDMA for DTC chips

Hi Finn,

On Sat, Dec 5, 2015 at 1:12 PM, Finn Thain <[email protected]> wrote:
>
> On Sat, 5 Dec 2015, Julian Calaby wrote:
>
>> Hi Finn,
>>
>> On Fri, Dec 4, 2015 at 7:38 PM, Finn Thain <[email protected]> wrote:
>> >
>> > On Fri, 4 Dec 2015, Julian Calaby wrote:
>> >
>> >> > - if (overrides[current_override].board == BOARD_NCR53C400A) {
>> >> > + if (overrides[current_override].board == BOARD_NCR53C400A ||
>> >> > + overrides[current_override].board == BOARD_DTC3181E) {
>> >>
>> >> These if statements are starting to get a bit long, would it make
>> >> sense to replace them with a flag or equivalent?
>> >
>> > To what end? Shorter lines? As in,
>>
>> Pretty much, each expression is quite long and they seem to be growing
>> fairly rapidly as you and Ondrej discover similar boards.
>
> Each BOARD_* macro actually refers to a whole category of devices. No new
> boards, devices or categories of devices have been discovered.
>
> Ondrej is enabling and/or fixing PDMA functionality for three existing
> device categories, for which the driver already has a nominally compatible
> PDMA implementation.

I meant discovering boards which are similar.

Either way, I'm not sure it matters that much.

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/

2015-12-05 21:19:06

by Ondrej Zary

[permalink] [raw]
Subject: [RFC PATCH 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)

HP C2502 cards (based on 53C400A chips) use different magic numbers for
software-based I/O address configuration than other cards.
The configuration is also extended to allow setting the IRQ.

Move the configuration to a new function magic_configure() and move
magic the magic numbers into an array. Add new magic numbers for these
HP cards and hp_53c400a module parameter to use them.

Tested with HP C2502 and DTCT-436P.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 69 +++++++++++++++++++++++++++++++++++-----------
drivers/scsi/g_NCR5380.h | 1 +
2 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 38579b0..52110e0 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -80,6 +80,7 @@ static int ncr_5380;
static int ncr_53c400;
static int ncr_53c400a;
static int dtc_3181e;
+static int hp_53c400a;

static struct override {
NCR5380_map_type NCR5380_map_name;
@@ -225,6 +226,26 @@ static int __init do_DTC3181E_setup(char *str)

#endif

+#ifndef SCSI_G_NCR5380_MEM
+static void magic_configure(int idx, u8 irq, u8 magic[])
+{
+ u8 cfg = 0;
+
+ outb(magic[0], 0x779);
+ outb(magic[1], 0x379);
+ outb(magic[2], 0x379);
+ outb(magic[3], 0x379);
+ outb(magic[4], 0x379);
+
+ /* allowed IRQs for HP 53C400A */
+ if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
+ irq = 0;
+ if (idx >= 0 && idx <= 7)
+ cfg = 0x80 | idx | (irq << 4);
+ outb(cfg, 0x379);
+}
+#endif
+
/**
* generic_NCR5380_detect - look for NCR5380 controllers
* @tpnt: the scsi template
@@ -241,8 +262,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static int current_override;
int count;
unsigned int *ports;
+ u8 *magic;
#ifndef SCSI_G_NCR5380_MEM
- int i;
+ int i, port_idx;
unsigned long region_size = 16;
#endif
static unsigned int __initdata ncr_53c400a_ports[] = {
@@ -251,6 +273,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static unsigned int __initdata dtc_3181e_ports[] = {
0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
};
+ static u8 ncr_53c400a_magic[] __initdata = {
+ 0x59, 0xb9, 0xc5, 0xae, 0xa6
+ };
+ static u8 hp_53c400a_magic[] __initdata = {
+ 0x0f, 0x22, 0xf0, 0x20, 0x80
+ };
int flags;
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
@@ -273,6 +301,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
overrides[0].board = BOARD_NCR53C400A;
else if (dtc_3181e)
overrides[0].board = BOARD_DTC3181E;
+ else if (hp_53c400a)
+ overrides[0].board = BOARD_HP53C400A;
#ifndef SCSI_G_NCR5380_MEM
if (!current_override && isapnp_present()) {
struct pnp_dev *dev = NULL;
@@ -323,13 +353,21 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
flags = FLAG_NO_PSEUDO_DMA;
#endif
break;
+ case BOARD_HP53C400A:
+ flags = FLAG_NO_DMA_FIXUP;
+ ports = ncr_53c400a_ports;
+ magic = hp_53c400a_magic;
+ overrides[current_override].board = BOARD_NCR53C400A;
+ break;
case BOARD_NCR53C400A:
flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
+ magic = ncr_53c400a_magic;
break;
case BOARD_DTC3181E:
flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
+ magic = ncr_53c400a_magic;
break;
}

@@ -338,12 +376,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
/* wakeup sequence for the NCR53C400A and DTC3181E */

/* Disable the adapter and look for a free io port */
- outb(0x59, 0x779);
- outb(0xb9, 0x379);
- outb(0xc5, 0x379);
- outb(0xae, 0x379);
- outb(0xa6, 0x379);
- outb(0x00, 0x379);
+ magic_configure(-1, 0, magic);

if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
for (i = 0; ports[i]; i++) {
@@ -362,17 +395,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
}
if (ports[i]) {
/* At this point we have our region reserved */
- outb(0x59, 0x779);
- outb(0xb9, 0x379);
- outb(0xc5, 0x379);
- outb(0xae, 0x379);
- outb(0xa6, 0x379);
- outb(0x80 | i, 0x379); /* set io port to be used */
+ magic_configure(i, 0, magic); /* no IRQ yet */
outb(0xc0, ports[i] + 9);
- if (inb(ports[i] + 9) != 0x80)
+ if (inb(ports[i] + 9) != 0x80) {
continue;
- else
+ } else {
overrides[current_override].NCR5380_map_name = ports[i];
+ port_idx = i;
+ }
} else
continue;
}
@@ -464,12 +494,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (instance->irq == 255)
instance->irq = NO_IRQ;

- if (instance->irq != NO_IRQ)
+ if (instance->irq != NO_IRQ) {
+#ifndef SCSI_G_NCR5380_MEM
+ /* set IRQ for HP 53C400A */
+ if (magic == hp_53c400a_magic)
+ magic_configure(port_idx, instance->irq, magic);
+#endif
if (request_irq(instance->irq, generic_NCR5380_intr,
0, "NCR5380", instance)) {
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
instance->irq = NO_IRQ;
}
+ }

if (instance->irq == NO_IRQ) {
printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
@@ -763,6 +799,7 @@ module_param(ncr_5380, int, 0);
module_param(ncr_53c400, int, 0);
module_param(ncr_53c400a, int, 0);
module_param(dtc_3181e, int, 0);
+module_param(hp_53c400a, int, 0);
MODULE_LICENSE("GPL");

#if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index b3936aa..369ab9e 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -89,6 +89,7 @@
#define BOARD_NCR53C400 1
#define BOARD_NCR53C400A 2
#define BOARD_DTC3181E 3
+#define BOARD_HP53C400A 4

#endif /* GENERIC_NCR5380_H */

--
Ondrej Zary

2015-12-06 03:20:17

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A


On Mon, 30 Nov 2015, Ondrej Zary wrote:

> On Monday 30 November 2015, Finn Thain wrote:
> >
> > On Sun, 29 Nov 2015, Ondrej Zary wrote:
> >
> > > Add I/O register mapping for NCR53C400A and enable PDMA mode to
> > > improve performance and fix non-working IRQ.
> > >
> >
> > Is CONFIG_SCSI_GENERIC_NCR53C400 is still needed? Can the driver be fully
> > configured at runtime now?
>
> Things depending on CONFIG_SCSI_GENERIC_NCR53C400:
>
> #ifdef CONFIG_SCSI_GENERIC_NCR53C400
> #define PSEUDO_DMA
> #endif
>
> Defining PSEUDO_DMA should not break anything, just makes code bigger a
> bit. We can probably just define it always in g_NCR5380.c.

Based on your test results, I think so.

>
>
> This looks weird. I don't have any card with a BIOS to test.
> #ifdef CONFIG_SCSI_GENERIC_NCR53C400
> #define BIOSPARAM
> #define NCR5380_BIOSPARAM generic_NCR5380_biosparam
> #else
> #define NCR5380_BIOSPARAM NULL
> #endif
>

I'm guessing that when you said "weird", you meant that it is weird to tie
BIOSPARAM to CONFIG_SCSI_GENERIC_NCR53C400, because a 53C400-compatible
device does not imply a card ROM, and generic_NCR5380_biosparam() does not
require any particular device...

Regardless, the Kconfig help text doesn't say anything about bios_param,
so I think that the weirdness you referred to should not prevent removal
of CONFIG_SCSI_GENERIC_NCR53C400. I'm happy to let users manually #define
BIOSPARAM if the default scsicam_bios_param() doesn't work. See patch
below for example.

But if scsicam_bios_param() is adequate, or if generic_NCR5380_biosparam()
is inadequate, then we should also remove generic_NCR5380_biosparam(),
NCR5380_BIOSPARAM and BIOSPARAM. I'm not sufficiently familiar with this
platform to say one way or the other.

>
> This looks very wrong and should be done at runtime:
> #ifdef CONFIG_SCSI_GENERIC_NCR53C400
> #define NCR5380_region_size 16
> #else
> #define NCR5380_region_size 8
> #endif
>

I'll have to leave that fix to you.

Thanks.


Index: linux/drivers/scsi/Kconfig
===================================================================
--- linux.orig/drivers/scsi/Kconfig 2015-12-06 12:29:36.000000000 +1100
+++ linux/drivers/scsi/Kconfig 2015-12-06 13:47:50.000000000 +1100
@@ -816,17 +816,6 @@ config SCSI_GENERIC_NCR5380_MMIO
To compile this driver as a module, choose M here: the
module will be called g_NCR5380_mmio.

-config SCSI_GENERIC_NCR53C400
- bool "Enable NCR53c400 extensions"
- depends on SCSI_GENERIC_NCR5380
- help
- This enables certain optimizations for the NCR53c400 SCSI cards.
- You might as well try it out. Note that this driver will only probe
- for the Trantor T130B in its default configuration; you might have
- to pass a command line option to the kernel at boot time if it does
- not detect your card. See the file
- <file:Documentation/scsi/g_NCR5380.txt> for details.
-
config SCSI_IPS
tristate "IBM ServeRAID support"
depends on PCI && SCSI
Index: linux/drivers/scsi/g_NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/g_NCR5380.c 2015-12-06 12:31:23.000000000 +1100
+++ linux/drivers/scsi/g_NCR5380.c 2015-12-06 13:45:42.000000000 +1100
@@ -57,10 +57,7 @@
*/

#define AUTOPROBE_IRQ
-
-#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define PSEUDO_DMA
-#endif

#include <asm/io.h>
#include <linux/blkdev.h>
@@ -506,6 +503,9 @@ generic_NCR5380_biosparam(struct scsi_de
ip[2] = capacity >> 11;
return 0;
}
+#define NCR5380_BIOSPARAM generic_NCR5380_biosparam
+#else
+#define NCR5380_BIOSPARAM NULL
#endif

#ifdef PSEUDO_DMA
Index: linux/drivers/scsi/g_NCR5380.h
===================================================================
--- linux.orig/drivers/scsi/g_NCR5380.h 2015-12-06 12:30:42.000000000 +1100
+++ linux/drivers/scsi/g_NCR5380.h 2015-12-06 13:47:12.000000000 +1100
@@ -14,13 +14,6 @@
#ifndef GENERIC_NCR5380_H
#define GENERIC_NCR5380_H

-#ifdef CONFIG_SCSI_GENERIC_NCR53C400
-#define BIOSPARAM
-#define NCR5380_BIOSPARAM generic_NCR5380_biosparam
-#else
-#define NCR5380_BIOSPARAM NULL
-#endif
-
#define __STRVAL(x) #x
#define STRVAL(x) __STRVAL(x)

@@ -31,11 +24,9 @@
#define NCR5380_map_name port
#define NCR53C400_register_offset 0

-#ifdef CONFIG_SCSI_GENERIC_NCR53C400
-#define NCR5380_region_size 16
-#else
-#define NCR5380_region_size 8
-#endif
+// FIXME
+// #define NCR5380_region_size 16
+// #define NCR5380_region_size 8

#define NCR5380_read(reg) \
inb(instance->io_port + (reg))

2015-12-06 03:39:27

by Finn Thain

[permalink] [raw]
Subject: Re: [RFC PATCH 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)


On Sat, 5 Dec 2015, Ondrej Zary wrote:

> HP C2502 cards (based on 53C400A chips) use different magic numbers for
> software-based I/O address configuration than other cards. The
> configuration is also extended to allow setting the IRQ.
>
> Move the configuration to a new function magic_configure() and move
> magic the magic numbers into an array. Add new magic numbers for these
> HP cards and hp_53c400a module parameter to use them.
>
> Tested with HP C2502 and DTCT-436P.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 69 +++++++++++++++++++++++++++++++++++-----------
> drivers/scsi/g_NCR5380.h | 1 +
> 2 files changed, 54 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index 38579b0..52110e0 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -80,6 +80,7 @@ static int ncr_5380;
> static int ncr_53c400;
> static int ncr_53c400a;
> static int dtc_3181e;
> +static int hp_53c400a;
>
> static struct override {
> NCR5380_map_type NCR5380_map_name;
> @@ -225,6 +226,26 @@ static int __init do_DTC3181E_setup(char *str)
>
> #endif
>
> +#ifndef SCSI_G_NCR5380_MEM
> +static void magic_configure(int idx, u8 irq, u8 magic[])
> +{
> + u8 cfg = 0;
> +
> + outb(magic[0], 0x779);
> + outb(magic[1], 0x379);
> + outb(magic[2], 0x379);
> + outb(magic[3], 0x379);
> + outb(magic[4], 0x379);
> +
> + /* allowed IRQs for HP 53C400A */
> + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
> + irq = 0;
> + if (idx >= 0 && idx <= 7)
> + cfg = 0x80 | idx | (irq << 4);
> + outb(cfg, 0x379);
> +}
> +#endif
> +
> /**
> * generic_NCR5380_detect - look for NCR5380 controllers
> * @tpnt: the scsi template
> @@ -241,8 +262,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> static int current_override;
> int count;
> unsigned int *ports;
> + u8 *magic;
> #ifndef SCSI_G_NCR5380_MEM
> - int i;
> + int i, port_idx;
> unsigned long region_size = 16;
> #endif
> static unsigned int __initdata ncr_53c400a_ports[] = {
> @@ -251,6 +273,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> static unsigned int __initdata dtc_3181e_ports[] = {
> 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
> };
> + static u8 ncr_53c400a_magic[] __initdata = {
> + 0x59, 0xb9, 0xc5, 0xae, 0xa6
> + };
> + static u8 hp_53c400a_magic[] __initdata = {
> + 0x0f, 0x22, 0xf0, 0x20, 0x80
> + };

Magic numbers that are clearly labeled as such tells me that no-one can
say what they actually mean... is that right?

> int flags;
> struct Scsi_Host *instance;
> struct NCR5380_hostdata *hostdata;
> @@ -273,6 +301,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> overrides[0].board = BOARD_NCR53C400A;
> else if (dtc_3181e)
> overrides[0].board = BOARD_DTC3181E;
> + else if (hp_53c400a)
> + overrides[0].board = BOARD_HP53C400A;
> #ifndef SCSI_G_NCR5380_MEM
> if (!current_override && isapnp_present()) {
> struct pnp_dev *dev = NULL;
> @@ -323,13 +353,21 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> flags = FLAG_NO_PSEUDO_DMA;
> #endif
> break;
> + case BOARD_HP53C400A:
> + flags = FLAG_NO_DMA_FIXUP;
> + ports = ncr_53c400a_ports;
> + magic = hp_53c400a_magic;

Nice! A new board.

> + overrides[current_override].board = BOARD_NCR53C400A;

Do you rewrite overrides[current_override].board in order to avoid another
term in a long conditional expression? Don't you find that confusing? Why
not consistently use switch statements when we have to test
overrides[current_override].board?

> + break;
> case BOARD_NCR53C400A:
> flags = FLAG_NO_DMA_FIXUP;
> ports = ncr_53c400a_ports;
> + magic = ncr_53c400a_magic;
> break;
> case BOARD_DTC3181E:
> flags = FLAG_NO_DMA_FIXUP;
> ports = dtc_3181e_ports;
> + magic = ncr_53c400a_magic;
> break;
> }
>
> @@ -338,12 +376,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> /* wakeup sequence for the NCR53C400A and DTC3181E */
>
> /* Disable the adapter and look for a free io port */
> - outb(0x59, 0x779);
> - outb(0xb9, 0x379);
> - outb(0xc5, 0x379);
> - outb(0xae, 0x379);
> - outb(0xa6, 0x379);
> - outb(0x00, 0x379);
> + magic_configure(-1, 0, magic);
>
> if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
> for (i = 0; ports[i]; i++) {
> @@ -362,17 +395,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> }
> if (ports[i]) {
> /* At this point we have our region reserved */
> - outb(0x59, 0x779);
> - outb(0xb9, 0x379);
> - outb(0xc5, 0x379);
> - outb(0xae, 0x379);
> - outb(0xa6, 0x379);
> - outb(0x80 | i, 0x379); /* set io port to be used */
> + magic_configure(i, 0, magic); /* no IRQ yet */
> outb(0xc0, ports[i] + 9);
> - if (inb(ports[i] + 9) != 0x80)
> + if (inb(ports[i] + 9) != 0x80) {
> continue;
> - else
> + } else {
> overrides[current_override].NCR5380_map_name = ports[i];
> + port_idx = i;
> + }
> } else
> continue;
> }
> @@ -464,12 +494,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> if (instance->irq == 255)
> instance->irq = NO_IRQ;
>
> - if (instance->irq != NO_IRQ)
> + if (instance->irq != NO_IRQ) {
> +#ifndef SCSI_G_NCR5380_MEM
> + /* set IRQ for HP 53C400A */
> + if (magic == hp_53c400a_magic)
> + magic_configure(port_idx, instance->irq, magic);
> +#endif

This would be better done earlier. We need to determine and assign the
instance->irq value before NCR5380_init() in order to fix the irq number
printed in the log messages when the driver starts. But that should
probably be a separate patch...

> if (request_irq(instance->irq, generic_NCR5380_intr,
> 0, "NCR5380", instance)) {
> printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
> instance->irq = NO_IRQ;
> }
> + }
>
> if (instance->irq == NO_IRQ) {
> printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
> @@ -763,6 +799,7 @@ module_param(ncr_5380, int, 0);
> module_param(ncr_53c400, int, 0);
> module_param(ncr_53c400a, int, 0);
> module_param(dtc_3181e, int, 0);
> +module_param(hp_53c400a, int, 0);
> MODULE_LICENSE("GPL");
>
> #if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
> diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> index b3936aa..369ab9e 100644
> --- a/drivers/scsi/g_NCR5380.h
> +++ b/drivers/scsi/g_NCR5380.h
> @@ -89,6 +89,7 @@
> #define BOARD_NCR53C400 1
> #define BOARD_NCR53C400A 2
> #define BOARD_DTC3181E 3
> +#define BOARD_HP53C400A 4
>
> #endif /* GENERIC_NCR5380_H */
>
>

--

2015-12-06 03:39:41

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 73/71] ncr5380: Use runtime register mapping


On Fri, 4 Dec 2015, Ondrej Zary wrote:

> Convert compile-time C400_ register mapping to runtime mapping.
> This removes the weird negative register offsets and allows adding
> additional mappings.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/NCR5380.h | 13 +---------
> drivers/scsi/g_NCR5380.c | 61 ++++++++++++++++++++++++++--------------------
> drivers/scsi/g_NCR5380.h | 12 ++++++---
> 3 files changed, 43 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
> index 36779df..923db6c 100644
> --- a/drivers/scsi/NCR5380.h
> +++ b/drivers/scsi/NCR5380.h
> @@ -163,8 +163,7 @@
> /* Write any value to this register to start an ini mode DMA receive */
> #define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */
>
> -#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
> -
> +/* NCR 53C400(A) Control Status Register bits: */
> #define CSR_RESET 0x80 /* wo Resets 53c400 */
> #define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
> #define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
> @@ -181,16 +180,6 @@
> #define CSR_BASE CSR_53C80_INTR
> #endif
>
> -/* Number of 128-byte blocks to be transferred */
> -#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
> -
> -/* Resume transfer after disconnect */
> -#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
> -
> -/* Access to host buffer stack */
> -#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
> -
> -
> /* Note : PHASE_* macros are based on the values of the STATUS register */
> #define PHASE_MASK (SR_MSG | SR_CD | SR_IO)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index a9a237f..ce444da 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -253,6 +253,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> };
> int flags;
> struct Scsi_Host *instance;
> + struct NCR5380_hostdata *hostdata;
> #ifdef SCSI_G_NCR5380_MEM
> unsigned long base;
> void __iomem *iomem;
> @@ -395,6 +396,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
> if (instance == NULL)
> goto out_release;
> + hostdata = shost_priv(instance);
>
> #ifndef SCSI_G_NCR5380_MEM
> instance->io_port = overrides[current_override].NCR5380_map_name;
> @@ -404,18 +406,27 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> * On NCR53C400 boards, NCR5380 registers are mapped 8 past
> * the base address.
> */
> - if (overrides[current_override].board == BOARD_NCR53C400)
> + if (overrides[current_override].board == BOARD_NCR53C400) {
> instance->io_port += 8;
> + hostdata->c400_ctl_status = 0;
> + hostdata->c400_blk_cnt = 1;
> + hostdata->c400_host_buf = 4;
> + }
> #else
> instance->base = overrides[current_override].NCR5380_map_name;
> - ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
> + hostdata->iomem = iomem;
> + if (overrides[current_override].board == BOARD_NCR53C400) {
> + hostdata->c400_ctl_status = 0x100;
> + hostdata->c400_blk_cnt = 0x101;
> + hostdata->c400_host_buf = 0x104;
> + }
> #endif
>
> if (NCR5380_init(instance, flags))
> goto out_unregister;
>
> if (overrides[current_override].board == BOARD_NCR53C400)
> - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
> + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
>
> @@ -523,30 +534,28 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
>
> static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
> {
> -#ifdef SCSI_G_NCR5380_MEM
> struct NCR5380_hostdata *hostdata = shost_priv(instance);
> -#endif
> int blocks = len / 128;
> int start = 0;
> int bl;
>
> - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
> - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
> + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
> + NCR5380_write(hostdata->c400_blk_cnt, blocks);
> while (1) {
> - if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
> + if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {
> break;
> }

Rewritten in Linux coding style that is,

bl = NCR5380_read(hostdata->c400_blk_cnt);
if (bl == 0)
break;

But in this case, bl is not used further so why not just remove it along
with the braces?

> - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
> + if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
> printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
> return -1;
> }
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);

The semicolon should appear on the next line where it is more visible.

>
> #ifndef SCSI_G_NCR5380_MEM
> {
> int i;
> for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
> + dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> }

Why not just change the loop to insb() now, rather than waiting until the
patch after next? Then you can remove the extra braces and 'int i'
declaration.

> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -558,7 +567,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> }
>
> if (blocks) {
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> {
> // FIXME - no timeout
> }
> @@ -567,7 +576,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> {
> int i;
> for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
> + dst[start + i] = NCR5380_read(hostdata->c400_host_buf);

Same here.

> }
> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -578,7 +587,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> blocks--;
> }
>
> - if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
> + if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> printk("53C400r: no 53C80 gated irq after transfer");
>
> #if 0
> @@ -586,7 +595,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> * DON'T DO THIS - THEY NEVER ARRIVE!
> */
> printk("53C400r: Waiting for 53C80 registers\n");
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
> ;
> #endif
> if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
> @@ -607,31 +616,29 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
>
> static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
> {
> -#ifdef SCSI_G_NCR5380_MEM
> struct NCR5380_hostdata *hostdata = shost_priv(instance);
> -#endif
> int blocks = len / 128;
> int start = 0;
> int bl;
> int i;
>
> - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
> - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
> + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
> + NCR5380_write(hostdata->c400_blk_cnt, blocks);
> while (1) {
> - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
> + if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
> printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
> return -1;
> }
>
> - if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
> + if ((bl = NCR5380_read(hostdata->c400_blk_cnt)) == 0) {

As above.

> break;
> }
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - timeout
> #ifndef SCSI_G_NCR5380_MEM
> {
> for (i = 0; i < 128; i++)
> - NCR5380_write(C400_HOST_BUFFER, src[start + i]);
> + NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> }

Also as above.

> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -642,13 +649,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> blocks--;
> }
> if (blocks) {
> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - no timeout
>
> #ifndef SCSI_G_NCR5380_MEM
> {
> for (i = 0; i < 128; i++)
> - NCR5380_write(C400_HOST_BUFFER, src[start + i]);
> + NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> }

Same here.

Thanks.

> #else
> /* implies SCSI_G_NCR5380_MEM */
> @@ -661,7 +668,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
>
> #if 0
> printk("53C400w: waiting for registers to be available\n");
> - THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
> + THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
> printk("53C400w: Got em\n");
> #endif
>
> @@ -669,7 +676,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> /* All documentation says to check for this. Maybe my hardware is too
> * fast. Waiting for it seems to work fine! KLL
> */
> - while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
> + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> ; // FIXME - no timeout
>
> /*
> diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> index fd201e9..c5e57b7 100644
> --- a/drivers/scsi/g_NCR5380.h
> +++ b/drivers/scsi/g_NCR5380.h
> @@ -29,7 +29,6 @@
>
> #define NCR5380_map_type int
> #define NCR5380_map_name port
> -#define NCR53C400_register_offset 0
>
> #ifdef CONFIG_SCSI_GENERIC_NCR53C400
> #define NCR5380_region_size 16
> @@ -42,7 +41,10 @@
> #define NCR5380_write(reg, value) \
> outb(value, instance->io_port + (reg))
>
> -#define NCR5380_implementation_fields /* none */
> +#define NCR5380_implementation_fields \
> + int c400_ctl_status; \
> + int c400_blk_cnt; \
> + int c400_host_buf;
>
> #else
> /* therefore SCSI_G_NCR5380_MEM */
> @@ -50,7 +52,6 @@
>
> #define NCR5380_map_type unsigned long
> #define NCR5380_map_name base
> -#define NCR53C400_register_offset 0x108
> #define NCR53C400_mem_base 0x3880
> #define NCR53C400_host_buffer 0x3900
> #define NCR5380_region_size 0x3a00
> @@ -63,7 +64,10 @@
> NCR53C400_mem_base + (reg))
>
> #define NCR5380_implementation_fields \
> - void __iomem *iomem;
> + void __iomem *iomem; \
> + int c400_ctl_status; \
> + int c400_blk_cnt; \
> + int c400_host_buf;
>
> #endif
>
>

--

2015-12-06 03:41:05

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 76/71] ncr5380: Enable PDMA for DTC chips


On Fri, 4 Dec 2015, Ondrej Zary wrote:

> Add I/O register mapping for DTC chips and enable PDMA mode.
>
> These chips have 16-bit wide HOST BUFFER register (counter register at
> offset 0x0d increments by 2 on each HOST BUFFER read). Detect it
> automatically.
>
> Large PIO transfers crash at least the DTCT-436P chip (all reads result
> in 0xFF) so this patch actually makes it work.
>
> The chip also crashes when we bang the C400 host status register too
> heavily after PDMA write - a small udelay is needed.
>
> Tested on DTCT-436P and verified that it does not break 53C400A.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 59 ++++++++++++++++++++++++++++------------------
> drivers/scsi/g_NCR5380.h | 4 +++-
> 2 files changed, 39 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index 85da3c2..9816b81 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> ports = ncr_53c400a_ports;
> break;
> case BOARD_DTC3181E:
> - flags = FLAG_NO_PSEUDO_DMA;
> + flags = FLAG_NO_DMA_FIXUP;

Nice!

> ports = dtc_3181e_ports;
> break;
> }
> @@ -412,10 +412,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> hostdata->c400_blk_cnt = 1;
> hostdata->c400_host_buf = 4;
> }
> - if (overrides[current_override].board == BOARD_NCR53C400A) {
> + if (overrides[current_override].board == BOARD_NCR53C400A ||
> + overrides[current_override].board == BOARD_DTC3181E) {
> hostdata->c400_ctl_status = 9;
> hostdata->c400_blk_cnt = 10;
> hostdata->c400_host_buf = 8;
> + hostdata->c400_host_idx = 13;
> }
> #else
> instance->base = overrides[current_override].NCR5380_map_name;
> @@ -430,8 +432,20 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> if (NCR5380_init(instance, flags))
> goto out_unregister;
>
> +#ifndef SCSI_G_NCR5380_MEM
> + /* read initial value of index register */
> + i = NCR5380_read(hostdata->c400_host_idx);
> + /* read something from host buffer */
> + NCR5380_read(hostdata->c400_host_buf);
> + /* I/O width = index register increment */
> + hostdata->io_width = NCR5380_read(hostdata->c400_host_idx) - i;
> + if (hostdata->io_width < 0)
> + hostdata->io_width += 128;
> +#endif

Will the result depend on the initial state of the chip, such as
CSR_TRANS_DIR or CSR_HOST_BUF_NOT_RDY?

It is possible to generate an interrupt with the buffer read, which should
be masked at the chip.

This buffer read may cause the 53C400 control logic to signal the 53C80
core. I suppose it is unlikely to cause any signalling on the SCSI bus
unless the 53C80 happened to be in DMA mode.

The possibility that io_width == 0 is not handled; wouldn't this result
indicate that PDMA shouldn't be used?

io_width can be calculated without a conditional statement, which may be
easier to read.

Can we be confident that detection will fail for all devices that don't
support word-sized IO, to avoid a regression?

The patch seems to assume that no memory-mapped card needs word-sized IO
for PDMA. Can you confirm?

The previous version of this patch was simpler and more predictable. You
enabled word-size IO for DTC3181E which is testable. Does this version
benefit any other cards?

> +
> if (overrides[current_override].board == BOARD_NCR53C400 ||
> - overrides[current_override].board == BOARD_NCR53C400A)
> + overrides[current_override].board == BOARD_NCR53C400A ||
> + overrides[current_override].board == BOARD_DTC3181E)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
> @@ -558,11 +572,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);
>
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - int i;
> - for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> - }
> + if (hostdata->io_width == 2)
> + insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
> + else
> + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_fromio(dst + start,
> @@ -579,11 +592,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> }
>
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - int i;
> - for (i = 0; i < 128; i++)
> - dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> - }
> + if (hostdata->io_width == 2)
> + insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
> + else
> + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_fromio(dst + start,
> @@ -642,10 +654,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - timeout
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - for (i = 0; i < 128; i++)
> - NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> - }
> + if (hostdata->io_width == 2)
> + outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
> + else
> + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
> @@ -657,12 +669,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> if (blocks) {
> while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> ; // FIXME - no timeout
> -
> #ifndef SCSI_G_NCR5380_MEM
> - {
> - for (i = 0; i < 128; i++)
> - NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> - }
> + if (hostdata->io_width == 2)
> + outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
> + else
> + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
> #else
> /* implies SCSI_G_NCR5380_MEM */
> memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
> @@ -682,8 +693,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> /* All documentation says to check for this. Maybe my hardware is too
> * fast. Waiting for it seems to work fine! KLL
> */
> - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
> + udelay(4); /* DTC436 chip hangs without this */
> ; // FIXME - no timeout
> + }

When you added the braces, the lone semicolon became redundant. But I
think the entire loop is bogus.

Why do we wait for CSR_GATED_53C80_IRQ? I can understand testing it during
a transfer but why afterwards? (The core driver could test for the IRQ
flag in the Bus and Status Register, at the end of a DMA, if this scsi
host has no IRQ line.)

The comments and the 53C400 datasheet say we should instead wait for
CSR_53C80_REG. I agree. The g_NCR5380 wrapper driver can't safely return
control to the core driver unless the 53C80 registers are available.

The algorithm in the datasheet waits for CSR_53C80_REG before checking
BASR_END_DMA_TRANSFER, checking interrupt flags, disabling DMA mode etc.

g_NCR5380.c has an '#if 0' around the BASR_END_DMA_TRANSFER check, because
it doesn't wait for CSR_53C80_REG. Does NCR's algorithm work with your
cards?

>
> /*
> * I know. i is certainly != 0 here but the loop is new. See previous
> diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> index c5e57b7..b3936aa 100644
> --- a/drivers/scsi/g_NCR5380.h
> +++ b/drivers/scsi/g_NCR5380.h
> @@ -44,7 +44,9 @@
> #define NCR5380_implementation_fields \
> int c400_ctl_status; \
> int c400_blk_cnt; \
> - int c400_host_buf;
> + int c400_host_buf; \
> + int c400_host_idx; \
> + int io_width;
>
> #else
> /* therefore SCSI_G_NCR5380_MEM */
>

--

2015-12-06 03:41:17

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH 74/71] ncr5380: Enable PDMA for NCR53C400A


On Fri, 4 Dec 2015, Ondrej Zary wrote:

> Add I/O register mapping for NCR53C400A and enable PDMA mode to
> improve performance and fix non-working IRQ.
>
> Tested with HP C2502 (and user-space enabler).
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index ce444da..cd483c6 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> #endif
> break;
> case BOARD_NCR53C400A:
> - flags = FLAG_NO_PSEUDO_DMA;
> + flags = FLAG_NO_DMA_FIXUP;

Nice!

> ports = ncr_53c400a_ports;
> break;
> case BOARD_DTC3181E:
> @@ -412,6 +412,11 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> hostdata->c400_blk_cnt = 1;
> hostdata->c400_host_buf = 4;
> }
> + if (overrides[current_override].board == BOARD_NCR53C400A) {

Please use an 'else' here. Or a switch statement.

> + hostdata->c400_ctl_status = 9;
> + hostdata->c400_blk_cnt = 10;
> + hostdata->c400_host_buf = 8;
> + }
> #else
> instance->base = overrides[current_override].NCR5380_map_name;
> hostdata->iomem = iomem;
> @@ -425,7 +430,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> if (NCR5380_init(instance, flags))
> goto out_unregister;
>
> - if (overrides[current_override].board == BOARD_NCR53C400)
> + if (overrides[current_override].board == BOARD_NCR53C400 ||
> + overrides[current_override].board == BOARD_NCR53C400A)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
>

--

2015-12-06 08:42:56

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH 73/71] ncr5380: Use runtime register mapping

On Sun, Dec 6, 2015 at 4:39 AM, Finn Thain <[email protected]> wrote:
>> - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
>> + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);
>
> The semicolon should appear on the next line where it is more visible.

And adding a cpu_relax() to the empty loop body is another good visual cue.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2015-12-06 22:20:51

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v2 73/71] ncr5380: Use runtime register mapping

Convert compile-time C400_ register mapping to runtime mapping.
This removes the weird negative register offsets and allows adding
additional mappings.

While at it, convert read/write loops into insb/outsb.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/NCR5380.h | 13 +------
drivers/scsi/g_NCR5380.c | 88 +++++++++++++++++++++-------------------------
drivers/scsi/g_NCR5380.h | 12 ++++---
3 files changed, 49 insertions(+), 64 deletions(-)

diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 36779df..923db6c 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -163,8 +163,7 @@
/* Write any value to this register to start an ini mode DMA receive */
#define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */

-#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
-
+/* NCR 53C400(A) Control Status Register bits: */
#define CSR_RESET 0x80 /* wo Resets 53c400 */
#define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
@@ -181,16 +180,6 @@
#define CSR_BASE CSR_53C80_INTR
#endif

-/* Number of 128-byte blocks to be transferred */
-#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
-
-/* Resume transfer after disconnect */
-#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
-
-/* Access to host buffer stack */
-#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
-
-
/* Note : PHASE_* macros are based on the values of the STATUS register */
#define PHASE_MASK (SR_MSG | SR_CD | SR_IO)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index a9a237f..86740fd 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -253,6 +253,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
};
int flags;
struct Scsi_Host *instance;
+ struct NCR5380_hostdata *hostdata;
#ifdef SCSI_G_NCR5380_MEM
unsigned long base;
void __iomem *iomem;
@@ -395,6 +396,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL)
goto out_release;
+ hostdata = shost_priv(instance);

#ifndef SCSI_G_NCR5380_MEM
instance->io_port = overrides[current_override].NCR5380_map_name;
@@ -404,18 +406,27 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
*/
- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400) {
instance->io_port += 8;
+ hostdata->c400_ctl_status = 0;
+ hostdata->c400_blk_cnt = 1;
+ hostdata->c400_host_buf = 4;
+ }
#else
instance->base = overrides[current_override].NCR5380_map_name;
- ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
+ hostdata->iomem = iomem;
+ if (overrides[current_override].board == BOARD_NCR53C400) {
+ hostdata->c400_ctl_status = 0x100;
+ hostdata->c400_blk_cnt = 0x101;
+ hostdata->c400_host_buf = 0x104;
+ }
#endif

if (NCR5380_init(instance, flags))
goto out_unregister;

if (overrides[current_override].board == BOARD_NCR53C400)
- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);

@@ -523,31 +534,25 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,

static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
{
-#ifdef SCSI_G_NCR5380_MEM
struct NCR5380_hostdata *hostdata = shost_priv(instance);
-#endif
int blocks = len / 128;
int start = 0;
- int bl;

- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
- NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
+ NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
- if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
+ if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
break;
- }
- if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
+ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
+ ; /* FIXME - no timeout */

#ifndef SCSI_G_NCR5380_MEM
- {
- int i;
- for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
- }
+ insb(instance->io_port + hostdata->c400_host_buf,
+ dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start,
@@ -558,17 +563,12 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
}

if (blocks) {
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
- {
- // FIXME - no timeout
- }
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
+ ; /* FIXME - no timeout */

#ifndef SCSI_G_NCR5380_MEM
- {
- int i;
- for (i = 0; i < 128; i++)
- dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
- }
+ insb(instance->io_port + hostdata->c400_host_buf,
+ dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start,
@@ -578,7 +578,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
blocks--;
}

- if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
+ if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
printk("53C400r: no 53C80 gated irq after transfer");

#if 0
@@ -586,7 +586,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
* DON'T DO THIS - THEY NEVER ARRIVE!
*/
printk("53C400r: Waiting for 53C80 registers\n");
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
;
#endif
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
@@ -607,32 +607,26 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,

static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
{
-#ifdef SCSI_G_NCR5380_MEM
struct NCR5380_hostdata *hostdata = shost_priv(instance);
-#endif
int blocks = len / 128;
int start = 0;
- int bl;
int i;

- NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
- NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
+ NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
+ NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
- if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
+ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}

- if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
+ if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
break;
- }
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
- {
- for (i = 0; i < 128; i++)
- NCR5380_write(C400_HOST_BUFFER, src[start + i]);
- }
+ outsb(instance->io_port + hostdata->c400_host_buf,
+ src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
@@ -642,14 +636,12 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
blocks--;
}
if (blocks) {
- while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+ while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout

#ifndef SCSI_G_NCR5380_MEM
- {
- for (i = 0; i < 128; i++)
- NCR5380_write(C400_HOST_BUFFER, src[start + i]);
- }
+ outsb(instance->io_port + hostdata->c400_host_buf,
+ src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
@@ -661,7 +653,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,

#if 0
printk("53C400w: waiting for registers to be available\n");
- THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
+ THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
printk("53C400w: Got em\n");
#endif

@@ -669,7 +661,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
; // FIXME - no timeout

/*
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index fd201e9..c5e57b7 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -29,7 +29,6 @@

#define NCR5380_map_type int
#define NCR5380_map_name port
-#define NCR53C400_register_offset 0

#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR5380_region_size 16
@@ -42,7 +41,10 @@
#define NCR5380_write(reg, value) \
outb(value, instance->io_port + (reg))

-#define NCR5380_implementation_fields /* none */
+#define NCR5380_implementation_fields \
+ int c400_ctl_status; \
+ int c400_blk_cnt; \
+ int c400_host_buf;

#else
/* therefore SCSI_G_NCR5380_MEM */
@@ -50,7 +52,6 @@

#define NCR5380_map_type unsigned long
#define NCR5380_map_name base
-#define NCR53C400_register_offset 0x108
#define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900
#define NCR5380_region_size 0x3a00
@@ -63,7 +64,10 @@
NCR53C400_mem_base + (reg))

#define NCR5380_implementation_fields \
- void __iomem *iomem;
+ void __iomem *iomem; \
+ int c400_ctl_status; \
+ int c400_blk_cnt; \
+ int c400_host_buf;

#endif

--
Ondrej Zary

2015-12-06 22:21:49

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v2 74/71] ncr5380: Enable PDMA for NCR53C400A

Add I/O register mapping for NCR53C400A and enable PDMA mode to
improve performance and fix non-working IRQ.

Tested with HP C2502 (and user-space enabler).

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 86740fd..099fdac 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
#endif
break;
case BOARD_NCR53C400A:
- flags = FLAG_NO_PSEUDO_DMA;
+ flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
@@ -406,11 +406,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
*/
- if (overrides[current_override].board == BOARD_NCR53C400) {
+ switch (overrides[current_override].board) {
+ case BOARD_NCR53C400:
instance->io_port += 8;
hostdata->c400_ctl_status = 0;
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
+ break;
+ case BOARD_NCR53C400A:
+ hostdata->c400_ctl_status = 9;
+ hostdata->c400_blk_cnt = 10;
+ hostdata->c400_host_buf = 8;
+ break;
}
#else
instance->base = overrides[current_override].NCR5380_map_name;
@@ -425,7 +432,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (NCR5380_init(instance, flags))
goto out_unregister;

- if (overrides[current_override].board == BOARD_NCR53C400)
+ if (overrides[current_override].board == BOARD_NCR53C400 ||
+ overrides[current_override].board == BOARD_NCR53C400A)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
--
Ondrej Zary

2015-12-06 22:48:11

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH 76/71] ncr5380: Enable PDMA for DTC chips

On Sunday 06 December 2015 04:40:56 Finn Thain wrote:
>
> On Fri, 4 Dec 2015, Ondrej Zary wrote:
>
> > Add I/O register mapping for DTC chips and enable PDMA mode.
> >
> > These chips have 16-bit wide HOST BUFFER register (counter register at
> > offset 0x0d increments by 2 on each HOST BUFFER read). Detect it
> > automatically.
> >
> > Large PIO transfers crash at least the DTCT-436P chip (all reads result
> > in 0xFF) so this patch actually makes it work.
> >
> > The chip also crashes when we bang the C400 host status register too
> > heavily after PDMA write - a small udelay is needed.
> >
> > Tested on DTCT-436P and verified that it does not break 53C400A.
> >
> > Signed-off-by: Ondrej Zary <[email protected]>
> > ---
> > drivers/scsi/g_NCR5380.c | 59 ++++++++++++++++++++++++++++------------------
> > drivers/scsi/g_NCR5380.h | 4 +++-
> > 2 files changed, 39 insertions(+), 24 deletions(-)
> >
> > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> > index 85da3c2..9816b81 100644
> > --- a/drivers/scsi/g_NCR5380.c
> > +++ b/drivers/scsi/g_NCR5380.c
> > @@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > ports = ncr_53c400a_ports;
> > break;
> > case BOARD_DTC3181E:
> > - flags = FLAG_NO_PSEUDO_DMA;
> > + flags = FLAG_NO_DMA_FIXUP;
>
> Nice!
>
> > ports = dtc_3181e_ports;
> > break;
> > }
> > @@ -412,10 +412,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > hostdata->c400_blk_cnt = 1;
> > hostdata->c400_host_buf = 4;
> > }
> > - if (overrides[current_override].board == BOARD_NCR53C400A) {
> > + if (overrides[current_override].board == BOARD_NCR53C400A ||
> > + overrides[current_override].board == BOARD_DTC3181E) {
> > hostdata->c400_ctl_status = 9;
> > hostdata->c400_blk_cnt = 10;
> > hostdata->c400_host_buf = 8;
> > + hostdata->c400_host_idx = 13;
> > }
> > #else
> > instance->base = overrides[current_override].NCR5380_map_name;
> > @@ -430,8 +432,20 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > if (NCR5380_init(instance, flags))
> > goto out_unregister;
> >
> > +#ifndef SCSI_G_NCR5380_MEM
> > + /* read initial value of index register */
> > + i = NCR5380_read(hostdata->c400_host_idx);
> > + /* read something from host buffer */
> > + NCR5380_read(hostdata->c400_host_buf);
> > + /* I/O width = index register increment */
> > + hostdata->io_width = NCR5380_read(hostdata->c400_host_idx) - i;
> > + if (hostdata->io_width < 0)
> > + hostdata->io_width += 128;
> > +#endif
>
> Will the result depend on the initial state of the chip, such as
> CSR_TRANS_DIR or CSR_HOST_BUF_NOT_RDY?
>
> It is possible to generate an interrupt with the buffer read, which should
> be masked at the chip.
>
> This buffer read may cause the 53C400 control logic to signal the 53C80
> core. I suppose it is unlikely to cause any signalling on the SCSI bus
> unless the 53C80 happened to be in DMA mode.
>
> The possibility that io_width == 0 is not handled; wouldn't this result
> indicate that PDMA shouldn't be used?
>
> io_width can be calculated without a conditional statement, which may be
> easier to read.
>
> Can we be confident that detection will fail for all devices that don't
> support word-sized IO, to avoid a regression?
>
> The patch seems to assume that no memory-mapped card needs word-sized IO
> for PDMA. Can you confirm?

My memory-mapped Canon card is a 8-bit ISA card so it can't do 16-bit I/O by
definition. Don't know if there are any 16-bit memory-mapped cards.

> The previous version of this patch was simpler and more predictable. You
> enabled word-size IO for DTC3181E which is testable. Does this version
> benefit any other cards?

Probably not. Looks like this code creates more problems that it solves.
I'll revert to the original approach.

> > +
> > if (overrides[current_override].board == BOARD_NCR53C400 ||
> > - overrides[current_override].board == BOARD_NCR53C400A)
> > + overrides[current_override].board == BOARD_NCR53C400A ||
> > + overrides[current_override].board == BOARD_DTC3181E)
> > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
> >
> > NCR5380_maybe_reset_bus(instance);
> > @@ -558,11 +572,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> > while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY);
> >
> > #ifndef SCSI_G_NCR5380_MEM
> > - {
> > - int i;
> > - for (i = 0; i < 128; i++)
> > - dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> > - }
> > + if (hostdata->io_width == 2)
> > + insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
> > + else
> > + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
> > #else
> > /* implies SCSI_G_NCR5380_MEM */
> > memcpy_fromio(dst + start,
> > @@ -579,11 +592,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> > }
> >
> > #ifndef SCSI_G_NCR5380_MEM
> > - {
> > - int i;
> > - for (i = 0; i < 128; i++)
> > - dst[start + i] = NCR5380_read(hostdata->c400_host_buf);
> > - }
> > + if (hostdata->io_width == 2)
> > + insw(instance->io_port + hostdata->c400_host_buf, dst + start, 64);
> > + else
> > + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128);
> > #else
> > /* implies SCSI_G_NCR5380_MEM */
> > memcpy_fromio(dst + start,
> > @@ -642,10 +654,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> > while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> > ; // FIXME - timeout
> > #ifndef SCSI_G_NCR5380_MEM
> > - {
> > - for (i = 0; i < 128; i++)
> > - NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> > - }
> > + if (hostdata->io_width == 2)
> > + outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
> > + else
> > + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
> > #else
> > /* implies SCSI_G_NCR5380_MEM */
> > memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
> > @@ -657,12 +669,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> > if (blocks) {
> > while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
> > ; // FIXME - no timeout
> > -
> > #ifndef SCSI_G_NCR5380_MEM
> > - {
> > - for (i = 0; i < 128; i++)
> > - NCR5380_write(hostdata->c400_host_buf, src[start + i]);
> > - }
> > + if (hostdata->io_width == 2)
> > + outsw(instance->io_port + hostdata->c400_host_buf, src + start, 64);
> > + else
> > + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128);
> > #else
> > /* implies SCSI_G_NCR5380_MEM */
> > memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
> > @@ -682,8 +693,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> > /* All documentation says to check for this. Maybe my hardware is too
> > * fast. Waiting for it seems to work fine! KLL
> > */
> > - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> > + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
> > + udelay(4); /* DTC436 chip hangs without this */
> > ; // FIXME - no timeout
> > + }
>
> When you added the braces, the lone semicolon became redundant. But I
> think the entire loop is bogus.
>
> Why do we wait for CSR_GATED_53C80_IRQ? I can understand testing it during
> a transfer but why afterwards? (The core driver could test for the IRQ
> flag in the Bus and Status Register, at the end of a DMA, if this scsi
> host has no IRQ line.)
>
> The comments and the 53C400 datasheet say we should instead wait for
> CSR_53C80_REG. I agree. The g_NCR5380 wrapper driver can't safely return
> control to the core driver unless the 53C80 registers are available.
>
> The algorithm in the datasheet waits for CSR_53C80_REG before checking
> BASR_END_DMA_TRANSFER, checking interrupt flags, disabling DMA mode etc.
>
> g_NCR5380.c has an '#if 0' around the BASR_END_DMA_TRANSFER check, because
> it doesn't wait for CSR_53C80_REG. Does NCR's algorithm work with your
> cards?

I'll leave this to patch 77. I guess that it will work properly without
waiting for CSR_GATED_53C80_IRQ.

> >
> > /*
> > * I know. i is certainly != 0 here but the loop is new. See previous
> > diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> > index c5e57b7..b3936aa 100644
> > --- a/drivers/scsi/g_NCR5380.h
> > +++ b/drivers/scsi/g_NCR5380.h
> > @@ -44,7 +44,9 @@
> > #define NCR5380_implementation_fields \
> > int c400_ctl_status; \
> > int c400_blk_cnt; \
> > - int c400_host_buf;
> > + int c400_host_buf; \
> > + int c400_host_idx; \
> > + int io_width;
> >
> > #else
> > /* therefore SCSI_G_NCR5380_MEM */
> >
>


--
Ondrej Zary

2015-12-06 22:55:23

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v2 76/71] ncr5380: Enable PDMA for DTC chips

Add I/O register mapping for DTC chips and enable PDMA mode.

These chips have 16-bit wide HOST BUFFER register and it must be read
by 16-bit accesses (we lose data otherwise).

Large PIO transfers crash at least the DTCT-436P chip (all reads result
in 0xFF) so this patch actually makes it work.

The chip also crashes when we bang the C400 host status register too
heavily after PDMA write - a small udelay is needed.

Tested on DTCT-436P and verified that it does not break 53C400A.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 40 ++++++++++++++++++++++++++++++++--------
drivers/scsi/g_NCR5380.h | 4 +++-
2 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 578d4fa..038dddf 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
- flags = FLAG_NO_PSEUDO_DMA;
+ flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
break;
}
@@ -401,6 +401,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
#ifndef SCSI_G_NCR5380_MEM
instance->io_port = overrides[current_override].NCR5380_map_name;
instance->n_io_port = region_size;
+ hostdata->io_width = 1; /* 8-bit PDMA by default */

/*
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
@@ -413,10 +414,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
break;
+ case BOARD_DTC3181E:
+ hostdata->io_width = 2; /* 16-bit PDMA */
+ /* fall through */
case BOARD_NCR53C400A:
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
hostdata->c400_host_buf = 8;
+ hostdata->c400_host_idx = 13;
break;
}
#else
@@ -433,7 +438,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
goto out_unregister;

if (overrides[current_override].board == BOARD_NCR53C400 ||
- overrides[current_override].board == BOARD_NCR53C400A)
+ overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_DTC3181E)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
@@ -559,7 +565,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
; /* FIXME - no timeout */

#ifndef SCSI_G_NCR5380_MEM
- insb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ insw(instance->io_port + hostdata->c400_host_buf,
+ dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf,
dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -575,7 +585,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
; /* FIXME - no timeout */

#ifndef SCSI_G_NCR5380_MEM
- insb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ insw(instance->io_port + hostdata->c400_host_buf,
+ dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf,
dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -633,7 +647,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
- outsb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ outsw(instance->io_port + hostdata->c400_host_buf,
+ src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf,
src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -648,7 +666,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
; // FIXME - no timeout

#ifndef SCSI_G_NCR5380_MEM
- outsb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ outsw(instance->io_port + hostdata->c400_host_buf,
+ src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf,
src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -669,8 +691,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
- ; // FIXME - no timeout
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
+ udelay(4); /* DTC436 chip hangs without this */
+ /* FIXME - no timeout */
+ }

/*
* I know. i is certainly != 0 here but the loop is new. See previous
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index c5e57b7..b3936aa 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -44,7 +44,9 @@
#define NCR5380_implementation_fields \
int c400_ctl_status; \
int c400_blk_cnt; \
- int c400_host_buf;
+ int c400_host_buf; \
+ int c400_host_idx; \
+ int io_width;

#else
/* therefore SCSI_G_NCR5380_MEM */
--
Ondrej Zary

2015-12-06 23:17:59

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v2 77/71] ncr5380: Fix wait for 53C80 registers registers after PDMA

The check for 53C80 registers accessibility was commented out because
it was broken (inverted). Fix and enable it.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 37 ++++++-------------------------------
1 file changed, 6 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 038dddf..a7479c6 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -603,14 +603,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
printk("53C400r: no 53C80 gated irq after transfer");

-#if 0
- /*
- * DON'T DO THIS - THEY NEVER ARRIVE!
- */
- printk("53C400r: Waiting for 53C80 registers\n");
- while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
+ /* wait for 53C80 registers to be available */
+ while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
;
-#endif
+
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
printk(KERN_ERR "53C400r: no end dma signal\n");

@@ -632,7 +628,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int blocks = len / 128;
int start = 0;
- int i;

NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
NCR5380_write(hostdata->c400_blk_cnt, blocks);
@@ -681,36 +676,16 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
blocks--;
}

-#if 0
- printk("53C400w: waiting for registers to be available\n");
- THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
- printk("53C400w: Got em\n");
-#endif
-
- /* Let's wait for this instead - could be ugly */
- /* All documentation says to check for this. Maybe my hardware is too
- * fast. Waiting for it seems to work fine! KLL
- */
- while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
+ /* wait for 53C80 registers to be available */
+ while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) {
udelay(4); /* DTC436 chip hangs without this */
/* FIXME - no timeout */
}

- /*
- * I know. i is certainly != 0 here but the loop is new. See previous
- * comment.
- */
- if (i) {
- if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
- printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i);
- } else
- printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n");
-
-#if 0
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
printk(KERN_ERR "53C400w: no end dma signal\n");
}
-#endif
+
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
; // TIMEOUT
return 0;
--
Ondrej Zary

2015-12-06 23:21:02

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v3 76/71] ncr5380: Enable PDMA for DTC chips

Add I/O register mapping for DTC chips and enable PDMA mode.

These chips have 16-bit wide HOST BUFFER register and it must be read
by 16-bit accesses (we lose data otherwise).

Large PIO transfers crash at least the DTCT-436P chip (all reads result
in 0xFF) so this patch actually makes it work.

The chip also crashes when we bang the C400 host status register too
heavily after PDMA write - a small udelay is needed.

Tested on DTCT-436P and verified that it does not break 53C400A.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 39 +++++++++++++++++++++++++++++++--------
drivers/scsi/g_NCR5380.h | 3 ++-
2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 578d4fa..ef719cf0 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
ports = ncr_53c400a_ports;
break;
case BOARD_DTC3181E:
- flags = FLAG_NO_PSEUDO_DMA;
+ flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
break;
}
@@ -401,6 +401,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
#ifndef SCSI_G_NCR5380_MEM
instance->io_port = overrides[current_override].NCR5380_map_name;
instance->n_io_port = region_size;
+ hostdata->io_width = 1; /* 8-bit PDMA by default */

/*
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
@@ -413,6 +414,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
break;
+ case BOARD_DTC3181E:
+ hostdata->io_width = 2; /* 16-bit PDMA */
+ /* fall through */
case BOARD_NCR53C400A:
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
@@ -433,7 +437,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
goto out_unregister;

if (overrides[current_override].board == BOARD_NCR53C400 ||
- overrides[current_override].board == BOARD_NCR53C400A)
+ overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_DTC3181E)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

NCR5380_maybe_reset_bus(instance);
@@ -559,7 +564,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
; /* FIXME - no timeout */

#ifndef SCSI_G_NCR5380_MEM
- insb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ insw(instance->io_port + hostdata->c400_host_buf,
+ dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf,
dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -575,7 +584,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
; /* FIXME - no timeout */

#ifndef SCSI_G_NCR5380_MEM
- insb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ insw(instance->io_port + hostdata->c400_host_buf,
+ dst + start, 64);
+ else
+ insb(instance->io_port + hostdata->c400_host_buf,
dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -633,7 +646,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
- outsb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ outsw(instance->io_port + hostdata->c400_host_buf,
+ src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf,
src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -648,7 +665,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
; // FIXME - no timeout

#ifndef SCSI_G_NCR5380_MEM
- outsb(instance->io_port + hostdata->c400_host_buf,
+ if (hostdata->io_width == 2)
+ outsw(instance->io_port + hostdata->c400_host_buf,
+ src + start, 64);
+ else
+ outsb(instance->io_port + hostdata->c400_host_buf,
src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
@@ -669,8 +690,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
- while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
- ; // FIXME - no timeout
+ while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
+ udelay(4); /* DTC436 chip hangs without this */
+ /* FIXME - no timeout */
+ }

/*
* I know. i is certainly != 0 here but the loop is new. See previous
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index c5e57b7..5ab64d9 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -44,7 +44,8 @@
#define NCR5380_implementation_fields \
int c400_ctl_status; \
int c400_blk_cnt; \
- int c400_host_buf;
+ int c400_host_buf; \
+ int io_width;

#else
/* therefore SCSI_G_NCR5380_MEM */
--
Ondrej Zary

2015-12-07 03:16:30

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH v2 77/71] ncr5380: Fix wait for 53C80 registers registers after PDMA


On Mon, 7 Dec 2015, Ondrej Zary wrote:

> The check for 53C80 registers accessibility was commented out because
> it was broken (inverted). Fix and enable it.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 37 ++++++-------------------------------
> 1 file changed, 6 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index 038dddf..a7479c6 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -603,14 +603,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> printk("53C400r: no 53C80 gated irq after transfer");
>
> -#if 0
> - /*
> - * DON'T DO THIS - THEY NEVER ARRIVE!
> - */
> - printk("53C400r: Waiting for 53C80 registers\n");
> - while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
> + /* wait for 53C80 registers to be available */
> + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
> ;

In the previous patch, udelay(4) was added to a CSR_GATED_53C80_IRQ
polling loop. It is interesting that you don't need it here when polling
CSR_53C80_REG.

> -#endif
> +
> if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
> printk(KERN_ERR "53C400r: no end dma signal\n");
>
> @@ -632,7 +628,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> struct NCR5380_hostdata *hostdata = shost_priv(instance);
> int blocks = len / 128;
> int start = 0;
> - int i;
>
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
> NCR5380_write(hostdata->c400_blk_cnt, blocks);
> @@ -681,36 +676,16 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> blocks--;
> }
>
> -#if 0
> - printk("53C400w: waiting for registers to be available\n");
> - THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
> - printk("53C400w: Got em\n");
> -#endif
> -
> - /* Let's wait for this instead - could be ugly */
> - /* All documentation says to check for this. Maybe my hardware is too
> - * fast. Waiting for it seems to work fine! KLL
> - */
> - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
> + /* wait for 53C80 registers to be available */
> + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) {
> udelay(4); /* DTC436 chip hangs without this */

... based on the above, this udelay is probably not needed.

(Or perhaps it is only needed once, in between the final host_buf register
access and the first ctl_status access??)

Is there any reference in the docs to timing sensitivity?

> /* FIXME - no timeout */
> }
>
> - /*
> - * I know. i is certainly != 0 here but the loop is new. See previous
> - * comment.
> - */

Thanks for cleaning up this mess!

--

> - if (i) {
> - if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
> - printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i);
> - } else
> - printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n");
> -
> -#if 0
> if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
> printk(KERN_ERR "53C400w: no end dma signal\n");
> }
> -#endif
> +
> while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
> ; // TIMEOUT
> return 0;
>

2015-12-07 08:08:41

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH v2 77/71] ncr5380: Fix wait for 53C80 registers registers after PDMA

On Monday 07 December 2015 04:16:14 Finn Thain wrote:
>
> On Mon, 7 Dec 2015, Ondrej Zary wrote:
>
> > The check for 53C80 registers accessibility was commented out because
> > it was broken (inverted). Fix and enable it.
> >
> > Signed-off-by: Ondrej Zary <[email protected]>
> > ---
> > drivers/scsi/g_NCR5380.c | 37 ++++++-------------------------------
> > 1 file changed, 6 insertions(+), 31 deletions(-)
> >
> > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> > index 038dddf..a7479c6 100644
> > --- a/drivers/scsi/g_NCR5380.c
> > +++ b/drivers/scsi/g_NCR5380.c
> > @@ -603,14 +603,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
> > if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
> > printk("53C400r: no 53C80 gated irq after transfer");
> >
> > -#if 0
> > - /*
> > - * DON'T DO THIS - THEY NEVER ARRIVE!
> > - */
> > - printk("53C400r: Waiting for 53C80 registers\n");
> > - while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
> > + /* wait for 53C80 registers to be available */
> > + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
> > ;
>
> In the previous patch, udelay(4) was added to a CSR_GATED_53C80_IRQ
> polling loop. It is interesting that you don't need it here when polling
> CSR_53C80_REG.

Yes, it's weird. Reads work fine without the delay. Small writes work most of
the time without the delay but crash sometimes. Large writes crash the chip
consistently without the delay.

> > -#endif
> > +
> > if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
> > printk(KERN_ERR "53C400r: no end dma signal\n");
> >
> > @@ -632,7 +628,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> > struct NCR5380_hostdata *hostdata = shost_priv(instance);
> > int blocks = len / 128;
> > int start = 0;
> > - int i;
> >
> > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
> > NCR5380_write(hostdata->c400_blk_cnt, blocks);
> > @@ -681,36 +676,16 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
> > blocks--;
> > }
> >
> > -#if 0
> > - printk("53C400w: waiting for registers to be available\n");
> > - THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG);
> > - printk("53C400w: Got em\n");
> > -#endif
> > -
> > - /* Let's wait for this instead - could be ugly */
> > - /* All documentation says to check for this. Maybe my hardware is too
> > - * fast. Waiting for it seems to work fine! KLL
> > - */
> > - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) {
> > + /* wait for 53C80 registers to be available */
> > + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) {
> > udelay(4); /* DTC436 chip hangs without this */
>
> ... based on the above, this udelay is probably not needed.
>
> (Or perhaps it is only needed once, in between the final host_buf register
> access and the first ctl_status access??)

I guess that the delay is needed when the chip does write in the background.
But why only on the last block?
Adding delays inside the while(1) loop does not help, it crashes anyway.
Single delay before the first ctl_status does not help either (perhaps only
if it's long enough for the write to complete).

The chip also crashes in transfer_pio during bigger transfers in a similar
way. With Quantum HDD, it did not crash once I got PDMA working.
But with a faster IBM HDD, it crashes even with smaller PIO trasnfers.

> Is there any reference in the docs to timing sensitivity?

Haven't found anything in NCR docs. Unfortunately, we don't have any DTC
docs.

> > /* FIXME - no timeout */
> > }
> >
> > - /*
> > - * I know. i is certainly != 0 here but the loop is new. See previous
> > - * comment.
> > - */
>
> Thanks for cleaning up this mess!
>


--
Ondrej Zary

2015-12-08 02:05:23

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH v2 74/71] ncr5380: Enable PDMA for NCR53C400A


On Sun, 6 Dec 2015, Ondrej Zary wrote:

> Add I/O register mapping for NCR53C400A and enable PDMA mode to
> improve performance and fix non-working IRQ.
>
> Tested with HP C2502 (and user-space enabler).
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index 86740fd..099fdac 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> #endif
> break;
> case BOARD_NCR53C400A:
> - flags = FLAG_NO_PSEUDO_DMA;
> + flags = FLAG_NO_DMA_FIXUP;
> ports = ncr_53c400a_ports;
> break;
> case BOARD_DTC3181E:
> @@ -406,11 +406,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> * On NCR53C400 boards, NCR5380 registers are mapped 8 past
> * the base address.
> */
> - if (overrides[current_override].board == BOARD_NCR53C400) {
> + switch (overrides[current_override].board) {
> + case BOARD_NCR53C400:
> instance->io_port += 8;
> hostdata->c400_ctl_status = 0;
> hostdata->c400_blk_cnt = 1;
> hostdata->c400_host_buf = 4;
> + break;
> + case BOARD_NCR53C400A:
> + hostdata->c400_ctl_status = 9;
> + hostdata->c400_blk_cnt = 10;
> + hostdata->c400_host_buf = 8;
> + break;
> }
> #else
> instance->base = overrides[current_override].NCR5380_map_name;


For SCSI_G_NCR5380_MEM and BOARD_NCR53C400A (or BOARD_DTC3181E), you have
not assigned c400_ctl_status, c400_blk_cnt and c400_host_buf. Perhaps we
should throw an error, something like this?

hostdata->iomem = iomem;
- if (overrides[current_override].board == BOARD_NCR53C400) {
+ switch (overrides[current_override].board) {
+ case BOARD_NCR53C400:
hostdata->c400_ctl_status = 0x100;
hostdata->c400_blk_cnt = 0x101;
hostdata->c400_host_buf = 0x104;
+ break;
+ case BOARD_NCR53C400A:
+ pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
+ goto out_unregister;
}
#endif

--

> @@ -425,7 +432,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> if (NCR5380_init(instance, flags))
> goto out_unregister;
>
> - if (overrides[current_override].board == BOARD_NCR53C400)
> + if (overrides[current_override].board == BOARD_NCR53C400 ||
> + overrides[current_override].board == BOARD_NCR53C400A)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> NCR5380_maybe_reset_bus(instance);
>

2015-12-08 07:51:54

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v2 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)

HP C2502 cards (based on 53C400A chips) use different magic numbers for
software-based I/O address configuration than other cards.
The configuration is also extended to allow setting the IRQ.

Move the configuration to a new function magic_configure() and move
magic the magic numbers into an array. Add new magic numbers for these
HP cards and hp_53c400a module parameter to use them.

Tested with HP C2502 and DTCT-436P.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 76 ++++++++++++++++++++++++++++++++++++----------
drivers/scsi/g_NCR5380.h | 1 +
2 files changed, 61 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 42fdeaf..121d143 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -80,6 +80,7 @@ static int ncr_5380;
static int ncr_53c400;
static int ncr_53c400a;
static int dtc_3181e;
+static int hp_53c400a;

static struct override {
NCR5380_map_type NCR5380_map_name;
@@ -225,6 +226,32 @@ static int __init do_DTC3181E_setup(char *str)

#endif

+#ifndef SCSI_G_NCR5380_MEM
+/*
+ * Configure I/O address of 53C400A or DTC 3181 by writing magic numbers
+ * to ports 0x779 and 0x379. Two magic number sequences are known:
+ * 1. for generic NCR 53C400A-based cards and DTC436 chips
+ * 2. for HP C2502 card (also based on 53C400A but different decode logic)
+ */
+static void magic_configure(int idx, u8 irq, u8 magic[])
+{
+ u8 cfg = 0;
+
+ outb(magic[0], 0x779);
+ outb(magic[1], 0x379);
+ outb(magic[2], 0x379);
+ outb(magic[3], 0x379);
+ outb(magic[4], 0x379);
+
+ /* allowed IRQs for HP 53C400A */
+ if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
+ irq = 0;
+ if (idx >= 0 && idx <= 7)
+ cfg = 0x80 | idx | (irq << 4);
+ outb(cfg, 0x379);
+}
+#endif
+
/**
* generic_NCR5380_detect - look for NCR5380 controllers
* @tpnt: the scsi template
@@ -241,8 +268,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static int current_override;
int count;
unsigned int *ports;
+ u8 *magic;
#ifndef SCSI_G_NCR5380_MEM
- int i;
+ int i, port_idx;
unsigned long region_size = 16;
#endif
static unsigned int __initdata ncr_53c400a_ports[] = {
@@ -251,6 +279,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static unsigned int __initdata dtc_3181e_ports[] = {
0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
};
+ static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC 3181 */
+ 0x59, 0xb9, 0xc5, 0xae, 0xa6
+ };
+ static u8 hp_53c400a_magic[] __initdata = { /* HP C2502 */
+ 0x0f, 0x22, 0xf0, 0x20, 0x80
+ };
int flags;
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
@@ -273,6 +307,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
overrides[0].board = BOARD_NCR53C400A;
else if (dtc_3181e)
overrides[0].board = BOARD_DTC3181E;
+ else if (hp_53c400a)
+ overrides[0].board = BOARD_HP53C400A;
#ifndef SCSI_G_NCR5380_MEM
if (!current_override && isapnp_present()) {
struct pnp_dev *dev = NULL;
@@ -326,10 +362,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
case BOARD_NCR53C400A:
flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
+ magic = ncr_53c400a_magic;
+ break;
+ case BOARD_HP53C400A:
+ flags = FLAG_NO_DMA_FIXUP;
+ ports = ncr_53c400a_ports;
+ magic = hp_53c400a_magic;
break;
case BOARD_DTC3181E:
flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
+ magic = ncr_53c400a_magic;
break;
}

@@ -338,12 +381,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
/* wakeup sequence for the NCR53C400A and DTC3181E */

/* Disable the adapter and look for a free io port */
- outb(0x59, 0x779);
- outb(0xb9, 0x379);
- outb(0xc5, 0x379);
- outb(0xae, 0x379);
- outb(0xa6, 0x379);
- outb(0x00, 0x379);
+ magic_configure(-1, 0, magic);

if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
for (i = 0; ports[i]; i++) {
@@ -362,17 +400,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
}
if (ports[i]) {
/* At this point we have our region reserved */
- outb(0x59, 0x779);
- outb(0xb9, 0x379);
- outb(0xc5, 0x379);
- outb(0xae, 0x379);
- outb(0xa6, 0x379);
- outb(0x80 | i, 0x379); /* set io port to be used */
+ magic_configure(i, 0, magic); /* no IRQ yet */
outb(0xc0, ports[i] + 9);
- if (inb(ports[i] + 9) != 0x80)
+ if (inb(ports[i] + 9) != 0x80) {
continue;
- else
+ } else {
overrides[current_override].NCR5380_map_name = ports[i];
+ port_idx = i;
+ }
} else
continue;
}
@@ -418,6 +453,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
hostdata->io_width = 2; /* 16-bit PDMA */
/* fall through */
case BOARD_NCR53C400A:
+ case BOARD_HP53C400A:
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
hostdata->c400_host_buf = 8;
@@ -438,6 +474,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)

if (overrides[current_override].board == BOARD_NCR53C400 ||
overrides[current_override].board == BOARD_NCR53C400A ||
+ overrides[current_override].board == BOARD_HP53C400A ||
overrides[current_override].board == BOARD_DTC3181E)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

@@ -452,12 +489,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (instance->irq == 255)
instance->irq = NO_IRQ;

- if (instance->irq != NO_IRQ)
+ if (instance->irq != NO_IRQ) {
+#ifndef SCSI_G_NCR5380_MEM
+ /* set IRQ for HP 53C400A */
+ if (overrides[current_override].board == BOARD_HP53C400A)
+ magic_configure(port_idx, instance->irq, magic);
+#endif
if (request_irq(instance->irq, generic_NCR5380_intr,
0, "NCR5380", instance)) {
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
instance->irq = NO_IRQ;
}
+ }

if (instance->irq == NO_IRQ) {
printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
@@ -743,6 +786,7 @@ module_param(ncr_5380, int, 0);
module_param(ncr_53c400, int, 0);
module_param(ncr_53c400a, int, 0);
module_param(dtc_3181e, int, 0);
+module_param(hp_53c400a, int, 0);
MODULE_LICENSE("GPL");

#if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index 5ab64d9..4fbae53 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -88,6 +88,7 @@
#define BOARD_NCR53C400 1
#define BOARD_NCR53C400A 2
#define BOARD_DTC3181E 3
+#define BOARD_HP53C400A 4

#endif /* GENERIC_NCR5380_H */

--
Ondrej Zary

2015-12-08 11:40:36

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH v2 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)


On Tue, 8 Dec 2015, Ondrej Zary wrote:

> HP C2502 cards (based on 53C400A chips) use different magic numbers for
> software-based I/O address configuration than other cards. The
> configuration is also extended to allow setting the IRQ.
>
> Move the configuration to a new function magic_configure() and move
> magic the magic numbers into an array. Add new magic numbers for these
> HP cards and hp_53c400a module parameter to use them.
>
> Tested with HP C2502 and DTCT-436P.
>
> Signed-off-by: Ondrej Zary <[email protected]>
> ---
> drivers/scsi/g_NCR5380.c | 76 ++++++++++++++++++++++++++++++++++++----------
> drivers/scsi/g_NCR5380.h | 1 +
> 2 files changed, 61 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> index 42fdeaf..121d143 100644
> --- a/drivers/scsi/g_NCR5380.c
> +++ b/drivers/scsi/g_NCR5380.c
> @@ -80,6 +80,7 @@ static int ncr_5380;
> static int ncr_53c400;
> static int ncr_53c400a;
> static int dtc_3181e;
> +static int hp_53c400a;

>From the photos that I've seen, the HP cards have either NCR or SYMBIOS
53C400A devices.

You've added a new setup option and a new board type, but the name you've
chosen is neither the board type nor the device type. It is a combination.

>
> static struct override {
> NCR5380_map_type NCR5380_map_name;
> @@ -225,6 +226,32 @@ static int __init do_DTC3181E_setup(char *str)
>
> #endif
>
> +#ifndef SCSI_G_NCR5380_MEM
> +/*
> + * Configure I/O address of 53C400A or DTC 3181 by writing magic numbers
> + * to ports 0x779 and 0x379. Two magic number sequences are known:
> + * 1. for generic NCR 53C400A-based cards and DTC436 chips
> + * 2. for HP C2502 card (also based on 53C400A but different decode logic)

Forgive my ignorance of ISA card design, but that suggests that these
magic numbers are only relevant to HP C2502 boards and not SYM 53C400A
devices in general (?) ...

> + */
> +static void magic_configure(int idx, u8 irq, u8 magic[])
> +{
> + u8 cfg = 0;
> +
> + outb(magic[0], 0x779);
> + outb(magic[1], 0x379);
> + outb(magic[2], 0x379);
> + outb(magic[3], 0x379);
> + outb(magic[4], 0x379);
> +
> + /* allowed IRQs for HP 53C400A */
> + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
> + irq = 0;
> + if (idx >= 0 && idx <= 7)
> + cfg = 0x80 | idx | (irq << 4);
> + outb(cfg, 0x379);
> +}
> +#endif
> +
> /**
> * generic_NCR5380_detect - look for NCR5380 controllers
> * @tpnt: the scsi template
> @@ -241,8 +268,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> static int current_override;
> int count;
> unsigned int *ports;
> + u8 *magic;
> #ifndef SCSI_G_NCR5380_MEM
> - int i;
> + int i, port_idx;
> unsigned long region_size = 16;
> #endif
> static unsigned int __initdata ncr_53c400a_ports[] = {
> @@ -251,6 +279,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> static unsigned int __initdata dtc_3181e_ports[] = {
> 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
> };
> + static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC 3181 */
> + 0x59, 0xb9, 0xc5, 0xae, 0xa6
> + };
> + static u8 hp_53c400a_magic[] __initdata = { /* HP C2502 */
> + 0x0f, 0x22, 0xf0, 0x20, 0x80
> + };

... so maybe that should be called 'hp_c2502_magic'?


> int flags;
> struct Scsi_Host *instance;
> struct NCR5380_hostdata *hostdata;
> @@ -273,6 +307,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> overrides[0].board = BOARD_NCR53C400A;
> else if (dtc_3181e)
> overrides[0].board = BOARD_DTC3181E;
> + else if (hp_53c400a)
> + overrides[0].board = BOARD_HP53C400A;
> #ifndef SCSI_G_NCR5380_MEM
> if (!current_override && isapnp_present()) {
> struct pnp_dev *dev = NULL;
> @@ -326,10 +362,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> case BOARD_NCR53C400A:
> flags = FLAG_NO_DMA_FIXUP;
> ports = ncr_53c400a_ports;
> + magic = ncr_53c400a_magic;
> + break;
> + case BOARD_HP53C400A:
> + flags = FLAG_NO_DMA_FIXUP;
> + ports = ncr_53c400a_ports;
> + magic = hp_53c400a_magic;
> break;
> case BOARD_DTC3181E:
> flags = FLAG_NO_DMA_FIXUP;
> ports = dtc_3181e_ports;
> + magic = ncr_53c400a_magic;
> break;
> }
>
> @@ -338,12 +381,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> /* wakeup sequence for the NCR53C400A and DTC3181E */
>
> /* Disable the adapter and look for a free io port */
> - outb(0x59, 0x779);
> - outb(0xb9, 0x379);
> - outb(0xc5, 0x379);
> - outb(0xae, 0x379);
> - outb(0xa6, 0x379);
> - outb(0x00, 0x379);
> + magic_configure(-1, 0, magic);
>
> if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
> for (i = 0; ports[i]; i++) {
> @@ -362,17 +400,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> }
> if (ports[i]) {
> /* At this point we have our region reserved */
> - outb(0x59, 0x779);
> - outb(0xb9, 0x379);
> - outb(0xc5, 0x379);
> - outb(0xae, 0x379);
> - outb(0xa6, 0x379);
> - outb(0x80 | i, 0x379); /* set io port to be used */
> + magic_configure(i, 0, magic); /* no IRQ yet */
> outb(0xc0, ports[i] + 9);
> - if (inb(ports[i] + 9) != 0x80)
> + if (inb(ports[i] + 9) != 0x80) {
> continue;
> - else
> + } else {
> overrides[current_override].NCR5380_map_name = ports[i];
> + port_idx = i;
> + }
> } else
> continue;
> }
> @@ -418,6 +453,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> hostdata->io_width = 2; /* 16-bit PDMA */
> /* fall through */
> case BOARD_NCR53C400A:
> + case BOARD_HP53C400A:
> hostdata->c400_ctl_status = 9;
> hostdata->c400_blk_cnt = 10;
> hostdata->c400_host_buf = 8;
> @@ -438,6 +474,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
>
> if (overrides[current_override].board == BOARD_NCR53C400 ||
> overrides[current_override].board == BOARD_NCR53C400A ||
> + overrides[current_override].board == BOARD_HP53C400A ||
> overrides[current_override].board == BOARD_DTC3181E)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> @@ -452,12 +489,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> if (instance->irq == 255)
> instance->irq = NO_IRQ;
>
> - if (instance->irq != NO_IRQ)
> + if (instance->irq != NO_IRQ) {
> +#ifndef SCSI_G_NCR5380_MEM
> + /* set IRQ for HP 53C400A */
> + if (overrides[current_override].board == BOARD_HP53C400A)
> + magic_configure(port_idx, instance->irq, magic);
> +#endif
> if (request_irq(instance->irq, generic_NCR5380_intr,
> 0, "NCR5380", instance)) {
> printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
> instance->irq = NO_IRQ;
> }
> + }
>
> if (instance->irq == NO_IRQ) {
> printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
> @@ -743,6 +786,7 @@ module_param(ncr_5380, int, 0);
> module_param(ncr_53c400, int, 0);
> module_param(ncr_53c400a, int, 0);
> module_param(dtc_3181e, int, 0);
> +module_param(hp_53c400a, int, 0);

Any reason you did not add the corresponding __setup option?

Did you consider re-using the existing ncr_53c400a option (for port & irq
settings) and adding a new setup option and module param for card magic?

(I like orthogonal command line options. dtc_3181e doesn't really bother
me because the dtc-436 device seems to correspond to the 3181e card and
vice versa.)

> MODULE_LICENSE("GPL");
>
> #if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
> diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> index 5ab64d9..4fbae53 100644
> --- a/drivers/scsi/g_NCR5380.h
> +++ b/drivers/scsi/g_NCR5380.h
> @@ -88,6 +88,7 @@
> #define BOARD_NCR53C400 1
> #define BOARD_NCR53C400A 2
> #define BOARD_DTC3181E 3
> +#define BOARD_HP53C400A 4
>
> #endif /* GENERIC_NCR5380_H */
>
>

--

2015-12-09 11:33:51

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH v2 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)

On Tuesday 08 December 2015 12:40:18 Finn Thain wrote:
>
> On Tue, 8 Dec 2015, Ondrej Zary wrote:
>
> > HP C2502 cards (based on 53C400A chips) use different magic numbers for
> > software-based I/O address configuration than other cards. The
> > configuration is also extended to allow setting the IRQ.
> >
> > Move the configuration to a new function magic_configure() and move
> > magic the magic numbers into an array. Add new magic numbers for these
> > HP cards and hp_53c400a module parameter to use them.
> >
> > Tested with HP C2502 and DTCT-436P.
> >
> > Signed-off-by: Ondrej Zary <[email protected]>
> > ---
> > drivers/scsi/g_NCR5380.c | 76 ++++++++++++++++++++++++++++++++++++----------
> > drivers/scsi/g_NCR5380.h | 1 +
> > 2 files changed, 61 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> > index 42fdeaf..121d143 100644
> > --- a/drivers/scsi/g_NCR5380.c
> > +++ b/drivers/scsi/g_NCR5380.c
> > @@ -80,6 +80,7 @@ static int ncr_5380;
> > static int ncr_53c400;
> > static int ncr_53c400a;
> > static int dtc_3181e;
> > +static int hp_53c400a;
>
> From the photos that I've seen, the HP cards have either NCR or SYMBIOS
> 53C400A devices.
>
> You've added a new setup option and a new board type, but the name you've
> chosen is neither the board type nor the device type. It is a combination.

Because it's a HP board with NCR/SYMBIOS 53C400A chip. Windows driver calls
it "Symbios Logic 53C400A (HP Version)", suggesting that there might be more
compatible cards.
But search did not found any on the web, only C2502. So I'll rename it to
hp_c2502.

> >
> > static struct override {
> > NCR5380_map_type NCR5380_map_name;
> > @@ -225,6 +226,32 @@ static int __init do_DTC3181E_setup(char *str)
> >
> > #endif
> >
> > +#ifndef SCSI_G_NCR5380_MEM
> > +/*
> > + * Configure I/O address of 53C400A or DTC 3181 by writing magic numbers
> > + * to ports 0x779 and 0x379. Two magic number sequences are known:
> > + * 1. for generic NCR 53C400A-based cards and DTC436 chips
> > + * 2. for HP C2502 card (also based on 53C400A but different decode logic)
>
> Forgive my ignorance of ISA card design, but that suggests that these
> magic numbers are only relevant to HP C2502 boards and not SYM 53C400A
> devices in general (?) ...

Looks like the original magic numbers (they came from the outb() calls, now
in ncr_53c400a_magic[]) are hardcoded in the 53C400A chip (and also DTC
chips).

HP C2502 card has some PALCE chips between the ISA bus and 53C400A. They
probably react to the HP-specific magic numbers (and don't pass the
"original" magic numbers to the 53C400A chip).

> > + */
> > +static void magic_configure(int idx, u8 irq, u8 magic[])
> > +{
> > + u8 cfg = 0;
> > +
> > + outb(magic[0], 0x779);
> > + outb(magic[1], 0x379);
> > + outb(magic[2], 0x379);
> > + outb(magic[3], 0x379);
> > + outb(magic[4], 0x379);
> > +
> > + /* allowed IRQs for HP 53C400A */
> > + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
> > + irq = 0;
> > + if (idx >= 0 && idx <= 7)
> > + cfg = 0x80 | idx | (irq << 4);
> > + outb(cfg, 0x379);
> > +}
> > +#endif
> > +
> > /**
> > * generic_NCR5380_detect - look for NCR5380 controllers
> > * @tpnt: the scsi template
> > @@ -241,8 +268,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > static int current_override;
> > int count;
> > unsigned int *ports;
> > + u8 *magic;
> > #ifndef SCSI_G_NCR5380_MEM
> > - int i;
> > + int i, port_idx;
> > unsigned long region_size = 16;
> > #endif
> > static unsigned int __initdata ncr_53c400a_ports[] = {
> > @@ -251,6 +279,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > static unsigned int __initdata dtc_3181e_ports[] = {
> > 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
> > };
> > + static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC 3181 */
> > + 0x59, 0xb9, 0xc5, 0xae, 0xa6
> > + };
> > + static u8 hp_53c400a_magic[] __initdata = { /* HP C2502 */
> > + 0x0f, 0x22, 0xf0, 0x20, 0x80
> > + };
>
> ... so maybe that should be called 'hp_c2502_magic'?

Yes.

> > int flags;
> > struct Scsi_Host *instance;
> > struct NCR5380_hostdata *hostdata;
> > @@ -273,6 +307,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > overrides[0].board = BOARD_NCR53C400A;
> > else if (dtc_3181e)
> > overrides[0].board = BOARD_DTC3181E;
> > + else if (hp_53c400a)
> > + overrides[0].board = BOARD_HP53C400A;
> > #ifndef SCSI_G_NCR5380_MEM
> > if (!current_override && isapnp_present()) {
> > struct pnp_dev *dev = NULL;
> > @@ -326,10 +362,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > case BOARD_NCR53C400A:
> > flags = FLAG_NO_DMA_FIXUP;
> > ports = ncr_53c400a_ports;
> > + magic = ncr_53c400a_magic;
> > + break;
> > + case BOARD_HP53C400A:
> > + flags = FLAG_NO_DMA_FIXUP;
> > + ports = ncr_53c400a_ports;
> > + magic = hp_53c400a_magic;
> > break;
> > case BOARD_DTC3181E:
> > flags = FLAG_NO_DMA_FIXUP;
> > ports = dtc_3181e_ports;
> > + magic = ncr_53c400a_magic;
> > break;
> > }
> >
> > @@ -338,12 +381,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > /* wakeup sequence for the NCR53C400A and DTC3181E */
> >
> > /* Disable the adapter and look for a free io port */
> > - outb(0x59, 0x779);
> > - outb(0xb9, 0x379);
> > - outb(0xc5, 0x379);
> > - outb(0xae, 0x379);
> > - outb(0xa6, 0x379);
> > - outb(0x00, 0x379);

Magic numbers from here were moved to ncr_53c400a_magic[].

> > + magic_configure(-1, 0, magic);
> >
> > if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
> > for (i = 0; ports[i]; i++) {
> > @@ -362,17 +400,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > }
> > if (ports[i]) {
> > /* At this point we have our region reserved */
> > - outb(0x59, 0x779);
> > - outb(0xb9, 0x379);
> > - outb(0xc5, 0x379);
> > - outb(0xae, 0x379);
> > - outb(0xa6, 0x379);
> > - outb(0x80 | i, 0x379); /* set io port to be used */
> > + magic_configure(i, 0, magic); /* no IRQ yet */
> > outb(0xc0, ports[i] + 9);
> > - if (inb(ports[i] + 9) != 0x80)
> > + if (inb(ports[i] + 9) != 0x80) {
> > continue;
> > - else
> > + } else {
> > overrides[current_override].NCR5380_map_name = ports[i];
> > + port_idx = i;
> > + }
> > } else
> > continue;
> > }
> > @@ -418,6 +453,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > hostdata->io_width = 2; /* 16-bit PDMA */
> > /* fall through */
> > case BOARD_NCR53C400A:
> > + case BOARD_HP53C400A:
> > hostdata->c400_ctl_status = 9;
> > hostdata->c400_blk_cnt = 10;
> > hostdata->c400_host_buf = 8;
> > @@ -438,6 +474,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> >
> > if (overrides[current_override].board == BOARD_NCR53C400 ||
> > overrides[current_override].board == BOARD_NCR53C400A ||
> > + overrides[current_override].board == BOARD_HP53C400A ||
> > overrides[current_override].board == BOARD_DTC3181E)
> > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
> >
> > @@ -452,12 +489,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > if (instance->irq == 255)
> > instance->irq = NO_IRQ;
> >
> > - if (instance->irq != NO_IRQ)
> > + if (instance->irq != NO_IRQ) {
> > +#ifndef SCSI_G_NCR5380_MEM
> > + /* set IRQ for HP 53C400A */
> > + if (overrides[current_override].board == BOARD_HP53C400A)
> > + magic_configure(port_idx, instance->irq, magic);
> > +#endif
> > if (request_irq(instance->irq, generic_NCR5380_intr,
> > 0, "NCR5380", instance)) {
> > printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
> > instance->irq = NO_IRQ;
> > }
> > + }
> >
> > if (instance->irq == NO_IRQ) {
> > printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
> > @@ -743,6 +786,7 @@ module_param(ncr_5380, int, 0);
> > module_param(ncr_53c400, int, 0);
> > module_param(ncr_53c400a, int, 0);
> > module_param(dtc_3181e, int, 0);
> > +module_param(hp_53c400a, int, 0);
>
> Any reason you did not add the corresponding __setup option?

I wonder if __setup is really required. I thought that it should go away and
module parameters used instead.

> Did you consider re-using the existing ncr_53c400a option (for port & irq
> settings) and adding a new setup option and module param for card magic?

Looks like a good idea.

> (I like orthogonal command line options. dtc_3181e doesn't really bother
> me because the dtc-436 device seems to correspond to the 3181e card and
> vice versa.)
>
> > MODULE_LICENSE("GPL");
> >
> > #if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
> > diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
> > index 5ab64d9..4fbae53 100644
> > --- a/drivers/scsi/g_NCR5380.h
> > +++ b/drivers/scsi/g_NCR5380.h
> > @@ -88,6 +88,7 @@
> > #define BOARD_NCR53C400 1
> > #define BOARD_NCR53C400A 2
> > #define BOARD_DTC3181E 3
> > +#define BOARD_HP53C400A 4
> >
> > #endif /* GENERIC_NCR5380_H */
> >
> >
>


--
Ondrej Zary

2015-12-09 12:11:57

by Ondrej Zary

[permalink] [raw]
Subject: [PATCH v3 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)

HP C2502 cards (based on 53C400A chips) use different magic numbers for
software-based I/O address configuration than other cards.
The configuration is also extended to allow setting the IRQ.

Move the configuration to a new function magic_configure() and move
magic the magic numbers into an array. Add new magic numbers for these
HP cards and hp_c2502 module parameter to use them, e.g.:
modprobe g_NCR5380 ncr_irq=7 ncr_addr=0x280 ncr_53c400a=1 hp_c2502=1

Tested with HP C2502 and DTCT-436P.

Signed-off-by: Ondrej Zary <[email protected]>
---
drivers/scsi/g_NCR5380.c | 74 ++++++++++++++++++++++++++++++++++++----------
1 file changed, 58 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 42fdeaf..dd32c68 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -80,12 +80,14 @@ static int ncr_5380;
static int ncr_53c400;
static int ncr_53c400a;
static int dtc_3181e;
+static int hp_c2502;

static struct override {
NCR5380_map_type NCR5380_map_name;
int irq;
int dma;
int board; /* Use NCR53c400, Ricoh, etc. extensions ? */
+ bool hp_c2502;
} overrides
#ifdef GENERIC_NCR5380_OVERRIDE
[] __initdata = GENERIC_NCR5380_OVERRIDE;
@@ -225,6 +227,32 @@ static int __init do_DTC3181E_setup(char *str)

#endif

+#ifndef SCSI_G_NCR5380_MEM
+/*
+ * Configure I/O address of 53C400A or DTC436 by writing magic numbers
+ * to ports 0x779 and 0x379. Two magic number sequences are known:
+ * 1. for generic NCR 53C400A-based cards and DTC436 chips
+ * 2. for HP C2502 card (also based on 53C400A but different decode logic)
+ */
+static void magic_configure(int idx, u8 irq, u8 magic[])
+{
+ u8 cfg = 0;
+
+ outb(magic[0], 0x779);
+ outb(magic[1], 0x379);
+ outb(magic[2], 0x379);
+ outb(magic[3], 0x379);
+ outb(magic[4], 0x379);
+
+ /* allowed IRQs for HP 53C400A */
+ if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
+ irq = 0;
+ if (idx >= 0 && idx <= 7)
+ cfg = 0x80 | idx | (irq << 4);
+ outb(cfg, 0x379);
+}
+#endif
+
/**
* generic_NCR5380_detect - look for NCR5380 controllers
* @tpnt: the scsi template
@@ -241,8 +269,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static int current_override;
int count;
unsigned int *ports;
+ u8 *magic;
#ifndef SCSI_G_NCR5380_MEM
- int i;
+ int i, port_idx;
unsigned long region_size = 16;
#endif
static unsigned int __initdata ncr_53c400a_ports[] = {
@@ -251,6 +280,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static unsigned int __initdata dtc_3181e_ports[] = {
0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
};
+ static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC436 */
+ 0x59, 0xb9, 0xc5, 0xae, 0xa6
+ };
+ static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */
+ 0x0f, 0x22, 0xf0, 0x20, 0x80
+ };
int flags;
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
@@ -273,6 +308,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
overrides[0].board = BOARD_NCR53C400A;
else if (dtc_3181e)
overrides[0].board = BOARD_DTC3181E;
+ if (hp_c2502)
+ overrides[0].hp_c2502 = true;
#ifndef SCSI_G_NCR5380_MEM
if (!current_override && isapnp_present()) {
struct pnp_dev *dev = NULL;
@@ -326,24 +363,25 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
case BOARD_NCR53C400A:
flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
+ magic = ncr_53c400a_magic;
break;
case BOARD_DTC3181E:
flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
+ magic = ncr_53c400a_magic;
break;
}
+ if (overrides[current_override].hp_c2502)
+ magic = hp_c2502_magic;
+ else
+ magic = ncr_53c400a_magic;

#ifndef SCSI_G_NCR5380_MEM
if (ports) {
/* wakeup sequence for the NCR53C400A and DTC3181E */

/* Disable the adapter and look for a free io port */
- outb(0x59, 0x779);
- outb(0xb9, 0x379);
- outb(0xc5, 0x379);
- outb(0xae, 0x379);
- outb(0xa6, 0x379);
- outb(0x00, 0x379);
+ magic_configure(-1, 0, magic);

if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
for (i = 0; ports[i]; i++) {
@@ -362,17 +400,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
}
if (ports[i]) {
/* At this point we have our region reserved */
- outb(0x59, 0x779);
- outb(0xb9, 0x379);
- outb(0xc5, 0x379);
- outb(0xae, 0x379);
- outb(0xa6, 0x379);
- outb(0x80 | i, 0x379); /* set io port to be used */
+ magic_configure(i, 0, magic); /* no IRQ yet */
outb(0xc0, ports[i] + 9);
- if (inb(ports[i] + 9) != 0x80)
+ if (inb(ports[i] + 9) != 0x80) {
continue;
- else
+ } else {
overrides[current_override].NCR5380_map_name = ports[i];
+ port_idx = i;
+ }
} else
continue;
}
@@ -452,12 +487,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (instance->irq == 255)
instance->irq = NO_IRQ;

- if (instance->irq != NO_IRQ)
+ if (instance->irq != NO_IRQ) {
+#ifndef SCSI_G_NCR5380_MEM
+ /* set IRQ for HP C2502 */
+ if (magic == hp_c2502_magic)
+ magic_configure(port_idx, instance->irq, magic);
+#endif
if (request_irq(instance->irq, generic_NCR5380_intr,
0, "NCR5380", instance)) {
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
instance->irq = NO_IRQ;
}
+ }

if (instance->irq == NO_IRQ) {
printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
@@ -743,6 +784,7 @@ module_param(ncr_5380, int, 0);
module_param(ncr_53c400, int, 0);
module_param(ncr_53c400a, int, 0);
module_param(dtc_3181e, int, 0);
+module_param(hp_c2502, int, 0);
MODULE_LICENSE("GPL");

#if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
--
Ondrej Zary

2015-12-09 13:39:17

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH v2 74/71] ncr5380: Enable PDMA for NCR53C400A

On Tuesday 08 December 2015 03:05:11 Finn Thain wrote:
>
> On Sun, 6 Dec 2015, Ondrej Zary wrote:
>
> > Add I/O register mapping for NCR53C400A and enable PDMA mode to
> > improve performance and fix non-working IRQ.
> >
> > Tested with HP C2502 (and user-space enabler).
> >
> > Signed-off-by: Ondrej Zary <[email protected]>
> > ---
> > drivers/scsi/g_NCR5380.c | 14 +++++++++++---
> > 1 file changed, 11 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> > index 86740fd..099fdac 100644
> > --- a/drivers/scsi/g_NCR5380.c
> > +++ b/drivers/scsi/g_NCR5380.c
> > @@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > #endif
> > break;
> > case BOARD_NCR53C400A:
> > - flags = FLAG_NO_PSEUDO_DMA;
> > + flags = FLAG_NO_DMA_FIXUP;
> > ports = ncr_53c400a_ports;
> > break;
> > case BOARD_DTC3181E:
> > @@ -406,11 +406,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > * On NCR53C400 boards, NCR5380 registers are mapped 8 past
> > * the base address.
> > */
> > - if (overrides[current_override].board == BOARD_NCR53C400) {
> > + switch (overrides[current_override].board) {
> > + case BOARD_NCR53C400:
> > instance->io_port += 8;
> > hostdata->c400_ctl_status = 0;
> > hostdata->c400_blk_cnt = 1;
> > hostdata->c400_host_buf = 4;
> > + break;
> > + case BOARD_NCR53C400A:
> > + hostdata->c400_ctl_status = 9;
> > + hostdata->c400_blk_cnt = 10;
> > + hostdata->c400_host_buf = 8;
> > + break;
> > }
> > #else
> > instance->base = overrides[current_override].NCR5380_map_name;
>
>
> For SCSI_G_NCR5380_MEM and BOARD_NCR53C400A (or BOARD_DTC3181E), you have
> not assigned c400_ctl_status, c400_blk_cnt and c400_host_buf. Perhaps we
> should throw an error, something like this?
>
> hostdata->iomem = iomem;
> - if (overrides[current_override].board == BOARD_NCR53C400) {
> + switch (overrides[current_override].board) {
> + case BOARD_NCR53C400:
> hostdata->c400_ctl_status = 0x100;
> hostdata->c400_blk_cnt = 0x101;
> hostdata->c400_host_buf = 0x104;
> + break;
> + case BOARD_NCR53C400A:
> + pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
> + goto out_unregister;
> }
> #endif

We don't need to fail, just disable PDMA by setting:
flags = FLAG_NO_PSEUDO_DMA;

And BTW. this:
if (overrides[current_override].board == BOARD_NCR53C400 ||
overrides[current_override].board == BOARD_NCR53C400A)
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

should then be, solving the problem of growing if condition:
if (!(flags & FLAG_NO_PSEUDO_DMA))
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);

--
Ondrej Zary

2015-12-10 23:38:15

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH v2 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)


On Wed, 9 Dec 2015, Ondrej Zary wrote:

> > > @@ -743,6 +786,7 @@ module_param(ncr_5380, int, 0);
> > > module_param(ncr_53c400, int, 0);
> > > module_param(ncr_53c400a, int, 0);
> > > module_param(dtc_3181e, int, 0);
> > > +module_param(hp_53c400a, int, 0);
> >
> > Any reason you did not add the corresponding __setup option?
>
> I wonder if __setup is really required. I thought that it should go away
> and module parameters used instead.

Yes, after re-reading the header files I see that you are right.

>
> > Did you consider re-using the existing ncr_53c400a option (for port &
> > irq settings) and adding a new setup option and module param for card
> > magic?
>
> Looks like a good idea.

What I had in mind was an 'ncr_magic' option, to go with 'ncr_irq' and
'ncr_addr'. This is supposed to be a generic driver, after all.

But now that I've seen what that would involve (adding another member to
struct override) I've changed my mind.

I think the new board type was the right approach. That is, a combination
of your v2 and v3 patches. I'll send my version to you to test.

Thanks.

--

2015-12-10 23:39:46

by Finn Thain

[permalink] [raw]
Subject: Re: [PATCH v2 74/71] ncr5380: Enable PDMA for NCR53C400A


On Wed, 9 Dec 2015, Ondrej Zary wrote:

> On Tuesday 08 December 2015 03:05:11 Finn Thain wrote:
> >
> > On Sun, 6 Dec 2015, Ondrej Zary wrote:
> >
> > > Add I/O register mapping for NCR53C400A and enable PDMA mode to
> > > improve performance and fix non-working IRQ.
> > >
> > > Tested with HP C2502 (and user-space enabler).
> > >
> > > Signed-off-by: Ondrej Zary <[email protected]>
> > > ---
> > > drivers/scsi/g_NCR5380.c | 14 +++++++++++---
> > > 1 file changed, 11 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
> > > index 86740fd..099fdac 100644
> > > --- a/drivers/scsi/g_NCR5380.c
> > > +++ b/drivers/scsi/g_NCR5380.c
> > > @@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > > #endif
> > > break;
> > > case BOARD_NCR53C400A:
> > > - flags = FLAG_NO_PSEUDO_DMA;
> > > + flags = FLAG_NO_DMA_FIXUP;
> > > ports = ncr_53c400a_ports;
> > > break;
> > > case BOARD_DTC3181E:
> > > @@ -406,11 +406,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
> > > * On NCR53C400 boards, NCR5380 registers are mapped 8 past
> > > * the base address.
> > > */
> > > - if (overrides[current_override].board == BOARD_NCR53C400) {
> > > + switch (overrides[current_override].board) {
> > > + case BOARD_NCR53C400:
> > > instance->io_port += 8;
> > > hostdata->c400_ctl_status = 0;
> > > hostdata->c400_blk_cnt = 1;
> > > hostdata->c400_host_buf = 4;
> > > + break;
> > > + case BOARD_NCR53C400A:
> > > + hostdata->c400_ctl_status = 9;
> > > + hostdata->c400_blk_cnt = 10;
> > > + hostdata->c400_host_buf = 8;
> > > + break;
> > > }
> > > #else
> > > instance->base = overrides[current_override].NCR5380_map_name;
> >
> >
> > For SCSI_G_NCR5380_MEM and BOARD_NCR53C400A (or BOARD_DTC3181E), you have
> > not assigned c400_ctl_status, c400_blk_cnt and c400_host_buf. Perhaps we
> > should throw an error, something like this?
> >
> > hostdata->iomem = iomem;
> > - if (overrides[current_override].board == BOARD_NCR53C400) {
> > + switch (overrides[current_override].board) {
> > + case BOARD_NCR53C400:
> > hostdata->c400_ctl_status = 0x100;
> > hostdata->c400_blk_cnt = 0x101;
> > hostdata->c400_host_buf = 0x104;
> > + break;
> > + case BOARD_NCR53C400A:
> > + pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
> > + goto out_unregister;
> > }
> > #endif
>
> We don't need to fail, just disable PDMA by setting:
> flags = FLAG_NO_PSEUDO_DMA;
>
> And BTW. this:
> if (overrides[current_override].board == BOARD_NCR53C400 ||
> overrides[current_override].board == BOARD_NCR53C400A)
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>
> should then be, solving the problem of growing if condition:
> if (!(flags & FLAG_NO_PSEUDO_DMA))
> NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
>

We already resolved that problem. Julian Calaby and I agreed that a switch
statement is better than a flag here.

Moreover, if the user sets the 'ncr_53c400' or 'ncr_53c400a' module
options I presume they expect corresponding device initialization. I don't
think PIO means we should skip that.

Passing 'ncr_53c400' or 'ncr_53c400a' options to the g_NCR5380_mmio module
has to give an error if we don't have enough information about the board
to allow us to do the right thing.

(Passing the 'ncr_5380' module param may give the result you wanted.)

BTW, I fixed up this patch when I added it to my queue. I'll send you my
version to test.

Thanks.

--