* [PATCH 1/3] [IDE] Add helper __ide_setup_pci_device() [not found] <09821349085390234lkjasdflkjasflkdj24746@havoc.gtf.org> @ 2007-10-24 23:48 ` Jeff Garzik 2007-10-25 19:33 ` Bartlomiej Zolnierkiewicz 2007-10-24 23:48 ` [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop Jeff Garzik 2007-10-24 23:48 ` [PATCH 3/3] drivers/ide/pci/sc1200.c: fix suspend/resume buglets and warnings Jeff Garzik 2 siblings, 1 reply; 8+ messages in thread From: Jeff Garzik @ 2007-10-24 23:48 UTC (permalink / raw) To: LKML, linux-ide; +Cc: akpm Like ide_setup_pci_device(), except with additional array argument 'u8 *idx' that permits low-level driver to become aware of its assigned hwifs. Signed-off-by: Jeff Garzik <jgarzik@redhat.com> --- drivers/ide/setup-pci.c | 17 ++++++++++++----- include/linux/ide.h | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 02d14bf..4960b9f 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -666,12 +666,10 @@ out: return ret; } -int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) +int __ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d, + u8 *idx) { - u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; - int ret; - - ret = do_ide_setup_pci_device(dev, d, &idx[0], 1); + int ret = do_ide_setup_pci_device(dev, d, idx, 1); if (ret >= 0) ide_device_add(idx); @@ -679,6 +677,15 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) return ret; } +EXPORT_SYMBOL_GPL(__ide_setup_pci_device); + +int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) +{ + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + + return __ide_setup_pci_device(dev, d, &idx[0]); +} + EXPORT_SYMBOL_GPL(ide_setup_pci_device); int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, diff --git a/include/linux/ide.h b/include/linux/ide.h index 4ed4777..3404fb9 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1244,6 +1244,7 @@ struct ide_port_info { u8 udma_mask; }; +int __ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *, u8 *); int ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *); int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, const struct ide_port_info *); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] [IDE] Add helper __ide_setup_pci_device() 2007-10-24 23:48 ` [PATCH 1/3] [IDE] Add helper __ide_setup_pci_device() Jeff Garzik @ 2007-10-25 19:33 ` Bartlomiej Zolnierkiewicz 0 siblings, 0 replies; 8+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2007-10-25 19:33 UTC (permalink / raw) To: Jeff Garzik; +Cc: LKML, linux-ide, akpm [ The last few days were extra busy with pushing previously queued IDE bits upstream but I'm back to reviewing the new stuff. ] Thanks for splitting your patch on smaller chunks. On Thursday 25 October 2007, Jeff Garzik wrote: > Like ide_setup_pci_device(), except with additional array argument > 'u8 *idx' that permits low-level driver to become aware of its assigned > hwifs. I would prefer to avoid exporting this information to host drivers if possible (they shouldn't need to know about higher-layer decisions, plus this change opens the door for various "creative" abuses). In case of sc1200 host driver fixes (patches #2-3/3) it should be possible to remove the need for the below patch and at the same time simplify sc1200 code further (more details in review of patch #2/2). > Signed-off-by: Jeff Garzik <jgarzik@redhat.com> > --- > drivers/ide/setup-pci.c | 17 ++++++++++++----- > include/linux/ide.h | 1 + > 2 files changed, 13 insertions(+), 5 deletions(-) > > diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c > index 02d14bf..4960b9f 100644 > --- a/drivers/ide/setup-pci.c > +++ b/drivers/ide/setup-pci.c > @@ -666,12 +666,10 @@ out: > return ret; > } > > -int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) > +int __ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d, > + u8 *idx) > { > - u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; > - int ret; > - > - ret = do_ide_setup_pci_device(dev, d, &idx[0], 1); > + int ret = do_ide_setup_pci_device(dev, d, idx, 1); > > if (ret >= 0) > ide_device_add(idx); > @@ -679,6 +677,15 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) > return ret; > } > > +EXPORT_SYMBOL_GPL(__ide_setup_pci_device); > + > +int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) > +{ > + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; > + > + return __ide_setup_pci_device(dev, d, &idx[0]); > +} > + > EXPORT_SYMBOL_GPL(ide_setup_pci_device); > > int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, > diff --git a/include/linux/ide.h b/include/linux/ide.h > index 4ed4777..3404fb9 100644 > --- a/include/linux/ide.h > +++ b/include/linux/ide.h > @@ -1244,6 +1244,7 @@ struct ide_port_info { > u8 udma_mask; > }; > > +int __ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *, u8 *); > int ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *); > int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, const struct ide_port_info *); ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop [not found] <09821349085390234lkjasdflkjasflkdj24746@havoc.gtf.org> 2007-10-24 23:48 ` [PATCH 1/3] [IDE] Add helper __ide_setup_pci_device() Jeff Garzik @ 2007-10-24 23:48 ` Jeff Garzik 2007-10-25 20:01 ` Bartlomiej Zolnierkiewicz 2007-10-24 23:48 ` [PATCH 3/3] drivers/ide/pci/sc1200.c: fix suspend/resume buglets and warnings Jeff Garzik 2 siblings, 1 reply; 8+ messages in thread From: Jeff Garzik @ 2007-10-24 23:48 UTC (permalink / raw) To: LKML, linux-ide; +Cc: akpm Store our hwif indices at probe time, in order to eliminate a needless and ugly loop across all hwifs, searching for our pci device. Signed-off-by: Jeff Garzik <jgarzik@redhat.com> --- drivers/ide/pci/sc1200.c | 76 +++++++++++++++++++++++++++++++--------------- 1 files changed, 51 insertions(+), 25 deletions(-) diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index d2c8b55..17e58d6 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -41,6 +41,8 @@ #define PCI_CLK_66 0x02 #define PCI_CLK_33A 0x03 +#define SC1200_IFS 4 + static unsigned short sc1200_get_pci_clock (void) { unsigned char chip_id, silicon_revision; @@ -261,31 +263,32 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) } #ifdef CONFIG_PM -static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) -{ - int h; - - for (h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if (prev) { - if (hwif == prev) - prev = NULL; // found previous, now look for next match - } else { - if (hwif && hwif->pci_dev == dev) - return hwif; // found next match - } - } - return NULL; // not found -} - typedef struct sc1200_saved_state_s { __u32 regs[4]; } sc1200_saved_state_t; +static unsigned int pack_hwif_idx(u8 *idx) +{ + return (((unsigned int) idx[0]) << 0) | + (((unsigned int) idx[1]) << 8) | + (((unsigned int) idx[2]) << 16) | + (((unsigned int) idx[3]) << 24); +} + +static ide_hwif_t *sc1200_hwif(struct pci_dev *pdev, unsigned int iface) +{ + unsigned int packed_hwifs, idx; + + packed_hwifs = (unsigned long) pci_get_drvdata(pdev); + idx = (packed_hwifs >> (iface * 8)) & 0xff; + + return (idx == 0xff) ? NULL : &ide_hwifs[idx]; +} static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) { - ide_hwif_t *hwif = NULL; + ide_hwif_t *hwif; + int i; printk("SC1200: suspend(%u)\n", state.event); @@ -295,9 +298,14 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) // // Loop over all interfaces that are part of this PCI device: // - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + for (i = 0; i < SC1200_IFS; i++) { sc1200_saved_state_t *ss; unsigned int basereg, r; + + hwif = sc1200_hwif(dev, i); + if (!hwif) + continue; + // // allocate a permanent save area, if not already allocated // @@ -310,7 +318,7 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) } ss = (sc1200_saved_state_t *)hwif->config_data; // - // Save timing registers: this may be unnecessary if + // Save timing registers: this may be unnecessary if // BIOS also does it // basereg = hwif->channel ? 0x50 : 0x40; @@ -320,7 +328,7 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) } } - /* You don't need to iterate over disks -- sysfs should have done that for you already */ + /* You don't need to iterate over disks -- sysfs should have done that for you already */ pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); @@ -330,7 +338,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) static int sc1200_resume (struct pci_dev *dev) { - ide_hwif_t *hwif = NULL; + ide_hwif_t *hwif; + int i; pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state dev->current_state = PM_EVENT_ON; @@ -338,9 +347,15 @@ static int sc1200_resume (struct pci_dev *dev) // // loop over all interfaces that are part of this pci device: // - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + for (i = 0; i < SC1200_IFS; i++) { unsigned int basereg, r; - sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; + sc1200_saved_state_t *ss; + + hwif = sc1200_hwif(dev, i); + if (!hwif) + continue; + + ss = (sc1200_saved_state_t *)hwif->config_data; // // Restore timing registers: this may be unnecessary if BIOS also does it @@ -386,7 +401,18 @@ static const struct ide_port_info sc1200_chipset __devinitdata = { static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_setup_pci_device(dev, &sc1200_chipset); + unsigned int packed_hwifs; + int rc; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + + rc = __ide_setup_pci_device(dev, &sc1200_chipset, &idx[0]); + if (rc) + return rc; + + packed_hwifs = pack_hwif_idx(&idx[0]); + + pci_set_drvdata(dev, (void *)(unsigned long) packed_hwifs); + return 0; } static const struct pci_device_id sc1200_pci_tbl[] = { -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop 2007-10-24 23:48 ` [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop Jeff Garzik @ 2007-10-25 20:01 ` Bartlomiej Zolnierkiewicz 2007-10-26 1:25 ` Jeff Garzik 0 siblings, 1 reply; 8+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2007-10-25 20:01 UTC (permalink / raw) To: Jeff Garzik; +Cc: LKML, linux-ide, akpm On Thursday 25 October 2007, Jeff Garzik wrote: > Store our hwif indices at probe time, in order to eliminate a needless > and ugly loop across all hwifs, searching for our pci device. It seems that we can simplify it even further and remove knowledge about hwifs altogether from suspend/resume methods. > Signed-off-by: Jeff Garzik <jgarzik@redhat.com> > --- > drivers/ide/pci/sc1200.c | 76 +++++++++++++++++++++++++++++++--------------- > 1 files changed, 51 insertions(+), 25 deletions(-) > > diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c > index d2c8b55..17e58d6 100644 > --- a/drivers/ide/pci/sc1200.c > +++ b/drivers/ide/pci/sc1200.c > @@ -41,6 +41,8 @@ > #define PCI_CLK_66 0x02 > #define PCI_CLK_33A 0x03 > > +#define SC1200_IFS 4 > + > static unsigned short sc1200_get_pci_clock (void) > { > unsigned char chip_id, silicon_revision; > @@ -261,31 +263,32 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) > } > > #ifdef CONFIG_PM > -static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) > -{ > - int h; > - > - for (h = 0; h < MAX_HWIFS; h++) { > - ide_hwif_t *hwif = &ide_hwifs[h]; > - if (prev) { > - if (hwif == prev) > - prev = NULL; // found previous, now look for next match > - } else { > - if (hwif && hwif->pci_dev == dev) > - return hwif; // found next match > - } > - } > - return NULL; // not found > -} > - > typedef struct sc1200_saved_state_s { > __u32 regs[4]; > } sc1200_saved_state_t; > > +static unsigned int pack_hwif_idx(u8 *idx) > +{ > + return (((unsigned int) idx[0]) << 0) | > + (((unsigned int) idx[1]) << 8) | > + (((unsigned int) idx[2]) << 16) | > + (((unsigned int) idx[3]) << 24); > +} > + > +static ide_hwif_t *sc1200_hwif(struct pci_dev *pdev, unsigned int iface) > +{ > + unsigned int packed_hwifs, idx; > + > + packed_hwifs = (unsigned long) pci_get_drvdata(pdev); > + idx = (packed_hwifs >> (iface * 8)) & 0xff; > + > + return (idx == 0xff) ? NULL : &ide_hwifs[idx]; > +} > > static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > { > - ide_hwif_t *hwif = NULL; > + ide_hwif_t *hwif; > + int i; > > printk("SC1200: suspend(%u)\n", state.event); > > @@ -295,9 +298,14 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > // > // Loop over all interfaces that are part of this PCI device: > // > - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { > + for (i = 0; i < SC1200_IFS; i++) { > sc1200_saved_state_t *ss; > unsigned int basereg, r; > + > + hwif = sc1200_hwif(dev, i); > + if (!hwif) > + continue; > + > // > // allocate a permanent save area, if not already allocated > // > @@ -310,7 +318,7 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > } > ss = (sc1200_saved_state_t *)hwif->config_data; > // > - // Save timing registers: this may be unnecessary if > + // Save timing registers: this may be unnecessary if > // BIOS also does it > // > basereg = hwif->channel ? 0x50 : 0x40; Please take a close look at the line above and the next three lines: for (r = 0; r < 4; ++r) { pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); } It is highly obfuscated but the sc1200_suspend() reads 16 bytes from the offset 0x40 (for the primary port) and puts them in the corresponding struct sc1200_saved_state_s buffer, then it reads another 16 bytes from the offset 0x50 (for the secondary port) and puts it in the another buffer. In summary sc1200_suspend() reads 32 continuous bytes from offset 0x40 and the exactly reverse operation happens in sc1200_resume(). Given that and the fact that struct sc1200_save_state_s buffers are used _only_ by sc1200_{suspend,resume}() we may safely convert the code to use one buffer for both ports (the whole PCI device). We just need to bump the size of struct sc1200_saved_state_s (from 4 to 8 double-words) and use pci_{get,set}_drvdata() instead of hwif->config_data. Then we can remove looping over interfaces completely from sc1200_{suspend,resume}()! :) > @@ -320,7 +328,7 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > } > } > > - /* You don't need to iterate over disks -- sysfs should have done that for you already */ > + /* You don't need to iterate over disks -- sysfs should have done that for you already */ > > pci_disable_device(dev); > pci_set_power_state(dev, pci_choose_state(dev, state)); > @@ -330,7 +338,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > > static int sc1200_resume (struct pci_dev *dev) > { > - ide_hwif_t *hwif = NULL; > + ide_hwif_t *hwif; > + int i; > > pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state > dev->current_state = PM_EVENT_ON; > @@ -338,9 +347,15 @@ static int sc1200_resume (struct pci_dev *dev) > // > // loop over all interfaces that are part of this pci device: > // > - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { > + for (i = 0; i < SC1200_IFS; i++) { > unsigned int basereg, r; > - sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; > + sc1200_saved_state_t *ss; > + > + hwif = sc1200_hwif(dev, i); > + if (!hwif) > + continue; > + > + ss = (sc1200_saved_state_t *)hwif->config_data; > > // > // Restore timing registers: this may be unnecessary if BIOS also does it > @@ -386,7 +401,18 @@ static const struct ide_port_info sc1200_chipset __devinitdata = { > > static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) > { > - return ide_setup_pci_device(dev, &sc1200_chipset); > + unsigned int packed_hwifs; > + int rc; > + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; > + > + rc = __ide_setup_pci_device(dev, &sc1200_chipset, &idx[0]); > + if (rc) > + return rc; > + > + packed_hwifs = pack_hwif_idx(&idx[0]); > + > + pci_set_drvdata(dev, (void *)(unsigned long) packed_hwifs); > + return 0; > } > > static const struct pci_device_id sc1200_pci_tbl[] = { ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop 2007-10-25 20:01 ` Bartlomiej Zolnierkiewicz @ 2007-10-26 1:25 ` Jeff Garzik 2007-10-31 21:53 ` Bartlomiej Zolnierkiewicz 0 siblings, 1 reply; 8+ messages in thread From: Jeff Garzik @ 2007-10-26 1:25 UTC (permalink / raw) To: Bartlomiej Zolnierkiewicz; +Cc: LKML, linux-ide, akpm Bartlomiej Zolnierkiewicz wrote: > On Thursday 25 October 2007, Jeff Garzik wrote: >> Store our hwif indices at probe time, in order to eliminate a needless >> and ugly loop across all hwifs, searching for our pci device. > > It seems that we can simplify it even further and remove knowledge about > hwifs altogether from suspend/resume methods. > >> Signed-off-by: Jeff Garzik <jgarzik@redhat.com> >> --- >> drivers/ide/pci/sc1200.c | 76 +++++++++++++++++++++++++++++++--------------- >> 1 files changed, 51 insertions(+), 25 deletions(-) >> >> diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c >> index d2c8b55..17e58d6 100644 >> --- a/drivers/ide/pci/sc1200.c >> +++ b/drivers/ide/pci/sc1200.c >> @@ -41,6 +41,8 @@ >> #define PCI_CLK_66 0x02 >> #define PCI_CLK_33A 0x03 >> >> +#define SC1200_IFS 4 >> + >> static unsigned short sc1200_get_pci_clock (void) >> { >> unsigned char chip_id, silicon_revision; >> @@ -261,31 +263,32 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) >> } >> >> #ifdef CONFIG_PM >> -static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) >> -{ >> - int h; >> - >> - for (h = 0; h < MAX_HWIFS; h++) { >> - ide_hwif_t *hwif = &ide_hwifs[h]; >> - if (prev) { >> - if (hwif == prev) >> - prev = NULL; // found previous, now look for next match >> - } else { >> - if (hwif && hwif->pci_dev == dev) >> - return hwif; // found next match >> - } >> - } >> - return NULL; // not found >> -} >> - >> typedef struct sc1200_saved_state_s { >> __u32 regs[4]; >> } sc1200_saved_state_t; >> >> +static unsigned int pack_hwif_idx(u8 *idx) >> +{ >> + return (((unsigned int) idx[0]) << 0) | >> + (((unsigned int) idx[1]) << 8) | >> + (((unsigned int) idx[2]) << 16) | >> + (((unsigned int) idx[3]) << 24); >> +} >> + >> +static ide_hwif_t *sc1200_hwif(struct pci_dev *pdev, unsigned int iface) >> +{ >> + unsigned int packed_hwifs, idx; >> + >> + packed_hwifs = (unsigned long) pci_get_drvdata(pdev); >> + idx = (packed_hwifs >> (iface * 8)) & 0xff; >> + >> + return (idx == 0xff) ? NULL : &ide_hwifs[idx]; >> +} >> >> static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) >> { >> - ide_hwif_t *hwif = NULL; >> + ide_hwif_t *hwif; >> + int i; >> >> printk("SC1200: suspend(%u)\n", state.event); >> >> @@ -295,9 +298,14 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) >> // >> // Loop over all interfaces that are part of this PCI device: >> // >> - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { >> + for (i = 0; i < SC1200_IFS; i++) { >> sc1200_saved_state_t *ss; >> unsigned int basereg, r; >> + >> + hwif = sc1200_hwif(dev, i); >> + if (!hwif) >> + continue; >> + >> // >> // allocate a permanent save area, if not already allocated >> // >> @@ -310,7 +318,7 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) >> } >> ss = (sc1200_saved_state_t *)hwif->config_data; >> // >> - // Save timing registers: this may be unnecessary if >> + // Save timing registers: this may be unnecessary if >> // BIOS also does it >> // >> basereg = hwif->channel ? 0x50 : 0x40; > > Please take a close look at the line above and the next three lines: > > for (r = 0; r < 4; ++r) { > pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); > } > > It is highly obfuscated but the sc1200_suspend() reads 16 bytes from > the offset 0x40 (for the primary port) and puts them in the corresponding > struct sc1200_saved_state_s buffer, then it reads another 16 bytes from the > offset 0x50 (for the secondary port) and puts it in the another buffer. > > In summary sc1200_suspend() reads 32 continuous bytes from offset 0x40 > and the exactly reverse operation happens in sc1200_resume(). > > Given that and the fact that struct sc1200_save_state_s buffers are used > _only_ by sc1200_{suspend,resume}() we may safely convert the code to use > one buffer for both ports (the whole PCI device). We just need to bump > the size of struct sc1200_saved_state_s (from 4 to 8 double-words) and use > pci_{get,set}_drvdata() instead of hwif->config_data. Then we can remove > looping over interfaces completely from sc1200_{suspend,resume}()! :) May I assume you'll handle that task? :) It sounds like you have a far better idea than mine, and my main goal -- fixing bugs and warning -- is accomplished anyway with the merging of patch #3. Jeff ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop 2007-10-26 1:25 ` Jeff Garzik @ 2007-10-31 21:53 ` Bartlomiej Zolnierkiewicz 0 siblings, 0 replies; 8+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2007-10-31 21:53 UTC (permalink / raw) To: Jeff Garzik; +Cc: LKML, linux-ide, akpm On Friday 26 October 2007, Jeff Garzik wrote: > Bartlomiej Zolnierkiewicz wrote: > > On Thursday 25 October 2007, Jeff Garzik wrote: > >> Store our hwif indices at probe time, in order to eliminate a needless > >> and ugly loop across all hwifs, searching for our pci device. > > > > It seems that we can simplify it even further and remove knowledge about > > hwifs altogether from suspend/resume methods. > > > >> Signed-off-by: Jeff Garzik <jgarzik@redhat.com> > >> --- > >> drivers/ide/pci/sc1200.c | 76 +++++++++++++++++++++++++++++++--------------- > >> 1 files changed, 51 insertions(+), 25 deletions(-) > >> > >> diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c > >> index d2c8b55..17e58d6 100644 > >> --- a/drivers/ide/pci/sc1200.c > >> +++ b/drivers/ide/pci/sc1200.c > >> @@ -41,6 +41,8 @@ > >> #define PCI_CLK_66 0x02 > >> #define PCI_CLK_33A 0x03 > >> > >> +#define SC1200_IFS 4 > >> + > >> static unsigned short sc1200_get_pci_clock (void) > >> { > >> unsigned char chip_id, silicon_revision; > >> @@ -261,31 +263,32 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) > >> } > >> > >> #ifdef CONFIG_PM > >> -static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) > >> -{ > >> - int h; > >> - > >> - for (h = 0; h < MAX_HWIFS; h++) { > >> - ide_hwif_t *hwif = &ide_hwifs[h]; > >> - if (prev) { > >> - if (hwif == prev) > >> - prev = NULL; // found previous, now look for next match > >> - } else { > >> - if (hwif && hwif->pci_dev == dev) > >> - return hwif; // found next match > >> - } > >> - } > >> - return NULL; // not found > >> -} > >> - > >> typedef struct sc1200_saved_state_s { > >> __u32 regs[4]; > >> } sc1200_saved_state_t; > >> > >> +static unsigned int pack_hwif_idx(u8 *idx) > >> +{ > >> + return (((unsigned int) idx[0]) << 0) | > >> + (((unsigned int) idx[1]) << 8) | > >> + (((unsigned int) idx[2]) << 16) | > >> + (((unsigned int) idx[3]) << 24); > >> +} > >> + > >> +static ide_hwif_t *sc1200_hwif(struct pci_dev *pdev, unsigned int iface) > >> +{ > >> + unsigned int packed_hwifs, idx; > >> + > >> + packed_hwifs = (unsigned long) pci_get_drvdata(pdev); > >> + idx = (packed_hwifs >> (iface * 8)) & 0xff; > >> + > >> + return (idx == 0xff) ? NULL : &ide_hwifs[idx]; > >> +} > >> > >> static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > >> { > >> - ide_hwif_t *hwif = NULL; > >> + ide_hwif_t *hwif; > >> + int i; > >> > >> printk("SC1200: suspend(%u)\n", state.event); > >> > >> @@ -295,9 +298,14 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > >> // > >> // Loop over all interfaces that are part of this PCI device: > >> // > >> - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { > >> + for (i = 0; i < SC1200_IFS; i++) { > >> sc1200_saved_state_t *ss; > >> unsigned int basereg, r; > >> + > >> + hwif = sc1200_hwif(dev, i); > >> + if (!hwif) > >> + continue; > >> + > >> // > >> // allocate a permanent save area, if not already allocated > >> // > >> @@ -310,7 +318,7 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) > >> } > >> ss = (sc1200_saved_state_t *)hwif->config_data; > >> // > >> - // Save timing registers: this may be unnecessary if > >> + // Save timing registers: this may be unnecessary if > >> // BIOS also does it > >> // > >> basereg = hwif->channel ? 0x50 : 0x40; > > > > Please take a close look at the line above and the next three lines: > > > > for (r = 0; r < 4; ++r) { > > pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); > > } > > > > It is highly obfuscated but the sc1200_suspend() reads 16 bytes from > > the offset 0x40 (for the primary port) and puts them in the corresponding > > struct sc1200_saved_state_s buffer, then it reads another 16 bytes from the > > offset 0x50 (for the secondary port) and puts it in the another buffer. > > > > In summary sc1200_suspend() reads 32 continuous bytes from offset 0x40 > > and the exactly reverse operation happens in sc1200_resume(). > > > > Given that and the fact that struct sc1200_save_state_s buffers are used > > _only_ by sc1200_{suspend,resume}() we may safely convert the code to use > > one buffer for both ports (the whole PCI device). We just need to bump > > the size of struct sc1200_saved_state_s (from 4 to 8 double-words) and use > > pci_{get,set}_drvdata() instead of hwif->config_data. Then we can remove > > looping over interfaces completely from sc1200_{suspend,resume}()! :) > > May I assume you'll handle that task? :) It sounds like you have a far > better idea than mine, and my main goal -- fixing bugs and warning -- is > accomplished anyway with the merging of patch #3. Uh, OK... [PATCH] sc1200: remove pointless hwif lookup loop Save PCI regs values for both IDE ports in one buffer, in order to eliminate a needless and ugly loop across all hwifs, searching for our PCI device. Partially based on the previous patch by Jeff Garzik. Cc: Jeff Garzik <jeff@garzik.org> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> --- drivers/ide/pci/sc1200.c | 106 ++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 69 deletions(-) Index: b/drivers/ide/pci/sc1200.c =================================================================== --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -261,66 +261,39 @@ static void sc1200_set_pio_mode(ide_driv } #ifdef CONFIG_PM -static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) -{ - int h; - - for (h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if (prev) { - if (hwif == prev) - prev = NULL; // found previous, now look for next match - } else { - if (hwif && hwif->pci_dev == dev) - return hwif; // found next match - } - } - return NULL; // not found -} - -typedef struct sc1200_saved_state_s { - __u32 regs[4]; -} sc1200_saved_state_t; - +struct sc1200_saved_state { + u32 regs[8]; +}; static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) { - ide_hwif_t *hwif = NULL; - printk("SC1200: suspend(%u)\n", state.event); + /* + * we only save state when going from full power to less + */ if (state.event == PM_EVENT_ON) { - // we only save state when going from full power to less + struct sc1200_saved_state *ss; + unsigned int r; - // - // Loop over all interfaces that are part of this PCI device: - // - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { - sc1200_saved_state_t *ss; - unsigned int basereg, r; - // - // allocate a permanent save area, if not already allocated - // - ss = (sc1200_saved_state_t *)hwif->config_data; - if (ss == NULL) { - ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); - if (ss == NULL) - return -ENOMEM; - hwif->config_data = (unsigned long)ss; - } - ss = (sc1200_saved_state_t *)hwif->config_data; - // - // Save timing registers: this may be unnecessary if - // BIOS also does it - // - basereg = hwif->channel ? 0x50 : 0x40; - for (r = 0; r < 4; ++r) { - pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); - } + /* + * allocate a permanent save area, if not already allocated + */ + ss = (struct sc1200_saved_state *)pci_get_drvdata(dev); + if (ss == NULL) { + ss = kmalloc(sizeof(*ss), GFP_KERNEL); + if (ss == NULL) + return -ENOMEM; + pci_set_drvdata(dev, ss); } - } - /* You don't need to iterate over disks -- sysfs should have done that for you already */ + /* + * save timing registers + * (this may be unnecessary if BIOS also does it) + */ + for (r = 0; r < 8; r++) + pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]); + } pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); @@ -329,30 +302,25 @@ static int sc1200_suspend (struct pci_de static int sc1200_resume (struct pci_dev *dev) { - ide_hwif_t *hwif = NULL; - int i; + struct sc1200_saved_state *ss; + unsigned int r; + int i; i = pci_enable_device(dev); if (i) return i; - // - // loop over all interfaces that are part of this pci device: - // - while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { - unsigned int basereg, r; - sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; - - // - // Restore timing registers: this may be unnecessary if BIOS also does it - // - basereg = hwif->channel ? 0x50 : 0x40; - if (ss != NULL) { - for (r = 0; r < 4; ++r) { - pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]); - } - } + ss = (struct sc1200_saved_state *)pci_get_drvdata(dev); + + /* + * restore timing registers + * (this may be unnecessary if BIOS also does it) + */ + if (ss) { + for (r = 0; r < 8; r++) + pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]); } + return 0; } #endif ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] drivers/ide/pci/sc1200.c: fix suspend/resume buglets and warnings [not found] <09821349085390234lkjasdflkjasflkdj24746@havoc.gtf.org> 2007-10-24 23:48 ` [PATCH 1/3] [IDE] Add helper __ide_setup_pci_device() Jeff Garzik 2007-10-24 23:48 ` [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop Jeff Garzik @ 2007-10-24 23:48 ` Jeff Garzik 2007-10-25 20:10 ` Bartlomiej Zolnierkiewicz 2 siblings, 1 reply; 8+ messages in thread From: Jeff Garzik @ 2007-10-24 23:48 UTC (permalink / raw) To: LKML, linux-ide; +Cc: akpm * We shouldn't bother with dev->current_state, the PCI API functions we call manage this for us (and do a far better job at it too). * Remove pci_set_power_state(dev, PCI_D0) call in resume, as pci_enable_device() does the same thing. * Check pci_enable_device() return value. If it failed, fail the entire resume and avoid programming timings into the [potentially dead/asleep] chip. Signed-off-by: Jeff Garzik <jgarzik@redhat.com> --- drivers/ide/pci/sc1200.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 17e58d6..10c79a5 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -332,7 +332,6 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); - dev->current_state = state.event; return 0; } @@ -341,9 +340,10 @@ static int sc1200_resume (struct pci_dev *dev) ide_hwif_t *hwif; int i; - pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state - dev->current_state = PM_EVENT_ON; - pci_enable_device(dev); + i = pci_enable_device(dev); + if (i) + return i; + // // loop over all interfaces that are part of this pci device: // -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 3/3] drivers/ide/pci/sc1200.c: fix suspend/resume buglets and warnings 2007-10-24 23:48 ` [PATCH 3/3] drivers/ide/pci/sc1200.c: fix suspend/resume buglets and warnings Jeff Garzik @ 2007-10-25 20:10 ` Bartlomiej Zolnierkiewicz 0 siblings, 0 replies; 8+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2007-10-25 20:10 UTC (permalink / raw) To: Jeff Garzik; +Cc: LKML, linux-ide, akpm On Thursday 25 October 2007, Jeff Garzik wrote: > * We shouldn't bother with dev->current_state, the PCI API functions we > call manage this for us (and do a far better job at it too). > > * Remove pci_set_power_state(dev, PCI_D0) call in resume, as > pci_enable_device() does the same thing. > > * Check pci_enable_device() return value. If it failed, fail > the entire resume and avoid programming timings into the [potentially > dead/asleep] chip. > > Signed-off-by: Jeff Garzik <jgarzik@redhat.com> applied, thanks ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-10-31 21:50 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <09821349085390234lkjasdflkjasflkdj24746@havoc.gtf.org>
2007-10-24 23:48 ` [PATCH 1/3] [IDE] Add helper __ide_setup_pci_device() Jeff Garzik
2007-10-25 19:33 ` Bartlomiej Zolnierkiewicz
2007-10-24 23:48 ` [PATCH 2/3] drivers/ide/pci/sc1200.c: remove pointless hwif lookup loop Jeff Garzik
2007-10-25 20:01 ` Bartlomiej Zolnierkiewicz
2007-10-26 1:25 ` Jeff Garzik
2007-10-31 21:53 ` Bartlomiej Zolnierkiewicz
2007-10-24 23:48 ` [PATCH 3/3] drivers/ide/pci/sc1200.c: fix suspend/resume buglets and warnings Jeff Garzik
2007-10-25 20:10 ` Bartlomiej Zolnierkiewicz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).