From 18137207236285989dfc0ee7f929b954199228f3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:07 +0200 Subject: [PATCH 01/11] ide: fix UDMA/MWDMA/SWDMA masks (v3) * use 0x00 instead of 0x80 to disable ->{ultra,mwdma,swdma}_mask * add udma_mask field to ide_pci_device_t and use it to initialize ->ultra_mask in aec62xx, cmd64x, pdc202xx_{new,old} and piix drivers * fix UDMA masks to match with chipset specific *_ratemask() (alim15x3, hpt366, serverworks and siimage drivers need UDMA mask filtering method - done in the next patch) v2: * piix: fix cable detection for 82801AA_1 and 82372FB_1 [ Noticed by Sergei Shtylyov . ] * cmd64x: use hwif->cds->udma_mask [ Suggested by Sergei Shtylyov . ] * aec62xx: fix newly introduced bug - check DMA status not command register [ Noticed by Sergei Shtylyov . ] v3: * piix: use hwif->cds->udma_mask [ Suggested by Sergei Shtylyov . ] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide.c | 3 -- drivers/ide/pci/aec62xx.c | 19 ++++++++- drivers/ide/pci/alim15x3.c | 13 +++++- drivers/ide/pci/cmd64x.c | 17 ++++---- drivers/ide/pci/pdc202xx_new.c | 10 ++++- drivers/ide/pci/pdc202xx_old.c | 7 +++- drivers/ide/pci/piix.c | 73 +++++++++++++++------------------- drivers/ide/pci/sis5513.c | 5 ++- include/linux/ide.h | 1 + 9 files changed, 88 insertions(+), 60 deletions(-) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ae5bf2be6f52..c06424fe647b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -216,9 +216,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->bus_state = BUSSTATE_ON; hwif->atapi_dma = 0; /* disable all atapi dma */ - hwif->ultra_mask = 0x80; /* disable all ultra */ - hwif->mwdma_mask = 0x80; /* disable all mwdma */ - hwif->swdma_mask = 0x80; /* disable all swdma */ init_completion(&hwif->gendev_rel_comp); diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 73bdf64dbbfc..abe0b1bb55ff 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -261,11 +261,13 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) { + struct pci_dev *dev = hwif->pci_dev; + hwif->autodma = 0; hwif->tuneproc = &aec62xx_tune_drive; hwif->speedproc = &aec62xx_tune_chipset; - if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) hwif->serialized = hwif->channel; if (hwif->mate) @@ -277,7 +279,15 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) return; } - hwif->ultra_mask = 0x7f; + hwif->ultra_mask = hwif->cds->udma_mask; + + /* atp865 and atp865r */ + if (hwif->ultra_mask == 0x3f) { + /* check bit 0x10 of DMA status register */ + if (inb(pci_resource_start(dev, 4) + 2) & 0x10) + hwif->ultra_mask = 0x7f; /* udma0-6 */ + } + hwif->mwdma_mask = 0x07; hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; @@ -344,6 +354,7 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = OFF_BOARD, + .udma_mask = 0x07, /* udma0-2 */ },{ /* 1 */ .name = "AEC6260", .init_setup = init_setup_aec62xx, @@ -353,6 +364,7 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .channels = 2, .autodma = NOAUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x1f, /* udma0-4 */ },{ /* 2 */ .name = "AEC6260R", .init_setup = init_setup_aec62xx, @@ -363,6 +375,7 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = NEVER_BOARD, + .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "AEC6X80", .init_setup = init_setup_aec6x80, @@ -372,6 +385,7 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x3f, /* udma0-5 */ },{ /* 4 */ .name = "AEC6X80R", .init_setup = init_setup_aec6x80, @@ -382,6 +396,7 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = OFF_BOARD, + .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 946a12746cb5..26c27d946c67 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -783,8 +783,17 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->atapi_dma = 1; - if (m5229_revision > 0x20) - hwif->ultra_mask = 0x7f; + if (m5229_revision <= 0x20) + hwif->ultra_mask = 0x00; /* no udma */ + else if (m5229_revision < 0xC2) + hwif->ultra_mask = 0x07; /* udma0-2 */ + else if (m5229_revision == 0xC2 || m5229_revision == 0xC3) + hwif->ultra_mask = 0x1f; /* udma0-4 */ + else if (m5229_revision == 0xC4) + hwif->ultra_mask = 0x3f; /* udma0-5 */ + else + hwif->ultra_mask = 0x7f; /* udma0-6 */ + hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 77f51ab6d439..610c45f7b4e2 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -644,15 +644,12 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) hwif->atapi_dma = 1; - hwif->ultra_mask = 0x3f; - hwif->mwdma_mask = 0x07; + hwif->ultra_mask = hwif->cds->udma_mask; - if (dev->device == PCI_DEVICE_ID_CMD_643) - hwif->ultra_mask = 0x80; - if (dev->device == PCI_DEVICE_ID_CMD_646) - hwif->ultra_mask = (class_rev > 0x04) ? 0x07 : 0x80; - if (dev->device == PCI_DEVICE_ID_CMD_648) - hwif->ultra_mask = 0x1f; + if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5) + hwif->ultra_mask = 0x00; + + hwif->mwdma_mask = 0x07; hwif->ide_dma_check = &cmd64x_config_drive_for_dma; if (!(hwif->udma_four)) @@ -716,6 +713,7 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, + .udma_mask = 0x00, /* no udma */ },{ /* 1 */ .name = "CMD646", .init_setup = init_setup_cmd646, @@ -725,6 +723,7 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, + .udma_mask = 0x07, /* udma0-2 */ },{ /* 2 */ .name = "CMD648", .init_setup = init_setup_cmd64x, @@ -734,6 +733,7 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, + .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "CMD649", .init_setup = init_setup_cmd64x, @@ -743,6 +743,7 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, + .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 2cdd629c653d..a23853445af9 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -543,7 +543,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; hwif->atapi_dma = 1; - hwif->ultra_mask = 0x7f; + + hwif->ultra_mask = hwif->cds->udma_mask; hwif->mwdma_mask = 0x07; hwif->err_stops_fifo = 1; @@ -619,6 +620,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x3f, /* udma0-5 */ },{ /* 1 */ .name = "PDC20269", .init_setup = init_setup_pdcnew, @@ -627,6 +629,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x7f, /* udma0-6*/ },{ /* 2 */ .name = "PDC20270", .init_setup = init_setup_pdc20270, @@ -635,6 +638,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x3f, /* udma0-5 */ },{ /* 3 */ .name = "PDC20271", .init_setup = init_setup_pdcnew, @@ -643,6 +647,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x7f, /* udma0-6*/ },{ /* 4 */ .name = "PDC20275", .init_setup = init_setup_pdcnew, @@ -651,6 +656,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x7f, /* udma0-6*/ },{ /* 5 */ .name = "PDC20276", .init_setup = init_setup_pdc20276, @@ -659,6 +665,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x7f, /* udma0-6*/ },{ /* 6 */ .name = "PDC20277", .init_setup = init_setup_pdcnew, @@ -667,6 +674,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .udma_mask = 0x7f, /* udma0-6*/ } }; diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index a7a639fe1eaf..d7a38067fb34 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -478,7 +478,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - hwif->ultra_mask = 0x3f; + hwif->ultra_mask = hwif->cds->udma_mask; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; hwif->atapi_dma = 1; @@ -587,6 +587,7 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 16, + .udma_mask = 0x07, /* udma0-2 */ },{ /* 1 */ .name = "PDC20262", .init_setup = init_setup_pdc202ata4, @@ -597,6 +598,7 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, + .udma_mask = 0x1f, /* udma0-4 */ },{ /* 2 */ .name = "PDC20263", .init_setup = init_setup_pdc202ata4, @@ -607,6 +609,7 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, + .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "PDC20265", .init_setup = init_setup_pdc20265, @@ -617,6 +620,7 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, + .udma_mask = 0x3f, /* udma0-5 */ },{ /* 4 */ .name = "PDC20267", .init_setup = init_setup_pdc202xx, @@ -627,6 +631,7 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, + .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 061d300ab8be..17ea44edb4eb 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -524,26 +524,14 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->ide_dma_clear_irq = &piix_dma_clear_irq; hwif->atapi_dma = 1; - hwif->ultra_mask = 0x3f; + + hwif->ultra_mask = hwif->cds->udma_mask; hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_INTEL_82371FB_0: - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371SB_1: - hwif->ultra_mask = 0x80; - break; - case PCI_DEVICE_ID_INTEL_82371AB: - case PCI_DEVICE_ID_INTEL_82443MX_1: - case PCI_DEVICE_ID_INTEL_82451NX: - case PCI_DEVICE_ID_INTEL_82801AB_1: - hwif->ultra_mask = 0x07; - break; - default: - if (!hwif->udma_four) - hwif->udma_four = piix_cable_detect(hwif); - break; + if (hwif->ultra_mask & 0x78) { + if (!hwif->udma_four) + hwif->udma_four = piix_cable_detect(hwif); } if (no_piix_dma) @@ -557,7 +545,7 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->drives[0].autodma = hwif->autodma; } -#define DECLARE_PIIX_DEV(name_str) \ +#define DECLARE_PIIX_DEV(name_str, udma) \ { \ .name = name_str, \ .init_chipset = init_chipset_piix, \ @@ -566,11 +554,12 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) .autodma = AUTODMA, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .bootable = ON_BOARD, \ + .udma_mask = udma, \ } static ide_pci_device_t piix_pci_info[] __devinitdata = { - /* 0 */ DECLARE_PIIX_DEV("PIIXa"), - /* 1 */ DECLARE_PIIX_DEV("PIIXb"), + /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */ + /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */ /* 2 */ { /* @@ -587,28 +576,28 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { .flags = IDEPCI_FLAG_ISA_PORTS }, - /* 3 */ DECLARE_PIIX_DEV("PIIX3"), - /* 4 */ DECLARE_PIIX_DEV("PIIX4"), - /* 5 */ DECLARE_PIIX_DEV("ICH0"), - /* 6 */ DECLARE_PIIX_DEV("PIIX4"), - /* 7 */ DECLARE_PIIX_DEV("ICH"), - /* 8 */ DECLARE_PIIX_DEV("PIIX4"), - /* 9 */ DECLARE_PIIX_DEV("PIIX4"), - /* 10 */ DECLARE_PIIX_DEV("ICH2"), - /* 11 */ DECLARE_PIIX_DEV("ICH2M"), - /* 12 */ DECLARE_PIIX_DEV("ICH3M"), - /* 13 */ DECLARE_PIIX_DEV("ICH3"), - /* 14 */ DECLARE_PIIX_DEV("ICH4"), - /* 15 */ DECLARE_PIIX_DEV("ICH5"), - /* 16 */ DECLARE_PIIX_DEV("C-ICH"), - /* 17 */ DECLARE_PIIX_DEV("ICH4"), - /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA"), - /* 19 */ DECLARE_PIIX_DEV("ICH5"), - /* 20 */ DECLARE_PIIX_DEV("ICH6"), - /* 21 */ DECLARE_PIIX_DEV("ICH7"), - /* 22 */ DECLARE_PIIX_DEV("ICH4"), - /* 23 */ DECLARE_PIIX_DEV("ESB2"), - /* 24 */ DECLARE_PIIX_DEV("ICH8M"), + /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */ + /* 4 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ + /* 5 */ DECLARE_PIIX_DEV("ICH0", 0x07), /* udma0-2 */ + /* 6 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ + /* 7 */ DECLARE_PIIX_DEV("ICH", 0x1f), /* udma0-4 */ + /* 8 */ DECLARE_PIIX_DEV("PIIX4", 0x1f), /* udma0-4 */ + /* 9 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ + /* 10 */ DECLARE_PIIX_DEV("ICH2", 0x3f), /* udma0-5 */ + /* 11 */ DECLARE_PIIX_DEV("ICH2M", 0x3f), /* udma0-5 */ + /* 12 */ DECLARE_PIIX_DEV("ICH3M", 0x3f), /* udma0-5 */ + /* 13 */ DECLARE_PIIX_DEV("ICH3", 0x3f), /* udma0-5 */ + /* 14 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ + /* 15 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */ + /* 16 */ DECLARE_PIIX_DEV("C-ICH", 0x3f), /* udma0-5 */ + /* 17 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ + /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA", 0x3f), /* udma0-5 */ + /* 19 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */ + /* 20 */ DECLARE_PIIX_DEV("ICH6", 0x3f), /* udma0-5 */ + /* 21 */ DECLARE_PIIX_DEV("ICH7", 0x3f), /* udma0-5 */ + /* 22 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ + /* 23 */ DECLARE_PIIX_DEV("ESB2", 0x3f), /* udma0-5 */ + /* 24 */ DECLARE_PIIX_DEV("ICH8M", 0x3f), /* udma0-5 */ }; /** diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 2ba0669f36a1..6fe4ecb6c06c 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -858,6 +858,8 @@ static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif) static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) { + u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; + hwif->autodma = 0; if (!hwif->irq) @@ -873,7 +875,8 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) } hwif->atapi_dma = 1; - hwif->ultra_mask = 0x7f; + + hwif->ultra_mask = udma_rates[chipset_family]; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; diff --git a/include/linux/ide.h b/include/linux/ide.h index 418dfb5adadd..c9375c863584 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1257,6 +1257,7 @@ typedef struct ide_pci_device_s { unsigned int extra; struct ide_pci_device_s *next; u8 flags; + u8 udma_mask; } ide_pci_device_t; extern int ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); From 2d5eaa6dd744a641e75503232a01f52d0768884c Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:08 +0200 Subject: [PATCH 02/11] ide: rework the code for selecting the best DMA transfer mode (v3) Depends on the "ide: fix UDMA/MWDMA/SWDMA masks" patch. * add ide_hwif_t.udma_filter hook for filtering UDMA mask (use it in alim15x3, hpt366, siimage and serverworks drivers) * add ide_max_dma_mode() for finding best DMA mode for the device (loosely based on some older libata-core.c code) * convert ide_dma_speed() users to use ide_max_dma_mode() * make ide_rate_filter() take "ide_drive_t *drive" as an argument instead of "u8 mode" and teach it to how to use UDMA mask to do filtering * use ide_rate_filter() in hpt366 driver * remove no longer needed ide_dma_speed() and *_ratemask() * unexport eighty_ninty_three() v2: * rename ->filter_udma_mask to ->udma_filter [ Suggested by Sergei Shtylyov . ] v3: * updated for scc_pata driver (fixes XFER_UDMA_6 filtering for user-space originated transfer mode change requests when 100MHz clock is used) Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/icside.c | 2 +- drivers/ide/cris/ide-cris.c | 2 +- drivers/ide/ide-dma.c | 74 +++++++++++++++++++ drivers/ide/ide-iops.c | 2 - drivers/ide/ide-lib.c | 125 +++++---------------------------- drivers/ide/ide.c | 1 + drivers/ide/pci/aec62xx.c | 32 +-------- drivers/ide/pci/alim15x3.c | 76 +++++--------------- drivers/ide/pci/atiixp.c | 20 +----- drivers/ide/pci/cmd64x.c | 65 ++++------------- drivers/ide/pci/cs5535.c | 20 +----- drivers/ide/pci/hpt34x.c | 9 +-- drivers/ide/pci/hpt366.c | 67 +++++++++--------- drivers/ide/pci/it8213.c | 20 +----- drivers/ide/pci/it821x.c | 20 +----- drivers/ide/pci/jmicron.c | 21 +----- drivers/ide/pci/pdc202xx_new.c | 14 +--- drivers/ide/pci/pdc202xx_old.c | 27 +------ drivers/ide/pci/piix.c | 66 +---------------- drivers/ide/pci/scc_pata.c | 21 +----- drivers/ide/pci/serverworks.c | 31 ++++---- drivers/ide/pci/siimage.c | 45 ++++++------ drivers/ide/pci/sis5513.c | 14 +--- drivers/ide/pci/slc90e66.c | 13 +--- drivers/ide/pci/tc86c001.c | 9 +-- drivers/ide/pci/triflex.c | 4 +- include/linux/ide.h | 10 ++- 27 files changed, 236 insertions(+), 574 deletions(-) diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index e2953fc1fafb..f383ace2a087 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -342,7 +342,7 @@ static int icside_dma_check(ide_drive_t *drive) * Enable DMA on any drive that has multiword DMA */ if (id->field_valid & 2) { - xfer_mode = ide_dma_speed(drive, 0); + xfer_mode = ide_max_dma_mode(drive); goto out; } diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index 5e8efc89255a..9691d089fce8 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -1004,7 +1004,7 @@ static int cris_ide_build_dmatable (ide_drive_t *drive) static int cris_config_drive_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, 1); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index fd213088b06b..f28fabb791fe 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -705,6 +705,80 @@ int ide_use_dma(ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_use_dma); +static const u8 xfer_mode_bases[] = { + XFER_UDMA_0, + XFER_MW_DMA_0, + XFER_SW_DMA_0, +}; + +static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = drive->hwif; + unsigned int mask = 0; + + switch(base) { + case XFER_UDMA_0: + if ((id->field_valid & 4) == 0) + break; + + mask = id->dma_ultra & hwif->ultra_mask; + + if (hwif->udma_filter) + mask &= hwif->udma_filter(drive); + + if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) + mask &= 0x07; + break; + case XFER_MW_DMA_0: + mask = id->dma_mword & hwif->mwdma_mask; + break; + case XFER_SW_DMA_0: + mask = id->dma_1word & hwif->swdma_mask; + break; + default: + BUG(); + break; + } + + return mask; +} + +/** + * ide_max_dma_mode - compute DMA speed + * @drive: IDE device + * + * Checks the drive capabilities and returns the speed to use + * for the DMA transfer. Returns 0 if the drive is incapable + * of DMA transfers. + */ + +u8 ide_max_dma_mode(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned int mask; + int x, i; + u8 mode = 0; + + if (drive->media != ide_disk && hwif->atapi_dma == 0) + return 0; + + for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { + mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); + x = fls(mask) - 1; + if (x >= 0) { + mode = xfer_mode_bases[i] + x; + break; + } + } + + printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); + + return mode; +} + +EXPORT_SYMBOL_GPL(ide_max_dma_mode); + void ide_dma_verbose(ide_drive_t *drive) { struct hd_driveid *id = drive->id; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 3caa176b3155..ed6128f6cd98 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -592,8 +592,6 @@ u8 eighty_ninty_three (ide_drive_t *drive) return 1; } -EXPORT_SYMBOL(eighty_ninty_three); - int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) { if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 68719314df3f..4557fc5a3ea3 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -69,123 +69,34 @@ char *ide_xfer_verbose (u8 xfer_rate) EXPORT_SYMBOL(ide_xfer_verbose); /** - * ide_dma_speed - compute DMA speed - * @drive: drive - * @mode: modes available - * - * Checks the drive capabilities and returns the speed to use - * for the DMA transfer. Returns 0 if the drive is incapable - * of DMA transfers. - */ - -u8 ide_dma_speed(ide_drive_t *drive, u8 mode) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - u8 ultra_mask, mwdma_mask, swdma_mask; - u8 speed = 0; - - if (drive->media != ide_disk && hwif->atapi_dma == 0) - return 0; - - /* Capable of UltraDMA modes? */ - ultra_mask = id->dma_ultra & hwif->ultra_mask; - - if (!(id->field_valid & 4)) - mode = 0; /* fallback to MW/SW DMA if no UltraDMA */ - - switch (mode) { - case 4: - if (ultra_mask & 0x40) { - speed = XFER_UDMA_6; - break; - } - case 3: - if (ultra_mask & 0x20) { - speed = XFER_UDMA_5; - break; - } - case 2: - if (ultra_mask & 0x10) { - speed = XFER_UDMA_4; - break; - } - if (ultra_mask & 0x08) { - speed = XFER_UDMA_3; - break; - } - case 1: - if (ultra_mask & 0x04) { - speed = XFER_UDMA_2; - break; - } - if (ultra_mask & 0x02) { - speed = XFER_UDMA_1; - break; - } - if (ultra_mask & 0x01) { - speed = XFER_UDMA_0; - break; - } - case 0: - mwdma_mask = id->dma_mword & hwif->mwdma_mask; - - if (mwdma_mask & 0x04) { - speed = XFER_MW_DMA_2; - break; - } - if (mwdma_mask & 0x02) { - speed = XFER_MW_DMA_1; - break; - } - if (mwdma_mask & 0x01) { - speed = XFER_MW_DMA_0; - break; - } - - swdma_mask = id->dma_1word & hwif->swdma_mask; - - if (swdma_mask & 0x04) { - speed = XFER_SW_DMA_2; - break; - } - if (swdma_mask & 0x02) { - speed = XFER_SW_DMA_1; - break; - } - if (swdma_mask & 0x01) { - speed = XFER_SW_DMA_0; - break; - } - } - - return speed; -} -EXPORT_SYMBOL(ide_dma_speed); - - -/** - * ide_rate_filter - return best speed for mode - * @mode: modes available + * ide_rate_filter - filter transfer mode + * @drive: IDE device * @speed: desired speed * - * Given the available DMA/UDMA mode this function returns + * Given the available transfer modes this function returns * the best available speed at or below the speed requested. + * + * FIXME: filter also PIO/SWDMA/MWDMA modes */ -u8 ide_rate_filter (u8 mode, u8 speed) +u8 ide_rate_filter(ide_drive_t *drive, u8 speed) { #ifdef CONFIG_BLK_DEV_IDEDMA - static u8 speed_max[] = { - XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, - XFER_UDMA_5, XFER_UDMA_6 - }; + ide_hwif_t *hwif = drive->hwif; + u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; + + if (hwif->udma_filter) + mask = hwif->udma_filter(drive); + + if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) + mask &= 0x07; + + if (mask) + mode = fls(mask) - 1 + XFER_UDMA_0; // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); - /* So that we remember to update this if new modes appear */ - BUG_ON(mode > 4); - return min(speed, speed_max[mode]); + return min(speed, mode); #else /* !CONFIG_BLK_DEV_IDEDMA */ return min(speed, (u8)XFER_PIO_4); #endif /* CONFIG_BLK_DEV_IDEDMA */ diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index c06424fe647b..73f752142f9e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -477,6 +477,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->tuneproc = tmp_hwif->tuneproc; hwif->speedproc = tmp_hwif->speedproc; + hwif->udma_filter = tmp_hwif->udma_filter; hwif->selectproc = tmp_hwif->selectproc; hwif->reset_poll = tmp_hwif->reset_poll; hwif->pre_reset = tmp_hwif->pre_reset; diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index abe0b1bb55ff..099539e8c7a3 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -87,38 +87,12 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr return chipset_table->ultra_settings; } -static u8 aec62xx_ratemask (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 mode; - - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP865: - case PCI_DEVICE_ID_ARTOP_ATP865R: - mode = (inb(hwif->channel ? - hwif->mate->dma_status : - hwif->dma_status) & 0x10) ? 4 : 3; - break; - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - mode = 2; - break; - case PCI_DEVICE_ID_ARTOP_ATP850UF: - default: - return 1; - } - - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - static int aec6210_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u16 d_conf = 0; - u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u8 ultra = 0, ultra_conf = 0; u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; unsigned long flags; @@ -145,7 +119,7 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u8 unit = (drive->select.b.unit & 0x01); u8 tmp1 = 0, tmp2 = 0; u8 ultra = 0, drive_conf = 0, ultra_conf = 0; @@ -183,7 +157,7 @@ static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!(speed)) return 0; diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 26c27d946c67..76643b626bdd 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -378,74 +378,31 @@ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) } /** - * ali15x3_can_ultra - check for ultra DMA support - * @drive: drive to do the check + * ali_udma_filter - compute UDMA mask + * @drive: IDE device * - * Check the drive and controller revisions. Return 0 if UDMA is - * not available, or 1 if UDMA can be used. The actual rules for - * the ALi are + * Return available UDMA modes. + * + * The actual rules for the ALi are: * No UDMA on revisions <= 0x20 * Disk only for revisions < 0xC2 * Not WDC drives for revisions < 0xC2 * * FIXME: WDC ifdef needs to die */ - -static u8 ali15x3_can_ultra (ide_drive_t *drive) + +static u8 ali_udma_filter(ide_drive_t *drive) { + if (m5229_revision > 0x20 && m5229_revision < 0xC2) { + if (drive->media != ide_disk) + return 0; #ifndef CONFIG_WDC_ALI15X3 - struct hd_driveid *id = drive->id; -#endif /* CONFIG_WDC_ALI15X3 */ - - if (m5229_revision <= 0x20) { - return 0; - } else if ((m5229_revision < 0xC2) && -#ifndef CONFIG_WDC_ALI15X3 - ((chip_is_1543c_e && strstr(id->model, "WDC ")) || - (drive->media!=ide_disk))) { -#else /* CONFIG_WDC_ALI15X3 */ - (drive->media!=ide_disk)) { -#endif /* CONFIG_WDC_ALI15X3 */ - return 0; - } else { - return 1; - } -} - -/** - * ali15x3_ratemask - generate DMA mode list - * @drive: drive to compute against - * - * Generate a list of the available DMA modes for the drive. - * FIXME: this function contains lots of bogus masking we can dump - * - * Return the highest available mode (UDMA33, UDMA66, UDMA100,..) - */ - -static u8 ali15x3_ratemask (ide_drive_t *drive) -{ - u8 mode = 0, can_ultra = ali15x3_can_ultra(drive); - - if (m5229_revision > 0xC4 && can_ultra) { - mode = 4; - } else if (m5229_revision == 0xC4 && can_ultra) { - mode = 3; - } else if (m5229_revision >= 0xC2 && can_ultra) { - mode = 2; - } else if (can_ultra) { - return 1; - } else { - return 0; + if (chip_is_1543c_e && strstr(drive->id->model, "WDC ")) + return 0; +#endif } - /* - * If the drive sees no suitable cable then UDMA 33 - * is the highest permitted mode - */ - - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; + return drive->hwif->ultra_mask; } /** @@ -461,7 +418,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(ali15x3_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u8 speed1 = speed; u8 unit = (drive->select.b.unit & 0x01); u8 tmpbyte = 0x00; @@ -511,7 +468,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, ali15x3_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!(speed)) return 0; @@ -771,6 +728,7 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->autodma = 0; hwif->tuneproc = &ali15x3_tune_drive; hwif->speedproc = &ali15x3_tune_chipset; + hwif->udma_filter = &ali_udma_filter; /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0; diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 2d48af32e3f4..f7e80d6076d7 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -48,22 +48,6 @@ static int save_mdma_mode[4]; static DEFINE_SPINLOCK(atiixp_lock); -/** - * atiixp_ratemask - compute rate mask for ATIIXP IDE - * @drive: IDE drive to compute for - * - * Returns the available modes for the ATIIXP IDE controller. - */ - -static u8 atiixp_ratemask(ide_drive_t *drive) -{ - u8 mode = 3; - - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - /** * atiixp_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -189,7 +173,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) u16 tmp16; u8 speed, pio; - speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed); + speed = ide_rate_filter(drive, xferspeed); spin_lock_irqsave(&atiixp_lock, flags); @@ -233,7 +217,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) static int atiixp_config_drive_for_dma(ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 610c45f7b4e2..19f5ac1f866c 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -292,55 +292,6 @@ static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio) (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); } -static u8 cmd64x_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mode = 0; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_649: - mode = 3; - break; - case PCI_DEVICE_ID_CMD_648: - mode = 2; - break; - case PCI_DEVICE_ID_CMD_643: - return 0; - - case PCI_DEVICE_ID_CMD_646: - { - unsigned int class_rev = 0; - pci_read_config_dword(dev, - PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - /* - * UltraDMA only supported on PCI646U and PCI646U2, which - * correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - switch(class_rev) { - case 0x07: - case 0x05: - return 1; - case 0x03: - case 0x01: - default: - return 0; - } - } - } - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); @@ -348,7 +299,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) u8 unit = drive->dn & 0x01; u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; - speed = ide_rate_filter(cmd64x_ratemask(drive), speed); + speed = ide_rate_filter(drive, speed); if (speed >= XFER_SW_DMA_0) { (void) pci_read_config_byte(dev, pciU, ®U); @@ -403,7 +354,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; @@ -646,6 +597,18 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) hwif->ultra_mask = hwif->cds->udma_mask; + /* + * UltraDMA only supported on PCI646U and PCI646U2, which + * correspond to revisions 0x03, 0x05 and 0x07 respectively. + * Actually, although the CMD tech support people won't + * tell me the details, the 0x03 revision cannot support + * UDMA correctly without hardware modifications, and even + * then it only works with Quantum disks due to some + * hold time assumptions in the 646U part which are fixed + * in the 646U2. + * + * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. + */ if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5) hwif->ultra_mask = 0x00; diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index 45f43efbf92c..66a101e470d0 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -127,20 +127,6 @@ static void cs5535_set_speed(ide_drive_t *drive, u8 speed) } } -static u8 cs5535_ratemask(ide_drive_t *drive) -{ - /* eighty93 will return 1 if it's 80core and capable of - exceeding udma2, 0 otherwise. we need ratemask to set - the max speed and if we can > udma2 then we return 2 - which selects speed_max as udma4 which is the 5535's max - speed, and 1 selects udma2 which is the max for 40c */ - if (!eighty_ninty_three(drive)) - return 1; - - return 2; -} - - /**** * cs5535_set_drive - Configure the drive to the new speed * @drive: Drive to set up @@ -151,7 +137,7 @@ static u8 cs5535_ratemask(ide_drive_t *drive) */ static int cs5535_set_drive(ide_drive_t *drive, u8 speed) { - speed = ide_rate_filter(cs5535_ratemask(drive), speed); + speed = ide_rate_filter(drive, speed); ide_config_drive_speed(drive, speed); cs5535_set_speed(drive, speed); @@ -180,9 +166,7 @@ static void cs5535_tuneproc(ide_drive_t *drive, u8 xferspeed) static int cs5535_config_drive_for_dma(ide_drive_t *drive) { - u8 speed; - - speed = ide_dma_speed(drive, cs5535_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); /* If no DMA speed was available then let dma_check hit pio */ if (!speed) { diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index 924eaa3a5708..473e1b33dbf7 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -43,15 +43,10 @@ #define HPT343_DEBUG_DRIVE_INFO 0 -static u8 hpt34x_ratemask (ide_drive_t *drive) -{ - return 1; -} - static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 speed = ide_rate_filter(hpt34x_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0; u8 hi_speed, lo_speed; @@ -98,7 +93,7 @@ static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!(speed)) return 0; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index cf9d344d19f8..de5ad9c35dc6 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -514,43 +514,31 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) return 0; } -static u8 hpt3xx_ratemask(ide_drive_t *drive) -{ - struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); - u8 mode = info->max_mode; - - if (!eighty_ninty_three(drive) && mode) - mode = min(mode, (u8)1); - return mode; -} - /* * Note for the future; the SATA hpt37x we must set * either PIO or UDMA modes 0,4,5 */ - -static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) + +static u8 hpt3xx_udma_filter(ide_drive_t *drive) { struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); u8 chip_type = info->chip_type; - u8 mode = hpt3xx_ratemask(drive); - - if (drive->media != ide_disk) - return min(speed, (u8)XFER_PIO_4); + u8 mode = info->max_mode; + u8 mask; switch (mode) { case 0x04: - speed = min_t(u8, speed, XFER_UDMA_6); + mask = 0x7f; break; case 0x03: - speed = min_t(u8, speed, XFER_UDMA_5); + mask = 0x3f; if (chip_type >= HPT374) break; if (!check_in_drive_list(drive, bad_ata100_5)) goto check_bad_ata33; /* fall thru */ case 0x02: - speed = min_t(u8, speed, XFER_UDMA_4); + mask = 0x1f; /* * CHECK ME, Does this need to be changed to HPT374 ?? @@ -561,13 +549,13 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) !check_in_drive_list(drive, bad_ata66_4)) goto check_bad_ata33; - speed = min_t(u8, speed, XFER_UDMA_3); + mask = 0x0f; if (HPT366_ALLOW_ATA66_3 && !check_in_drive_list(drive, bad_ata66_3)) goto check_bad_ata33; /* fall thru */ case 0x01: - speed = min_t(u8, speed, XFER_UDMA_2); + mask = 0x07; check_bad_ata33: if (chip_type >= HPT370A) @@ -577,10 +565,10 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) /* fall thru */ case 0x00: default: - speed = min_t(u8, speed, XFER_MW_DMA_2); + mask = 0x00; break; } - return speed; + return mask; } static u32 get_speed_setting(u8 speed, struct hpt_info *info) @@ -608,12 +596,19 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u8 itr_addr = drive->dn ? 0x44 : 0x40; - u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : - (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); - u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; + u32 itr_mask, new_itr; + + /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ + if (drive->media != ide_disk) + speed = min_t(u8, speed, XFER_PIO_4); + + itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : + (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); + + new_itr = get_speed_setting(speed, info); /* * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) @@ -633,12 +628,19 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u8 itr_addr = 0x40 + (drive->dn * 4); - u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : - (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); - u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; + u32 itr_mask, new_itr; + + /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ + if (drive->media != ide_disk) + speed = min_t(u8, speed, XFER_PIO_4); + + itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : + (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); + + new_itr = get_speed_setting(speed, info); pci_read_config_dword(dev, itr_addr, &old_itr); new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); @@ -676,7 +678,7 @@ static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) */ static int config_chipset_for_dma(ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; @@ -1271,6 +1273,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; hwif->busproc = &hpt3xx_busproc; + hwif->udma_filter = &hpt3xx_udma_filter; /* * HPT3xxN chips have some complications: diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index 424f00bb160d..02b56cb7bb1b 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -17,22 +17,6 @@ #include -/* - * it8213_ratemask - Compute available modes - * @drive: IDE drive - * - * Compute the available speeds for the devices on the interface. This - * is all modes to ATA133 clipped by drive cable setup. - */ - -static u8 it8213_ratemask (ide_drive_t *drive) -{ - u8 mode = 4; - if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); - return mode; -} - /** * it8213_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -145,7 +129,7 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = 0x40; - u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -222,7 +206,7 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 4e1254813ee0..442f658c6ae7 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -228,22 +228,6 @@ static void it821x_clock_strategy(ide_drive_t *drive) } } -/** - * it821x_ratemask - Compute available modes - * @drive: IDE drive - * - * Compute the available speeds for the devices on the interface. This - * is all modes to ATA133 clipped by drive cable setup. - */ - -static u8 it821x_ratemask (ide_drive_t *drive) -{ - u8 mode = 4; - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - /** * it821x_tunepio - tune a drive * @drive: drive to tune @@ -438,7 +422,7 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) ide_hwif_t *hwif = drive->hwif; struct it821x_dev *itdev = ide_get_hwifdata(hwif); - u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); switch (speed) { case XFER_PIO_4: @@ -488,7 +472,7 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (speed == 0) return 0; diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index be4fc96c29e0..dbb3c199cba9 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -21,22 +21,6 @@ typedef enum { PORT_SATA = 2, } port_type; -/** - * jmicron_ratemask - Compute available modes - * @drive: IDE drive - * - * Compute the available speeds for the devices on the interface. This - * is all modes to ATA133 clipped by drive cable setup. - */ - -static u8 jmicron_ratemask(ide_drive_t *drive) -{ - u8 mode = 4; - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - /** * ata66_jmicron - Cable check * @hwif: IDE port @@ -129,8 +113,7 @@ static void config_jmicron_chipset_for_pio (ide_drive_t *drive, byte set_speed) static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) { - - u8 speed = ide_rate_filter(jmicron_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); return ide_config_drive_speed(drive, speed); } @@ -145,7 +128,7 @@ static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, jmicron_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index a23853445af9..772ca4007de4 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -82,16 +82,6 @@ static u8 max_dma_rate(struct pci_dev *pdev) return mode; } -static u8 pdcnew_ratemask(ide_drive_t *drive) -{ - u8 mode = max_dma_rate(HWIF(drive)->pci_dev); - - if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); - - return mode; -} - /** * get_indexed_reg - Get indexed register * @hwif: for the port address @@ -164,7 +154,7 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) u8 adj = (drive->dn & 1) ? 0x08 : 0x00; int err; - speed = ide_rate_filter(pdcnew_ratemask(drive), speed); + speed = ide_rate_filter(drive, speed); /* * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will @@ -267,7 +257,7 @@ static int config_chipset_for_dma(ide_drive_t *drive) set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03); } - speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); + speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index d7a38067fb34..207a6191fac7 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -101,35 +101,12 @@ static const char *pdc_quirk_drives[] = { #define MC1 0x02 /* DMA"C" timing */ #define MC0 0x01 /* DMA"C" timing */ -static u8 pdc202xx_ratemask (ide_drive_t *drive) -{ - u8 mode; - - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - mode = 3; - break; - case PCI_DEVICE_ID_PROMISE_20263: - case PCI_DEVICE_ID_PROMISE_20262: - mode = 2; - break; - case PCI_DEVICE_ID_PROMISE_20246: - return 1; - default: - return 0; - } - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 drive_pci = 0x60 + (drive->dn << 2); - u8 speed = ide_rate_filter(pdc202xx_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); u32 drive_conf; u8 AP, BP, CP, DP; @@ -308,7 +285,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) if (drive->media == ide_disk) /* PREFETCH_EN */ pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - speed = ide_dma_speed(drive, pdc202xx_ratemask(drive)); + speed = ide_max_dma_mode(drive); if (!(speed)) { /* restore original pci-config space */ diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 17ea44edb4eb..84d3938a430a 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -105,68 +105,6 @@ static int no_piix_dma; -/** - * piix_ratemask - compute rate mask for PIIX IDE - * @drive: IDE drive to compute for - * - * Returns the available modes for the PIIX IDE controller. - */ - -static u8 piix_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mode; - - switch(dev->device) { - case PCI_DEVICE_ID_INTEL_82801EB_1: - mode = 3; - break; - /* UDMA 100 capable */ - case PCI_DEVICE_ID_INTEL_82801BA_8: - case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - case PCI_DEVICE_ID_INTEL_82801DB_1: - case PCI_DEVICE_ID_INTEL_82801DB_10: - case PCI_DEVICE_ID_INTEL_82801DB_11: - case PCI_DEVICE_ID_INTEL_82801EB_11: - case PCI_DEVICE_ID_INTEL_ESB_2: - case PCI_DEVICE_ID_INTEL_ICH6_19: - case PCI_DEVICE_ID_INTEL_ICH7_21: - case PCI_DEVICE_ID_INTEL_ESB2_18: - case PCI_DEVICE_ID_INTEL_ICH8_6: - mode = 3; - break; - /* UDMA 66 capable */ - case PCI_DEVICE_ID_INTEL_82801AA_1: - case PCI_DEVICE_ID_INTEL_82372FB_1: - mode = 2; - break; - /* UDMA 33 capable */ - case PCI_DEVICE_ID_INTEL_82371AB: - case PCI_DEVICE_ID_INTEL_82443MX_1: - case PCI_DEVICE_ID_INTEL_82451NX: - case PCI_DEVICE_ID_INTEL_82801AB_1: - return 1; - /* Non UDMA capable (MWDMA2) */ - case PCI_DEVICE_ID_INTEL_82371SB_1: - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371FB_0: - case PCI_DEVICE_ID_INTEL_82371MX: - default: - return 0; - } - - /* - * If we are UDMA66 capable fall back to UDMA33 - * if the drive cannot see an 80pin cable. - */ - if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); - return mode; -} - /** * piix_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -301,7 +239,7 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -376,7 +314,7 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int piix_config_drive_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); /* * If no DMA speed was available or the chipset has DMA bugs diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index f84bf791f72e..cbf936325355 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -189,23 +189,6 @@ scc_ide_outsl(unsigned long port, void *addr, u32 count) } } -/** - * scc_ratemask - Compute available modes - * @drive: IDE drive - * - * Compute the available speeds for the devices on the interface. - * Enforce UDMA33 as a limit if there is no 80pin cable present. - */ - -static u8 scc_ratemask(ide_drive_t *drive) -{ - u8 mode = 4; - - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - /** * scc_tuneproc - tune a drive PIO mode * @drive: drive to tune @@ -273,7 +256,7 @@ static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted) static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); - u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); struct scc_ports *ports = ide_get_hwifdata(hwif); unsigned long ctl_base = ports->ctl; unsigned long cckctrl_port = ctl_base + 0xff0; @@ -347,7 +330,7 @@ static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) static int scc_config_chipset_for_dma(ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, scc_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index dbcd37a0c652..2fa6d92d16cc 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -65,16 +65,16 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) return 0; } -static u8 svwks_ratemask (ide_drive_t *drive) +static u8 svwks_udma_filter(ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mode = 0; + u8 mask = 0; if (!svwks_revision) pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) - return 2; + return 0x1f; if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { u32 reg = 0; if (isa_dev) @@ -86,25 +86,31 @@ static u8 svwks_ratemask (ide_drive_t *drive) if(drive->media == ide_disk) return 0; /* Check the OSB4 DMA33 enable bit */ - return ((reg & 0x00004000) == 0x00004000) ? 1 : 0; + return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0; } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { - return 1; + return 0x07; } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { - u8 btr = 0; + u8 btr = 0, mode; pci_read_config_byte(dev, 0x5A, &btr); mode = btr & 0x3; - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + /* If someone decides to do UDMA133 on CSB5 the same issue will bite so be inclusive */ if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) mode = 2; + + switch(mode) { + case 2: mask = 0x1f; break; + case 1: mask = 0x07; break; + default: mask = 0x00; break; + } } if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && (!(PCI_FUNC(dev->devfn) & 1))) - mode = 2; - return mode; + mask = 0x1f; + + return mask; } static u8 svwks_csb_check (struct pci_dev *dev) @@ -141,7 +147,7 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) if (xferspeed == 255) /* PIO auto-tuning */ speed = XFER_PIO_0 + pio; else - speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); + speed = ide_rate_filter(drive, xferspeed); /* If we are about to put a disk into UDMA mode we screwed up. Our code assumes we never _ever_ do this on an OSB4 */ @@ -304,7 +310,7 @@ static void svwks_tune_drive (ide_drive_t *drive, u8 pio) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, svwks_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!(speed)) speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); @@ -500,6 +506,7 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) hwif->tuneproc = &svwks_tune_drive; hwif->speedproc = &svwks_tune_chipset; + hwif->udma_filter = &svwks_udma_filter; hwif->atapi_dma = 1; diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index c0188de3cc66..5314ec913724 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -122,45 +122,41 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) } /** - * siimage_ratemask - Compute available modes - * @drive: IDE drive + * sil_udma_filter - compute UDMA mask + * @drive: IDE device + * + * Compute the available UDMA speeds for the device on the interface. * - * Compute the available speeds for the devices on the interface. * For the CMD680 this depends on the clocking mode (scsc), for the - * SI3312 SATA controller life is a bit simpler. Enforce UDMA33 - * as a limit if there is no 80pin cable present. + * SI3112 SATA controller life is a bit simpler. */ - -static byte siimage_ratemask (ide_drive_t *drive) + +static u8 sil_udma_filter(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - u8 mode = 0, scsc = 0; + ide_hwif_t *hwif = drive->hwif; unsigned long base = (unsigned long) hwif->hwif_data; + u8 mask = 0, scsc = 0; if (hwif->mmio) scsc = hwif->INB(base + 0x4A); else pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - if(is_sata(hwif)) - { - if(strstr(drive->id->model, "Maxtor")) - return 3; - return 4; + if (is_sata(hwif)) { + mask = strstr(drive->id->model, "Maxtor") ? 0x3f : 0x7f; + goto out; } - + if ((scsc & 0x30) == 0x10) /* 133 */ - mode = 4; + mask = 0x7f; else if ((scsc & 0x30) == 0x20) /* 2xPCI */ - mode = 4; + mask = 0x7f; else if ((scsc & 0x30) == 0x00) /* 100 */ - mode = 3; + mask = 0x3f; else /* Disabled ? */ BUG(); - - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; +out: + return mask; } /** @@ -306,7 +302,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) ide_hwif_t *hwif = HWIF(drive); u16 ultra = 0, multi = 0; u8 mode = 0, unit = drive->select.b.unit; - u8 speed = ide_rate_filter(siimage_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); unsigned long base = (unsigned long)hwif->hwif_data; u8 scsc = 0, addr_mask = ((hwif->channel) ? ((hwif->mmio) ? 0xF4 : 0x84) : @@ -389,7 +385,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, siimage_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; @@ -989,6 +985,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) hwif->tuneproc = &siimage_tuneproc; hwif->reset_poll = &siimage_reset_poll; hwif->pre_reset = &siimage_pre_reset; + hwif->udma_filter = &sil_udma_filter; if(is_sata(hwif)) { static int first = 1; diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 6fe4ecb6c06c..83c80ed73e99 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -428,16 +428,6 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) } #endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ -static u8 sis5513_ratemask (ide_drive_t *drive) -{ - u8 rates[] = { 0, 0, 1, 2, 3, 3, 4, 4 }; - u8 mode = rates[chipset_family]; - - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - /* * Configuration functions */ @@ -563,7 +553,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) u8 drive_pci, reg, speed; u32 regdw; - speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed); + speed = ide_rate_filter(drive, xferspeed); /* See config_art_rwp_pio for drive pci config registers */ drive_pci = 0x40; @@ -653,7 +643,7 @@ static void sis5513_tune_drive (ide_drive_t *drive, u8 pio) */ static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, sis5513_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); #ifdef DEBUG printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n", diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 852ccb36da1d..9e95a5cbf984 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -21,15 +21,6 @@ #include -static u8 slc90e66_ratemask (ide_drive_t *drive) -{ - u8 mode = 2; - - if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); - return mode; -} - static u8 slc90e66_dma_2_pio (u8 xfer_rate) { switch(xfer_rate) { case XFER_UDMA_4: @@ -122,7 +113,7 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(slc90e66_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); int sitre = 0, a_speed = 7 << (drive->dn * 4); int u_speed = 0, u_flag = 1 << drive->dn; u16 reg4042, reg44, reg48, reg4a; @@ -171,7 +162,7 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int slc90e66_config_drive_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 0b6d81d6ce48..168f035caa3f 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -13,18 +13,13 @@ #include #include -static inline u8 tc86c001_ratemask(ide_drive_t *drive) -{ - return eighty_ninty_three(drive) ? 2 : 1; -} - static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); u16 mode, scr = hwif->INW(scr_port); - speed = ide_rate_filter(tc86c001_ratemask(drive), speed); + speed = ide_rate_filter(drive, speed); switch (speed) { case XFER_UDMA_4: mode = 0x00c0; break; @@ -174,7 +169,7 @@ static int tc86c001_busproc(ide_drive_t *drive, int state) static int config_chipset_for_dma(ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive)); + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index 5e06179c3469..8a877235b949 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -48,7 +48,7 @@ static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) u16 timing = 0; u32 triflex_timings = 0; u8 unit = (drive->select.b.unit & 0x01); - u8 speed = ide_rate_filter(0, xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); pci_read_config_dword(dev, channel_offset, &triflex_timings); @@ -102,7 +102,7 @@ static void triflex_tune_drive(ide_drive_t *drive, u8 pio) static int triflex_config_drive_for_dma(ide_drive_t *drive) { - int speed = ide_dma_speed(drive, 0); /* No ultra speeds */ + u8 speed = ide_max_dma_mode(drive); if (!speed) return 0; diff --git a/include/linux/ide.h b/include/linux/ide.h index c9375c863584..23ab4dc05009 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -717,11 +717,8 @@ typedef struct hwif_s { int (*quirkproc)(ide_drive_t *); /* driver soft-power interface */ int (*busproc)(ide_drive_t *, int); -// /* host rate limiter */ -// u8 (*ratemask)(ide_drive_t *); -// /* device rate limiter */ -// u8 (*ratefilter)(ide_drive_t *, u8); #endif + u8 (*udma_filter)(ide_drive_t *); void (*ata_input_data)(ide_drive_t *, void *, u32); void (*ata_output_data)(ide_drive_t *, void *, u32); @@ -1279,6 +1276,7 @@ int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *); int __ide_dma_bad_drive(ide_drive_t *); int __ide_dma_good_drive(ide_drive_t *); int ide_use_dma(ide_drive_t *); +u8 ide_max_dma_mode(ide_drive_t *); void ide_dma_off(ide_drive_t *); void ide_dma_verbose(ide_drive_t *); int ide_set_dma(ide_drive_t *); @@ -1305,6 +1303,7 @@ extern int __ide_dma_timeout(ide_drive_t *); #else static inline int ide_use_dma(ide_drive_t *drive) { return 0; } +static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } static inline void ide_dma_off(ide_drive_t *drive) { ; } static inline void ide_dma_verbose(ide_drive_t *drive) { ; } static inline int ide_set_dma(ide_drive_t *drive) { return 1; } @@ -1349,8 +1348,7 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data) } /* ide-lib.c */ -extern u8 ide_dma_speed(ide_drive_t *drive, u8 mode); -extern u8 ide_rate_filter(u8 mode, u8 speed); +u8 ide_rate_filter(ide_drive_t *, u8); extern int ide_dma_enable(ide_drive_t *drive); extern char *ide_xfer_verbose(u8 xfer_rate); extern void ide_toggle_bounce(ide_drive_t *drive, int on); From 29e744d088e3555f4efbdf390f01088dd66993b6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:09 +0200 Subject: [PATCH 03/11] ide: add ide_tune_dma() helper After reworking the code responsible for selecting the best DMA transfer mode it is now possible to add generic ide_tune_dma() helper. Convert some IDE PCI host drivers to use it (the ones left need more work). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-dma.c | 20 ++++++++++++++++++++ drivers/ide/pci/aec62xx.c | 13 +------------ drivers/ide/pci/atiixp.c | 22 +--------------------- drivers/ide/pci/cs5535.c | 15 +-------------- drivers/ide/pci/hpt34x.c | 20 +------------------- drivers/ide/pci/hpt366.c | 20 +------------------- drivers/ide/pci/it8213.c | 21 +-------------------- drivers/ide/pci/jmicron.c | 21 +-------------------- drivers/ide/pci/piix.c | 26 +------------------------- drivers/ide/pci/sis5513.c | 21 +-------------------- drivers/ide/pci/slc90e66.c | 13 +------------ drivers/ide/pci/tc86c001.c | 13 +------------ drivers/ide/pci/triflex.c | 13 +------------ include/linux/ide.h | 2 ++ 14 files changed, 34 insertions(+), 206 deletions(-) diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index f28fabb791fe..5fe85191d49c 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -779,6 +779,26 @@ u8 ide_max_dma_mode(ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_max_dma_mode); +int ide_tune_dma(ide_drive_t *drive) +{ + u8 speed; + + /* TODO: use only ide_max_dma_mode() */ + if (!ide_use_dma(drive)) + return 0; + + speed = ide_max_dma_mode(drive); + + if (!speed) + return 0; + + drive->hwif->speedproc(drive, speed); + + return ide_dma_enable(drive); +} + +EXPORT_SYMBOL_GPL(ide_tune_dma); + void ide_dma_verbose(ide_drive_t *drive) { struct hd_driveid *id = drive->id; diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 099539e8c7a3..b173bc66ce1e 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -155,17 +155,6 @@ static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed) } } -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!(speed)) - return 0; - - (void) aec62xx_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -174,7 +163,7 @@ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) { - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index f7e80d6076d7..0e52ad722a72 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -206,26 +206,6 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } -/** - * atiixp_config_drive_for_dma - configure drive for DMA - * @drive: IDE drive to configure - * - * Set up a ATIIXP interface channel for the best available speed. - * We prefer UDMA if it is available and then MWDMA. If DMA is - * not available we switch to PIO and return 0. - */ - -static int atiixp_config_drive_for_dma(ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - (void) atiixp_speedproc(drive, speed); - return ide_dma_enable(drive); -} - /** * atiixp_dma_check - set up an IDE device * @drive: IDE drive to configure @@ -240,7 +220,7 @@ static int atiixp_dma_check(ide_drive_t *drive) drive->init_speed = 0; - if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) { diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index 66a101e470d0..41925c47ef05 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -164,26 +164,13 @@ static void cs5535_tuneproc(ide_drive_t *drive, u8 xferspeed) cs5535_set_speed(drive, xferspeed); } -static int cs5535_config_drive_for_dma(ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - /* If no DMA speed was available then let dma_check hit pio */ - if (!speed) { - return 0; - } - - cs5535_set_drive(drive, speed); - return ide_dma_enable(drive); -} - static int cs5535_dma_check(ide_drive_t *drive) { u8 speed; drive->init_speed = 0; - if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) { diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index 473e1b33dbf7..2c24c3de8846 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -84,29 +84,11 @@ static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio) (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); } -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initially for designed for - * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. - */ - -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!(speed)) - return 0; - - (void) hpt34x_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) #ifndef CONFIG_HPT34X_AUTODMA return -1; #else diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index de5ad9c35dc6..fcbc5605b38e 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -669,24 +669,6 @@ static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio); } -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initially designed for - * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. - * - */ -static int config_chipset_for_dma(ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - (void) hpt3xx_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static int hpt3xx_quirkproc(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -741,7 +723,7 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) { drive->init_speed = 0; - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index 02b56cb7bb1b..c04a02687b95 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -197,25 +197,6 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } -/* - * config_chipset_for_dma - configure for DMA - * @drive: drive to configure - * - * Called by the IDE layer when it wants the timings set up. - */ - -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - it8213_tune_chipset(drive, speed); - - return ide_dma_enable(drive); -} - /** * it8213_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -230,7 +211,7 @@ static int it8213_config_drive_for_dma (ide_drive_t *drive) { u8 pio; - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; pio = ide_get_best_pio_mode(drive, 255, 4, NULL); diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index dbb3c199cba9..76ed25147229 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -118,25 +118,6 @@ static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) return ide_config_drive_speed(drive, speed); } -/** - * config_chipset_for_dma - configure for DMA - * @drive: drive to configure - * - * As the JMicron snoops for timings all we actually need to do is - * make sure we don't set an invalid mode. - */ - -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - jmicron_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - /** * jmicron_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -147,7 +128,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) static int jmicron_config_drive_for_dma (ide_drive_t *drive) { - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; config_jmicron_chipset_for_pio(drive, 1); diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 84d3938a430a..8b219dd63024 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -303,30 +303,6 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } -/** - * piix_config_drive_for_dma - configure drive for DMA - * @drive: IDE drive to configure - * - * Set up a PIIX interface channel for the best available speed. - * We prefer UDMA if it is available and then MWDMA. If DMA is - * not available we switch to PIO and return 0. - */ - -static int piix_config_drive_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - /* - * If no DMA speed was available or the chipset has DMA bugs - * then disable DMA and use PIO - */ - if (!speed) - return 0; - - (void) piix_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - /** * piix_config_drive_xfer_rate - set up an IDE device * @drive: IDE drive to configure @@ -339,7 +315,7 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_use_dma(drive) && piix_config_drive_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 83c80ed73e99..41953fe4fa6b 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -638,32 +638,13 @@ static void sis5513_tune_drive (ide_drive_t *drive, u8 pio) (void) config_chipset_for_pio(drive, pio); } -/* - * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - -#ifdef DEBUG - printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n", - drive->dn, drive->id->dma_ultra); -#endif - - if (!(speed)) - return 0; - - sis5513_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static int sis5513_config_xfer_rate(ide_drive_t *drive) { config_art_rwp_pio(drive, 5); drive->init_speed = 0; - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 9e95a5cbf984..c40f291f91e0 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -160,22 +160,11 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } -static int slc90e66_config_drive_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - (void) slc90e66_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 168f035caa3f..cee619bb2eaf 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -167,20 +167,9 @@ static int tc86c001_busproc(ide_drive_t *drive, int state) return 0; } -static int config_chipset_for_dma(ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - (void) tc86c001_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) { - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index 8a877235b949..35e8c612638f 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -100,20 +100,9 @@ static void triflex_tune_drive(ide_drive_t *drive, u8 pio) (void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio)); } -static int triflex_config_drive_for_dma(ide_drive_t *drive) -{ - u8 speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - (void) triflex_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - static int triflex_config_drive_xfer_rate(ide_drive_t *drive) { - if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive)) + if (ide_tune_dma(drive)) return 0; triflex_tune_drive(drive, 255); diff --git a/include/linux/ide.h b/include/linux/ide.h index 23ab4dc05009..d03fa2d5d75a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1277,6 +1277,7 @@ int __ide_dma_bad_drive(ide_drive_t *); int __ide_dma_good_drive(ide_drive_t *); int ide_use_dma(ide_drive_t *); u8 ide_max_dma_mode(ide_drive_t *); +int ide_tune_dma(ide_drive_t *); void ide_dma_off(ide_drive_t *); void ide_dma_verbose(ide_drive_t *); int ide_set_dma(ide_drive_t *); @@ -1304,6 +1305,7 @@ extern int __ide_dma_timeout(ide_drive_t *); #else static inline int ide_use_dma(ide_drive_t *drive) { return 0; } static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } +static inline int ide_tune_dma(ide_drive_t *drive) { return 0; } static inline void ide_dma_off(ide_drive_t *drive) { ; } static inline void ide_dma_verbose(ide_drive_t *drive) { ; } static inline int ide_set_dma(ide_drive_t *drive) { return 1; } From ecfd80e4a514123070b4cfb674b817ba75055df2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:09 +0200 Subject: [PATCH 04/11] ide: make /proc/ide/ optional All important information/features should be already available through sysfs and ioctl interfaces. Add CONFIG_IDE_PROC_FS (CONFIG_SCSI_PROC_FS rip-off) config option, disabling it makes IDE driver ~5 kB smaller (on x86-32). While at it add CONFIG_PROC_FS=n versions of proc_ide_{create,destroy}() and remove no longer needed #ifdefs. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 11 +++++++++++ drivers/ide/Makefile | 2 +- drivers/ide/ide-cd.c | 4 ++-- drivers/ide/ide-disk.c | 4 ++-- drivers/ide/ide-floppy.c | 4 ++-- drivers/ide/ide-tape.c | 2 +- drivers/ide/ide.c | 15 ++++++--------- drivers/ide/pci/alim15x3.c | 8 ++++---- drivers/ide/pci/amd74xx.c | 6 +++--- drivers/ide/pci/cmd64x.c | 8 ++++---- drivers/ide/pci/sis5513.c | 6 +++--- drivers/scsi/ide-scsi.c | 2 +- include/linux/ide.h | 14 ++++++++------ 13 files changed, 48 insertions(+), 38 deletions(-) diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 5bdf64b77913..a678bbecb489 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -291,6 +291,17 @@ config IDE_TASK_IOCTL If you are unsure, say N here. +config IDE_PROC_FS + bool "legacy /proc/ide/ support" + depends on IDE && PROC_FS + default y + help + This option enables support for the various files in + /proc/ide. In Linux 2.6 this has been superseded by + files in sysfs but many legacy applications rely on this. + + If unsure say Y. + comment "IDE chipset support/bugfixes" config IDE_GENERIC diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d9f029e8ff74..75dc6969e0a7 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -20,7 +20,7 @@ ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o # Core IDE code - must come before legacy ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o -ide-core-$(CONFIG_PROC_FS) += ide-proc.o +ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 638becda81c6..c3a0079789fd 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3274,7 +3274,7 @@ int ide_cdrom_setup (ide_drive_t *drive) return 0; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS static sector_t ide_cdrom_capacity (ide_drive_t *drive) { @@ -3321,7 +3321,7 @@ static void ide_cd_release(struct kref *kref) static int ide_cd_probe(ide_drive_t *); -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS static int proc_idecd_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 37aa6ddd9702..e7bc4d35c40c 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -559,7 +559,7 @@ static sector_t idedisk_capacity (ide_drive_t *drive) return drive->capacity64 - drive->sect0; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS static int smart_enable(ide_drive_t *drive) { @@ -683,7 +683,7 @@ static ide_proc_entry_t idedisk_proc[] = { #define idedisk_proc NULL -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_IDE_PROC_FS */ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) { diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 57cd21c5b2c1..84d398f71e0f 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1892,7 +1892,7 @@ static void ide_floppy_release(struct kref *kref) kfree(floppy); } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS static int proc_idefloppy_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) @@ -1914,7 +1914,7 @@ static ide_proc_entry_t idefloppy_proc[] = { #define idefloppy_proc NULL -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_IDE_PROC_FS */ static int ide_floppy_probe(ide_drive_t *); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 4e59239fef75..ad306ae24e24 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4730,7 +4730,7 @@ static void ide_tape_release(struct kref *kref) kfree(tape); } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS static int proc_idetape_read_name (char *page, char **start, off_t off, int count, int *eof, void *data) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 73f752142f9e..7a96f6f07494 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -350,7 +350,7 @@ static int ide_system_bus_speed(void) return system_bus_speed; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS struct proc_dir_entry *proc_ide_root; #endif @@ -1892,7 +1892,7 @@ static void __init probe_for_hwifs (void) void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS ide_add_proc_entries(drive->proc, driver->proc, drive); #endif } @@ -1914,8 +1914,8 @@ EXPORT_SYMBOL(ide_register_subdriver); void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; - -#ifdef CONFIG_PROC_FS + +#ifdef CONFIG_IDE_PROC_FS ide_remove_proc_entries(drive->proc, driver->proc); #endif down(&ide_setting_sem); @@ -2069,7 +2069,7 @@ static int __init ide_init(void) init_ide_data(); -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS proc_ide_root = proc_mkdir("ide", NULL); #endif @@ -2099,9 +2099,8 @@ static int __init ide_init(void) probe_for_hwifs(); initializing = 0; -#ifdef CONFIG_PROC_FS proc_ide_create(); -#endif + return 0; } @@ -2141,9 +2140,7 @@ void __exit cleanup_module (void) pnpide_exit(); #endif -#ifdef CONFIG_PROC_FS proc_ide_destroy(); -#endif bus_unregister(&ide_bus_type); } diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 76643b626bdd..428efdae0c7b 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -50,7 +50,7 @@ static u8 m5229_revision; static u8 chip_is_1543c_e; static struct pci_dev *isa_dev; -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) #include #include @@ -278,7 +278,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count) return p-buffer; /* => must be less than 4k! */ } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ /** * ali15x3_tune_pio - set up chipset for PIO mode @@ -566,13 +566,13 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) if (!ali_proc) { ali_proc = 1; bmide_dev = dev; ide_pci_create_host_proc("ali", ali_get_info); } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ local_irq_save(flags); diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 7989bdd842a2..becb1a5648b0 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -92,7 +92,7 @@ static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3 * AMD /proc entry. */ -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS #include #include @@ -402,14 +402,14 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch * Register /proc/ide/amd74xx entry */ -#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_IDE_PROC_FS) if (!amd74xx_proc) { amd_base = pci_resource_start(dev, 4); bmide_dev = dev; ide_pci_create_host_proc("amd74xx", amd74xx_get_info); amd74xx_proc = 1; } -#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ +#endif /* DISPLAY_AMD_TIMINGS && CONFIG_IDE_PROC_FS */ return dev->irq; } diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 19f5ac1f866c..61ea96b5555c 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -74,7 +74,7 @@ #define UDIDETCR1 0x7B #define DTPR1 0x7C -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) #include #include @@ -165,7 +165,7 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) return p-buffer; /* => must be less than 4k! */ } -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ static u8 quantize_timing(int timing, int quant) { @@ -548,7 +548,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); #endif /* CONFIG_PPC */ -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) cmd_devs[n_cmd_devs++] = dev; @@ -556,7 +556,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha cmd64x_proc = 1; ide_pci_create_host_proc("cmd64x", cmd64x_get_info); } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ +#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */ return 0; } diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 41953fe4fa6b..2bde1b92784a 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -191,7 +191,7 @@ static char* chipset_capability[] = { "ATA 133 (1st gen)", "ATA 133 (2nd gen)" }; -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) #include #include @@ -426,7 +426,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) return len > count ? count : len; } -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ /* * Configuration functions @@ -797,7 +797,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c break; } -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) if (!sis_proc) { sis_proc = 1; bmide_dev = dev; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 2b5b8a93bc10..531df3a29c47 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -770,7 +770,7 @@ static void ide_scsi_remove(ide_drive_t *drive) static int ide_scsi_probe(ide_drive_t *); -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS static ide_proc_entry_t idescsi_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL } diff --git a/include/linux/ide.h b/include/linux/ide.h index d03fa2d5d75a..697c39dd66a1 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -912,15 +912,15 @@ typedef struct { write_proc_t *write_proc; } ide_proc_entry_t; -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_IDE_PROC_FS extern struct proc_dir_entry *proc_ide_root; -extern void proc_ide_create(void); -extern void proc_ide_destroy(void); -extern void create_proc_ide_interfaces(void); +void proc_ide_create(void); +void proc_ide_destroy(void); +void create_proc_ide_interfaces(void); void destroy_proc_ide_interface(ide_hwif_t *); -extern void ide_add_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *, void *); -extern void ide_remove_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *); +void ide_add_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *, void *); +void ide_remove_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *); read_proc_t proc_ide_read_capacity; read_proc_t proc_ide_read_geometry; @@ -944,6 +944,8 @@ void ide_pci_create_host_proc(const char *, get_info_t *); return len; \ } #else +static inline void proc_ide_create(void) { ; } +static inline void proc_ide_destroy(void) { ; } static inline void create_proc_ide_interfaces(void) { ; } static inline void destroy_proc_ide_interface(ide_hwif_t *hwif) { ; } #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; From 1497943ee692aa7519fa972d0e3a339649bf3a96 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:10 +0200 Subject: [PATCH 05/11] ide: split off ioctl handling from IDE settings (v2) * do write permission and min/max checks in ide_procset_t functions * ide-disk.c: drive->id is always available so cleanup "multcount" setting accordingly * ide-disk.c: "address" setting was incorrectly defined as type TYPE_INTA, fix it by using type TYPE_BYTE and updating ide_drive_t->adressing field, the bug didn't trigger because this IDE setting uses custom ->set function * ide.c: add set_ksettings() for handling HDIO_SET_KEEPSETTINGS ioctl * ide.c: add set_unmaskirq() for handling HDIO_SET_UNMASKINTR ioctl * handle ioctls directly in generic_ide_ioclt() and idedisk_ioctl() instead of using IDE settings to deal with them * remove no longer needed ide_find_setting_by_ioctl() and {read,write}_ioctl fields from ide_settings_t, also remove now unused TYPE_INTA handling v2: * add missing EXPORT_SYMBOL_GPL(ide_setting_sem) needed now for ide-disk Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 2 +- drivers/ide/ide-disk.c | 81 +++++++++++++++--- drivers/ide/ide-floppy.c | 10 +-- drivers/ide/ide-tape.c | 30 +++---- drivers/ide/ide.c | 176 +++++++++++++++++++++++---------------- drivers/scsi/ide-scsi.c | 12 +-- include/linux/ide.h | 16 +--- 7 files changed, 203 insertions(+), 124 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index c3a0079789fd..29408cfd9869 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3061,7 +3061,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) static void ide_cdrom_add_settings(ide_drive_t *drive) { - ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); + ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); } /* diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index e7bc4d35c40c..fb162cb3ebf5 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -737,6 +737,9 @@ static int set_multcount(ide_drive_t *drive, int arg) { struct request rq; + if (arg < 0 || arg > drive->id->max_multsect) + return -EINVAL; + if (drive->special.b.set_multmode) return -EBUSY; ide_init_drive_cmd (&rq); @@ -749,6 +752,9 @@ static int set_multcount(ide_drive_t *drive, int arg) static int set_nowerr(ide_drive_t *drive, int arg) { + if (arg < 0 || arg > 1) + return -EINVAL; + if (ide_spin_wait_hwgroup(drive)) return -EBUSY; drive->nowerr = arg; @@ -800,6 +806,9 @@ static int write_cache(ide_drive_t *drive, int arg) ide_task_t args; int err = 1; + if (arg < 0 || arg > 1) + return -EINVAL; + if (ide_id_has_flush_cache(drive->id)) { memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? @@ -835,6 +844,9 @@ static int set_acoustic (ide_drive_t *drive, int arg) { ide_task_t args; + if (arg < 0 || arg > 254) + return -EINVAL; + memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM; @@ -855,6 +867,9 @@ static int set_acoustic (ide_drive_t *drive, int arg) */ static int set_lba_addressing(ide_drive_t *drive, int arg) { + if (arg < 0 || arg > 2) + return -EINVAL; + drive->addressing = 0; if (HWIF(drive)->no_lba48) @@ -870,18 +885,18 @@ static void idedisk_add_settings(ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); - ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); - ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); - ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); - ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); - ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); - ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); + ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); + ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); + ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); + ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); + ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); + ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); + ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); + ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } static void idedisk_setup (ide_drive_t *drive) @@ -1140,9 +1155,49 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int idedisk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + unsigned long flags; struct block_device *bdev = inode->i_bdev; struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); - return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); + ide_drive_t *drive = idkp->drive; + int err, (*setfunc)(ide_drive_t *, int); + u8 *val; + + switch (cmd) { + case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; + case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; + case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; + case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; + case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; + case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; + case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; + case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; + case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; + case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; + } + + return generic_ide_ioctl(drive, file, bdev, cmd, arg); + +read_val: + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); + err = *val; + spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); + return err >= 0 ? put_user(err, (long __user *)arg) : err; + +set_val: + if (bdev != bdev->bd_contains) + err = -EINVAL; + else { + if (!capable(CAP_SYS_ADMIN)) + err = -EACCES; + else { + down(&ide_setting_sem); + err = setfunc(drive, arg); + up(&ide_setting_sem); + } + } + return err; } static int idedisk_media_changed(struct gendisk *disk) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 84d398f71e0f..38fe45cf4019 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1816,12 +1816,12 @@ static void idefloppy_add_settings(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; /* - * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "ticks", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); } /* diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index ad306ae24e24..fa0d22de37a7 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4566,22 +4566,22 @@ static void idetape_add_settings (ide_drive_t *drive) idetape_tape_t *tape = drive->driver_data; /* - * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); - ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); - ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); - ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); - ide_add_setting(drive, "stage", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); - ide_add_setting(drive, "tdsc", SETTING_RW, -1, -1, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); - ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); - ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); - ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); - ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); - ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); + ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); + ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); + ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); + ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); + ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); + ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); + ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); + ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); + ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); + ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); + ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); + ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed,NULL); + ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); + ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); } /* diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 7a96f6f07494..8793a960210c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -823,13 +823,13 @@ EXPORT_SYMBOL(ide_register_hw); DECLARE_MUTEX(ide_setting_sem); +EXPORT_SYMBOL_GPL(ide_setting_sem); + /** * __ide_add_setting - add an ide setting option * @drive: drive to use * @name: setting name * @rw: true if the function is read write - * @read_ioctl: function to call on read - * @write_ioctl: function to call on write * @data_type: type of data * @min: range minimum * @max: range maximum @@ -850,7 +850,7 @@ DECLARE_MUTEX(ide_setting_sem); * remove. */ -static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; @@ -863,8 +863,6 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r goto abort; strcpy(setting->name, name); setting->rw = rw; - setting->read_ioctl = read_ioctl; - setting->write_ioctl = write_ioctl; setting->data_type = data_type; setting->min = min; setting->max = max; @@ -885,9 +883,9 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r return -1; } -int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) { - return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); + return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); } EXPORT_SYMBOL(ide_add_setting); @@ -918,29 +916,6 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name) kfree(setting); } -/** - * ide_find_setting_by_ioctl - find a drive specific ioctl - * @drive: drive to scan - * @cmd: ioctl command to handle - * - * Scan's the device setting table for a matching entry and returns - * this or NULL if no entry is found. The caller must hold the - * setting semaphore - */ - -static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (setting->read_ioctl == cmd || setting->write_ioctl == cmd) - break; - setting = setting->next; - } - - return setting; -} - /** * ide_find_setting_by_name - find a drive specific setting * @drive: drive to scan @@ -1014,7 +989,6 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) val = *((u16 *) setting->data); break; case TYPE_INT: - case TYPE_INTA: val = *((u32 *) setting->data); break; } @@ -1076,17 +1050,14 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup); int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { - int i; - u32 *p; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (setting->set) + return setting->set(drive, val); if (!(setting->rw & SETTING_WRITE)) return -EPERM; if (val < setting->min || val > setting->max) return -EINVAL; - if (setting->set) - return setting->set(drive, val); if (ide_spin_wait_hwgroup(drive)) return -EBUSY; switch (setting->data_type) { @@ -1099,11 +1070,6 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) case TYPE_INT: *((u32 *) setting->data) = val; break; - case TYPE_INTA: - p = (u32 *) setting->data; - for (i = 0; i < 1 << PARTN_BITS; i++, p++) - *p = val; - break; } spin_unlock_irq(&ide_lock); return 0; @@ -1111,6 +1077,12 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) static int set_io_32bit(ide_drive_t *drive, int arg) { + if (drive->no_io_32bit) + return -EPERM; + + if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) + return -EINVAL; + drive->io_32bit = arg; #ifdef CONFIG_BLK_DEV_DTC2278 if (HWIF(drive)->chipset == ide_dtc2278) @@ -1119,12 +1091,28 @@ static int set_io_32bit(ide_drive_t *drive, int arg) return 0; } +static int set_ksettings(ide_drive_t *drive, int arg) +{ + if (arg < 0 || arg > 1) + return -EINVAL; + + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + drive->keep_settings = arg; + spin_unlock_irq(&ide_lock); + + return 0; +} + static int set_using_dma (ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = drive->hwif; int err = -EPERM; + if (arg < 0 || arg > 1) + return -EINVAL; + if (!drive->id || !(drive->id->capability & 1)) goto out; @@ -1157,6 +1145,9 @@ static int set_using_dma (ide_drive_t *drive, int arg) out: return err; #else + if (arg < 0 || arg > 1) + return -EINVAL; + return -EPERM; #endif } @@ -1165,6 +1156,9 @@ static int set_pio_mode (ide_drive_t *drive, int arg) { struct request rq; + if (arg < 0 || arg > 255) + return -EINVAL; + if (!HWIF(drive)->tuneproc) return -ENOSYS; if (drive->special.b.set_tune) @@ -1176,9 +1170,30 @@ static int set_pio_mode (ide_drive_t *drive, int arg) return 0; } +static int set_unmaskirq(ide_drive_t *drive, int arg) +{ + if (drive->no_unmask) + return -EPERM; + + if (arg < 0 || arg > 1) + return -EINVAL; + + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + drive->unmask = arg; + spin_unlock_irq(&ide_lock); + + return 0; +} + static int set_xfer_rate (ide_drive_t *drive, int arg) { - int err = ide_wait_cmd(drive, + int err; + + if (arg < 0 || arg > 70) + return -EINVAL; + + err = ide_wait_cmd(drive, WIN_SETFEATURES, (u8) arg, SETFEATURES_XFER, 0, NULL); @@ -1193,25 +1208,24 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) * ide_add_generic_settings - generic ide settings * @drive: drive being configured * - * Add the generic parts of the system settings to the /proc files and - * ioctls for this IDE device. The caller must not be holding the - * ide_setting_sem. + * Add the generic parts of the system settings to the /proc files. + * The caller must not be holding the ide_setting_sem. */ void ide_add_generic_settings (ide_drive_t *drive) { /* - * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write access data type min max mul_factor div_factor data pointer set function */ - __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); - __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); - __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); - __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); - __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); - __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); - __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); - __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); - __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); } /** @@ -1283,27 +1297,23 @@ static int generic_ide_resume(struct device *dev) int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { - ide_settings_t *setting; + unsigned long flags; ide_driver_t *drv; - int err = 0; void __user *p = (void __user *)arg; + int err = 0, (*setfunc)(ide_drive_t *, int); + u8 *val; - down(&ide_setting_sem); - if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { - if (cmd == setting->read_ioctl) { - err = ide_read_setting(drive, setting); - up(&ide_setting_sem); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - } else { - if (bdev != bdev->bd_contains) - err = -EINVAL; - else - err = ide_write_setting(drive, setting, arg); - up(&ide_setting_sem); - return err; - } + switch (cmd) { + case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; + case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; + case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; + case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; + case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; + case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; + case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; + case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val; + case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val; } - up(&ide_setting_sem); switch (cmd) { case HDIO_OBSOLETE_IDENTITY: @@ -1432,6 +1442,28 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device default: return -EINVAL; } + +read_val: + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); + err = *val; + spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); + return err >= 0 ? put_user(err, (long __user *)arg) : err; + +set_val: + if (bdev != bdev->bd_contains) + err = -EINVAL; + else { + if (!capable(CAP_SYS_ADMIN)) + err = -EACCES; + else { + down(&ide_setting_sem); + err = setfunc(drive, arg); + up(&ide_setting_sem); + } + } + return err; } EXPORT_SYMBOL(generic_ide_ioctl); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 531df3a29c47..4388b8ab69a1 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -726,13 +726,13 @@ static void idescsi_add_settings(ide_drive_t *drive) idescsi_scsi_t *scsi = drive_to_idescsi(drive); /* - * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function + * drive setting name read/write data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "transform", SETTING_RW, -1, -1, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); - ide_add_setting(drive, "log", SETTING_RW, -1, -1, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); + ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); } /* diff --git a/include/linux/ide.h b/include/linux/ide.h index 697c39dd66a1..591a0b55e31c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -601,16 +601,11 @@ typedef struct ide_drive_s { unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */ unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */ unsigned vdma : 1; /* 1=doing PIO over DMA 0=doing normal DMA */ - unsigned addressing; /* : 3; - * 0=28-bit - * 1=48-bit - * 2=48-bit doing 28-bit - * 3=64-bit - */ unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */ unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ unsigned post_reset : 1; + u8 addressing; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */ u8 quirk_list; /* considered quirky, set for a specific host */ u8 init_speed; /* transfer rate set at boot */ u8 current_speed; /* current transfer rate set */ @@ -870,9 +865,8 @@ typedef struct hwgroup_s { */ #define TYPE_INT 0 -#define TYPE_INTA 1 -#define TYPE_BYTE 2 -#define TYPE_SHORT 3 +#define TYPE_BYTE 1 +#define TYPE_SHORT 2 #define SETTING_READ (1 << 0) #define SETTING_WRITE (1 << 1) @@ -882,8 +876,6 @@ typedef int (ide_procset_t)(ide_drive_t *, int); typedef struct ide_settings_s { char *name; int rw; - int read_ioctl; - int write_ioctl; int data_type; int min; int max; @@ -896,7 +888,7 @@ typedef struct ide_settings_s { } ide_settings_t; extern struct semaphore ide_setting_sem; -extern int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set); +int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set); extern ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name); extern int ide_read_setting(ide_drive_t *t, ide_settings_t *setting); extern int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val); From 7662d046df09e80680b77b68de896beab45e675e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:10 +0200 Subject: [PATCH 06/11] ide: move IDE settings handling to ide-proc.c * move __ide_add_setting() ide_add_setting() __ide_remove_setting() auto_remove_settings() ide_find_setting_by_name() ide_read_setting() ide_write_setting() set_xfer_rate() ide_add_generic_settings() ide_register_subdriver() ide_unregister_subdriver() from ide.c to ide-proc.c * set_{io_32bit,pio_mode,using_dma}() cannot be marked static now, fix it * rename ide_[un]register_subdriver() to ide_proc_[un]register_driver(), update device drivers to use new names * add CONFIG_IDE_PROC_FS=n versions of ide_proc_[un]register_driver() and ide_add_generic_settings() * make ide_find_setting_by_name(), ide_{read,write}_setting() and ide_{add,remove}_proc_entries() static * cover IDE settings code in device drivers with CONFIG_IDE_PROC_FS #ifdef, also while at it cover with CONFIG_IDE_PROC_FS #ifdef ide_driver_t.proc * remove bogus comment from ide.h * cover with CONFIG_IDE_PROC_FS #ifdef .proc and .settings in ide_drive_t Besides saner code this patch results in the IDE core smaller by ~2 kB (on x86-32) and IDE disk driver by ~1 kB (ditto) when CONFIG_IDE_PROC_FS=n. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 14 +- drivers/ide/ide-disk.c | 16 +- drivers/ide/ide-floppy.c | 16 +- drivers/ide/ide-proc.c | 310 +++++++++++++++++++++++++++++++++++++- drivers/ide/ide-tape.c | 17 ++- drivers/ide/ide.c | 313 +-------------------------------------- drivers/scsi/ide-scsi.c | 16 +- include/linux/ide.h | 39 +++-- 8 files changed, 378 insertions(+), 363 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 29408cfd9869..252ab8295edf 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3059,10 +3059,14 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) return nslots; } +#ifdef CONFIG_IDE_PROC_FS static void ide_cdrom_add_settings(ide_drive_t *drive) { ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); } +#else +static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } +#endif /* * standard prep_rq_fn that builds 10 byte cmds @@ -3291,7 +3295,7 @@ static void ide_cd_remove(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; - ide_unregister_subdriver(drive, info->driver); + ide_proc_unregister_driver(drive, info->driver); del_gendisk(info->disk); @@ -3336,8 +3340,6 @@ static ide_proc_entry_t idecd_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, { NULL, 0, NULL, NULL } }; -#else -# define idecd_proc NULL #endif static ide_driver_t ide_cdrom_driver = { @@ -3355,7 +3357,9 @@ static ide_driver_t ide_cdrom_driver = { .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, +#ifdef CONFIG_IDE_PROC_FS .proc = idecd_proc, +#endif }; static int idecd_open(struct inode * inode, struct file * file) @@ -3517,7 +3521,7 @@ static int ide_cd_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_register_subdriver(drive, &ide_cdrom_driver); + ide_proc_register_driver(drive, &ide_cdrom_driver); kref_init(&info->kref); @@ -3534,7 +3538,7 @@ static int ide_cd_probe(ide_drive_t *drive) g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; - ide_unregister_subdriver(drive, &ide_cdrom_driver); + ide_proc_unregister_driver(drive, &ide_cdrom_driver); kfree(info->buffer); kfree(info->toc); kfree(info->changer_info); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index fb162cb3ebf5..7fff773f2df7 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -560,7 +560,6 @@ static sector_t idedisk_capacity (ide_drive_t *drive) } #ifdef CONFIG_IDE_PROC_FS - static int smart_enable(ide_drive_t *drive) { ide_task_t args; @@ -678,11 +677,6 @@ static ide_proc_entry_t idedisk_proc[] = { { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, { NULL, 0, NULL, NULL } }; - -#else - -#define idedisk_proc NULL - #endif /* CONFIG_IDE_PROC_FS */ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) @@ -881,6 +875,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) return 0; } +#ifdef CONFIG_IDE_PROC_FS static void idedisk_add_settings(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -898,6 +893,9 @@ static void idedisk_add_settings(ide_drive_t *drive) ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } +#else +static inline void idedisk_add_settings(ide_drive_t *drive) { ; } +#endif static void idedisk_setup (ide_drive_t *drive) { @@ -1016,7 +1014,7 @@ static void ide_disk_remove(ide_drive_t *drive) struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = idkp->disk; - ide_unregister_subdriver(drive, idkp->driver); + ide_proc_unregister_driver(drive, idkp->driver); del_gendisk(g); @@ -1081,7 +1079,9 @@ static ide_driver_t idedisk_driver = { .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, +#ifdef CONFIG_IDE_PROC_FS .proc = idedisk_proc, +#endif }; static int idedisk_open(struct inode *inode, struct file *filp) @@ -1257,7 +1257,7 @@ static int ide_disk_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_register_subdriver(drive, &idedisk_driver); + ide_proc_register_driver(drive, &idedisk_driver); kref_init(&idkp->kref); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 38fe45cf4019..f429be88c4f9 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1811,6 +1811,7 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) return 0; } +#ifdef CONFIG_IDE_PROC_FS static void idefloppy_add_settings(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -1823,6 +1824,9 @@ static void idefloppy_add_settings(ide_drive_t *drive) ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); } +#else +static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } +#endif /* * Driver initialization. @@ -1873,7 +1877,7 @@ static void ide_floppy_remove(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; - ide_unregister_subdriver(drive, floppy->driver); + ide_proc_unregister_driver(drive, floppy->driver); del_gendisk(g); @@ -1893,7 +1897,6 @@ static void ide_floppy_release(struct kref *kref) } #ifdef CONFIG_IDE_PROC_FS - static int proc_idefloppy_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1909,11 +1912,6 @@ static ide_proc_entry_t idefloppy_proc[] = { { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL } }; - -#else - -#define idefloppy_proc NULL - #endif /* CONFIG_IDE_PROC_FS */ static int ide_floppy_probe(ide_drive_t *); @@ -1933,7 +1931,9 @@ static ide_driver_t idefloppy_driver = { .end_request = idefloppy_do_end_request, .error = __ide_error, .abort = __ide_abort, +#ifdef CONFIG_IDE_PROC_FS .proc = idefloppy_proc, +#endif }; static int idefloppy_open(struct inode *inode, struct file *filp) @@ -2159,7 +2159,7 @@ static int ide_floppy_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_register_subdriver(drive, &idefloppy_driver); + ide_proc_register_driver(drive, &idefloppy_driver); kref_init(&floppy->kref); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a9e0b30fb1f2..949a6f609d84 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -3,6 +3,8 @@ * * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 2003 Red Hat + * + * Some code was moved here from ide.c, see it for original copyrights. */ /* @@ -121,6 +123,265 @@ static int proc_ide_read_identify PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +/** + * __ide_add_setting - add an ide setting option + * @drive: drive to use + * @name: setting name + * @rw: true if the function is read write + * @data_type: type of data + * @min: range minimum + * @max: range maximum + * @mul_factor: multiplication scale + * @div_factor: divison scale + * @data: private data field + * @set: setting + * @auto_remove: setting auto removal flag + * + * Removes the setting named from the device if it is present. + * The function takes the settings_lock to protect against + * parallel changes. This function must not be called from IRQ + * context. Returns 0 on success or -1 on failure. + * + * BUGS: This code is seriously over-engineered. There is also + * magic about how the driver specific features are setup. If + * a driver is attached we assume the driver settings are auto + * remove. + */ + +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) +{ + ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; + + down(&ide_setting_sem); + while ((*p) && strcmp((*p)->name, name) < 0) + p = &((*p)->next); + if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) + goto abort; + if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) + goto abort; + strcpy(setting->name, name); + setting->rw = rw; + setting->data_type = data_type; + setting->min = min; + setting->max = max; + setting->mul_factor = mul_factor; + setting->div_factor = div_factor; + setting->data = data; + setting->set = set; + + setting->next = *p; + if (auto_remove) + setting->auto_remove = 1; + *p = setting; + up(&ide_setting_sem); + return 0; +abort: + up(&ide_setting_sem); + kfree(setting); + return -1; +} + +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +{ + return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); +} + +EXPORT_SYMBOL(ide_add_setting); + +/** + * __ide_remove_setting - remove an ide setting option + * @drive: drive to use + * @name: setting name + * + * Removes the setting named from the device if it is present. + * The caller must hold the setting semaphore. + */ + +static void __ide_remove_setting (ide_drive_t *drive, char *name) +{ + ide_settings_t **p, *setting; + + p = (ide_settings_t **) &drive->settings; + + while ((*p) && strcmp((*p)->name, name)) + p = &((*p)->next); + if ((setting = (*p)) == NULL) + return; + + (*p) = setting->next; + + kfree(setting->name); + kfree(setting); +} + +/** + * auto_remove_settings - remove driver specific settings + * @drive: drive + * + * Automatically remove all the driver specific settings for this + * drive. This function may not be called from IRQ context. The + * caller must hold ide_setting_sem. + */ + +static void auto_remove_settings (ide_drive_t *drive) +{ + ide_settings_t *setting; +repeat: + setting = drive->settings; + while (setting) { + if (setting->auto_remove) { + __ide_remove_setting(drive, setting->name); + goto repeat; + } + setting = setting->next; + } +} + +/** + * ide_find_setting_by_name - find a drive specific setting + * @drive: drive to scan + * @name: setting name + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + +static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) +{ + ide_settings_t *setting = drive->settings; + + while (setting) { + if (strcmp(setting->name, name) == 0) + break; + setting = setting->next; + } + return setting; +} + +/** + * ide_read_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * + * Read a drive setting and return the value. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + */ + +static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) +{ + int val = -EINVAL; + unsigned long flags; + + if ((setting->rw & SETTING_READ)) { + spin_lock_irqsave(&ide_lock, flags); + switch(setting->data_type) { + case TYPE_BYTE: + val = *((u8 *) setting->data); + break; + case TYPE_SHORT: + val = *((u16 *) setting->data); + break; + case TYPE_INT: + val = *((u32 *) setting->data); + break; + } + spin_unlock_irqrestore(&ide_lock, flags); + } + return val; +} + +/** + * ide_write_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * @val: value + * + * Write a drive setting if it is possible. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + * + * FIXME: This should be changed to enqueue a special request + * to the driver to change settings, and then wait on a sema for completion. + * The current scheme of polling is kludgy, though safe enough. + */ + +static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (setting->set) + return setting->set(drive, val); + if (!(setting->rw & SETTING_WRITE)) + return -EPERM; + if (val < setting->min || val > setting->max) + return -EINVAL; + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + switch (setting->data_type) { + case TYPE_BYTE: + *((u8 *) setting->data) = val; + break; + case TYPE_SHORT: + *((u16 *) setting->data) = val; + break; + case TYPE_INT: + *((u32 *) setting->data) = val; + break; + } + spin_unlock_irq(&ide_lock); + return 0; +} + +static int set_xfer_rate (ide_drive_t *drive, int arg) +{ + int err; + + if (arg < 0 || arg > 70) + return -EINVAL; + + err = ide_wait_cmd(drive, + WIN_SETFEATURES, (u8) arg, + SETFEATURES_XFER, 0, NULL); + + if (!err && arg) { + ide_set_xfer_rate(drive, (u8) arg); + ide_driveid_update(drive); + } + return err; +} + +/** + * ide_add_generic_settings - generic ide settings + * @drive: drive being configured + * + * Add the generic parts of the system settings to the /proc files. + * The caller must not be holding the ide_setting_sem. + */ + +void ide_add_generic_settings (ide_drive_t *drive) +{ +/* + * drive setting name read/write access data type min max mul_factor div_factor data pointer set function + */ + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); +} + static void proc_ide_settings_warn(void) { static int warned = 0; @@ -399,7 +660,7 @@ static ide_proc_entry_t generic_drive_entries[] = { { NULL, 0, NULL, NULL } }; -void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) +static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) { struct proc_dir_entry *ent; @@ -415,7 +676,7 @@ void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void } } -void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) +static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) { if (!dir || !p) return; @@ -425,6 +686,51 @@ void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) } } +void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) +{ + ide_add_proc_entries(drive->proc, driver->proc, drive); +} + +EXPORT_SYMBOL(ide_proc_register_driver); + +/** + * ide_proc_unregister_driver - remove driver specific data + * @drive: drive + * @driver: driver + * + * Clean up the driver specific /proc files and IDE settings + * for a given drive. + * + * Takes ide_setting_sem and ide_lock. + * Caller must hold none of the locks. + */ + +void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) +{ + unsigned long flags; + + ide_remove_proc_entries(drive->proc, driver->proc); + + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); + /* + * ide_setting_sem protects the settings list + * ide_lock protects the use of settings + * + * so we need to hold both, ide_settings_sem because we want to + * modify the settings list, and ide_lock because we cannot take + * a setting out that is being used. + * + * OTOH both ide_{read,write}_setting are only ever used under + * ide_setting_sem. + */ + auto_remove_settings(drive); + spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); +} + +EXPORT_SYMBOL(ide_proc_unregister_driver); + static void create_proc_ide_drives(ide_hwif_t *hwif) { int d; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index fa0d22de37a7..e82bfa5e0ab8 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4561,6 +4561,8 @@ static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive) printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); #endif /* IDETAPE_DEBUG_INFO */ } + +#ifdef CONFIG_IDE_PROC_FS static void idetape_add_settings (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -4583,6 +4585,9 @@ static void idetape_add_settings (ide_drive_t *drive) ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); } +#else +static inline void idetape_add_settings(ide_drive_t *drive) { ; } +#endif /* * ide_setup is called to: @@ -4703,7 +4708,7 @@ static void ide_tape_remove(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - ide_unregister_subdriver(drive, tape->driver); + ide_proc_unregister_driver(drive, tape->driver); ide_unregister_region(tape->disk); @@ -4731,7 +4736,6 @@ static void ide_tape_release(struct kref *kref) } #ifdef CONFIG_IDE_PROC_FS - static int proc_idetape_read_name (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -4749,11 +4753,6 @@ static ide_proc_entry_t idetape_proc[] = { { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, { NULL, 0, NULL, NULL } }; - -#else - -#define idetape_proc NULL - #endif static int ide_tape_probe(ide_drive_t *); @@ -4773,7 +4772,9 @@ static ide_driver_t idetape_driver = { .end_request = idetape_end_request, .error = __ide_error, .abort = __ide_abort, +#ifdef CONFIG_IDE_PROC_FS .proc = idetape_proc, +#endif }; /* @@ -4864,7 +4865,7 @@ static int ide_tape_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_register_subdriver(drive, &idetape_driver); + ide_proc_register_driver(drive, &idetape_driver); kref_init(&tape->kref); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8793a960210c..614c5fd43cd2 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -825,178 +825,6 @@ DECLARE_MUTEX(ide_setting_sem); EXPORT_SYMBOL_GPL(ide_setting_sem); -/** - * __ide_add_setting - add an ide setting option - * @drive: drive to use - * @name: setting name - * @rw: true if the function is read write - * @data_type: type of data - * @min: range minimum - * @max: range maximum - * @mul_factor: multiplication scale - * @div_factor: divison scale - * @data: private data field - * @set: setting - * @auto_remove: setting auto removal flag - * - * Removes the setting named from the device if it is present. - * The function takes the settings_lock to protect against - * parallel changes. This function must not be called from IRQ - * context. Returns 0 on success or -1 on failure. - * - * BUGS: This code is seriously over-engineered. There is also - * magic about how the driver specific features are setup. If - * a driver is attached we assume the driver settings are auto - * remove. - */ - -static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; - - down(&ide_setting_sem); - while ((*p) && strcmp((*p)->name, name) < 0) - p = &((*p)->next); - if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) - goto abort; - if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) - goto abort; - strcpy(setting->name, name); - setting->rw = rw; - setting->data_type = data_type; - setting->min = min; - setting->max = max; - setting->mul_factor = mul_factor; - setting->div_factor = div_factor; - setting->data = data; - setting->set = set; - - setting->next = *p; - if (auto_remove) - setting->auto_remove = 1; - *p = setting; - up(&ide_setting_sem); - return 0; -abort: - up(&ide_setting_sem); - kfree(setting); - return -1; -} - -int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) -{ - return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); -} - -EXPORT_SYMBOL(ide_add_setting); - -/** - * __ide_remove_setting - remove an ide setting option - * @drive: drive to use - * @name: setting name - * - * Removes the setting named from the device if it is present. - * The caller must hold the setting semaphore. - */ - -static void __ide_remove_setting (ide_drive_t *drive, char *name) -{ - ide_settings_t **p, *setting; - - p = (ide_settings_t **) &drive->settings; - - while ((*p) && strcmp((*p)->name, name)) - p = &((*p)->next); - if ((setting = (*p)) == NULL) - return; - - (*p) = setting->next; - - kfree(setting->name); - kfree(setting); -} - -/** - * ide_find_setting_by_name - find a drive specific setting - * @drive: drive to scan - * @name: setting name - * - * Scan's the device setting table for a matching entry and returns - * this or NULL if no entry is found. The caller must hold the - * setting semaphore - */ - -ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (strcmp(setting->name, name) == 0) - break; - setting = setting->next; - } - return setting; -} - -/** - * auto_remove_settings - remove driver specific settings - * @drive: drive - * - * Automatically remove all the driver specific settings for this - * drive. This function may not be called from IRQ context. The - * caller must hold ide_setting_sem. - */ - -static void auto_remove_settings (ide_drive_t *drive) -{ - ide_settings_t *setting; -repeat: - setting = drive->settings; - while (setting) { - if (setting->auto_remove) { - __ide_remove_setting(drive, setting->name); - goto repeat; - } - setting = setting->next; - } -} - -/** - * ide_read_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * - * Read a drive setting and return the value. The caller - * must hold the ide_setting_sem when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - */ - -int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) -{ - int val = -EINVAL; - unsigned long flags; - - if ((setting->rw & SETTING_READ)) { - spin_lock_irqsave(&ide_lock, flags); - switch(setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - val = *((u32 *) setting->data); - break; - } - spin_unlock_irqrestore(&ide_lock, flags); - } - return val; -} - /** * ide_spin_wait_hwgroup - wait for group * @drive: drive in the group @@ -1030,52 +858,7 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive) EXPORT_SYMBOL(ide_spin_wait_hwgroup); -/** - * ide_write_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * @val: value - * - * Write a drive setting if it is possible. The caller - * must hold the ide_setting_sem when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - * - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgy, though safe enough. - */ - -int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) -{ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (setting->set) - return setting->set(drive, val); - if (!(setting->rw & SETTING_WRITE)) - return -EPERM; - if (val < setting->min || val > setting->max) - return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; - } - spin_unlock_irq(&ide_lock); - return 0; -} - -static int set_io_32bit(ide_drive_t *drive, int arg) +int set_io_32bit(ide_drive_t *drive, int arg) { if (drive->no_io_32bit) return -EPERM; @@ -1104,7 +887,7 @@ static int set_ksettings(ide_drive_t *drive, int arg) return 0; } -static int set_using_dma (ide_drive_t *drive, int arg) +int set_using_dma(ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = drive->hwif; @@ -1152,7 +935,7 @@ static int set_using_dma (ide_drive_t *drive, int arg) #endif } -static int set_pio_mode (ide_drive_t *drive, int arg) +int set_pio_mode(ide_drive_t *drive, int arg) { struct request rq; @@ -1186,48 +969,6 @@ static int set_unmaskirq(ide_drive_t *drive, int arg) return 0; } -static int set_xfer_rate (ide_drive_t *drive, int arg) -{ - int err; - - if (arg < 0 || arg > 70) - return -EINVAL; - - err = ide_wait_cmd(drive, - WIN_SETFEATURES, (u8) arg, - SETFEATURES_XFER, 0, NULL); - - if (!err && arg) { - ide_set_xfer_rate(drive, (u8) arg); - ide_driveid_update(drive); - } - return err; -} - -/** - * ide_add_generic_settings - generic ide settings - * @drive: drive being configured - * - * Add the generic parts of the system settings to the /proc files. - * The caller must not be holding the ide_setting_sem. - */ - -void ide_add_generic_settings (ide_drive_t *drive) -{ -/* - * drive setting name read/write access data type min max mul_factor div_factor data pointer set function - */ - __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); - __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); - __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); - __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); - __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); - __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); - __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); - __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); - __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); -} - /** * system_bus_clock - clock guess * @@ -1922,54 +1663,6 @@ static void __init probe_for_hwifs (void) #endif } -void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) -{ -#ifdef CONFIG_IDE_PROC_FS - ide_add_proc_entries(drive->proc, driver->proc, drive); -#endif -} - -EXPORT_SYMBOL(ide_register_subdriver); - -/** - * ide_unregister_subdriver - disconnect drive from driver - * @drive: drive to unplug - * @driver: driver - * - * Disconnect a drive from the driver it was attached to and then - * clean up the various proc files and other objects attached to it. - * - * Takes ide_setting_sem and ide_lock. - * Caller must hold none of the locks. - */ - -void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) -{ - unsigned long flags; - -#ifdef CONFIG_IDE_PROC_FS - ide_remove_proc_entries(drive->proc, driver->proc); -#endif - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - /* - * ide_setting_sem protects the settings list - * ide_lock protects the use of settings - * - * so we need to hold both, ide_settings_sem because we want to - * modify the settings list, and ide_lock because we cannot take - * a setting out that is being used. - * - * OTOH both ide_{read,write}_setting are only ever used under - * ide_setting_sem. - */ - auto_remove_settings(drive); - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); -} - -EXPORT_SYMBOL(ide_unregister_subdriver); - /* * Probe module */ diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 4388b8ab69a1..8263f752809d 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -721,6 +721,7 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r return ide_stopped; } +#ifdef CONFIG_IDE_PROC_FS static void idescsi_add_settings(ide_drive_t *drive) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); @@ -734,6 +735,9 @@ static void idescsi_add_settings(ide_drive_t *drive) ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); } +#else +static inline void idescsi_add_settings(ide_drive_t *drive) { ; } +#endif /* * Driver initialization. @@ -756,7 +760,7 @@ static void ide_scsi_remove(ide_drive_t *drive) struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct gendisk *g = scsi->disk; - ide_unregister_subdriver(drive, scsi->driver); + ide_proc_unregister_driver(drive, scsi->driver); ide_unregister_region(g); @@ -775,8 +779,6 @@ static ide_proc_entry_t idescsi_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL } }; -#else -# define idescsi_proc NULL #endif static ide_driver_t idescsi_driver = { @@ -790,11 +792,13 @@ static ide_driver_t idescsi_driver = { .version = IDESCSI_VERSION, .media = ide_scsi, .supports_dsc_overlap = 0, - .proc = idescsi_proc, .do_request = idescsi_do_request, .end_request = idescsi_end_request, .error = idescsi_atapi_error, .abort = idescsi_atapi_abort, +#ifdef CONFIG_IDE_PROC_FS + .proc = idescsi_proc, +#endif }; static int idescsi_ide_open(struct inode *inode, struct file *filp) @@ -1153,7 +1157,7 @@ static int ide_scsi_probe(ide_drive_t *drive) idescsi->host = host; idescsi->disk = g; g->private_data = &idescsi->driver; - ide_register_subdriver(drive, &idescsi_driver); + ide_proc_register_driver(drive, &idescsi_driver); err = 0; idescsi_setup(drive, idescsi); g->fops = &idescsi_ops; @@ -1165,7 +1169,7 @@ static int ide_scsi_probe(ide_drive_t *drive) } /* fall through on error */ ide_unregister_region(g); - ide_unregister_subdriver(drive, &idescsi_driver); + ide_proc_unregister_driver(drive, &idescsi_driver); put_disk(g); out_host_put: diff --git a/include/linux/ide.h b/include/linux/ide.h index 591a0b55e31c..477b8c6be727 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -559,9 +559,10 @@ typedef struct ide_drive_s { struct ide_drive_s *next; /* circular list of hwgroup drives */ void *driver_data; /* extra driver data */ struct hd_driveid *id; /* drive model identification info */ +#ifdef CONFIG_IDE_PROC_FS struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ struct ide_settings_s *settings;/* /proc/ide/ drive settings */ - +#endif struct hwif_s *hwif; /* actually (ide_hwif_t *) */ unsigned long sleep; /* sleep until this time */ @@ -858,8 +859,15 @@ typedef struct hwgroup_s { unsigned char cmd_buf[4]; } ide_hwgroup_t; -/* structure attached to the request for IDE_TASK_CMDS */ +typedef struct ide_driver_s ide_driver_t; +extern struct semaphore ide_setting_sem; + +int set_io_32bit(ide_drive_t *, int); +int set_pio_mode(ide_drive_t *, int); +int set_using_dma(ide_drive_t *, int); + +#ifdef CONFIG_IDE_PROC_FS /* * configurable drive settings */ @@ -887,12 +895,7 @@ typedef struct ide_settings_s { struct ide_settings_s *next; } ide_settings_t; -extern struct semaphore ide_setting_sem; int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set); -extern ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name); -extern int ide_read_setting(ide_drive_t *t, ide_settings_t *setting); -extern int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val); -extern void ide_add_generic_settings(ide_drive_t *drive); /* * /proc/ide interface @@ -904,15 +907,17 @@ typedef struct { write_proc_t *write_proc; } ide_proc_entry_t; -#ifdef CONFIG_IDE_PROC_FS extern struct proc_dir_entry *proc_ide_root; void proc_ide_create(void); void proc_ide_destroy(void); void create_proc_ide_interfaces(void); void destroy_proc_ide_interface(ide_hwif_t *); -void ide_add_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *, void *); -void ide_remove_proc_entries(struct proc_dir_entry *, ide_proc_entry_t *); +void ide_proc_register_driver(ide_drive_t *, ide_driver_t *); +void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *); + +void ide_add_generic_settings(ide_drive_t *); + read_proc_t proc_ide_read_capacity; read_proc_t proc_ide_read_geometry; @@ -940,6 +945,9 @@ static inline void proc_ide_create(void) { ; } static inline void proc_ide_destroy(void) { ; } static inline void create_proc_ide_interfaces(void) { ; } static inline void destroy_proc_ide_interface(ide_hwif_t *hwif) { ; } +static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } +static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } +static inline void ide_add_generic_settings(ide_drive_t *drive) { ; } #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; #endif @@ -982,7 +990,7 @@ enum { * The gendriver.owner field should be set to the module owner of this driver. * The gendriver.name field should be set to the name of this driver */ -typedef struct ide_driver_s { +struct ide_driver_s { const char *version; u8 media; unsigned supports_dsc_overlap : 1; @@ -990,12 +998,14 @@ typedef struct ide_driver_s { int (*end_request)(ide_drive_t *, int, int); ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); - ide_proc_entry_t *proc; struct device_driver gen_driver; int (*probe)(ide_drive_t *); void (*remove)(ide_drive_t *); void (*shutdown)(ide_drive_t *); -} ide_driver_t; +#ifdef CONFIG_IDE_PROC_FS + ide_proc_entry_t *proc; +#endif +}; #define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) @@ -1205,9 +1215,6 @@ extern void default_hwif_iops(ide_hwif_t *); extern void default_hwif_mmiops(ide_hwif_t *); extern void default_hwif_transport(ide_hwif_t *); -void ide_register_subdriver(ide_drive_t *, ide_driver_t *); -void ide_unregister_subdriver(ide_drive_t *, ide_driver_t *); - #define ON_BOARD 1 #define NEVER_BOARD 0 From 7f8f48af0861c38c28d4abd550102643e0ea9e6a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:10 +0200 Subject: [PATCH 07/11] ide: cable detection fixes (take 2) Tejun's recent eighty_ninty_three() fix has inspired me to do more thorough review of the cable detection code... * print user-friendly warning about limiting the maximum transfer speed to UDMA33 (and the reason behind it) when 80-wire cable is not detected, also while at it cleanup eighty_ninty_three() a bit * use eighty_ninty_three() in ide_ata66_check(), this actually fixes 3 bugs: - bit 14 (word 93 validity check) == 1 && bit 13 (80-wire cable test) == 1 were used as 80-wire cable present test for CONFIG_IDEDMA_IVB=n case (please see FIXME comment in eighty_ninty_three() for more details) - CONFIG_IDEDMA_IVB=y/n cases were interchanged - check for SATA devices was missing * remove private cable warnings from pdc_202xx{old,new} drivers now that core code provides this functionality (plus, in pdc202xx_new case the test could give false warnings for ATAPI devices because pdc202xx_new driver doesn't even support ATAPI DMA) Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 53 +++++++++++++++++++--------------- drivers/ide/ide-lib.c | 11 +++++-- drivers/ide/pci/pdc202xx_new.c | 16 ---------- drivers/ide/pci/pdc202xx_old.c | 20 +------------ include/linux/ide.h | 1 + 5 files changed, 40 insertions(+), 61 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index ed6128f6cd98..f0be5f665a0e 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -571,25 +571,40 @@ EXPORT_SYMBOL(ide_wait_stat); */ u8 eighty_ninty_three (ide_drive_t *drive) { - if(HWIF(drive)->udma_four == 0) - return 0; + ide_hwif_t *hwif = drive->hwif; + struct hd_driveid *id = drive->id; + + if (hwif->udma_four == 0) + goto no_80w; /* Check for SATA but only if we are ATA5 or higher */ - if (drive->id->hw_config == 0 && (drive->id->major_rev_num & 0x7FE0)) + if (id->hw_config == 0 && (id->major_rev_num & 0x7FE0)) return 1; - if (!(drive->id->hw_config & 0x6000)) - return 0; -#ifndef CONFIG_IDEDMA_IVB - if(!(drive->id->hw_config & 0x4000)) - return 0; -#endif /* CONFIG_IDEDMA_IVB */ + /* * FIXME: * - change master/slave IDENTIFY order * - force bit13 (80c cable present) check * (unless the slave device is pre-ATA3) */ - return 1; +#ifndef CONFIG_IDEDMA_IVB + if (id->hw_config & 0x4000) +#else + if (id->hw_config & 0x6000) +#endif + return 1; + +no_80w: + if (drive->udma33_warned == 1) + return 0; + + printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, " + "limiting max speed to UDMA33\n", + drive->name, hwif->udma_four ? "drive" : "host"); + + drive->udma33_warned = 1; + + return 0; } int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) @@ -597,23 +612,13 @@ int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else /* !CONFIG_IDEDMA_IVB */ - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif /* CONFIG_IDEDMA_IVB */ - printk("%s: Speed warnings UDMA 3/4/5 is not " - "functional.\n", drive->name); - return 1; - } - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not " - "functional.\n", - HWIF(drive)->name); + if (eighty_ninty_three(drive) == 0) { + printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " + "be set\n", drive->name); return 1; } } + return 0; } diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 4557fc5a3ea3..3be3c69383f2 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -88,8 +88,15 @@ u8 ide_rate_filter(ide_drive_t *drive, u8 speed) if (hwif->udma_filter) mask = hwif->udma_filter(drive); - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; + /* + * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false + * cable warning from eighty_ninty_three(), moving ide_rate_filter() + * calls from ->speedproc to core code will make this hack go away + */ + if (speed > XFER_UDMA_2) { + if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) + mask &= 0x07; + } if (mask) mode = fls(mask) - 1 + XFER_UDMA_0; diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 772ca4007de4..65b1e124edf7 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -37,8 +37,6 @@ #include #endif -#define PDC202_DEBUG_CABLE 0 - #undef DEBUG #ifdef DEBUG @@ -234,17 +232,8 @@ static int config_chipset_for_dma(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0; - u8 cable = pdcnew_cable_detect(hwif); u8 speed; - if (ultra_66 && cable) { - printk(KERN_WARNING "Warning: %s channel " - "requires an 80-pin cable for operation.\n", - hwif->channel ? "Secondary" : "Primary"); - printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); - } - if (id->capability & 4) { /* * Set IORDY_EN & PREFETCH_EN (this seems to have @@ -547,11 +536,6 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; - -#if PDC202_DEBUG_CABLE - printk(KERN_DEBUG "%s: %s-pin cable\n", - hwif->name, hwif->udma_four ? "80" : "40"); -#endif /* PDC202_DEBUG_CABLE */ } static int __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d) diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 207a6191fac7..7146fe3f6ba7 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -46,7 +46,6 @@ #include #include -#define PDC202_DEBUG_CABLE 0 #define PDC202XX_DEBUG_DRIVE_INFO 0 static const char *pdc_quirk_drives[] = { @@ -238,20 +237,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) u32 drive_conf = 0; u8 drive_pci = 0x60 + (drive->dn << 2); u8 test1 = 0, test2 = 0, speed = -1; - u8 AP = 0, cable = 0; - - u8 ultra_66 = ((id->dma_ultra & 0x0010) || - (id->dma_ultra & 0x0008)) ? 1 : 0; - - if (dev->device != PCI_DEVICE_ID_PROMISE_20246) - cable = pdc202xx_old_cable_detect(hwif); - else - ultra_66 = 0; - - if (ultra_66 && cable) { - printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); - printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); - } + u8 AP = 0; if (dev->device != PCI_DEVICE_ID_PROMISE_20246) pdc_old_disable_66MHz_clock(drive->hwif); @@ -477,10 +463,6 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; -#if PDC202_DEBUG_CABLE - printk(KERN_DEBUG "%s: %s-pin cable\n", - hwif->name, hwif->udma_four ? "80" : "40"); -#endif /* PDC202_DEBUG_CABLE */ } static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) diff --git a/include/linux/ide.h b/include/linux/ide.h index 477b8c6be727..ca924b295c2e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -605,6 +605,7 @@ typedef struct ide_drive_s { unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */ unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ unsigned post_reset : 1; + unsigned udma33_warned : 1; u8 addressing; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */ u8 quirk_list; /* considered quirky, set for a specific host */ From 869c56ee9de1b72cd3f8ab9cdfbd3601e55c61f2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:10 +0200 Subject: [PATCH 08/11] ide: add "initializing" argument to ide_register_hw() Add "initializing" argument to ide_register_hw() and use it instead of ide.c wide variable of the same name. Update all users of ide_register_hw() accordingly. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/bast-ide.c | 2 +- drivers/ide/arm/ide_arm.c | 2 +- drivers/ide/cris/ide-cris.c | 2 +- drivers/ide/h8300/ide-h8300.c | 2 +- drivers/ide/ide-pnp.c | 2 +- drivers/ide/ide.c | 16 +++++++--------- drivers/ide/legacy/buddha.c | 2 +- drivers/ide/legacy/falconide.c | 2 +- drivers/ide/legacy/gayle.c | 2 +- drivers/ide/legacy/ide-cs.c | 2 +- drivers/ide/legacy/macide.c | 6 +++--- drivers/ide/legacy/q40ide.c | 2 +- drivers/ide/pci/delkin_cb.c | 2 +- drivers/macintosh/mediabay.c | 2 +- include/linux/ide.h | 5 +++-- 15 files changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c index 9d474e5fd8dc..f7449d04114a 100644 --- a/drivers/ide/arm/bast-ide.c +++ b/drivers/ide/arm/bast-ide.c @@ -45,7 +45,7 @@ bastide_register(unsigned int base, unsigned int aux, int irq, hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20); hw.irq = irq; - ide_register_hw(&hw, hwif); + ide_register_hw(&hw, 0, hwif); return 0; } diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c index 23488c4d1fcd..a3d6744e870a 100644 --- a/drivers/ide/arm/ide_arm.c +++ b/drivers/ide/arm/ide_arm.c @@ -38,6 +38,6 @@ void __init ide_arm_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, NULL); + ide_register_hw(&hw, 1, NULL); } } diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index 9691d089fce8..c04cb25a01ff 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -796,7 +796,7 @@ init_e100_ide (void) ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); - ide_register_hw(&hw, &hwif); + ide_register_hw(&hw, 1, &hwif); hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->tuneproc = &tune_cris_ide; diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c index 88750a300337..6d26ad7360d5 100644 --- a/drivers/ide/h8300/ide-h8300.c +++ b/drivers/ide/h8300/ide-h8300.c @@ -101,7 +101,7 @@ void __init h8300_ide_init(void) hw_setup(&hw); /* register if */ - idx = ide_register_hw(&hw, &hwif); + idx = ide_register_hw(&hw, 1, &hwif); if (idx == -1) { printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); return; diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index 98410ca044cf..2b8009c50e91 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -42,7 +42,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id hw.irq = pnp_irq(dev, 0); hw.dma = NO_DMA; - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); if (index != -1) { printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 614c5fd43cd2..0fc532850bbe 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -168,7 +168,6 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, static int idebus_parameter; /* holds the "idebus=" parameter */ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ -static int initializing; /* set while initializing built-in drivers */ DECLARE_MUTEX(ide_cfg_sem); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); @@ -302,9 +301,7 @@ static void __init init_ide_data (void) #endif } #ifdef CONFIG_IDE_ARM - initializing = 1; ide_arm_init(); - initializing = 0; #endif } @@ -749,6 +746,7 @@ void ide_setup_ports ( hw_regs_t *hw, /** * ide_register_hw_with_fixup - register IDE interface * @hw: hardware registers + * @initializing: set while initializing built-in drivers * @hwifp: pointer to returned hwif * @fixup: fixup function * @@ -758,7 +756,9 @@ void ide_setup_ports ( hw_regs_t *hw, * Returns -1 on error. */ -int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif)) +int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, + ide_hwif_t **hwifp, + void(*fixup)(ide_hwif_t *hwif)) { int index, retry = 1; ide_hwif_t *hwif; @@ -810,9 +810,9 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(i EXPORT_SYMBOL(ide_register_hw_with_fixup); -int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp) +int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp) { - return ide_register_hw_with_fixup(hw, hwifp, NULL); + return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL); } EXPORT_SYMBOL(ide_register_hw); @@ -1108,7 +1108,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ide_init_hwif_ports(&hw, (unsigned long) args[0], (unsigned long) args[1], NULL); hw.irq = args[2]; - if (ide_register_hw(&hw, NULL) == -1) + if (ide_register_hw(&hw, 0, NULL) == -1) return -EIO; return 0; } @@ -1819,10 +1819,8 @@ static int __init ide_init(void) (void)qd65xx_init(); #endif - initializing = 1; /* Probe for special PCI and other "known" interface chipsets. */ probe_for_hwifs(); - initializing = 0; proc_ide_create(); diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index 1ed224a01f79..101aee1711c4 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -213,7 +213,7 @@ void __init buddha_init(void) IRQ_AMIGA_PORTS); } - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); if (index != -1) { hwif->mmio = 1; printk("ide%d: ", index); diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index a9f2cd5bb81e..e1e9d9d6893f 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -70,7 +70,7 @@ void __init falconide_init(void) 0, 0, NULL, // falconide_iops, IRQ_MFP_IDE); - index = ide_register_hw(&hw, NULL); + index = ide_register_hw(&hw, 1, NULL); if (index != -1) printk("ide%d: Falcon IDE interface\n", index); diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index dcfadbbf55d8..0830a021bbb6 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -165,7 +165,7 @@ void __init gayle_init(void) // &gayle_iops, IRQ_AMIGA_PORTS); - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); if (index != -1) { hwif->mmio = 1; switch (i) { diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index c6522a64d7ec..2f3977f195b7 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -153,7 +153,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave); + return ide_register_hw_with_fixup(&hw, 0, NULL, ide_undecoded_slave); } /*====================================================================== diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index 4c0079ad52ac..c211fc78345d 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -102,21 +102,21 @@ void macide_init(void) 0, 0, macide_ack_intr, // quadra_ide_iops, IRQ_NUBUS_F); - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); break; case MAC_IDE_PB: ide_setup_ports(&hw, IDE_BASE, macide_offsets, 0, 0, macide_ack_intr, // macide_pb_iops, IRQ_NUBUS_C); - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); break; case MAC_IDE_BABOON: ide_setup_ports(&hw, BABOON_BASE, macide_offsets, 0, 0, NULL, // macide_baboon_iops, IRQ_BABOON_1); - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); if (index == -1) break; if (macintosh_config->ident == MAC_MODEL_PB190) { diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 74f08124eabb..e628a983ce33 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -142,7 +142,7 @@ void q40ide_init(void) 0, NULL, // m68kide_iops, q40ide_default_irq(pcide_bases[i])); - index = ide_register_hw(&hw, &hwif); + index = ide_register_hw(&hw, 1, &hwif); // **FIXME** if (index != -1) hwif->mmio = 1; diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index dd7ec37fdeab..46f4a888c037 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -80,7 +80,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave); + rc = ide_register_hw_with_fixup(&hw, 0, &hwif, ide_undecoded_slave); if (rc < 0) { printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); pci_disable_device(dev); diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 0acf2f7fd9d7..c803d2bba65d 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -563,7 +563,7 @@ static void media_bay_step(int i) ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL); hw.irq = bay->cd_irq; hw.chipset = ide_pmac; - bay->cd_index = ide_register_hw(&hw, NULL); + bay->cd_index = ide_register_hw(&hw, 0, NULL); pmu_resume(); } if (bay->cd_index == -1) { diff --git a/include/linux/ide.h b/include/linux/ide.h index ca924b295c2e..bdb97655ef61 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -223,8 +223,9 @@ typedef struct hw_regs_s { /* * Register new hardware with ide */ -int ide_register_hw(hw_regs_t *hw, struct hwif_s **hwifp); -int ide_register_hw_with_fixup(hw_regs_t *, struct hwif_s **, void (*)(struct hwif_s *)); +int ide_register_hw(hw_regs_t *, int, struct hwif_s **); +int ide_register_hw_with_fixup(hw_regs_t *, int, struct hwif_s **, + void (*)(struct hwif_s *)); /* * Set up hw_regs_t structure before calling ide_register_hw (optional) From 5cbf79cdb37be2aa2a1b4fa94144526b14557060 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:11 +0200 Subject: [PATCH 09/11] ide: add ide_proc_register_port() * create_proc_ide_interfaces() tries to add /proc entries for every probed and initialized IDE port, replace it by ide_proc_register_port() which does it only for the given port (also rename destroy_proc_ide_interface() to ide_proc_unregister_port() for consistency) * convert {create,destroy}_proc_ide_interface[s]() users to use new functions * pmac driver depended on proc_ide_create() to add /proc port entries, fix it * au1xxx-ide, swarm and cs5520 drivers depended indirectly on ide-generic driver (CONFIG_IDE_GENERIC=y) to add port /proc entries, fix them * there is now no need to add /proc entries for IDE ports in proc_ide_create() so don't do it * proc_ide_create() needs now to be called before drivers are probed - fix it, while at it make proc_ide_create() create /proc "ide" directory Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/icside.c | 7 +++++-- drivers/ide/arm/rapide.c | 2 +- drivers/ide/ide-generic.c | 2 -- drivers/ide/ide-probe.c | 3 +++ drivers/ide/ide-proc.c | 34 +++++++++++++++++----------------- drivers/ide/ide.c | 14 +++----------- drivers/ide/legacy/ali14xx.c | 3 ++- drivers/ide/legacy/dtc2278.c | 3 ++- drivers/ide/legacy/ht6560b.c | 3 ++- drivers/ide/legacy/qd65xx.c | 7 ++++--- drivers/ide/legacy/umc8672.c | 3 ++- drivers/ide/mips/au1xxx-ide.c | 3 +++ drivers/ide/mips/swarm.c | 3 +++ drivers/ide/pci/cs5520.c | 20 ++++++++++++++++---- drivers/ide/pci/sgiioc4.c | 2 +- drivers/ide/ppc/pmac.c | 2 ++ drivers/ide/setup-pci.c | 25 +++++++++++++++++++++---- include/linux/ide.h | 10 ++++------ 18 files changed, 91 insertions(+), 55 deletions(-) diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index f383ace2a087..1fe0457243db 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -591,7 +591,8 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) state->hwif[0] = hwif; probe_hwif_init(hwif); - create_proc_ide_interfaces(); + + ide_proc_register_port(hwif); return 0; } @@ -679,7 +680,9 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) probe_hwif_init(hwif); probe_hwif_init(mate); - create_proc_ide_interfaces(); + + ide_proc_register_port(hwif); + ide_proc_register_port(mate); return 0; diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index 9c6c49fdd2b1..890ea3fac3c6 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -76,7 +76,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) hwif->gendev.parent = &ec->dev; hwif->noprobe = 0; probe_hwif_init(hwif); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); ecard_set_drvdata(ec, hwif); goto out; } diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 99fd56151131..0f72b98d727f 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -22,8 +22,6 @@ static int __init ide_generic_init(void) if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) ide_release_lock(); /* for atari only */ - create_proc_ide_interfaces(); - return 0; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 8f15c23aa70d..3cebed77f55d 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1427,6 +1427,9 @@ int ideprobe_init (void) } } } + for (index = 0; index < MAX_HWIFS; ++index) + if (probe[index]) + ide_proc_register_port(&ide_hwifs[index]); return 0; } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 949a6f609d84..d50bd996ff22 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -39,6 +39,8 @@ #include +static struct proc_dir_entry *proc_ide_root; + static int proc_ide_read_imodel (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -783,26 +785,24 @@ static ide_proc_entry_t hwif_entries[] = { { NULL, 0, NULL, NULL } }; -void create_proc_ide_interfaces(void) +void ide_proc_register_port(ide_hwif_t *hwif) { - int h; + if (!hwif->present) + return; - for (h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; + if (!hwif->proc) { + hwif->proc = proc_mkdir(hwif->name, proc_ide_root); - if (!hwif->present) - continue; - if (!hwif->proc) { - hwif->proc = proc_mkdir(hwif->name, proc_ide_root); - if (!hwif->proc) - return; - ide_add_proc_entries(hwif->proc, hwif_entries, hwif); - } - create_proc_ide_drives(hwif); + if (!hwif->proc) + return; + + ide_add_proc_entries(hwif->proc, hwif_entries, hwif); } + + create_proc_ide_drives(hwif); } -EXPORT_SYMBOL(create_proc_ide_interfaces); +EXPORT_SYMBOL_GPL(ide_proc_register_port); #ifdef CONFIG_BLK_DEV_IDEPCI void ide_pci_create_host_proc(const char *name, get_info_t *get_info) @@ -813,7 +813,7 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info) EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); #endif -void destroy_proc_ide_interface(ide_hwif_t *hwif) +void ide_proc_unregister_port(ide_hwif_t *hwif) { if (hwif->proc) { destroy_proc_ide_drives(hwif); @@ -860,11 +860,11 @@ void proc_ide_create(void) { struct proc_dir_entry *entry; + proc_ide_root = proc_mkdir("ide", NULL); + if (!proc_ide_root) return; - create_proc_ide_interfaces(); - entry = create_proc_entry("drivers", 0, proc_ide_root); if (entry) entry->proc_fops = &ide_drivers_operations; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 0fc532850bbe..038f2610e734 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -347,10 +347,6 @@ static int ide_system_bus_speed(void) return system_bus_speed; } -#ifdef CONFIG_IDE_PROC_FS -struct proc_dir_entry *proc_ide_root; -#endif - static struct resource* hwif_request_region(ide_hwif_t *hwif, unsigned long addr, int num) { @@ -594,7 +590,7 @@ void ide_unregister(unsigned int index) spin_unlock_irq(&ide_lock); - destroy_proc_ide_interface(hwif); + ide_proc_unregister_port(hwif); hwgroup = hwif->hwgroup; /* @@ -799,7 +795,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, if (!initializing) { probe_hwif_init_with_fixup(hwif, fixup); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); } if (hwifp) @@ -1794,9 +1790,7 @@ static int __init ide_init(void) init_ide_data(); -#ifdef CONFIG_IDE_PROC_FS - proc_ide_root = proc_mkdir("ide", NULL); -#endif + proc_ide_create(); #ifdef CONFIG_BLK_DEV_ALI14XX if (probe_ali14xx) @@ -1822,8 +1816,6 @@ static int __init ide_init(void) /* Probe for special PCI and other "known" interface chipsets. */ probe_for_hwifs(); - proc_ide_create(); - return 0; } diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 91961aa03047..df17ed68c0bc 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -223,7 +223,8 @@ static int __init ali14xx_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); + ide_proc_register_port(mate); return 0; } diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index 0219ffa64db6..36a3f0ac6162 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -138,7 +138,8 @@ static int __init dtc2278_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); + ide_proc_register_port(mate); return 0; } diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index a2832643c522..c8f353b1296f 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -357,7 +357,8 @@ int __init ht6560b_init(void) probe_hwif_init(hwif); probe_hwif_init(mate); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); + ide_proc_register_port(mate); return 0; diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 2fb8f50f1293..d1414a75b523 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -427,7 +427,7 @@ static int __init qd_probe(int base) qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); return 1; } @@ -459,7 +459,7 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); return 1; } else { @@ -479,7 +479,8 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); + ide_proc_register_port(mate); return 0; /* no other qd65xx possible */ } diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index ca7974455578..ddc403a0bd82 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -160,7 +160,8 @@ static int __init umc8672_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); + ide_proc_register_port(mate); return 0; } diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index d54d9fe92a7d..ca95e990862e 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -760,6 +760,9 @@ static int au_ide_probe(struct device *dev) #endif probe_hwif_init(hwif); + + ide_proc_register_port(hwif); + dev_set_drvdata(dev, hwif); printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index 81fa06851b27..6e935d7c63fd 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -129,6 +129,9 @@ static int __devinit swarm_ide_probe(struct device *dev) hwif->irq = hwif->hw.irq; probe_hwif_init(hwif); + + ide_proc_register_port(hwif); + dev_set_drvdata(dev, hwif); return 0; diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 400859a839f7..3b88a3a56116 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -213,6 +213,7 @@ static ide_pci_device_t cyrix_chipsets[] __devinitdata = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { + ide_hwif_t *hwif = NULL, *mate = NULL; ata_index_t index; ide_pci_device_t *d = &cyrix_chipsets[id->driver_data]; @@ -239,10 +240,21 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, 14, &index); - if((index.b.low & 0xf0) != 0xf0) - probe_hwif_init(&ide_hwifs[index.b.low]); - if((index.b.high & 0xf0) != 0xf0) - probe_hwif_init(&ide_hwifs[index.b.high]); + if ((index.b.low & 0xf0) != 0xf0) + hwif = &ide_hwifs[index.b.low]; + if ((index.b.high & 0xf0) != 0xf0) + mate = &ide_hwifs[index.b.high]; + + if (hwif) + probe_hwif_init(hwif); + if (mate) + probe_hwif_init(mate); + + if (hwif) + ide_proc_register_port(hwif); + if (mate) + ide_proc_register_port(mate); + return 0; } diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index fd09b295a69d..d3185e29a38e 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -692,7 +692,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) return -EIO; /* Create /proc/ide entries */ - create_proc_ide_interfaces(); + ide_proc_register_port(hwif); return 0; } diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index a49ebe44babd..45fc36f0f219 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1276,6 +1276,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* We probe the hwif now */ probe_hwif_init(hwif); + ide_proc_register_port(hwif); + return 0; } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 118fb3205ca8..892cda755782 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -702,6 +702,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d, int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) { + ide_hwif_t *hwif = NULL, *mate = NULL; ata_index_t index_list; int ret; @@ -710,11 +711,19 @@ int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) goto out; if ((index_list.b.low & 0xf0) != 0xf0) - probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup); + hwif = &ide_hwifs[index_list.b.low]; if ((index_list.b.high & 0xf0) != 0xf0) - probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup); + mate = &ide_hwifs[index_list.b.high]; - create_proc_ide_interfaces(); + if (hwif) + probe_hwif_init_with_fixup(hwif, d->fixup); + if (mate) + probe_hwif_init_with_fixup(mate, d->fixup); + + if (hwif) + ide_proc_register_port(hwif); + if (mate) + ide_proc_register_port(mate); out: return ret; } @@ -748,7 +757,15 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, } } - create_proc_ide_interfaces(); + for (i = 0; i < 2; i++) { + u8 idx[2] = { index_list[i].b.low, index_list[i].b.high }; + int j; + + for (j = 0; j < 2; j++) { + if ((idx[j] & 0xf0) != 0xf0) + ide_proc_register_port(ide_hwifs + idx[j]); + } + } out: return ret; } diff --git a/include/linux/ide.h b/include/linux/ide.h index bdb97655ef61..52d482a16dd9 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -909,12 +909,10 @@ typedef struct { write_proc_t *write_proc; } ide_proc_entry_t; -extern struct proc_dir_entry *proc_ide_root; - void proc_ide_create(void); void proc_ide_destroy(void); -void create_proc_ide_interfaces(void); -void destroy_proc_ide_interface(ide_hwif_t *); +void ide_proc_register_port(ide_hwif_t *); +void ide_proc_unregister_port(ide_hwif_t *); void ide_proc_register_driver(ide_drive_t *, ide_driver_t *); void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *); @@ -945,8 +943,8 @@ void ide_pci_create_host_proc(const char *, get_info_t *); #else static inline void proc_ide_create(void) { ; } static inline void proc_ide_destroy(void) { ; } -static inline void create_proc_ide_interfaces(void) { ; } -static inline void destroy_proc_ide_interface(ide_hwif_t *hwif) { ; } +static inline void ide_proc_register_port(ide_hwif_t *hwif) { ; } +static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; } static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } static inline void ide_add_generic_settings(ide_drive_t *drive) { ; } From 6d208b39c45edee5def6c201fcd51561c5a39828 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:11 +0200 Subject: [PATCH 10/11] ide: legacy PCI bus order probing fixes IDE PCI host drivers should register themselves with IDE core only when IDE driver is built-in, otherwise (IDE driver is modular and thus IDE PCI host drivers are also modular) the code has no effect and just complicates the probing. Fix it by adding new config option CONFIG_IDEPCI_PCIBUS (defined only when needed and invisible to the user) and covering by #ifdef/#endif the code in question. It turned out that "ide=reverse" was silently accepted but did nothing in case when IDE driver was modular, this is fixed now. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 3 +++ drivers/ide/ide.c | 10 +++++----- drivers/ide/setup-pci.c | 2 ++ include/linux/ide.h | 5 +++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index a678bbecb489..1d06b415ede9 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -371,6 +371,9 @@ config IDEPCI_SHARE_IRQ It is safe to say Y to this question, in most cases. If unsure, say N. +config IDEPCI_PCIBUS_ORDER + def_bool PCI && BLK_DEV_IDE=y && BLK_DEV_IDEPCI + config BLK_DEV_OFFBOARD bool "Boot off-board chipsets first support" depends on PCI && BLK_DEV_IDEPCI diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 038f2610e734..f2b547ff7722 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -172,7 +172,7 @@ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ DECLARE_MUTEX(ide_cfg_sem); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); -#ifdef CONFIG_BLK_DEV_IDEPCI +#ifdef CONFIG_IDEPCI_PCIBUS_ORDER static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ #endif @@ -1333,13 +1333,13 @@ static int __init ide_setup(char *s) return 1; } -#ifdef CONFIG_BLK_DEV_IDEPCI +#ifdef CONFIG_IDEPCI_PCIBUS_ORDER if (!strcmp(s, "ide=reverse")) { ide_scan_direction = 1; printk(" : Enabled support for IDE inverse scan order.\n"); return 1; } -#endif /* CONFIG_BLK_DEV_IDEPCI */ +#endif #ifdef CONFIG_BLK_DEV_IDEACPI if (!strcmp(s, "ide=noacpi")) { @@ -1599,9 +1599,9 @@ extern void __init h8300_ide_init(void); */ static void __init probe_for_hwifs (void) { -#ifdef CONFIG_BLK_DEV_IDEPCI +#ifdef CONFIG_IDEPCI_PCIBUS_ORDER ide_scan_pcibus(ide_scan_direction); -#endif /* CONFIG_BLK_DEV_IDEPCI */ +#endif #ifdef CONFIG_ETRAX_IDE { diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 892cda755782..67035ba4bf5e 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -772,6 +772,7 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, EXPORT_SYMBOL_GPL(ide_setup_pci_devices); +#ifdef CONFIG_IDEPCI_PCIBUS_ORDER /* * Module interfaces */ @@ -878,3 +879,4 @@ void __init ide_scan_pcibus (int scan_direction) __pci_register_driver(d, d->driver.owner, d->driver.mod_name); } } +#endif diff --git a/include/linux/ide.h b/include/linux/ide.h index 52d482a16dd9..df4e6a510310 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1205,9 +1205,14 @@ void ide_init_disk(struct gendisk *, ide_drive_t *); extern int ideprobe_init(void); +#ifdef CONFIG_IDEPCI_PCIBUS_ORDER extern void ide_scan_pcibus(int scan_direction) __init; extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name); #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME) +#else +#define ide_pci_register_driver(d) pci_register_driver(d) +#endif + void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); From 317a46a200e6514a1acf50ed30291160185a5c73 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 10 May 2007 00:01:11 +0200 Subject: [PATCH 11/11] ide: fix PIO setup on resume for ATAPI devices PIO should be restored also for ATAPI devices during resume, fix it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 8670112f1d39..8e568143d90d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -172,15 +172,6 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * memset(args, 0, sizeof(*args)); - if (drive->media != ide_disk) { - /* - * skip idedisk_pm_restore_pio and idedisk_pm_idle for ATAPI - * devices - */ - if (pm->pm_step == idedisk_pm_restore_pio) - pm->pm_step = ide_pm_restore_dma; - } - switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ if (drive->media != ide_disk) @@ -207,7 +198,13 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ if (drive->hwif->tuneproc != NULL) drive->hwif->tuneproc(drive, 255); - ide_complete_power_step(drive, rq, 0, 0); + /* + * skip idedisk_pm_idle for ATAPI devices + */ + if (drive->media != ide_disk) + pm->pm_step = ide_pm_restore_dma; + else + ide_complete_power_step(drive, rq, 0, 0); return ide_stopped; case idedisk_pm_idle: /* Resume step 2 (idle) */