Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Finn,

thanks for your review!

Am 04.03.2018 um 15:55 schrieb Finn Thain:
> On Sun, 4 Mar 2018, Michael Schmitz wrote:
> 
>> From: Michael Schmitz <schmitz@xxxxxxxxxx>
>>
>> New combined SCSI driver for all ESP based Zorro SCSI boards for
>> m68k Amiga.
>>
> 
> Nice work!
> 
> Shouldn't both patches be combined into one? The first patch can't be used 
> without this one.

I can certainly do that, if that's the preferred way.

>> +/* zorro_esp.c: ESP front-end for Amiga ZORRO SCSI systems.
>> + *
>> + * Copyright (C) 1996 Jesper Skov (jskov@xxxxxxxxxxxx)
>> + *
>> + * Copyright (C) 2011,2018 Michael Schmitz (schmitz@xxxxxxxxxx) for
>> + *               migration to ESP SCSI core
> 
> You can blame me for some of this ;-)

Oops - did acknowledge you in the commit message but forgot to do it in
the code ... or did you mean something else?

>> +#define DRV_MODULE_NAME     "zorro_esp"
>> +#define PFX                 DRV_MODULE_NAME ": "
> 
> This should be pr_fmt(). mac_esp used PFX because it is older than the 
> pr_*() stuff.
> 
> Also, KBUILD_MODNAME might be appropriate here? This idiom is common:
> 
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

OK, I'll change the logging to current standard.

>> +/*
>> + * private data used for PIO
>> + */
>> +struct zorro_esp_priv {
>> +	struct esp *esp;
> 
> You don't need this backpointer -- every time you use the zorro_esp_priv 
> struct, you already have the esp pointer.

True - not sure what I was anticipating to use that for anymore.

>> +	int error;
>> +} zorro_esp_private_data[8];
>> +
> 
> Many of these 8 structs probably aren't going to get used, which seems 
> wasteful. I'd allocate the private struct dynamically, as mac_esp does.

I had tried that, but couldn't get it stored in either the esp or the
zorro_device structs.

>> +#define ZORRO_ESP_GET_PRIV(esp) ((struct zorro_esp_priv *) \
>> +				&zorro_esp_private_data[(esp->host->host_no)])
>> +
> 
> How do you know that host_no won't exceed the array bounds?
> Why not use dev_{set,get}_drvdata(esp->dev)? -- much as mac_esp uses
> platform_{set,get}_drvdata() here.

I don't think you can have more than 8 Zorro cards in an Amiga. And I
had tried zorro_{set,get}_drvdata() to no avail (the private data pinter
is used for something else there). Will try dev_{set,get}_drvdata() now.


>> +	/* We are passed DMA addresses i.e. physical addresses, but must use
>> +	 * kernel virtual addresses here, so remap to virtual. This is easy
> 
> IMHO "convert" is probably more clear than "remap" here.

Right.


>> +			esp->ireg = zorro_esp_read8(esp, ESP_INTRPT);
>> +			/* This is tricky - ~ESP_INTR_BSERV is the wrong mask
>> +			 * a ESP_CMD_SELAS command which also generates
>> +			 * ESP_INTR_FDONE! Use ~(ESP_INTR_BSERV|ESP_INTR_FDONE)
>> +			 * since ESP_INTR_FDONE is not raised by any other
>> +			 * error condition. Unfortunately, this is still not
>> +			 * sufficient to make the single message byte transfer
>> +			 * of ESP_CMD_SELAS work ...
> 
> Is that comment correct? This is the !write branch, that is, read acccess 
> from memory. But tag bytes move in the other direction for ESP_CMD_SELAS.
> 
> I suspect that the mac_esp PIO code should work fine here unchanged. If 
> so, let's avoid a new variation on that code if that's possible (?)

The Mac PIO code did not work unchanged here, that's why I checked the
interrupt bit raised and changed the mask. But that was only for one
quirky target (CD-ROM, SCSI-1 CCS IIRC) and only when testing the entire
driver without DMA. Doesn't happen in DMA mode.

You would have seen the error only with such a special target, and
probably not in PDMA mode...

Regarding your other comment on this code: I'll have to review what
phase was present when the select with attention and stop condition
occurred, but setting the mask up front according to the bus phase would
make a lot of sense.

>> +	BUG_ON(!(cmd & ESP_CMD_DMA));
> 
> WARN_ON is preferred. Please see Johannes Thumshirn's message from last 
> week,
> https://www.spinics.net/lists/linux-scsi/msg117919.html

Well, should we ever see this condition trigger (I have never!), I don't
think there is a way we can recover from it. We expect a DMA command
(DMA i.e. physical address), how can we reliably determine whether the
calling code just forgot to set the bit, or really passed us a kernel
virtual address?

Since I've never seen this trigger, may as well remove the test.

> 
>> +
>> +	if (write)
>> +		cache_clear(addr, esp_count);
>> +	else
>> +		cache_push(addr, esp_count);
>> +
>> +	addr >>= 1;
>> +	if (write)
>> +		addr &= ~(DMA_WRITE);
>> +	else
>> +		addr |= DMA_WRITE;
>> +
>> +	dregs->dma_latch = (addr >> 24) & 0xff;
>> +	dregs->dma_addr  = (addr >> 24) & 0xff;
>> +	dregs->dma_addr  = (addr >> 16) & 0xff;
>> +	dregs->dma_addr  = (addr >>  8) & 0xff;
>> +	dregs->dma_addr  =  addr & 0xff;
>> +
>> +	scsi_esp_cmd(esp, ESP_CMD_DMA);
>> +	zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
>> +	zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
>> +//	zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> 
> Maybe set esp_ops.dma_length_limit and drop the dead code.
> See also mac_esp_dma_length_limit.

I need to go back to the old driver code and see whether there were any
card variants that allow such large transfer sizes.

>> +	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
>> +	 * so when (write) is true, it actually means READ (from the ESP)!
>> +	 */
> 
> It's not a SPARC thing. A "DMA write" is literally a memory access. So a 

Yes, that's from the old driver where the author evidently saw things
more from the SCSI controller perspective... No longer needed now.

> "SCSI READ" command is always a "write access" when DMA is involved. I 
> suggest a comment here only needs to remind the reader that the write flag 
> indicates a DMA receive operation. E.g.
> 
>> +	if (write) {
> 
> 		/* DMA receive */
> 
>> +		cache_clear(addr, esp_count);
>> +		addr &= ~(1);
>> +	} else {
> 
> 		/* DMA send */

I can do that.

>> +static int zorro_esp_dma_error(struct esp *esp)
>> +{
>> +	struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
>> +	u8 phase = esp->sreg & ESP_STAT_PMASK;
>> +
>> +	/* if doing PIO, check for error */
>> +	if (phase == ESP_MIP && zep->error == 1)
>> +		return 1;
> 
> Don't check the bus phase here, the target controls that. Just make sure 
> zep->error gets set to zero when not using PIO; that's what 
> mac_esp_send_pdma_cmd() does.

You mean before sending each DMA command? Couldn't find a way to figure
out whether we're been doing DMA or PIO otherwise.


>> +	/* Switch to the correct the DMA routine and clock frequency. */
>> +	switch (ent->id) {
>> +	case ZORRO_PROD_PHASE5_BLIZZARD_2060: {
>> +		zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz2060_dma_cmd;
>> +		esp->cfreq = 40000000;
> 
> This constant is the same in each case; you might want to lift it out of 
> the switch statement.

It is for the currently supported boards - not sure for CyberstormII and
Fastlane. Will check again, and move that outside the switch if the same
there.

> 
>> +		break;
>> +		}
>> +	case ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260: {
>> +		zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz1230_dma_cmd;
>> +		esp->cfreq = 40000000;
>> +		break;
>> +		}
>> +	case ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM: {
>> +		zorro_esp_ops.send_dma_cmd = zorro_esp_send_cyber_dma_cmd;
>> +		zorro_esp_ops.irq_pending  = cyber_esp_irq_pending;
>> +		esp->cfreq = 40000000;
>> +		break;
>> +		}
>> +	default: {
>> +		/* Oh noes */
>> +		pr_err(PFX "Unsupported board!\n");
> 
> I think you should set err = -ENODEV here.

I'm always returning -ENODEV at present which is clearly wrong, so yes.

>> +		goto fail_free_host;
>> +		}
> 
> Can you remove these pairs of braces?

They're indeed redundant ... copy&paste error.

> 
>> +	}
>> +
>> +	esp->ops = &zorro_esp_ops;
>> +
>> +	if (ioaddr > 0xffffff)
>> +		esp->regs = ioremap_nocache(ioaddr, 0x20);
>> +	else
>> +		esp->regs = (void __iomem *)ZTWO_VADDR(ioaddr);
>> +
>> +	if (!esp->regs)
>> +		goto fail_free_host;
>> +
>> +	/* Let's check whether a Blizzard 12x0 really has SCSI */
>> +	if ((ent->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260) ||
>> +	   (ent->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060)) {
>> +		zorro_esp_write8(esp, (ESP_CONFIG1_PENABLE | 7), ESP_CFG1);
>> +		if (zorro_esp_read8(esp, ESP_CFG1) != (ESP_CONFIG1_PENABLE|7))
>> +			goto fail_free_host;
> 
> goto fail_unmap_regs?

My bad ... of course.

> 
>> +	}
>> +
>> +	if (ioaddr > 0xffffff) {
>> +		// I guess the Fastlane Z3 will be the only one to catch this?
>> +		// Here's a placeholder for now...
>> +		if (ent->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260)
>> +			esp->dma_regs = ioremap_nocache(dmaaddr,
>> +					sizeof(struct blz1230_dma_registers));
>> +	} else
>> +		esp->dma_regs = (void __iomem *)ZTWO_VADDR(dmaaddr);
>> +
>> +	if (!esp->dma_regs)
>> +		goto fail_unmap_regs;
>> +
>> +	esp->command_block = dma_alloc_coherent(esp->dev, 16,
>> +						&esp->command_block_dma,
>> +						GFP_KERNEL);
>> +
>> +	if (!esp->command_block)
>> +		goto fail_unmap_dma_regs;
>> +
>> +	host->irq = IRQ_AMIGA_PORTS;
>> +	err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED,
>> +			  "Amiga Zorro ESP", esp);
>> +	if (err < 0)
>> +		goto fail_free_command_block;
>> +
>> +	/* register the chip */
>> +	err = scsi_esp_register(esp, &z->dev);
>> +
>> +	if (err)
>> +		goto fail_free_irq;
>> +
>> +	zorro_set_drvdata(z, host);
>> +
>> +	zep = ZORRO_ESP_GET_PRIV(esp);
>> +	zep->esp = esp;
>> +
>> +	return 0;
>> +
>> +fail_free_irq:
>> +	free_irq(host->irq, esp);
>> +
>> +fail_free_command_block:
>> +	dma_free_coherent(esp->dev, 16,
>> +			  esp->command_block,
>> +			  esp->command_block_dma);
>> +
>> +fail_unmap_dma_regs:
>> +	if (ioaddr > 0xffffff)
>> +		iounmap(esp->dma_regs);
> 
> I think you need to test for ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260 here?

You're correct there.

>> +
>> +fail_unmap_regs:
>> +	if (ioaddr > 0xffffff)
>> +		iounmap(esp->regs);
>> +
>> +fail_free_host:
>> +	scsi_host_put(host);
>> +
>> +out_free:
>> +	zorro_release_device(z);
>> +
>> +	return -ENODEV;
> 
> return err?

Yep.

>> +}
>> +
>> +static void zorro_esp_remove_one(struct zorro_dev *z)
>> +{
>> +	struct Scsi_Host *host = zorro_get_drvdata(z);
>> +	struct esp *esp	= shost_priv(host);
>> +
>> +	scsi_esp_unregister(esp);
>> +
>> +	/* Disable interrupts. Perhaps use disable_irq instead ... */
>> +
>> +	free_irq(host->irq, esp);
>> +	dma_free_coherent(esp->dev, 16,
>> +			  esp->command_block,
>> +			  esp->command_block_dma);
>> +
>> +	if (host->base > 0xffffff) {
>> +		iounmap(esp->dma_regs);
> 
> Do you need to test for ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260 first?

Indeed!

>> +		iounmap(esp->regs);
>> +		}
> 
> Too much indentation here.

Ouch ...

>> +
>> +	scsi_host_put(host);
>> +
>> +	zorro_release_device(z);
>> +}
>> +
>> +static struct zorro_driver zorro_esp_driver = {
>> +	.name	  = "zorro_esp-scsi",
> 
> Maybe DRV_MODULE_NAME or KBUILD_MODNAME would be more appropriate here?

May as well use that.

> 
>> +	.id_table = zorro_esp_zorro_tbl,
>> +	.probe	  = zorro_esp_init_one,
>> +	.remove	  = zorro_esp_remove_one,
>> +};
>> +
>> +static int __init zorro_esp_scsi_init(void)
>> +{
>> +	return zorro_register_driver(&zorro_esp_driver);
>> +}
>> +
>> +static void __exit zorro_esp_scsi_exit(void)
>> +{
>> +	zorro_unregister_driver(&zorro_esp_driver);
>> +}
>> +
>> +module_init(zorro_esp_scsi_init);
>> +module_exit(zorro_esp_scsi_exit);
>>
> 
> Thanks.

Thanks for reviewing my sloppy work - I'll respin after testing the
changes!

Cheers,

	Michael





[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux