ide: fix host drivers missing hwif->chipset initialization
PATCH 1/9 ide: fix host drivers missing hwif->chipset initialization
ide_find_port() now depends on ->chipset being set for occupied ide_hwifs[] slots so all host drivers have to initialize hwif->chipset properly.
This patch fixes a regression on hosts with > 1 port or with a single port but no devices attached to it for an affected host drivers.
--- drivers/ide/arm/bast-ide.c | 1 + drivers/ide/arm/ide_arm.c | 1 + drivers/ide/ide-pnp.c | 1 + drivers/ide/ide-probe.c | 1 + drivers/ide/legacy/buddha.c | 2 ++ drivers/ide/legacy/falconide.c | 2 ++ drivers/ide/legacy/gayle.c | 2 ++ drivers/ide/legacy/macide.c | 2 ++ drivers/ide/legacy/q40ide.c | 2 ++ drivers/ide/pci/cmd640.c | 2 ++ drivers/ide/ppc/mpc8xx.c | 4 ++++ 11 files changed, 20 insertions(+)
drivers/ide/arm/bast-ide.c +1 -0
@@ -42,6 +42,7 @@ static int __init bastide_register(unsig hw.io_ports.ctl_addr = aux + (6 *0x20 ); hw.irq = irq; + hw.chipset = ide_generic; hwif =ide_find_port ();if (hwif ==NULL )
drivers/ide/arm/ide_arm.c +1 -0
@@ -49,6 +49,7 @@ static int __init ide_arm_init(void)memset (&hw,0 ,sizeof (hw));ide_std_init_ports (&hw, base, ctl); hw.irq =IDE_ARM_IRQ ; + hw.chipset = ide_generic; hwif =ide_find_port ();if (hwif) {
drivers/ide/ide-pnp.c +1 -0
@@ -55,6 +55,7 @@ static int idepnp_probe(struct pnp_dev *memset (&hw,0 ,sizeof (hw));ide_std_init_ports (&hw, base, ctl); hw.irq =pnp_irq (dev,0 ); + hw.chipset = ide_generic; hwif =ide_find_port ();if (hwif) {
drivers/ide/ide-probe.c +1 -0
@@ -1670,6 +1670,7 @@ static void ide_legacy_init_one(u8 *idx,ide_std_init_ports (hw, base, ctl); hw->irq = irq; + hw->chipset = d->chipset; hwif =ide_find_port_slot (d);if (hwif) {
drivers/ide/legacy/buddha.c +2 -0
@@ -138,6 +138,8 @@ static void __init buddha_setup_ports(hw hw->irq =IRQ_AMIGA_PORTS ; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; }/*
drivers/ide/legacy/falconide.c +2 -0
@@ -81,6 +81,8 @@ static void __init falconide_setup_ports hw->irq =IRQ_MFP_IDE ; hw->ack_intr =NULL ; + + hw->chipset = ide_generic; }/*
drivers/ide/legacy/gayle.c +2 -0
@@ -113,6 +113,8 @@ static void __init gayle_setup_ports(hw_ hw->irq =IRQ_AMIGA_PORTS ; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; }/*
drivers/ide/legacy/macide.c +2 -0
@@ -78,6 +78,8 @@ static void __init macide_setup_ports(hw hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const char *mac_ide_name[] =
drivers/ide/legacy/q40ide.c +2 -0
@@ -70,6 +70,8 @@ static void q40_ide_setup_ports(hw_regs_ hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
drivers/ide/pci/cmd640.c +2 -0
@@ -749,9 +749,11 @@ static int __init cmd640x_init(void)ide_std_init_ports (&hw[0 ],0x1f0 ,0x3f6 ); hw[0 ].irq =14 ; + hw[0 ].chipset = ide_cmd640;ide_std_init_ports (&hw[1 ],0x170 ,0x376 ); hw[1 ].irq =15 ; + hw[1 ].chipset = ide_cmd640;printk (KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n" ,'a' + cmd640_chip_version -1 , bus_type, cfr);
drivers/ide/ppc/mpc8xx.c +4 -0
@@ -296,6 +296,8 @@ static int __init m8xx_ide_init_ports(hw pcmp->pcmc_per =0x100000 >> (16 * _slot_);#endif /* CONFIG_IDE_8xx_PCCARD */ + hw->chipset = ide_generic; + return 0; }#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
@@ -370,6 +372,8 @@ static int __init m8xx_ide_init_ports(hw ((immap_t *)IMAP_ADDR )->im_siu_conf.sc_siel |= (0x80000000 >> ioport_dsc[data_port].irq); + hw->chipset = ide_generic; + return 0; }#endif /* CONFIG_IDE_8xx_DIRECT */
PATCH 2/9 ide: set hwif->dev in ide_init_port_hw()
* Add 'parent' field to hw_regs_t for optional parent device pointer (needed by macio PMAC IDE controllers) and set hwif->dev in ide_init_port_hw().
* Update au1xxx-ide.c, sgiioc4.c, pmac.c and setup-pci.c accordingly.
There should be no functional changes caused by this patch.
--- drivers/ide/ide.c | 3 ++- drivers/ide/mips/au1xxx-ide.c | 2 -- drivers/ide/pci/sgiioc4.c | 2 -- drivers/ide/ppc/pmac.c | 6 ++---- drivers/ide/setup-pci.c | 2 -- include/linux/ide.h | 2 +- 6 files changed, 5 insertions(+), 12 deletions(-)
drivers/ide/ide.c +2 -1
@@ -297,7 +297,8 @@ void ide_init_port_hw(ide_hwif_t *hwif,memcpy (&hwif->io_ports, &hw->io_ports,sizeof (hwif->io_ports)); hwif->irq = hw->irq; hwif->chipset = hw->chipset; - hwif->gendev.parent = hw->dev; + hwif->dev = hw->dev; + hwif->gendev.parent = hw->parent ? hw->parent : hw->dev; hwif->ack_intr = hw->ack_intr; }EXPORT_SYMBOL_GPL (ide_init_port_hw);
drivers/ide/mips/au1xxx-ide.c +0 -2
@@ -600,8 +600,6 @@ static int au_ide_probe(struct device *dide_init_port_hw (hwif, &hw); - hwif->dev = dev; -/* If the user has selected DDMA assisted copies, then set up a few local I/O function entry points */
drivers/ide/pci/sgiioc4.c +0 -2
@@ -625,8 +625,6 @@ sgiioc4_ide_setup_pci_device(struct pci_ hw.dev = &dev->dev;ide_init_port_hw (hwif, &hw); - hwif->dev = &dev->dev; -/* The IOC4 uses MMIO rather than Port IO. */ default_hwif_mmiops (hwif);
drivers/ide/ppc/pmac.c +2 -4
@@ -1144,8 +1144,6 @@ pmac_ide_macio_attach(struct macio_dev * base =ioremap (macio_resource_start (mdev,0 ),0x400 ); regbase = (unsigned long ) base; - hwif->dev = &mdev->bus->pdev->dev; - pmif->mdev = mdev; pmif->node = mdev->ofdev.node; pmif->regbase = regbase;
@@ -1167,7 +1165,8 @@ pmac_ide_macio_attach(struct macio_dev *memset (&hw,0 ,sizeof (hw));pmac_ide_init_ports (&hw, pmif->regbase); hw.irq = irq; - hw.dev = &mdev->ofdev.dev; + hw.dev = &mdev->bus->pdev->dev; + hw.parent = &mdev->ofdev.dev; rc =pmac_ide_setup_device (pmif, hwif, &hw);if (rc !=0 ) {
@@ -1267,7 +1266,6 @@ pmac_ide_pci_attach(struct pci_dev *pdev goto out_free_pmif; } - hwif->dev = &pdev->dev; pmif->mdev =NULL ; pmif->node = np;
drivers/ide/setup-pci.c +0 -2
@@ -346,8 +346,6 @@ static ide_hwif_t *ide_hwif_configure(stide_init_port_hw (hwif, &hw); - hwif->dev = &dev->dev; -return hwif; }
include/linux/ide.h +1 -1
@@ -171,7 +171,7 @@ typedef struct hw_regs_s {int irq;/* our irq number */ ide_ack_intr_t *ack_intr;/* acknowledge interrupt */ hwif_chipset_t chipset; -struct device *dev; +struct device *dev, *parent; } hw_regs_t;void ide_init_port_data (struct hwif_s *,unsigned int );
PATCH 3/9 delkin_cb: set proper hwif->gendev.parent value
In reply to Bartlomiej Zolnierkiewiczhwif->dev was set too late (after ide_device_add() call) so hwif->gendev.parent was not initialized properly.
Fix it by setting hw.dev and letting ide_init_port_hw() do the rest.
--- drivers/ide/pci/delkin_cb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/ide/pci/delkin_cb.c +2 -1
@@ -79,6 +79,7 @@ delkin_cb_probe (struct pci_dev *dev, comemset (&hw,0 ,sizeof (hw));ide_std_init_ports (&hw, base +0x10 , base +0x1e ); hw.irq = dev->irq; + hw.dev = &dev->dev; hw.chipset = ide_pci;/* this enables IRQ sharing */ hwif =ide_find_port ();
@@ -98,7 +99,7 @@ delkin_cb_probe (struct pci_dev *dev, co goto out_disable;pci_set_drvdata (dev, hwif); - hwif->dev = &dev->dev; + drive = &hwif->drives[0 ];if (drive->present) { drive->io_32bit =1 ;
Re: [PATCH 3/9] delkin_cb: set proper hwif->gendev.parent value
Hello.
Quoted 7 lines · Bartlomiej Zolnierkiewicz
hwif->devwas set too late (afteride_device_add()call) sohwif->gendev.parentwas not initialized properly.Fix it by setting hw.dev and letting
ide_init_port_hw()do the rest.Signed-off-by Bartlomiej Zolnierkiewicz <[email protected]>
MBR, Sergei
PATCH 4/9 delkin_cb: use struct ide_port_info
In reply to Bartlomiej ZolnierkiewiczConvert the driver to use struct ide_port_info - as a nice side-effect this fixes racy setup of ->io_32bit/unmask settings (after ide_device_add() call device can be already in use).
--- drivers/ide/pci/delkin_cb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
drivers/ide/pci/delkin_cb.c +7 -8
@@ -47,13 +47,18 @@ static const struct ide_port_ops delkin_ .quirkproc = ide_undecoded_slave, }; +static const struct ide_port_info delkin_cb_port_info = { + .port_ops = &delkin_cb_port_ops, + .host_flags =IDE_HFLAG_IO_32BIT |IDE_HFLAG_UNMASK_IRQS | +IDE_HFLAG_NO_DMA , +}; +static int __devinit delkin_cb_probe (struct pci_dev *dev,const struct pci_device_id *id) {unsigned long base;hw_regs_t hw;ide_hwif_t *hwif =NULL ; -ide_drive_t *drive;int i, rc;u8 idx[4 ] = {0xff ,0xff ,0xff ,0xff };
@@ -89,22 +94,16 @@ delkin_cb_probe (struct pci_dev *dev, co i = hwif->index;ide_init_port_hw (hwif, &hw); - hwif->port_ops = &delkin_cb_port_ops; idx[0 ] = i; -ide_device_add (idx,NULL ); +ide_device_add (idx, &delkin_cb_port_info);if (!hwif->present) goto out_disable;pci_set_drvdata (dev, hwif); - drive = &hwif->drives[0 ]; -if (drive->present) { - drive->io_32bit =1 ; - drive->unmask =1 ; - }return 0 ; out_disable:
PATCH 5/9 delkin_cb: add warm-plug support
In reply to Bartlomiej ZolnierkiewiczDon't fail the probe if there are no devices attached to the controller.
--- drivers/ide/pci/delkin_cb.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/ide/pci/delkin_cb.c +0 -4
@@ -99,15 +99,11 @@ delkin_cb_probe (struct pci_dev *dev, coide_device_add (idx, &delkin_cb_port_info); -if (!hwif->present) - goto out_disable; -pci_set_drvdata (dev, hwif);return 0 ; out_disable: -printk (KERN_ERR "delkin_cb: no IDE devices found\n" );pci_release_regions (dev);pci_disable_device (dev);return -ENODEV ;
PATCH 6/9 delkin_cb: add missing __init/__exit tags
In reply to Bartlomiej Zolnierkiewicz--- drivers/ide/pci/delkin_cb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/ide/pci/delkin_cb.c +2 -4
@@ -134,14 +134,12 @@ static struct pci_driver driver = { .remove = delkin_cb_remove, }; -static int -delkin_cb_init (void ) +static int __init delkin_cb_init (void ) {return pci_register_driver (&driver); } -static void -delkin_cb_exit (void ) +static void __exit delkin_cb_exit(void) {pci_unregister_driver (&driver); }
Re: [PATCH 6/9] delkin_cb: add missing __init/__exit tags
Quoted 2 lines · Bartlomiej Zolnierkiewicz
Signed-off-by Bartlomiej Zolnierkiewicz <[email protected]>
MBR, Sergei
PATCH 7/9 au1xxx-ide: don't use hwif->hwif_data
In reply to Bartlomiej Zolnierkiewicz* Use &auide_hwif directly instead of using hwif->hwif_data.
While at it:
* No need to initialize hwif->{select,config}_data.
There should be no functional changes caused by this patch.
--- drivers/ide/mips/au1xxx-ide.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
drivers/ide/mips/au1xxx-ide.c +3 -8
@@ -213,10 +213,8 @@ static int auide_build_dmatable(ide_driv {int i, iswrite, count =0 ;ide_hwif_t *hwif =HWIF (drive); -struct request *rq =HWGROUP (drive)->rq; - -_auide_hwif *ahwif = (_auide_hwif *)hwif->hwif_data; +_auide_hwif *ahwif = &auide_hwif;struct scatterlist *sg; iswrite = (rq_data_dir (rq) ==WRITE );
@@ -402,7 +400,7 @@ static const struct ide_dma_ops au1xxx_dstatic int auide_ddma_init (ide_hwif_t *hwif,const struct ide_port_info *d) { -_auide_hwif *auide = (_auide_hwif *)hwif->hwif_data; +_auide_hwif *auide = &auide_hwif;dbdev_tab_t source_dev_tab, target_dev_tab;u32 dev_id, tsize, devwidth, flags;
@@ -463,7 +461,7 @@ static int auide_ddma_init(ide_hwif_t *h#else static int auide_ddma_init (ide_hwif_t *hwif,const struct ide_port_info *d) { -_auide_hwif *auide = (_auide_hwif *)hwif->hwif_data; +_auide_hwif *auide = &auide_hwif;dbdev_tab_t source_dev_tab;int flags;
@@ -608,11 +606,8 @@ static int au_ide_probe(struct device *d hwif->input_data = au1xxx_input_data; hwif->output_data = au1xxx_output_data;#endif - hwif->select_data =0 ;/* no chipset-specific code */ - hwif->config_data =0 ;/* no chipset-specific code */ auide_hwif.hwif = hwif; - hwif->hwif_data = &auide_hwif; idx[0 ] = hwif->index;
Re: [PATCH 7/9] au1xxx-ide: don't use hwif->hwif_data
Quoted 10 lines · Bartlomiej Zolnierkiewicz
* Use
&auide_hwifdirectly instead of usinghwif->hwif_data.While at it:
* No need to initialize hwif->{select,config}_data.
There should be no functional changes caused by this patch.
Signed-off-by Bartlomiej Zolnierkiewicz <[email protected]>
MBR, Sergei
PATCH 8/9 ide_4drives: use struct ide_port_info
In reply to Bartlomiej ZolnierkiewiczConvert the driver to use struct ide_port_info - as a nice side-effect this fixes hwif->channel initialization.
--- drivers/ide/legacy/ide-4drives.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
drivers/ide/legacy/ide-4drives.c +18 -9
@@ -11,6 +11,23 @@ static int probe_4drives;module_param_named (probe, probe_4drives, bool,0 );MODULE_PARM_DESC (probe,"probe for generic IDE chipset with 4 drives/port" ); +static void ide_4drives_port_init_devs (ide_hwif_t *hwif) +{ +if (hwif->channel) { + hwif->drives[0 ].select.all ^=0x20 ; + hwif->drives[1 ].select.all ^=0x20 ; + } +} + +static const struct ide_port_ops ide_4drives_port_ops = { + .port_init_devs = ide_4drives_port_init_devs, +}; + +static const struct ide_port_info ide_4drives_port_info = { + .port_ops = &ide_4drives_port_ops, + .host_flags =IDE_HFLAG_SERIALIZE |IDE_HFLAG_NO_DMA , +}; +static int __init ide_4drives_init (void ) {ide_hwif_t *hwif, *mate;
@@ -49,18 +66,10 @@ static int __init ide_4drives_init(void) mate =ide_find_port ();if (mate) {ide_init_port_hw (mate, &hw); - mate->drives[0 ].select.all ^=0x20 ; - mate->drives[1 ].select.all ^=0x20 ; idx[1 ] = mate->index; - -if (hwif) { - hwif->mate = mate; - mate->mate = hwif; - hwif->serialized = mate->serialized =1 ; - } } -ide_device_add (idx,NULL ); +ide_device_add (idx, &ide_4drives_port_info);return 0 ; }
PATCH 9/9 ide-cs: use struct ide_port_info
In reply to Bartlomiej ZolnierkiewiczConvert the driver to use struct ide_port_info.
There should be no functional changes caused by this patch.
--- drivers/ide/legacy/ide-cs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/ide/legacy/ide-cs.c +6 -2
@@ -150,6 +150,11 @@ static const struct ide_port_ops idecs_p .quirkproc = ide_undecoded_slave, }; +static const struct ide_port_info idecs_port_info = { + .port_ops = &idecs_port_ops, + .host_flags =IDE_HFLAG_NO_DMA , +}; +static ide_hwif_t *idecs_register (unsigned long io,unsigned long ctl,unsigned long irq,struct pcmcia_device *handle) {
@@ -184,11 +189,10 @@ static ide_hwif_t *idecs_register(unsign i = hwif->index;ide_init_port_hw (hwif, &hw); - hwif->port_ops = &idecs_port_ops; idx[0 ] = i; -ide_device_add (idx,NULL ); +ide_device_add (idx, &idecs_port_info);if (hwif->present)return hwif;