From 453112975108ee2b002fc7e95b1c01f735be6d36 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Tue, 4 Jun 2002 00:57:10 -0700 Subject: Change unused_initcall to postcore_initcall for things that must be initialized early, but not too early (after the core is done) --- include/linux/init.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/init.h b/include/linux/init.h index ca7e75f37883..b45b95c5e640 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -61,7 +61,7 @@ extern initcall_t __initcall_start, __initcall_end; static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".initcall" level ".init"))) = fn #define core_initcall(fn) __define_initcall("1",fn) -#define unused_initcall(fn) __define_initcall("2",fn) +#define postcore_initcall(fn) __define_initcall("2",fn) #define arch_initcall(fn) __define_initcall("3",fn) #define subsys_initcall(fn) __define_initcall("4",fn) #define fs_initcall(fn) __define_initcall("5",fn) @@ -160,7 +160,7 @@ typedef void (*__cleanup_module_func_t)(void); #define __setup(str,func) /* nothing */ #define core_initcall(fn) module_init(fn) -#define unused_initcall(fn) module_init(fn) +#define postcore_initcall(fn) module_init(fn) #define arch_initcall(fn) module_init(fn) #define subsys_initcall(fn) module_init(fn) #define fs_initcall(fn) module_init(fn) -- cgit v1.2.3 From 4b0e0af3d4afe9d011f2419cfb36eaff4b00c562 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Wed, 5 Jun 2002 00:43:23 -0700 Subject: device model update s/{driver,device}_bind/{driver,device}_attach/ and s/{driver,device}_unbind/{driver,device}_detach/ call bus's match callback instead of bind callback --- drivers/base/base.h | 4 ++-- drivers/base/core.c | 36 ++++++++++++++++++------------------ drivers/base/driver.c | 4 ++-- drivers/pci/pci-driver.c | 6 +++--- include/linux/device.h | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/base.h b/drivers/base/base.h index aed2c93ba12c..5413942ce8f6 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -18,5 +18,5 @@ extern void device_remove_dir(struct device * dev); extern int device_bus_link(struct device * dev); -extern int driver_bind(struct device_driver * drv); -extern void driver_unbind(struct device_driver * drv); +extern int driver_attach(struct device_driver * drv); +extern void driver_detach(struct device_driver * drv); diff --git a/drivers/base/core.c b/drivers/base/core.c index 5b29a4943f7f..01887cd6942e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -31,7 +31,7 @@ spinlock_t device_lock = SPIN_LOCK_UNLOCKED; * @dev: device * @drv: driver * - * We're here because the bus's bind callback returned success for this + * We're here because the bus's match callback returned success for this * pair. We call the driver's probe callback to verify they're really a * match made in heaven. * @@ -67,60 +67,60 @@ static int found_match(struct device * dev, struct device_driver * drv) } /** - * bind_device - try to associated device with a driver + * device_attach - try to associated device with a driver * @drv: current driver to try * @data: device in disguise * * This function is used as a callback to bus_for_each_drv. - * It calls the bus's ::bind callback to check if the driver supports + * It calls the bus's match callback to check if the driver supports * the device. If so, it calls the found_match() function above to * take care of all the details. */ -static int do_device_bind(struct device_driver * drv, void * data) +static int do_device_attach(struct device_driver * drv, void * data) { struct device * dev = (struct device *)data; int error = 0; if (!dev->driver) { - if (drv->bus->bind && drv->bus->bind(dev,drv)) + if (drv->bus->match && drv->bus->match(dev,drv)) error = found_match(dev,drv); } return error; } -static int device_bind(struct device * dev) +static int device_attach(struct device * dev) { int error = 0; if (dev->bus) - error = bus_for_each_drv(dev->bus,dev,do_device_bind); + error = bus_for_each_drv(dev->bus,dev,do_device_attach); return error; } -static void device_unbind(struct device * dev) +static void device_detach(struct device * dev) { - /* unbind from driver */ + /* detach from driver */ if (dev->driver && dev->driver->remove) dev->driver->remove(dev); } -static int do_driver_bind(struct device * dev, void * data) +static int do_driver_attach(struct device * dev, void * data) { struct device_driver * drv = (struct device_driver *)data; int error = 0; if (!dev->driver) { - if (dev->bus->bind && dev->bus->bind(dev,drv)) + if (dev->bus->match && dev->bus->match(dev,drv)) error = found_match(dev,drv); } return error; } -int driver_bind(struct device_driver * drv) +int driver_attach(struct device_driver * drv) { - return bus_for_each_dev(drv->bus,drv,do_driver_bind); + return bus_for_each_dev(drv->bus,drv,do_driver_attach); } -static int do_driver_unbind(struct device * dev, struct device_driver * drv) +static int do_driver_detach(struct device * dev, struct device_driver * drv) { lock_device(dev); if (dev->driver == drv) { @@ -133,7 +133,7 @@ static int do_driver_unbind(struct device * dev, struct device_driver * drv) return 0; } -void driver_unbind(struct device_driver * drv) +void driver_detach(struct device_driver * drv) { struct device * next; struct device * dev = NULL; @@ -150,7 +150,7 @@ void driver_unbind(struct device_driver * drv) if (dev) put_device(dev); dev = next; - if ((error = do_driver_unbind(dev,drv))) { + if ((error = do_driver_detach(dev,drv))) { put_device(dev); break; } @@ -212,7 +212,7 @@ int device_register(struct device *dev) bus_add_device(dev); /* bind to driver */ - device_bind(dev); + device_attach(dev); /* notify platform of device entry */ if (platform_notify) @@ -246,7 +246,7 @@ void put_device(struct device * dev) if (platform_notify_remove) platform_notify_remove(dev); - device_unbind(dev); + device_detach(dev); bus_remove_device(dev); /* remove the driverfs directory */ diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 820d4bac5651..d3a4a5596299 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -74,7 +74,7 @@ int driver_register(struct device_driver * drv) list_add(&drv->bus_list,&drv->bus->drivers); write_unlock(&drv->bus->lock); driver_make_dir(drv); - driver_bind(drv); + driver_attach(drv); put_driver(drv); return 0; } @@ -84,7 +84,7 @@ static void __remove_driver(struct device_driver * drv) if (drv->bus) { pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name); - driver_unbind(drv); + driver_detach(drv); write_lock(&drv->bus->lock); list_del_init(&drv->bus_list); write_unlock(&drv->bus->lock); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7bfbbab8087f..0260ccf2092a 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -165,7 +165,7 @@ pci_dev_driver(const struct pci_dev *dev) } /** - * pci_bus_bind - Tell if a PCI device structure has a matching PCI device id structure + * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure * @ids: array of PCI device id structures to search in * @dev: the PCI device structure to match against * @@ -173,7 +173,7 @@ pci_dev_driver(const struct pci_dev *dev) * system is in its list of supported devices.Returns the matching * pci_device_id structure or %NULL if there is no match. */ -static int pci_bus_bind(struct device * dev, struct device_driver * drv) +static int pci_bus_match(struct device * dev, struct device_driver * drv) { struct pci_dev * pci_dev = list_entry(dev, struct pci_dev, dev); struct pci_driver * pci_drv = list_entry(drv,struct pci_driver,driver); @@ -196,7 +196,7 @@ static int pci_bus_bind(struct device * dev, struct device_driver * drv) struct bus_type pci_bus_type = { name: "pci", - bind: pci_bus_bind, + match: pci_bus_match, }; static int __init pci_driver_init(void) diff --git a/include/linux/device.h b/include/linux/device.h index 1c35f87abc9e..053572009fa1 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -64,7 +64,7 @@ struct bus_type { struct driver_dir_entry device_dir; struct driver_dir_entry driver_dir; - int (*bind) (struct device * dev, struct device_driver * drv); + int (*match) (struct device * dev, struct device_driver * drv); }; -- cgit v1.2.3 From 98c4217c8bd55f527165ba82d9602ca3dc966dcf Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Thu, 6 Jun 2002 09:48:39 -0500 Subject: ISDN: Add support for Eicon Diva 2.02 (by Joerg Petersohn/Karsten Keil) --- Documentation/isdn/README.HiSax | 7 +- drivers/isdn/hisax/Makefile | 2 +- drivers/isdn/hisax/config.c | 1 + drivers/isdn/hisax/diva.c | 126 ++++- drivers/isdn/hisax/ipacx.c | 1029 +++++++++++++++++++++++++++++++++++++++ drivers/isdn/hisax/ipacx.h | 161 ++++++ include/linux/pci_ids.h | 1 + 7 files changed, 1311 insertions(+), 16 deletions(-) create mode 100644 drivers/isdn/hisax/ipacx.c create mode 100644 drivers/isdn/hisax/ipacx.h (limited to 'include/linux') diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax index ab5a306e5570..ce646436842f 100644 --- a/Documentation/isdn/README.HiSax +++ b/Documentation/isdn/README.HiSax @@ -41,9 +41,10 @@ ELSA Quickstep 3000 (same settings as QS1000) ELSA Quickstep 3000PCI ELSA PCMCIA ITK ix1-micro Rev.2 -Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version) -Eicon.Diehl Diva 2.01 ISA and PCI -Eicon.Diehl Diva Piccola +Eicon Diva 2.0 ISA and PCI (S0 and U interface, no PRO version) +Eicon Diva 2.01 ISA and PCI +Eicon Diva 2.02 PCI +Eicon Diva Piccola ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D) Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter) PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink) diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index b06f3428e669..de0bd72ab434 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -39,7 +39,7 @@ hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index f8f8d32097b5..5efd91c392d8 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -2094,6 +2094,7 @@ static struct pci_device_id hisax_pci_tbl[] __initdata = { {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, PCI_ANY_ID, PCI_ANY_ID}, #endif #ifdef CONFIG_HISAX_ELSA {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID}, diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 02478dc5e3ab..dfc147c70440 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -22,6 +22,7 @@ #include "isac.h" #include "hscx.h" #include "ipac.h" +#include "ipacx.h" #include "isdnl1.h" #include @@ -49,6 +50,7 @@ const char *Diva_revision = "$Revision: 1.25.6.5 $"; #define DIVA_PCI 2 #define DIVA_IPAC_ISA 3 #define DIVA_IPAC_PCI 4 +#define DIVA_IPACX_PCI 5 /* CTRL (Read) */ #define DIVA_IRQ_STAT 0x01 @@ -68,10 +70,12 @@ const char *Diva_revision = "$Revision: 1.25.6.5 $"; #define PITA_MISC_REG 0x1c #ifdef __BIG_ENDIAN #define PITA_PARA_SOFTRESET 0x00000001 +#define PITA_SER_SOFTRESET 0x00000002 #define PITA_PARA_MPX_MODE 0x00000004 #define PITA_INT0_ENABLE 0x00000200 #else #define PITA_PARA_SOFTRESET 0x01000000 +#define PITA_SER_SOFTRESET 0x02000000 #define PITA_PARA_MPX_MODE 0x04000000 #define PITA_INT0_ENABLE 0x00020000 #endif @@ -239,6 +243,47 @@ MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value); } +/* IO-Functions for IPACX type cards */ +static u_char +MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset) +{ + return (memreadreg(cs->hw.diva.cfg_reg, offset)); +} + +static void +MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value) +{ + memwritereg(cs->hw.diva.cfg_reg, offset, value); +} + +static void +MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) +{ + while(size--) + *data++ = memreadreg(cs->hw.diva.cfg_reg, 0); +} + +static void +MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) +{ + while(size--) + memwritereg(cs->hw.diva.cfg_reg, 0, *data++); +} + +static u_char +MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return(memreadreg(cs->hw.diva.cfg_reg, offset + + (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1))); +} + +static void +MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + memwritereg(cs->hw.diva.cfg_reg, offset + + (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value); +} + /* * fast interrupt HSCX stuff goes here */ @@ -549,7 +594,7 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val) u_char exval; struct BCState *bcs; - if (val & 0x01) { + if (val & 0x01) { // EXB bcs = cs->bcs + 1; exval = MemReadHSCX(cs, 1, HSCX_EXIR); if (exval & 0x40) { @@ -576,7 +621,7 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val) debugl1(cs, "HSCX B interrupt %x", val); Memhscx_interrupt(cs, val, 1); } - if (val & 0x02) { + if (val & 0x02) { // EXA bcs = cs->bcs; exval = MemReadHSCX(cs, 0, HSCX_EXIR); if (exval & 0x40) { @@ -598,7 +643,7 @@ Memhscx_int_main(struct IsdnCardState *cs, u_char val) } else if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX A EXIR %x", exval); } - if (val & 0x04) { + if (val & 0x04) { // ICA exval = MemReadHSCX(cs, 0, HSCX_ISTA); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX A interrupt %x", exval); @@ -659,12 +704,31 @@ Start_IPACPCI: memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0); } +static void +diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_char *cfg; + + if (!cs) { + printk(KERN_WARNING "Diva: Spurious interrupt!\n"); + return; + } + cfg = (u_char *) cs->hw.diva.pci_cfg; + val = *cfg; + if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ + interrupt_ipacx(cs); // handler for chip + *cfg = PITA_INT0_STATUS; // Reset PLX interrupt +} + void release_io_diva(struct IsdnCardState *cs) { int bytecnt; - if (cs->subtyp == DIVA_IPAC_PCI) { + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) { u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg; *cfg = 0; /* disable INT0/1 */ @@ -711,6 +775,16 @@ reset_diva(struct IsdnCardState *cs) set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); + } else if (cs->subtyp == DIVA_IPACX_PCI) { + unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + + PITA_MISC_REG); + *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off } else { /* DIVA 2.0 */ cs->hw.diva.ctrl_reg = 0; /* Reset On */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); @@ -739,7 +813,10 @@ diva_led_handler(struct IsdnCardState *cs) { int blink = 0; - if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI)) +// if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI)) + if ((cs->subtyp == DIVA_IPAC_ISA) || + (cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) return; del_timer(&cs->hw.diva.tl); if (cs->hw.diva.status & DIVA_ASSIGN) @@ -782,6 +859,12 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) release_io_diva(cs); return(0); case CARD_INIT: + if (cs->subtyp == DIVA_IPACX_PCI) { + ireg = (unsigned int *)cs->hw.diva.pci_cfg; + *ireg = PITA_INT0_ENABLE; + init_ipacx(cs, 3); // init chip and enable interrupts + return (0); + } if (cs->subtyp == DIVA_IPAC_PCI) { ireg = (unsigned int *)cs->hw.diva.pci_cfg; *ireg = PITA_INT0_ENABLE; @@ -818,7 +901,9 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) } break; } - if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI)) + if ((cs->subtyp != DIVA_IPAC_ISA) && + (cs->subtyp != DIVA_IPAC_PCI) && + (cs->subtyp != DIVA_IPACX_PCI) ) diva_led_handler(cs); return(0); } @@ -916,7 +1001,8 @@ setup_diva(struct IsdnCard *card) printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); return (0); #endif /* CONFIG_PCI */ - if (cs->subtyp == DIVA_IPAC_PCI) { + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) { cs->hw.diva.ctrl = 0; cs->hw.diva.isac = 0; cs->hw.diva.hscx = 0; @@ -938,13 +1024,18 @@ setup_diva(struct IsdnCard *card) "Diva: %s card configured at %#lx IRQ %d\n", (cs->subtyp == DIVA_PCI) ? "PCI" : (cs->subtyp == DIVA_ISA) ? "ISA" : - (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI", + (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : + (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq); - if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI)) - printk(KERN_INFO "Diva: %s PCI space at %#lx\n", - (cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI", + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) || + (cs->subtyp == DIVA_PCI) ) + printk(KERN_INFO "Diva: %s space at %#lx\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : + (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", cs->hw.diva.pci_cfg); - if (cs->subtyp != DIVA_IPAC_PCI) { + if ((cs->subtyp != DIVA_IPAC_PCI) && + (cs->subtyp != DIVA_IPACX_PCI) ) { if (check_region(cs->hw.diva.cfg_reg, bytecnt)) { printk(KERN_WARNING "HiSax: %s config port %lx-%lx already in use\n", @@ -980,6 +1071,17 @@ setup_diva(struct IsdnCard *card) cs->irq_func = &diva_irq_ipac_pci; val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID); printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else if (cs->subtyp == DIVA_IPACX_PCI) { + cs->readisac = &MemReadISAC_IPACX; + cs->writeisac = &MemWriteISAC_IPACX; + cs->readisacfifo = &MemReadISACfifo_IPACX; + cs->writeisacfifo = &MemWriteISACfifo_IPACX; + cs->BC_Read_Reg = &MemReadHSCX_IPACX; + cs->BC_Write_Reg = &MemWriteHSCX_IPACX; + cs->BC_Send_Data = 0; // function located in ipacx module + cs->irq_func = &diva_irq_ipacx_pci; + printk(KERN_INFO "Diva: IPACX Design Id: %x\n", + MemReadISAC_IPACX(cs, IPACX_ID) &0x3F); } else { /* DIVA 2.0 */ cs->hw.diva.tl.function = (void *) diva_led_handler; cs->hw.diva.tl.data = (long) cs; diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c new file mode 100644 index 000000000000..2d4d4a47ffd9 --- /dev/null +++ b/drivers/isdn/hisax/ipacx.c @@ -0,0 +1,1029 @@ +/* + * + * IPACX specific routines + * + * Author Joerg Petersohn + * Derived from hisax_isac.c, isac.c, hscx.c and others + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ +#define __NO_VERSION__ +#include +#include +#include +#include "hisax_if.h" +#include "hisax.h" +#include "isdnl1.h" +#include "ipacx.h" + +#define DBUSY_TIMER_VALUE 80 +#define TIMER3_VALUE 7000 +#define MAX_DFRAME_LEN_L1 300 +#define B_FIFO_SIZE 64 +#define D_FIFO_SIZE 32 + + +// ipacx interrupt mask values +#define _MASK_IMASK 0x2E // global mask +#define _MASKB_IMASK 0x0B +#define _MASKD_IMASK 0x03 // all on + +//---------------------------------------------------------- +// local function declarations +//---------------------------------------------------------- +static void ph_command(struct IsdnCardState *cs, unsigned int command); +static inline void cic_int(struct IsdnCardState *cs); +static void dch_l2l1(struct PStack *st, int pr, void *arg); +static void dbusy_timer_handler(struct IsdnCardState *cs); +static void ipacx_new_ph(struct IsdnCardState *cs); +static void dch_bh(struct IsdnCardState *cs); +static void dch_sched_event(struct IsdnCardState *cs, int event); +static void dch_empty_fifo(struct IsdnCardState *cs, int count); +static void dch_fill_fifo(struct IsdnCardState *cs); +static inline void dch_int(struct IsdnCardState *cs); +static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs); +static void __devinit dch_init(struct IsdnCardState *cs); +static void bch_l2l1(struct PStack *st, int pr, void *arg); +static void bch_sched_event(struct BCState *bcs, int event); +static void bch_empty_fifo(struct BCState *bcs, int count); +static void bch_fill_fifo(struct BCState *bcs); +static void bch_int(struct IsdnCardState *cs, u_char hscx); +static void bch_mode(struct BCState *bcs, int mode, int bc); +static void bch_close_state(struct BCState *bcs); +static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs); +static int bch_setstack(struct PStack *st, struct BCState *bcs); +static void __devinit bch_init(struct IsdnCardState *cs, int hscx); +static void __init clear_pending_ints(struct IsdnCardState *cs); + +//---------------------------------------------------------- +// Issue Layer 1 command to chip +//---------------------------------------------------------- +static void +ph_command(struct IsdnCardState *cs, unsigned int command) +{ + if (cs->debug &L1_DEB_ISAC) + debugl1(cs, "ph_command (%#x) in (%#x)", command, + cs->dc.isac.ph_state); +//################################### +// printk(KERN_INFO "ph_command (%#x)\n", command); +//################################### + cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E); +} + +//---------------------------------------------------------- +// Transceiver interrupt handler +//---------------------------------------------------------- +static inline void +cic_int(struct IsdnCardState *cs) +{ + u_char event; + + event = cs->readisac(cs, IPACX_CIR0) >> 4; + if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event); +//######################################### +// printk(KERN_INFO "cic_int(%x)\n", event); +//######################################### + cs->dc.isac.ph_state = event; + dch_sched_event(cs, D_L1STATECHANGE); +} + +//========================================================== +// D channel functions +//========================================================== + +//---------------------------------------------------------- +// Command entry point +//---------------------------------------------------------- +static void +dch_l2l1(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; + struct sk_buff *skb = arg; + u_char cda1_cr, cda2_cr; + + switch (pr) { + case (PH_DATA |REQUEST): + if (cs->debug &DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); + if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG + if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG + if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + dch_fill_fifo(cs); + } + break; + + case (PH_PULL |INDICATION): + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + dch_fill_fifo(cs); + break; + + case (PH_PULL | REQUEST): +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l2.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + + case (HW_RESET | REQUEST): + case (HW_ENABLE | REQUEST): + ph_command(cs, IPACX_CMD_TIM); + break; + + case (HW_INFO3 | REQUEST): + ph_command(cs, IPACX_CMD_AR8); + break; + + case (HW_TESTLOOP | REQUEST): + cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 + cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 + cda1_cr = cs->readisac(cs, IPACX_CDA1_CR); + cda2_cr = cs->readisac(cs, IPACX_CDA2_CR); + if ((long)arg &1) { // loop B1 + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a); + } + else { // B1 off + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); + } + if ((long)arg &2) { // loop B2 + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x14); + } + else { // B2 off + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x14); + } + break; + + case (HW_DEACTIVATE | RESPONSE): + skb_queue_purge(&cs->rq); + skb_queue_purge(&cs->sq); + if (cs->tx_skb) { + dev_kfree_skb_any(cs->tx_skb); + cs->tx_skb = NULL; + } + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + break; + + default: + if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_l2l1 unknown %04x", pr); + break; + } +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static void +dbusy_timer_handler(struct IsdnCardState *cs) +{ + struct PStack *st; + int rbchd, stard; + + if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + rbchd = cs->readisac(cs, IPACX_RBCHD); + stard = cs->readisac(cs, IPACX_STARD); + if (cs->debug) + debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard); + if (!(stard &0x40)) { // D-Channel Busy + set_bit(FLG_L1_DBUSY, &cs->HW_Flags); + for (st = cs->stlist; st; st = st->next) { + st->l2.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on + } + } else { + // seems we lost an interrupt; reset transceiver */ + clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); + if (cs->tx_skb) { + dev_kfree_skb_any(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } else { + printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); + debugl1(cs, "D-Channel Busy no skb"); + } + cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR + } + } +} + +//---------------------------------------------------------- +// L1 state machine intermediate layer to isdnl1 module +//---------------------------------------------------------- +static void +ipacx_new_ph(struct IsdnCardState *cs) +{ + switch (cs->dc.isac.ph_state) { + case (IPACX_IND_RES): + ph_command(cs, IPACX_CMD_DI); + l1_msg(cs, HW_RESET | INDICATION, NULL); + break; + + case (IPACX_IND_DC): + l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); + break; + + case (IPACX_IND_DR): + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); + break; + + case (IPACX_IND_PU): + l1_msg(cs, HW_POWERUP | CONFIRM, NULL); + break; + + case (IPACX_IND_RSY): + l1_msg(cs, HW_RSYNC | INDICATION, NULL); + break; + + case (IPACX_IND_AR): + l1_msg(cs, HW_INFO2 | INDICATION, NULL); + break; + + case (IPACX_IND_AI8): + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); + break; + + case (IPACX_IND_AI10): + l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL); + break; + + default: + break; + } +} + +//---------------------------------------------------------- +// bottom half handler for D channel +//---------------------------------------------------------- +static void +dch_bh(struct IsdnCardState *cs) +{ + struct PStack *st; + + if (!cs) return; + + if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { + if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); + for (st = cs->stlist; st; st = st->next) { + st->l2.l1l2(st, PH_PAUSE | CONFIRM, NULL); + } + } + + if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) { + DChannel_proc_rcv(cs); + } + + if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) { + DChannel_proc_xmt(cs); + } + + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { + ipacx_new_ph(cs); + } +} + +//---------------------------------------------------------- +// proceed with bottom half handler dch_bh() +//---------------------------------------------------------- +static void +dch_sched_event(struct IsdnCardState *cs, int event) +{ + set_bit(event, &cs->event); + queue_task(&cs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +//---------------------------------------------------------- +// Fill buffer from receive FIFO +//---------------------------------------------------------- +static void +dch_empty_fifo(struct IsdnCardState *cs, int count) +{ + long flags; + u_char *ptr; + + if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) + debugl1(cs, "dch_empty_fifo()"); + + // message too large, remove + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "dch_empty_fifo() incoming message too large"); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + cs->rcvidx = 0; + return; + } + + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + + save_flags(flags); + cli(); + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + restore_flags(flags); + + if (cs->debug &L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "dch_empty_fifo() cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } +} + +//---------------------------------------------------------- +// Fill transmit FIFO +//---------------------------------------------------------- +static void +dch_fill_fifo(struct IsdnCardState *cs) +{ + long flags; + int count; + u_char cmd, *ptr; + + if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) + debugl1(cs, "dch_fill_fifo()"); + + if (!cs->tx_skb) return; + count = cs->tx_skb->len; + if (count <= 0) return; + + if (count > D_FIFO_SIZE) { + count = D_FIFO_SIZE; + cmd = 0x08; // XTF + } else { + cmd = 0x0A; // XTF | XME + } + + save_flags(flags); + cli(); + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, IPACX_CMDRD, cmd); + + // set timeout for transmission contol + if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + debugl1(cs, "dch_fill_fifo dbusytimer running"); + del_timer(&cs->dbusytimer); + } + init_timer(&cs->dbusytimer); + cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); + add_timer(&cs->dbusytimer); + restore_flags(flags); + + if (cs->debug &L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "dch_fill_fifo() cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } +} + +//---------------------------------------------------------- +// D channel interrupt handler +//---------------------------------------------------------- +static inline void +dch_int(struct IsdnCardState *cs) +{ + struct sk_buff *skb; + u_char istad, rstad; + long flags; + int count; + + istad = cs->readisac(cs, IPACX_ISTAD); +//############################################## +// printk(KERN_WARNING "dch_int(istad=%02x)\n", istad); +//############################################## + + if (istad &0x80) { // RME + rstad = cs->readisac(cs, IPACX_RSTAD); + if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) + if (!(rstad &0x80)) + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "dch_int(): invalid frame"); + if ((rstad &0x40)) + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "dch_int(): RDO"); + if (!(rstad &0x20)) + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "dch_int(): CRC error"); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + } else { // received frame ok + count = cs->readisac(cs, IPACX_RBCLD); + if (count) count--; // RSTAB is last byte + count &= D_FIFO_SIZE-1; + if (count == 0) count = D_FIFO_SIZE; + dch_empty_fifo(cs, count); + save_flags(flags); + cli(); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } + restore_flags(flags); + } + cs->rcvidx = 0; + dch_sched_event(cs, D_RCVBUFREADY); + } + + if (istad &0x40) { // RPF + dch_empty_fifo(cs, D_FIFO_SIZE); + } + + if (istad &0x20) { // RFO + if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): RFO"); + cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES + } + + if (istad &0x10) { // XPR + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + dch_sched_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + dch_fill_fifo(cs); + goto afterXPR; + } + else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_skb = NULL; + cs->tx_cnt = 0; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + dch_fill_fifo(cs); + } + else { + dch_sched_event(cs, D_XMTBUFREADY); + } + } + afterXPR: + + if (istad &0x0C) { // XDU or XMR + if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU"); + if (cs->tx_skb) { + skb_push(cs->tx_skb, cs->tx_cnt); // retransmit + cs->tx_cnt = 0; + dch_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); + debugl1(cs, "ISAC XDU no skb"); + } + } +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static void __devinit +dch_setstack(struct PStack *st, struct IsdnCardState *cs) +{ + st->l1.l1hw = dch_l2l1; +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static void __devinit +dch_init(struct IsdnCardState *cs) +{ + printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n"); + + cs->tqueue.routine = (void *)(void *) dch_bh; + cs->setstack_d = dch_setstack; + + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + + cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD + cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter + cs->writeisac(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go + cs->writeisac(cs, IPACX_MON_CR, 0x00); // disable monitor channel +} + + +//========================================================== +// B channel functions +//========================================================== + +//---------------------------------------------------------- +// Entry point for commands +//---------------------------------------------------------- +static void +bch_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->hw.hscx.count = 0; + restore_flags(flags); + bch_fill_fifo(st->l1.bcs); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n"); + break; + } + set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->tx_skb = skb; + st->l1.bcs->hw.hscx.count = 0; + bch_fill_fifo(st->l1.bcs); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l2.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + bch_mode(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + bch_mode(st->l1.bcs, 0, st->l1.bc); + st->l2.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +//---------------------------------------------------------- +// proceed with bottom half handler BChannel_bh() +//---------------------------------------------------------- +static void +bch_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +//---------------------------------------------------------- +// Read B channel fifo to receive buffer +//---------------------------------------------------------- +static void +bch_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr, hscx; + struct IsdnCardState *cs; + long flags; + int cnt; + + cs = bcs->cs; + hscx = bcs->hw.hscx.hscx; + if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) + debugl1(cs, "bch_empty_fifo()"); + + // message too large, remove + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_empty_fifo() incoming packet too large"); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + bcs->hw.hscx.rcvidx = 0; + return; + } + + // Read data uninterruptible + save_flags(flags); + cli(); + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + cnt = count; + while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + restore_flags(flags); + + if (cs->debug &L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +//---------------------------------------------------------- +// Fill buffer to transmit FIFO +//---------------------------------------------------------- +static void +bch_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs; + int more, count, cnt; + u_char *ptr, *p, hscx; + long flags; + + cs = bcs->cs; + if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) + debugl1(cs, "bch_fill_fifo()"); + + if (!bcs->tx_skb) return; + if (bcs->tx_skb->len <= 0) return; + + hscx = bcs->hw.hscx.hscx; + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > B_FIFO_SIZE) { + more = 1; + count = B_FIFO_SIZE; + } else { + count = bcs->tx_skb->len; + } + cnt = count; + + save_flags(flags); + cli(); + p = ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a)); + restore_flags(flags); + + if (cs->debug &L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +//---------------------------------------------------------- +// B channel interrupt handler +//---------------------------------------------------------- +static void +bch_int(struct IsdnCardState *cs, u_char hscx) +{ + u_char istab; + struct BCState *bcs; + struct sk_buff *skb; + int count; + u_char rstab; + + bcs = cs->bcs + hscx; + istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB); +//############################################## +// printk(KERN_WARNING "bch_int(istab=%02x)\n", istab); +//############################################## + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return; + + if (istab &0x80) { // RME + rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB); + if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) + if (!(rstab &0x80)) + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d: invalid frame", hscx); + if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL)) + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); + if (!(rstab &0x20)) + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d: CRC error", hscx); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + } + else { // received frame ok + count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) &(B_FIFO_SIZE-1); + if (count == 0) count = B_FIFO_SIZE; + bch_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug &L1_DEB_HSCX_FIFO) + debugl1(cs, "bch_int Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.hscx.rcvidx = 0; + bch_sched_event(bcs, B_RCVBUFREADY); + } + + if (istab &0x40) { // RPF + bch_empty_fifo(bcs, B_FIFO_SIZE); + + if (bcs->mode == L1_MODE_TRANS) { // queue every chunk + // receive transparent audio data + if (!(skb = dev_alloc_skb(B_FIFO_SIZE))) + printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n"); + else { + memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + bch_sched_event(bcs, B_RCVBUFREADY); + } + } + + if (istab &0x20) { // RFO + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d: RFO error", hscx); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES + } + + if (istab &0x10) { // XPR + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + bch_fill_fifo(bcs); + goto afterXPR; + } + else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bch_fill_fifo(bcs); + } else { + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bch_sched_event(bcs, B_XMTBUFREADY); + } + } + afterXPR: + + if (istab &0x04) { // XDU + if (bcs->mode == L1_MODE_TRANS) { + bch_fill_fifo(bcs); + } + else { + if (bcs->tx_skb) { // restart transmitting the whole frame + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d XDU error", hscx); + } + } +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static void +bch_mode(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + int hscx = bcs->hw.hscx.hscx; + + bc = bc ? 1 : 0; // in case bc is greater than 1 + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "mode_bch() switch B-% mode %d chan %d", hscx, mode, bc); + bcs->mode = mode; + bcs->channel = bc; + + // map controller to according timeslot + if (!hscx) + { + cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc); + cs->writeisac(cs, IPACX_BCHA_CR, 0x88); + } + else + { + cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc); + cs->writeisac(cs, IPACX_BCHB_CR, 0x88); + } + + switch (mode) { + case (L1_MODE_NULL): + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0); // rec off + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x30); // std adj. + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF); // ints off + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + break; + case (L1_MODE_TRANS): + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88); // ext transp mode + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x00); // xxx00000 + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); + break; + case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8); // transp mode 0 + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); + break; + } +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static void +bch_close_state(struct BCState *bcs) +{ + bch_mode(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static int +bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax open_bchstate(): No memory for hscx.rcvbuf\n"); + clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax open_bchstate: No memory for bcs->blog\n"); + clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static int +bch_setstack(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (bch_open_state(st->l1.hardware, bcs)) return (-1); + st->l1.bcs = bcs; + st->l1.l2l1 = bch_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +//---------------------------------------------------------- +//---------------------------------------------------------- +static void __devinit +bch_init(struct IsdnCardState *cs, int hscx) +{ + cs->bcs[hscx].BC_SetStack = bch_setstack; + cs->bcs[hscx].BC_Close = bch_close_state; + cs->bcs[hscx].hw.hscx.hscx = hscx; + cs->bcs[hscx].cs = cs; + bch_mode(cs->bcs + hscx, 0, hscx); +} + + +//========================================================== +// Shared functions +//========================================================== + +//---------------------------------------------------------- +// Main interrupt handler +//---------------------------------------------------------- +void +interrupt_ipacx(struct IsdnCardState *cs) +{ + u_char ista; + + while ((ista = cs->readisac(cs, IPACX_ISTA))) { +//################################################# +// printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista); +//################################################# + if (ista &0x80) bch_int(cs, 0); // B channel interrupts + if (ista &0x40) bch_int(cs, 1); + + if (ista &0x01) dch_int(cs); // D channel + if (ista &0x10) cic_int(cs); // Layer 1 state + } +} + +//---------------------------------------------------------- +// Clears chip interrupt status +//---------------------------------------------------------- +static void __init +clear_pending_ints(struct IsdnCardState *cs) +{ + int ista; + + // all interrupts off + cs->writeisac(cs, IPACX_MASK, 0xff); + cs->writeisac(cs, IPACX_MASKD, 0xff); + cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff); + cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff); + + ista = cs->readisac(cs, IPACX_ISTA); + if (ista &0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB); + if (ista &0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB); + if (ista &0x10) cs->readisac(cs, IPACX_CIR0); + if (ista &0x01) cs->readisac(cs, IPACX_ISTAD); +} + +//---------------------------------------------------------- +// Does chip configuration work +// Work to do depends on bit mask in part +//---------------------------------------------------------- +void __init +init_ipacx(struct IsdnCardState *cs, int part) +{ + if (part &1) { // initialise chip +//################################################## +// printk(KERN_INFO "init_ipacx(%x)\n", part); +//################################################## + clear_pending_ints(cs); + bch_init(cs, 0); + bch_init(cs, 1); + dch_init(cs); + } + if (part &2) { // reenable all interrupts and start chip + cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK); + cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK); + cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register + + // reset HDLC Transmitters/receivers + cs->writeisac(cs, IPACX_CMDRD, 0x41); + cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41); + cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41); + ph_command(cs, IPACX_CMD_RES); + } +} + +//----------------- end of file ----------------------- + diff --git a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h new file mode 100644 index 000000000000..fef4021f3eb1 --- /dev/null +++ b/drivers/isdn/hisax/ipacx.h @@ -0,0 +1,161 @@ +/* + * + * IPACX specific defines + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +/* All Registers original Siemens Spec */ + +#ifndef INCLUDE_IPACX_H +#define INCLUDE_IPACX_H + +/* D-channel registers */ +#define IPACX_RFIFOD 0x00 /* RD */ +#define IPACX_XFIFOD 0x00 /* WR */ +#define IPACX_ISTAD 0x20 /* RD */ +#define IPACX_MASKD 0x20 /* WR */ +#define IPACX_STARD 0x21 /* RD */ +#define IPACX_CMDRD 0x21 /* WR */ +#define IPACX_MODED 0x22 /* RD/WR */ +#define IPACX_EXMD1 0x23 /* RD/WR */ +#define IPACX_TIMR1 0x24 /* RD/WR */ +#define IPACX_SAP1 0x25 /* WR */ +#define IPACX_SAP2 0x26 /* WR */ +#define IPACX_RBCLD 0x26 /* RD */ +#define IPACX_RBCHD 0x27 /* RD */ +#define IPACX_TEI1 0x27 /* WR */ +#define IPACX_TEI2 0x28 /* WR */ +#define IPACX_RSTAD 0x28 /* RD */ +#define IPACX_TMD 0x29 /* RD/WR */ +#define IPACX_CIR0 0x2E /* RD */ +#define IPACX_CIX0 0x2E /* WR */ +#define IPACX_CIR1 0x2F /* RD */ +#define IPACX_CIX1 0x2F /* WR */ + +/* Transceiver registers */ +#define IPACX_TR_CONF0 0x30 /* RD/WR */ +#define IPACX_TR_CONF1 0x31 /* RD/WR */ +#define IPACX_TR_CONF2 0x32 /* RD/WR */ +#define IPACX_TR_STA 0x33 /* RD */ +#define IPACX_TR_CMD 0x34 /* RD/WR */ +#define IPACX_SQRR1 0x35 /* RD */ +#define IPACX_SQXR1 0x35 /* WR */ +#define IPACX_SQRR2 0x36 /* RD */ +#define IPACX_SQXR2 0x36 /* WR */ +#define IPACX_SQRR3 0x37 /* RD */ +#define IPACX_SQXR3 0x37 /* WR */ +#define IPACX_ISTATR 0x38 /* RD */ +#define IPACX_MASKTR 0x39 /* RD/WR */ +#define IPACX_TR_MODE 0x3A /* RD/WR */ +#define IPACX_ACFG1 0x3C /* RD/WR */ +#define IPACX_ACFG2 0x3D /* RD/WR */ +#define IPACX_AOE 0x3E /* RD/WR */ +#define IPACX_ARX 0x3F /* RD */ +#define IPACX_ATX 0x3F /* WR */ + +/* IOM: Timeslot, DPS, CDA */ +#define IPACX_CDA10 0x40 /* RD/WR */ +#define IPACX_CDA11 0x41 /* RD/WR */ +#define IPACX_CDA20 0x42 /* RD/WR */ +#define IPACX_CDA21 0x43 /* RD/WR */ +#define IPACX_CDA_TSDP10 0x44 /* RD/WR */ +#define IPACX_CDA_TSDP11 0x45 /* RD/WR */ +#define IPACX_CDA_TSDP20 0x46 /* RD/WR */ +#define IPACX_CDA_TSDP21 0x47 /* RD/WR */ +#define IPACX_BCHA_TSDP_BC1 0x48 /* RD/WR */ +#define IPACX_BCHA_TSDP_BC2 0x49 /* RD/WR */ +#define IPACX_BCHB_TSDP_BC1 0x4A /* RD/WR */ +#define IPACX_BCHB_TSDP_BC2 0x4B /* RD/WR */ +#define IPACX_TR_TSDP_BC1 0x4C /* RD/WR */ +#define IPACX_TR_TSDP_BC2 0x4D /* RD/WR */ +#define IPACX_CDA1_CR 0x4E /* RD/WR */ +#define IPACX_CDA2_CR 0x4F /* RD/WR */ + +/* IOM: Contol, Sync transfer, Monitor */ +#define IPACX_TR_CR 0x50 /* RD/WR */ +#define IPACX_TRC_CR 0x50 /* RD/WR */ +#define IPACX_BCHA_CR 0x51 /* RD/WR */ +#define IPACX_BCHB_CR 0x52 /* RD/WR */ +#define IPACX_DCI_CR 0x53 /* RD/WR */ +#define IPACX_DCIC_CR 0x53 /* RD/WR */ +#define IPACX_MON_CR 0x54 /* RD/WR */ +#define IPACX_SDS1_CR 0x55 /* RD/WR */ +#define IPACX_SDS2_CR 0x56 /* RD/WR */ +#define IPACX_IOM_CR 0x57 /* RD/WR */ +#define IPACX_STI 0x58 /* RD */ +#define IPACX_ASTI 0x58 /* WR */ +#define IPACX_MSTI 0x59 /* RD/WR */ +#define IPACX_SDS_CONF 0x5A /* RD/WR */ +#define IPACX_MCDA 0x5B /* RD */ +#define IPACX_MOR 0x5C /* RD */ +#define IPACX_MOX 0x5C /* WR */ +#define IPACX_MOSR 0x5D /* RD */ +#define IPACX_MOCR 0x5E /* RD/WR */ +#define IPACX_MSTA 0x5F /* RD */ +#define IPACX_MCONF 0x5F /* WR */ + +/* Interrupt and general registers */ +#define IPACX_ISTA 0x60 /* RD */ +#define IPACX_MASK 0x60 /* WR */ +#define IPACX_AUXI 0x61 /* RD */ +#define IPACX_AUXM 0x61 /* WR */ +#define IPACX_MODE1 0x62 /* RD/WR */ +#define IPACX_MODE2 0x63 /* RD/WR */ +#define IPACX_ID 0x64 /* RD */ +#define IPACX_SRES 0x64 /* WR */ +#define IPACX_TIMR2 0x65 /* RD/WR */ + +/* B-channel registers */ +#define IPACX_OFF_B1 0x70 +#define IPACX_OFF_B2 0x80 + +#define IPACX_ISTAB 0x00 /* RD */ +#define IPACX_MASKB 0x00 /* WR */ +#define IPACX_STARB 0x01 /* RD */ +#define IPACX_CMDRB 0x01 /* WR */ +#define IPACX_MODEB 0x02 /* RD/WR */ +#define IPACX_EXMB 0x03 /* RD/WR */ +#define IPACX_RAH1 0x05 /* WR */ +#define IPACX_RAH2 0x06 /* WR */ +#define IPACX_RBCLB 0x06 /* RD */ +#define IPACX_RBCHB 0x07 /* RD */ +#define IPACX_RAL1 0x07 /* WR */ +#define IPACX_RAL2 0x08 /* WR */ +#define IPACX_RSTAB 0x08 /* RD */ +#define IPACX_TMB 0x09 /* RD/WR */ +#define IPACX_RFIFOB 0x0A /*- RD */ +#define IPACX_XFIFOB 0x0A /*- WR */ + +/* Layer 1 Commands */ +#define IPACX_CMD_TIM 0x0 +#define IPACX_CMD_RES 0x1 +#define IPACX_CMD_SSP 0x2 +#define IPACX_CMD_SCP 0x3 +#define IPACX_CMD_AR8 0x8 +#define IPACX_CMD_AR10 0x9 +#define IPACX_CMD_ARL 0xa +#define IPACX_CMD_DI 0xf + +/* Layer 1 Indications */ +#define IPACX_IND_DR 0x0 +#define IPACX_IND_RES 0x1 +#define IPACX_IND_TMA 0x2 +#define IPACX_IND_SLD 0x3 +#define IPACX_IND_RSY 0x4 +#define IPACX_IND_DR6 0x5 +#define IPACX_IND_PU 0x7 +#define IPACX_IND_AR 0x8 +#define IPACX_IND_ARL 0xa +#define IPACX_IND_CVR 0xb +#define IPACX_IND_AI8 0xc +#define IPACX_IND_AI10 0xd +#define IPACX_IND_AIL 0xe +#define IPACX_IND_DC 0xf + +extern void init_ipacx(struct IsdnCardState *cs, int part); +extern void interrupt_ipacx(struct IsdnCardState *cs); + +#endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5fd0a9198a2a..6a45e0eb97e5 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1054,6 +1054,7 @@ #define PCI_DEVICE_ID_EICON_DIVA20PRO_U 0xe003 #define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004 #define PCI_DEVICE_ID_EICON_DIVA201 0xe005 +#define PCI_DEVICE_ID_EICON_DIVA202 0xe00b #define PCI_DEVICE_ID_EICON_MAESTRA 0xe010 #define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012 #define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 -- cgit v1.2.3 From 3f77edfe88b59b70bc538f835cec0a7b797face1 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Sat, 8 Jun 2002 02:12:09 -0700 Subject: [PATCH] Move vmalloc wrappers out of include/linux/vmalloc.h This moves the vmalloc wrappers from into mm/vmalloc.c. Doing this will later allow us to remove from , along with some other #include fixups. --- include/linux/vmalloc.h | 28 ++++------------------------ mm/vmalloc.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index e08fcf85c24f..a40c2064832b 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -24,33 +24,13 @@ extern long vread(char *buf, char *addr, unsigned long count); extern void vmfree_area_pages(unsigned long address, unsigned long size); extern int vmalloc_area_pages(unsigned long address, unsigned long size, int gfp_mask, pgprot_t prot); - -/* - * Allocate any pages - */ - -static inline void * vmalloc (unsigned long size) -{ - return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); -} - /* - * Allocate ISA addressable pages for broke crap + * Various ways to allocate pages. */ -static inline void * vmalloc_dma (unsigned long size) -{ - return __vmalloc(size, GFP_KERNEL|GFP_DMA, PAGE_KERNEL); -} - -/* - * vmalloc 32bit PA addressable pages - eg for PCI 32bit devices - */ - -static inline void * vmalloc_32(unsigned long size) -{ - return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL); -} +extern void * vmalloc(unsigned long size); +extern void * vmalloc_dma(unsigned long size); +extern void * vmalloc_32(unsigned long size); /* * vmlist_lock is a read-write spinlock that protects vmlist diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 5e269765466a..a3082fa949ce 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -232,6 +232,33 @@ void vfree(void * addr) printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr); } +/* + * Allocate any pages + */ + +void * vmalloc (unsigned long size) +{ + return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); +} + +/* + * Allocate ISA addressable pages for broke crap + */ + +void * vmalloc_dma (unsigned long size) +{ + return __vmalloc(size, GFP_KERNEL|GFP_DMA, PAGE_KERNEL); +} + +/* + * vmalloc 32bit PA addressable pages - eg for PCI 32bit devices + */ + +void * vmalloc_32(unsigned long size) +{ + return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL); +} + void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot) { void * addr; -- cgit v1.2.3 From 0bcf1924f303b69b36ae159e3406af4642dc8d3d Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Sat, 8 Jun 2002 02:13:15 -0700 Subject: [PATCH] Remove from This removes from . This then goes and fixes all of the files (x86 and PPC) which relied on implicit includes which don't happen anymore. This also takes out of fs/mpage.c and puts it into include/linux/bio.h where it belongs since references 'kdev_t' directly. A quick summary of the of the added includes: arch/i386/kernel/microcode.c: needs extern for num_physpages, in linux/mm.h include/linux/spinlock.h: local_irq* is defined in but this was never directly included. --- arch/i386/kernel/microcode.c | 1 + fs/mpage.c | 1 - include/asm-i386/pci.h | 1 + include/asm-i386/pgalloc.h | 1 + include/linux/bio.h | 1 + include/linux/spinlock.h | 2 ++ include/linux/vmalloc.h | 1 - 7 files changed, 6 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 328febf1f679..f48bd676ab80 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include diff --git a/fs/mpage.c b/fs/mpage.c index 3b014df61d35..238b7d608925 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index 1d957c02e541..57100de26c0c 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -4,6 +4,7 @@ #include #ifdef __KERNEL__ +#include /* for struct page */ /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h index 10e7021c33a6..f2d63db16cf5 100644 --- a/include/asm-i386/pgalloc.h +++ b/include/asm-i386/pgalloc.h @@ -5,6 +5,7 @@ #include #include #include +#include /* for struct page */ #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) diff --git a/include/linux/bio.h b/include/linux/bio.h index de52fa8f15e3..b244108a27a8 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -20,6 +20,7 @@ #ifndef __LINUX_BIO_H #define __LINUX_BIO_H +#include /* Platforms may set this to teach the BIO layer about IOMMU hardware. */ #include #ifndef BIO_VMERGE_BOUNDARY diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index a78cd80f4ab6..e46232e8e126 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -7,6 +7,8 @@ #include #include +#include + /* * These are the generic versions of the spinlocks and read-write * locks.. diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index a40c2064832b..18cce6c6526a 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -1,7 +1,6 @@ #ifndef __LINUX_VMALLOC_H #define __LINUX_VMALLOC_H -#include #include #include -- cgit v1.2.3 From dce2f963e28e62f2e961d13d41015059a226acee Mon Sep 17 00:00:00 2001 From: "Mitchell Blank Jr." Date: Sat, 8 Jun 2002 20:24:15 -0700 Subject: [PATCH] atm warning fix (vs 2.5.21) This fixes a large batch of warnings that popped up with the new stricter bitops.h that recently was introduced. We actually didn't have 64-bit bug, but we had built our own *_flags_t typedef's that were just struct wrappers around an unsigned long. We used to pass their addresses directly to set_bit() and friends but now that causes an error. The typedef's really didn't serve much purpose so the cleanest fix is to just eliminate them and use "unsigned long" directly. --- include/linux/atmdev.h | 14 +++----------- net/atm/clip.c | 2 +- net/atm/lec.c | 2 +- net/atm/proc.c | 2 +- net/atm/resources.c | 2 +- net/atm/signaling.c | 2 +- 6 files changed, 8 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 61f9ed77c999..ac6dbe9dd062 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -275,12 +275,8 @@ enum { #define ATM_ATMOPT_CLP 1 /* set CLP bit */ - -typedef struct { unsigned long bits; } atm_vcc_flags_t; - - struct atm_vcc { - atm_vcc_flags_t flags; /* VCC flags (ATM_VF_*) */ + unsigned long flags; /* VCC flags (ATM_VF_*) */ unsigned char family; /* address family; 0 if unused */ short vpi; /* VPI and VCI (types must be equal */ /* with sockaddr) */ @@ -330,10 +326,6 @@ struct atm_dev_addr { struct atm_dev_addr *next; /* next address */ }; - -typedef struct { unsigned int bits; } atm_dev_flags_t; - - struct atm_dev { const struct atmdev_ops *ops; /* device operations; NULL if unused */ const struct atmphy_ops *phy; /* PHY operations, may be undefined */ @@ -344,7 +336,7 @@ struct atm_dev { struct atm_vcc *last; /* last VCC (or undefined) */ void *dev_data; /* per-device data */ void *phy_data; /* private PHY date */ - atm_dev_flags_t flags; /* device flags (ATM_DF_*) */ + unsigned long flags; /* device flags (ATM_DF_*) */ struct atm_dev_addr *local; /* local ATM addresses */ unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ struct atm_cirange ci_range; /* VPI/VCI range */ @@ -414,7 +406,7 @@ struct atm_skb_data { #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb)) struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, - int number,atm_dev_flags_t *flags); /* number == -1: pick first available */ + int number,unsigned long *flags); /* number == -1: pick first available */ struct atm_dev *atm_find_dev(int number); void atm_dev_deregister(struct atm_dev *dev); void shutdown_atm_dev(struct atm_dev *dev); diff --git a/net/atm/clip.c b/net/atm/clip.c index c467acbe633d..3ae5ae8757aa 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -710,7 +710,7 @@ static struct atm_dev atmarpd_dev = { 999, /* dummy device number */ NULL,NULL, /* pretend not to have any VCCs */ NULL,NULL, /* no data */ - { 0 }, /* no flags */ + 0, /* no flags */ NULL, /* no local address */ { 0 } /* no ESI, no statistics */ }; diff --git a/net/atm/lec.c b/net/atm/lec.c index e481864a9f61..6d9f865720cd 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -564,7 +564,7 @@ static struct atm_dev lecatm_dev = { 999, /*dummy device number*/ NULL,NULL, /*no VCCs*/ NULL,NULL, /*no data*/ - { 0 }, /*no flags*/ + 0, /*no flags*/ NULL, /* no local address*/ { 0 } /*no ESI or rest of the atm_dev struct things*/ }; diff --git a/net/atm/proc.c b/net/atm/proc.c index e19a6a69a0a4..bc11d58e7931 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -220,7 +220,7 @@ static void vc_info(struct atm_vcc *vcc,char *buf) default: here += sprintf(here,"%3d",vcc->family); } - here += sprintf(here," %04lx %5d %7d/%7d %7d/%7d\n",vcc->flags.bits, + here += sprintf(here," %04lx %5d %7d/%7d %7d/%7d\n",vcc->flags, vcc->reply, atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf, atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf); diff --git a/net/atm/resources.c b/net/atm/resources.c index 3857176cc8bc..6a0ce727a8d0 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -83,7 +83,7 @@ struct atm_dev *atm_find_dev(int number) struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, - int number, atm_dev_flags_t *flags) + int number, unsigned long *flags) { struct atm_dev *dev; diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 278317ca8a85..2d27f200c901 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -239,7 +239,7 @@ static struct atm_dev sigd_dev = { 999, /* dummy device number */ NULL,NULL, /* pretend not to have any VCCs */ NULL,NULL, /* no data */ - { 0 }, /* no flags */ + 0, /* no flags */ NULL, /* no local address */ { 0 } /* no ESI, no statistics */ }; -- cgit v1.2.3 From 71e3ff68a75ab9dc6276fe0e519938003007ad8e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 8 Jun 2002 21:30:30 -0700 Subject: fix up fall-out from header cleanups --- include/linux/suspend.h | 1 + sound/pci/emu10k1/emumpu401.c | 1 + 2 files changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index c73dc5655a24..f63d72634a07 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -7,6 +7,7 @@ #include #include #include +#include extern unsigned char software_suspend_enabled; diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index 70646f78c31f..c2cf0ff1b27c 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c @@ -22,6 +22,7 @@ #define __NO_VERSION__ #include #include +#include #include #include -- cgit v1.2.3 From 467b45ea6236af91d8119422b19e4b1f8c4a67d6 Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sat, 8 Jun 2002 21:45:15 -0700 Subject: [PATCH] 2.5.20 IDE 86 Most importantly this makes ide-scsi work again, which I broke IDE 85. And we are starting to be serious about locking issues. However the locking issues will take some patches until they stabilize. - Add spin locks in ata_special_intr. - Add Server Works CSB6 handling by Matt Domsch. - Atari updates by Geert Uytterhoeven: * irq_lock is used in more than one file, so make it global and rename it to ide_irq_lock * `hwgroup' is dead, use `channel' instead * ide_irq_lock depends on ATA_ARCH_LOCK, not on m68k or APUS - Small janitorial tidbits by Angus Sawyer. - PIIX driver updates by Vojtech Pavlik: * Removes the CONFIG_BLK_DEV_PIIX_TRY133 option. I've got an official statement from Intel saying that the controller definitely isn't intended to operate at this speed and doing so may cause severe trouble. * Fixes a bug in ata-timing.c, where EIDE timing data was discarded by accident. * Fixed a couple bugs in the Artop driver (UDMA clocks, active/recovery timing), 8-bit timing merging. * Removes an unused variable from piix.c - Move locking out from ide_set_handler(). There are places where it incurred too frequent lock grab and release or where we did miss to lock against concurrent hardware access. Generally the locking appears to be too fine grained and inconsistent at many places. This is the first cut. We will deal with it step by step. - Make sure message string is initialized even if FANCY_STATUS_DUMPS is disabled. - Don't lock directly inside udma_init and implementations of this method. - Guard against REQ_SPECIAL issued by the SCSI layer on us. Use REQ_PC in ide-scsi.c instead. --- arch/cris/drivers/ide.c | 8 ++-- drivers/ide/Config.help | 10 ----- drivers/ide/Config.in | 3 -- drivers/ide/aec62xx.c | 28 ++++++++++---- drivers/ide/ata-timing.c | 34 +++++++++++----- drivers/ide/ata-timing.h | 3 +- drivers/ide/hpt34x.c | 9 ++--- drivers/ide/icside.c | 7 ++-- drivers/ide/ide-cd.c | 41 ++++++++++++++++---- drivers/ide/ide-disk.c | 77 ++++++++++++++++++++++++++++++------- drivers/ide/ide-floppy.c | 82 ++++++++++++++++++++++++++++++--------- drivers/ide/ide-pmac.c | 5 +-- drivers/ide/ide-tape.c | 55 +++++++++++++++++++++----- drivers/ide/ide-taskfile.c | 16 +++++++- drivers/ide/ide.c | 96 ++++++++++++++++++++++++++++------------------ drivers/ide/ioctl.c | 12 +++--- drivers/ide/main.c | 12 +++--- drivers/ide/pcidma.c | 20 ++++++++-- drivers/ide/pdc4030.c | 90 ++++++++++++++++++++++++++++++++++--------- drivers/ide/piix.c | 6 --- drivers/ide/serverworks.c | 7 ++-- drivers/ide/tcq.c | 13 +++++++ drivers/ide/trm290.c | 10 ++--- drivers/scsi/ide-scsi.c | 54 ++++++++++++++++++++++---- include/linux/ide.h | 7 +--- include/linux/pci_ids.h | 1 + 26 files changed, 510 insertions(+), 196 deletions(-) (limited to 'include/linux') diff --git a/arch/cris/drivers/ide.c b/arch/cris/drivers/ide.c index 170af129f738..330734bc6bd3 100644 --- a/arch/cris/drivers/ide.c +++ b/arch/cris/drivers/ide.c @@ -791,7 +791,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct if(!atapi) { /* set the irq handler which will finish the request when DMA is done */ - ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG); @@ -802,10 +802,10 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start); /* initiate a multi word dma read using DMA handshaking */ - + *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); - + *R_ATA_CTRL_DATA = IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) | IO_STATE(R_ATA_CTRL_DATA, rw, read) | @@ -831,7 +831,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct if(!atapi) { /* set the irq handler which will finish the request when DMA is done */ - ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG); diff --git a/drivers/ide/Config.help b/drivers/ide/Config.help index d204a0738390..2857a52905e6 100644 --- a/drivers/ide/Config.help +++ b/drivers/ide/Config.help @@ -408,16 +408,6 @@ CONFIG_BLK_DEV_PIIX the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. -CONFIG_BLK_DEV_PIIX_TRY133 - The ICH2, ICH2-M, ICH3, ICH3-M, ICH3-S, ICH-4 and CICH chips can - support UDMA133 in hardware, even though the specifications of - the chips say otherwise. By enabling this option, you allow the - driver to enable the UDMA133 mode on these chips. Note that if - it doesn't work, your data gets lost, you're on your own, don't - expect any help. - - Say N here, unless you really know what are you doing. - CONFIG_BLK_DEV_PDC202XX Promise Ultra33 or PDC20246 Promise Ultra66 or PDC20262 diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in index 28ffe462dc04..3fd5637ce79f 100644 --- a/drivers/ide/Config.in +++ b/drivers/ide/Config.in @@ -52,9 +52,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then dep_mbool ' HPT34X AUTODMA support (EXPERMENTAL)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_EXPERIMENTAL dep_bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Intel and Efar (SMsC) chipset support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI - if [ "$CONFIG_BLK_DEV_PIIX" = "y" ]; then - dep_bool ' Allow undocumented UDMA133 on ICH chips (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TRY133 $CONFIG_EXPERIMENTAL - fi if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 8267396a47f3..4f542ae679ac 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -1,6 +1,6 @@ /* * - * $Id: aec62xx.c,v 1.0 2002/05/24 14:37:19 vojtech Exp $ + * aec62xx.c, v1.2 2002/05/24 * * Copyright (c) 2002 Vojtech Pavlik * @@ -60,7 +60,9 @@ #define AEC_PLLCLK_ATA133 0x10 #define AEC_CABLEPINS_INPUT 0x10 -static unsigned char aec_cyc2udma[17] = { 0, 0, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1 }; +static unsigned char aec_cyc2udma[9] = { 5, 5, 5, 4, 3, 2, 2, 1, 1 }; +static unsigned char aec_cyc2act[16] = { 1, 1, 2, 3, 4, 5, 6, 0, 0, 7, 7, 7, 7, 7, 7, 7 }; +static unsigned char aec_cyc2rec[16] = { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 12, 13, 14 }; /* * aec_set_speed_old() writes timing values to @@ -71,8 +73,10 @@ static void aec_set_speed_old(struct pci_dev *dev, unsigned char dn, struct ata_ { unsigned char t; - pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1), FIT(timing->active, 0, 15)); - pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1) + 1, FIT(timing->recover, 0, 15)); + pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1), + aec_cyc2act[FIT(timing->active, 0, 15)]); + pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1) + 1, + aec_cyc2rec[FIT(timing->recover, 0, 15)]); pci_read_config_byte(dev, AEC_UDMA_OLD, &t); t &= ~(3 << (dn << 1)); @@ -91,12 +95,19 @@ static void aec_set_speed_new(struct pci_dev *dev, unsigned char dn, struct ata_ unsigned char t; pci_write_config_byte(dev, AEC_DRIVE_TIMING + dn, - (FIT(timing->active, 0, 15) << 4) | FIT(timing->recover, 0, 15)); + (aec_cyc2act[FIT(timing->active, 0, 15)] << 4) + | aec_cyc2rec[FIT(timing->recover, 0, 15)]); pci_read_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), &t); t &= ~(0xf << ((dn & 1) << 2)); - if (timing->udma) - t |= aec_cyc2udma[FIT(timing->udma, 2, 16)] << ((dn & 1) << 2); + if (timing->udma) { + if (timing->udma >= 2) + t |= aec_cyc2udma[FIT(timing->udma, 2, 8)] << ((dn & 1) << 2); + if (timing->mode == XFER_UDMA_5) + t |= 6; + if (timing->mode == XFER_UDMA_6) + t |= 7; + } pci_write_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), t); } @@ -120,9 +131,10 @@ static int aec_set_drive(struct ata_device *drive, unsigned char speed) drive->dn >> 1, drive->dn & 1); T = 1000000000 / system_bus_speed; - UT = T / (aec_old ? 1 : 4); + UT = T / (aec_old ? 1 : 2); ata_timing_compute(drive, speed, &t, T, UT); + ata_timing_merge_8bit(&t); if (aec_old) aec_set_speed_old(drive->channel->pci_dev, drive->dn, &t); diff --git a/drivers/ide/ata-timing.c b/drivers/ide/ata-timing.c index 548718d48be6..3047e30bfe2c 100644 --- a/drivers/ide/ata-timing.c +++ b/drivers/ide/ata-timing.c @@ -136,6 +136,20 @@ short ata_timing_mode(struct ata_device *drive, int map) (drive->id->tPIO == 0) ? XFER_PIO_0 : XFER_PIO_SLOW; } +/* + * Just get a pointer to the struct describing the timing values used commonly + * for a particular mode. + */ +struct ata_timing* ata_timing_data(short speed) +{ + struct ata_timing *t; + + for (t = ata_timing; t->mode != speed; t++) + if (t->mode < 0) + return NULL; + return t; +} + /* * This is just unit conversion. */ @@ -179,17 +193,15 @@ void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, } /* - * Just get a pointer to the struct describing the timing values used commonly - * for a particular mode. + * Not all controllers can do separate timing for 8-bit command transfers + * and 16-bit data transfers. */ -struct ata_timing* ata_timing_data(short speed) -{ - struct ata_timing *t; - for (t = ata_timing; t->mode != speed; t++) - if (t->mode < 0) - return NULL; - return t; +void ata_timing_merge_8bit(struct ata_timing *t) +{ + t->active = max(t->active, t->act8b); + t->recover = max(t->recover, t->rec8b); + t->cycle = max(t->cycle, t->cyc8b); } int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing *t, @@ -204,6 +216,8 @@ int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing if (!(s = ata_timing_data(speed))) return -EINVAL; + memcpy(t, s, sizeof(struct ata_timing)); + /* If the drive is an EIDE drive, it can tell us it needs extended * PIO/MWDMA cycle timing. */ @@ -229,7 +243,7 @@ int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing /* Convert the timing to bus clock counts. */ - ata_timing_quantize(s, t, T, UT); + ata_timing_quantize(t, t, T, UT); /* Even in DMA/UDMA modes we still use PIO access for IDENTIFY, * S.M.A.R.T and some other commands. We have to ensure that the DMA diff --git a/drivers/ide/ata-timing.h b/drivers/ide/ata-timing.h index f8c9f7ce9643..4e64b3f5832c 100644 --- a/drivers/ide/ata-timing.h +++ b/drivers/ide/ata-timing.h @@ -69,7 +69,7 @@ extern struct ata_timing ata_timing[]; #define XFER_EPIO 0x01 #define XFER_PIO 0x00 -/* External interface to host chips chanell timing setup. +/* External interface to host chips channel timing setup. * * It's a bit elaborate due to the legacy we have to bear. */ @@ -79,6 +79,7 @@ extern void ata_timing_quantize(struct ata_timing *t, struct ata_timing *q, int T, int UT); extern void ata_timing_merge(struct ata_timing *a, struct ata_timing *b, struct ata_timing *m, unsigned int what); +void ata_timing_merge_8bit(struct ata_timing *t); extern struct ata_timing* ata_timing_data(short speed); extern int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing *t, int T, int UT); diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c index 59ea54d109b0..8dd23001cd24 100644 --- a/drivers/ide/hpt34x.c +++ b/drivers/ide/hpt34x.c @@ -266,11 +266,10 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq) outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ drive->waiting_for_dma = 1; - if (drive->type != ATA_DISK) - return 0; - - ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + if (drive->type == ATA_DISK) { + ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ + OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + } return 0; } diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 809bcab7770b..b674cf76e7fb 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -281,7 +281,7 @@ static int ide_build_sglist(struct ata_device *drive, struct request *rq) struct scatterlist *sg = ch->sg_table; int nents; - if (rq->flags & REQ_SPECIAL) { + if ((rq->flags & REQ_SPECIAL) && (drive->type == ATA_DISK)) { struct ata_taskfile *args = rq->special; if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) @@ -521,7 +521,7 @@ icside_dma_common(struct ata_device *drive, struct request *rq, static int icside_dma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; - unsigned int cmd; + u8 int cmd; if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) return 1; @@ -529,7 +529,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq) if (drive->type != ATA_DISK) return 0; - ide_set_handler(drive, icside_dmaintr, WAIT_CMD, NULL); + ata_set_handler(drive, icside_dmaintr, WAIT_CMD, NULL); if ((rq->flags & REQ_SPECIAL) && drive->addressing == 1) { struct ata_taskfile *args = rq->special; @@ -542,6 +542,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq) OUT_BYTE(cmd, IDE_COMMAND_REG); enable_dma(ch->hw.dma); + return 0; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 0ea324c2d5dd..c31adf88d86d 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -728,6 +728,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, int xferlen, ata_handler_t handler) { + unsigned long flags; + struct ata_channel *ch = drive->channel; ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; @@ -735,6 +737,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, if (ide_wait_stat(&startstop, drive, rq, 0, BUSY_STAT, WAIT_READY)) return startstop; + spin_lock_irqsave(ch->lock, flags); + if (info->dma) { if (info->cmd == READ || info->cmd == WRITE) info->dma = !udma_init(drive, rq); @@ -754,11 +758,18 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, udma_start(drive, rq); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry); + ata_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + spin_unlock_irqrestore(ch->lock, flags); + + /* FIXME: Woah we have to ungrab the lock before the IRQ + * handler gets called. + */ return handler(drive, rq); } } @@ -773,6 +784,8 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive, unsigned char *cmd, unsigned long timeout, ata_handler_t handler) { + unsigned long flags; + struct ata_channel *ch = drive->channel; ide_startstop_t startstop; if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { @@ -789,11 +802,11 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive, return startstop; } - /* Arm the interrupt handler. */ - ide_set_handler(drive, handler, timeout, cdrom_timer_expiry); - - /* Send the command to the device. */ + /* Arm the interrupt handler and send the command to the device. */ + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, handler, timeout, cdrom_timer_expiry); atapi_write(drive, cmd, CDROM_PACKET_SIZE); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -893,6 +906,8 @@ int cdrom_read_check_ireason(struct ata_device *drive, struct request *rq, int l */ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; int stat; int ireason, len, sectors_to_transfer, nskip; struct cdrom_info *info = drive->driver_data; @@ -1007,7 +1022,9 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request } /* Done moving data! Wait for another interrupt. */ - ide_set_handler(drive, cdrom_read_intr, WAIT_CMD, NULL); + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, cdrom_read_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -1234,6 +1251,8 @@ static ide_startstop_t cdrom_start_read(struct ata_device *drive, struct request /* Interrupt routine for packet command completion. */ static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; int ireason, len, stat, thislen; /* FIXME --mdcki */ @@ -1326,7 +1345,9 @@ static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *r } /* Now we wait for another interrupt. */ - ide_set_handler(drive, cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -1469,6 +1490,8 @@ static inline int cdrom_write_check_ireason(struct ata_device *drive, struct req static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; int stat, ireason, len, sectors_to_transfer, uptodate; struct cdrom_info *info = drive->driver_data; int dma_error = 0, dma = info->dma; @@ -1559,7 +1582,9 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request } /* re-arm handler */ - ide_set_handler(drive, cdrom_write_intr, 5 * WAIT_CMD, NULL); + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, cdrom_write_intr, 5 * WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 2b0624126f0c..f32c60fdcc30 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -95,8 +95,9 @@ static int lba_capacity_is_ok(struct hd_driveid *id) */ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq) { - char *buf = NULL; unsigned long flags; + struct ata_channel *ch = drive->channel; + char *buf = NULL; if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { if (drive->status & (ERR_STAT|DRQ_STAT)) @@ -106,7 +107,14 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq #if 0 printk("task_in_intr to Soon wait for next interrupt\n"); #endif - ide_set_handler(drive, task_in_intr, WAIT_CMD, NULL); + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -132,8 +140,14 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq return ide_stopped; } + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); /* still data left to transfer */ - ide_set_handler(drive, task_in_intr, WAIT_CMD, NULL); + ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -143,8 +157,9 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq */ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq) { - char *buf = NULL; unsigned long flags; + struct ata_channel *ch = drive->channel; + char *buf = NULL; if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) return ata_error(drive, rq, __FUNCTION__); @@ -165,7 +180,13 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r rq->current_nr_sectors--; } - ide_set_handler(drive, task_out_intr, WAIT_CMD, NULL); + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, task_out_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -175,16 +196,25 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r */ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq) { - char *buf = NULL; - unsigned int msect, nsect; unsigned long flags; + struct ata_channel *ch = drive->channel; + char *buf = NULL; + unsigned int msect; + unsigned int nsect; if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { if (drive->status & (ERR_STAT|DRQ_STAT)) return ata_error(drive, rq, __FUNCTION__); + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } @@ -213,17 +243,24 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request } } while (msect); + /* FIXME: this locking should encompass the above register + * file access too. + */ + spin_lock_irqsave(ch->lock, flags); /* * more data left */ - ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; int ok; int mcount = drive->mult_count; ide_startstop_t startstop; @@ -255,8 +292,15 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request if (!ok) { /* no data yet, so wait for another interrupt */ - if (!drive->channel->handler) - ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); + if (!ch->handler) { + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); + } return ide_started; } @@ -298,8 +342,15 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request } while (mcount); rq->errors = 0; - if (!drive->channel->handler) - ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); + if (!ch->handler) { + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); + } return ide_started; } diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 85c7c77c6725..62f31c007af9 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -821,6 +821,8 @@ static void idefloppy_retry_pc(struct ata_device *drive) */ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_status_reg_t status; idefloppy_bcount_reg_t bcount; @@ -833,7 +835,7 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques #endif #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { + if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { if (udma_stop(drive)) { set_bit (PC_DMA_ERROR, &pc->flags); } else { @@ -883,15 +885,24 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques return ide_stopped; } #endif + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ ireason.all=IN_BYTE (IDE_IREASON_REG); if (ireason.b.cod) { + spin_unlock_irqrestore(ch->lock, flags); + printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); return ide_stopped; } if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ + spin_unlock_irqrestore(ch->lock, flags); + printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read"); printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write"); return ide_stopped; @@ -901,8 +912,11 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques if ( temp > pc->request_transfer) { if (temp > pc->buffer_size) { printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); + atapi_discard_data (drive,bcount.all); - ide_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); + ata_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } #if IDEFLOPPY_DEBUG_LOG @@ -924,7 +938,8 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ + ata_set_handler(drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -936,6 +951,8 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques */ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; ide_startstop_t startstop; idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_ireason_reg_t ireason; @@ -944,14 +961,23 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); return startstop; } + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); ireason.all=IN_BYTE (IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { + spin_unlock_irqrestore(ch->lock, flags); + printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); return ide_stopped; } - ide_set_handler (drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ + ata_set_handler (drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */ + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -979,6 +1005,8 @@ static int idefloppy_transfer_pc2(struct ata_device *drive, struct request *__rq static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; idefloppy_floppy_t *floppy = drive->driver_data; ide_startstop_t startstop; idefloppy_ireason_reg_t ireason; @@ -987,22 +1015,32 @@ static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct r printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); return startstop; } + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); ireason.all=IN_BYTE (IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { + spin_unlock_irqrestore(ch->lock, flags); + printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); return ide_stopped; } + /* - * The following delay solves a problem with ATAPI Zip 100 drives where the - * Busy flag was apparently being deasserted before the unit was ready to - * receive data. This was happening on a 1200 MHz Athlon system. 10/26/01 - * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will - * not be actually used until after the packet is moved in about 50 msec. + * The following delay solves a problem with ATAPI Zip 100 drives where + * the Busy flag was apparently being deasserted before the unit was + * ready to receive data. This was happening on a 1200 MHz Athlon + * system. 10/26/01 25msec is too short, 40 and 50msec work well. + * idefloppy_pc_intr will not be actually used until after the packet + * is moved in about 50 msec. */ - ide_set_handler(drive, - idefloppy_pc_intr, /* service routine for packet command */ - floppy->ticks, /* wait this long before "failing" */ - idefloppy_transfer_pc2); /* fail == transfer_pc2 */ + ata_set_handler(drive, + idefloppy_pc_intr, /* service routine for packet command */ + floppy->ticks, /* wait this long before "failing" */ + idefloppy_transfer_pc2); /* fail == transfer_pc2 */ + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -1047,7 +1085,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque } #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Retry number - %d\n",pc->retries); -#endif /* IDEFLOPPY_DEBUG_LOG */ +#endif pc->retries++; pc->actually_transferred=0; /* We haven't transferred any data yet */ @@ -1082,9 +1120,19 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */ } - if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ide_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); + if (test_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { + unsigned long flags; + struct ata_channel *ch = drive->channel; + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); @@ -1750,8 +1798,6 @@ static void idefloppy_release(struct inode *inode, struct file *filp, struct ata if (!drive->usage) { idefloppy_floppy_t *floppy = drive->driver_data; - invalidate_bdev (inode->i_bdev, 0); - /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 0); diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c index afd616f0fd83..d583b2ea65b5 100644 --- a/drivers/ide/ide-pmac.c +++ b/drivers/ide/ide-pmac.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ide-pmac.c Version ?.?? Mar. 18, 2000 - * * Support for IDE interfaces on PowerMacs. * These IDE interfaces are memory-mapped and have a DBDMA channel * for doing DMA. @@ -1436,7 +1434,8 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq) drive->waiting_for_dma = 1; if (drive->type != ATA_DISK) return 0; - ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); + + ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); if ((rq->flags & REQ_SPECIAL) && (drive->addressing == 1)) { struct ata_taskfile *args = rq->special; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 91a979252d48..09f6ccaaf686 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -892,7 +892,7 @@ typedef struct { struct bio *bio; char *b_data; int b_count; - + /* * Pipeline parameters. * @@ -1864,6 +1864,7 @@ static int idetape_end_request(struct ata_device *drive, struct request *rq, int idetape_increase_max_pipeline_stages (drive); } } + blkdev_dequeue_request(rq); drive->rq = NULL; end_that_request_last(rq); @@ -1977,6 +1978,8 @@ static void idetape_postpone_request(struct ata_device *drive, struct request *r */ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; idetape_tape_t *tape = drive->driver_data; idetape_status_reg_t status; idetape_bcount_reg_t bcount; @@ -2080,15 +2083,24 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request return ide_stopped; } #endif + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); bcount.b.high = IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.low = IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ ireason.all = IN_BYTE (IDE_IREASON_REG); if (ireason.b.cod) { + spin_unlock_irqrestore(ch->lock, flags); + printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); return ide_stopped; } if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ + spin_unlock_irqrestore(ch->lock, flags); + printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read"); printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); return ide_stopped; @@ -2099,7 +2111,9 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request if (temp > pc->buffer_size) { printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); atapi_discard_data (drive, bcount.all); - ide_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); + ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } #if IDETAPE_DEBUG_LOG @@ -2125,7 +2139,9 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); #endif - ide_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ + ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } @@ -2173,6 +2189,8 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request */ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; idetape_tape_t *tape = drive->driver_data; struct atapi_packet_command *pc = tape->pc; idetape_ireason_reg_t ireason; @@ -2183,6 +2201,12 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); return startstop; } + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); ireason.all = IN_BYTE (IDE_IREASON_REG); while (retries-- && (!ireason.b.cod || ireason.b.io)) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n"); @@ -2196,11 +2220,14 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ } if (!ireason.b.cod || ireason.b.io) { printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); + spin_unlock_irqrestore(ch->lock, flags); + return ide_stopped; } tape->cmd_start_time = jiffies; - ide_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ + ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_write(drive,pc->c,12); /* Send the actual packet */ + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -2274,8 +2301,18 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, } #endif if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); + unsigned long flags; + struct ata_channel *ch = drive->channel; + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } else { OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); @@ -3326,7 +3363,7 @@ static int __idetape_discard_read_pipeline(struct ata_device *drive) tape->merge_stage = NULL; } tape->chrdev_direction = idetape_direction_none; - + if (tape->first_stage == NULL) return 0; @@ -3723,10 +3760,10 @@ static int idetape_add_chrdev_write_request(struct ata_device *drive, int blocks #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n"); -#endif /* IDETAPE_DEBUG_LOG */ +#endif - /* - * Attempt to allocate a new stage. + /* + * Attempt to allocate a new stage. * Pay special attention to possible race conditions. */ while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) { diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index dbc1ec952471..1066b3f329b3 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -199,13 +199,21 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, IDE_SELECT_REG); if (ar->handler) { + unsigned long flags; + struct ata_channel *ch = drive->channel; /* This is apparently supposed to reset the wait timeout for * the interrupt to accur. */ - ide_set_handler(drive, ar->handler, WAIT_CMD, NULL); + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, ar->handler, WAIT_CMD, NULL); OUT_BYTE(ar->cmd, IDE_COMMAND_REG); + spin_unlock_irqrestore(ch->lock, flags); /* FIXME: Warning check for race between handler and prehandler * for writing first block of data. however since we are well @@ -373,8 +381,12 @@ ide_startstop_t ata_special_intr(struct ata_device *drive, struct struct ata_taskfile *ar = rq->special; ide_startstop_t ret = ide_stopped; + unsigned long flags; ide__sti(); /* local CPU only */ + + spin_lock_irqsave(drive->channel->lock, flags); + if (rq->buffer && ar->taskfile.sector_number) { if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) { int retries = 10; @@ -409,6 +421,8 @@ ide_startstop_t ata_special_intr(struct ata_device *drive, struct drive->rq = NULL; end_that_request_last(rq); + spin_unlock_irqrestore(drive->channel->lock, flags); + return ret; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 01361405a92f..f9e2c0ddcce5 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -160,25 +160,25 @@ int ide_end_request(struct ata_device *drive, struct request *rq, int uptodate) * at the appropriate code to handle the next interrupt, and a * timer is started to prevent us from waiting forever in case * something goes wrong (see the ide_timer_expiry() handler later on). + * + * Channel lock should be held. */ -void ide_set_handler(struct ata_device *drive, ata_handler_t handler, +void ata_set_handler(struct ata_device *drive, ata_handler_t handler, unsigned long timeout, ata_expiry_t expiry) { - unsigned long flags; struct ata_channel *ch = drive->channel; - spin_lock_irqsave(ch->lock, flags); + if (ch->handler) + printk("%s: %s: handler not null; old=%p, new=%p, from %p\n", + drive->name, __FUNCTION__, ch->handler, handler, __builtin_return_address(0)); - if (ch->handler != NULL) { - printk("%s: ide_set_handler: handler not null; old=%p, new=%p, from %p\n", - drive->name, ch->handler, handler, __builtin_return_address(0)); - } ch->handler = handler; + ch->expiry = expiry; ch->timer.expires = jiffies + timeout; + add_timer(&ch->timer); - spin_unlock_irqrestore(ch->lock, flags); } static void check_crc_errors(struct ata_device *drive) @@ -256,26 +256,30 @@ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */ */ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq) { + unsigned long flags; struct ata_channel *ch = drive->channel; + int ret = ide_stopped; ata_select(drive, 10); - if (ata_status(drive, 0, BUSY_STAT)) - printk("%s: ATAPI reset complete\n", drive->name); - else { + if (!ata_status(drive, 0, BUSY_STAT)) { if (time_before(jiffies, ch->poll_timeout)) { - ide_set_handler (drive, atapi_reset_pollfunc, HZ/20, NULL); + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); + spin_unlock_irqrestore(ch->lock, flags); + ret = ide_started; /* continue polling */ + } else { + ch->poll_timeout = 0; /* end of polling */ + printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status); - return ide_started; /* continue polling */ + ret = do_reset1(drive, 1); /* do it the old fashioned way */ } - ch->poll_timeout = 0; /* end of polling */ - printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status); - - return do_reset1(drive, 1); /* do it the old fashioned way */ + } else { + printk("%s: ATAPI reset complete\n", drive->name); + ch->poll_timeout = 0; /* done polling */ } - ch->poll_timeout = 0; /* done polling */ - return ide_stopped; + return ret; } /* @@ -289,12 +293,16 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * if (!ata_status(drive, 0, BUSY_STAT)) { if (time_before(jiffies, ch->poll_timeout)) { - ide_set_handler(drive, reset_pollfunc, HZ/20, NULL); + unsigned long flags; + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, reset_pollfunc, HZ/20, NULL); + spin_unlock_irqrestore(ch->lock, flags); return ide_started; /* continue polling */ } printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status); - drive->failures++; + ++drive->failures; } else { u8 stat; @@ -303,11 +311,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * printk("success\n"); drive->failures = 0; } else { - char *msg; + const char *msg = ""; #if FANCY_STATUS_DUMPS u8 val; - static char *messages[5] = { + static const char *messages[5] = { " passed", " formatter device", " sector buffer", @@ -319,13 +327,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * val = stat & 0x7f; if (val >= 1 && val <= 5) msg = messages[val -1]; - else - msg = ""; if (stat & 0x80) printk("; slave:"); #endif - printk("%s error [%02x]\n", msg, stat); - drive->failures++; + printk(KERN_ERR "%s error [%02x]\n", msg, stat); + ++drive->failures; } } ch->poll_timeout = 0; /* done polling */ @@ -347,6 +353,8 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * * Equally poor, though, is the fact that this may a very long time to * complete, (up to 30 seconds worst case). So, instead of busy-waiting here * for it, we set a timer to poll at 50ms intervals. + * + * Channel lock should be held. */ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) @@ -364,7 +372,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ata_select(drive, 20); OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); + ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); __restore_flags(flags); /* local CPU only */ return ide_started; @@ -377,7 +385,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) for (unit = 0; unit < MAX_DRIVES; ++unit) check_crc_errors(&ch->drives[unit]); - __restore_flags (flags); /* local CPU only */ + __restore_flags(flags); /* local CPU only */ return ide_started; } @@ -546,6 +554,8 @@ static int do_recalibrate(struct ata_device *drive) /* * Take action based on the error returned by the drive. + * + * FIXME: Channel lock should be held. */ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const char *msg) { @@ -613,6 +623,8 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch * That could be done by busy-waiting for the first jiffy or two, and then * setting a timer to wake up at half second intervals thereafter, until * timeout is achieved, before timing out. + * + * FIXME: Channel lock should be held. */ int ide_wait_stat(ide_startstop_t *startstop, struct ata_device *drive, struct request *rq, @@ -709,7 +721,8 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r /* This issues a special drive command. */ if (rq->flags & REQ_SPECIAL) - return ata_taskfile(drive, rq->special, NULL); + if (drive->type == ATA_DISK) + return ata_taskfile(drive, rq->special, NULL); /* The normal way of execution is to pass and execute the request * handler down to the device type driver. @@ -744,6 +757,7 @@ ide_startstop_t restart_request(struct ata_device *drive) { struct ata_channel *ch = drive->channel; unsigned long flags; + int ret; spin_lock_irqsave(ch->lock, flags); @@ -752,7 +766,12 @@ ide_startstop_t restart_request(struct ata_device *drive) spin_unlock_irqrestore(ch->lock, flags); - return start_request(drive, drive->rq); + /* FIXME make start_request do the unlock itself and + * push this locking further down. */ + + ret = start_request(drive, drive->rq); + + return ret; } /* @@ -844,14 +863,16 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel) sleep = jiffies + WAIT_MIN_SLEEP; #if 1 if (timer_pending(&channel->timer)) - printk(KERN_ERR "ide_set_handler: timer already active\n"); + printk(KERN_ERR "%s: timer already active\n", __FUNCTION__); #endif set_bit(IDE_SLEEP, channel->active); mod_timer(&channel->timer, sleep); /* we purposely leave hwgroup busy while sleeping */ } else { + /* FIXME: use queue plugging instead of active to + * block upper layers from stomping on us */ /* Ugly, but how can we sleep for the lock otherwise? */ - ide_release_lock(&irq_lock);/* for atari only */ + ide_release_lock(&ide_irq_lock);/* for atari only */ clear_bit(IDE_BUSY, channel->active); } @@ -918,11 +939,10 @@ static void queue_commands(struct ata_device *drive) drive->rq = rq; + /* FIXME: push this locaing further down */ spin_unlock(drive->channel->lock); - ide__sti(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); - spin_lock_irq(drive->channel->lock); /* command started, we are busy */ @@ -948,7 +968,7 @@ static void queue_commands(struct ata_device *drive) */ static void do_request(struct ata_channel *channel) { - ide_get_lock(&irq_lock, ata_irq_request, hwgroup);/* for atari only: POSSIBLY BROKEN HERE(?) */ + ide_get_lock(&ide_irq_lock, ata_irq_request, channel);/* for atari only: POSSIBLY BROKEN HERE(?) */ // __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */ while (!test_and_set_bit(IDE_BUSY, channel->active)) { @@ -1142,7 +1162,7 @@ void ide_timer_expiry(unsigned long data) * * In reality, this is a non-issue. The new command is not sent unless the * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ide_set_handler() is always invoked before + * trying to interrupt us. And ata_set_handler() is always invoked before * completing the issuance of any new drive command, so we will not be * accidentally invoked as a result of any valid command completion interrupt. * @@ -1416,7 +1436,7 @@ EXPORT_SYMBOL(drive_is_flashcard); EXPORT_SYMBOL(ide_timer_expiry); EXPORT_SYMBOL(do_ide_request); -EXPORT_SYMBOL(ide_set_handler); +EXPORT_SYMBOL(ata_set_handler); EXPORT_SYMBOL(ata_dump); EXPORT_SYMBOL(ata_error); diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c index 182ba5e0a17d..4f8269dbbd1c 100644 --- a/drivers/ide/ioctl.c +++ b/drivers/ide/ioctl.c @@ -47,15 +47,15 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) u8 *argbuf = vals; int argsize = 4; struct ata_taskfile args; - struct request rq; + struct request req; /* Second phase. */ if (copy_from_user(vals, (void *)arg, 4)) return -EFAULT; - memset(&rq, 0, sizeof(rq)); - rq.flags = REQ_SPECIAL; + memset(&req, 0, sizeof(req)); + req.flags = REQ_SPECIAL; memset(&args, 0, sizeof(args)); @@ -85,9 +85,9 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) */ args.handler = ata_special_intr; - rq.buffer = argbuf + 4; - rq.special = &args; - err = ide_do_drive_cmd(drive, &rq, ide_wait); + req.buffer = argbuf + 4; + req.special = &args; + err = ide_do_drive_cmd(drive, &req, ide_wait); argbuf[0] = drive->status; argbuf[1] = args.taskfile.feature; diff --git a/drivers/ide/main.c b/drivers/ide/main.c index da66d65cbdbb..f9d19df1de40 100644 --- a/drivers/ide/main.c +++ b/drivers/ide/main.c @@ -114,12 +114,12 @@ spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ #endif -#if defined(__mc68000__) || defined(CONFIG_APUS) +#ifdef ATA_ARCH_LOCK /* * This is used by the Atari code to obtain access to the IDE interrupt, * which is shared between several drivers. */ -static int irq_lock; +int ide_irq_lock; #endif int noautodma = 0; @@ -679,8 +679,8 @@ static int __init stridx (const char *s, char c) */ static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals) { - static const char *decimal = "0123456789"; - static const char *hex = "0123456789abcdef"; + static const char decimal[] = "0123456789"; + static const char hex[] = "0123456789abcdef"; int i, n; if (*s++ == '=') { @@ -1449,7 +1449,7 @@ static int __init ata_module_init(void) #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) # if defined(__mc68000__) || defined(CONFIG_APUS) if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - // ide_get_lock(&irq_lock, NULL, NULL);/* for atari only */ + ide_get_lock(&ide_irq_lock, NULL, NULL);/* for atari only */ disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ // disable_irq_nosync(ide_hwifs[0].irq); } @@ -1460,7 +1460,7 @@ static int __init ata_module_init(void) # if defined(__mc68000__) || defined(CONFIG_APUS) if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { enable_irq(ide_hwifs[0].irq); - ide_release_lock(&irq_lock);/* for atari only */ + ide_release_lock(&ide_irq_lock);/* for atari only */ } # endif #endif diff --git a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c index 794fb5752567..18c7dd74da7a 100644 --- a/drivers/ide/pcidma.c +++ b/drivers/ide/pcidma.c @@ -64,7 +64,7 @@ static int build_sglist(struct ata_device *drive, struct request *rq) struct scatterlist *sg = ch->sg_table; int nents = 0; - if (rq->flags & REQ_SPECIAL) { + if ((rq->flags & REQ_SPECIAL) && (drive->type == ATA_DISK)) { struct ata_taskfile *args = rq->special; #if 1 unsigned char *virt_addr = rq->buffer; @@ -388,7 +388,11 @@ int udma_new_table(struct ata_device *drive, struct request *rq) return count; } -/* Teardown mappings after DMA has completed. */ +/* + * Teardown mappings after DMA has completed. + * + * Channel lock should be held. + */ void udma_destroy_table(struct ata_channel *ch) { pci_unmap_sg(ch->pci_dev, ch->sg_table, ch->sg_nents, ch->sg_dma_direction); @@ -398,8 +402,9 @@ void udma_destroy_table(struct ata_channel *ch) * Prepare the channel for a DMA startfer. Please note that only the broken * Pacific Digital host chip needs the reques to be passed there to decide * about addressing modes. + * + * Channel lock should be held. */ - int udma_pci_start(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; @@ -414,6 +419,9 @@ int udma_pci_start(struct ata_device *drive, struct request *rq) return 0; } +/* + * Channel lock should be held. + */ int udma_pci_stop(struct ata_device *drive) { struct ata_channel *ch = drive->channel; @@ -431,6 +439,8 @@ int udma_pci_stop(struct ata_device *drive) /* * FIXME: This should be attached to a channel as we can see now! + * + * Channel lock should be held. */ int udma_pci_irq_status(struct ata_device *drive) { @@ -517,6 +527,8 @@ dma_alloc_failure: * * It's exported only for host chips which use it for fallback or (too) late * capability checking. + * + * Channel lock should be held. */ int udma_pci_init(struct ata_device *drive, struct request *rq) { @@ -534,7 +546,7 @@ int udma_pci_init(struct ata_device *drive, struct request *rq) else cmd = 0x00; - ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); + ata_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); if (drive->addressing) outb(cmd ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); else diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c index 30d920893a69..97c478808602 100644 --- a/drivers/ide/pdc4030.c +++ b/drivers/ide/pdc4030.c @@ -428,7 +428,16 @@ read_next: if (drive->status & DRQ_STAT) goto read_again; if (drive->status & BUSY_STAT) { - ide_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); + unsigned long flags; + struct ata_channel *ch = drive->channel; + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); @@ -456,7 +465,17 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc if (!ata_status(drive, 0, BUSY_STAT)) { if (time_before(jiffies, ch->poll_timeout)) { - ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); + unsigned long flags; + struct ata_channel *ch = drive->channel; + + /* FIXME: this locking should encompass the above + * register file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; /* continue polling... */ } ch->poll_timeout = 0; @@ -531,16 +550,22 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int */ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq) { + unsigned long flags; struct ata_channel *ch = drive->channel; + spin_lock_irqsave(ch->lock, flags); if (inb(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, ch->poll_timeout)) { - ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); + ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; /* continue polling... */ } ch->poll_timeout = 0; printk(KERN_ERR "%s: write timed out!\n", drive->name); ata_status(drive, 0, 0); + spin_unlock_irqrestore(ch->lock, flags); + return ata_error(drive, rq, "write timeout"); } @@ -549,11 +574,12 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r */ promise_multwrite(drive, rq, 4); ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); + ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, drive->status); #endif + spin_unlock_irqrestore(ch->lock, flags); return ide_started; } @@ -566,6 +592,7 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r */ static ide_startstop_t promise_do_write(struct ata_device *drive, struct request *rq) { + unsigned long flags; struct ata_channel *ch = drive->channel; #ifdef DEBUG_WRITE @@ -573,26 +600,38 @@ static ide_startstop_t promise_do_write(struct ata_device *drive, struct request "buffer=%p\n", drive->name, rq->sector, rq->sector + rq->nr_sectors - 1, rq->buffer); #endif + /* FIXME: this locking should encompass the above register + * file access too. + */ + spin_lock_irqsave(ch->lock, flags); /* * If there are more than 4 sectors to transfer, do n-4 then go into * the polling strategy as defined above. */ if (rq->nr_sectors > 4) { - if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) + if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) { + spin_unlock_irqrestore(ch->lock, flags); return ide_stopped; + } ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); + ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } else { /* * There are 4 or fewer sectors to transfer, do them all in one go * and wait for NOT BUSY. */ - if (promise_multwrite(drive, rq, rq->nr_sectors)) + if (promise_multwrite(drive, rq, rq->nr_sectors)) { + spin_unlock_irqrestore(ch->lock, flags); return ide_stopped; + } ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); + ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); + spin_unlock_irqrestore(ch->lock, flags); + #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, drive->status); @@ -629,16 +668,19 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg switch (rq_data_dir(rq)) { case READ: -/* - * The card's behaviour is odd at this point. If the data is - * available, DRQ will be true, and no interrupt will be - * generated by the card. If this is the case, we need to call the - * "interrupt" handler (promise_read_intr) directly. Otherwise, if - * an interrupt is going to occur, bit0 of the SELECT register will - * be high, so we can set the handler the just return and be interrupted. - * If neither of these is the case, we wait for up to 50ms (badly I'm - * afraid!) until one of them is. - */ + + /* + * The card's behaviour is odd at this point. If the data is + * available, DRQ will be true, and no interrupt will be + * generated by the card. If this is the case, we need to call + * the "interrupt" handler (promise_read_intr) directly. + * Otherwise, if an interrupt is going to occur, bit0 of the + * SELECT register will be high, so we can set the handler the + * just return and be interrupted. If neither of these is the + * case, we wait for up to 50ms (badly I'm afraid!) until one + * of them is. + */ + timeout = jiffies + HZ/20; /* 50ms wait */ do { if (!ata_status(drive, 0, DRQ_STAT)) { @@ -646,11 +688,21 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg return promise_read_intr(drive, rq); } if (inb(IDE_SELECT_REG) & 0x01) { + unsigned long flags; + struct ata_channel *ch = drive->channel; + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: read: waiting for " "interrupt\n", drive->name); #endif - ide_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); + ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } udelay(1); diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 033f66eca09d..59d6a4896e11 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -72,11 +72,6 @@ #define PIIX_CHECK_REV 0x40 /* May be a buggy revision of PIIX */ #define PIIX_NODMA 0x80 /* Don't do DMA with this chip */ -#ifdef CONFIG_BLK_DEV_PIIX_TRY133 /* I think even the older ICHs should be able to do UDMA133 */ -#undef PIIX_UDMA_100 -#define PIIX_UDMA_100 PIIX_UDMA_133 -#endif - /* * Intel IDE chips */ @@ -104,7 +99,6 @@ static struct piix_ide_chip { static struct piix_ide_chip *piix_config; static unsigned char piix_enabled; -static unsigned int piix_80w; static char *piix_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index f69f12630a22..7660da32a45f 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -432,8 +432,8 @@ static unsigned int __init svwks_init_chipset(struct pci_dev *dev) return 0; } -/* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem - * device ID indicate presence of an 80-pin cable. +/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits + * of the subsystem device ID indicate presence of an 80-pin cable. * Bit 15 clear = secondary IDE channel does not have 80-pin cable. * Bit 15 set = secondary IDE channel has 80-pin cable. * Bit 14 clear = primary IDE channel does not have 80-pin cable. @@ -444,7 +444,8 @@ static unsigned int __init ata66_svwks_dell(struct ata_channel *hwif) struct pci_dev *dev = hwif->pci_dev; if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) return ((1 << (hwif->unit + 14)) & dev->subsystem_device) ? 1 : 0; return 0; diff --git a/drivers/ide/tcq.c b/drivers/ide/tcq.c index 54d5353df860..a7d5254d7464 100644 --- a/drivers/ide/tcq.c +++ b/drivers/ide/tcq.c @@ -58,11 +58,18 @@ static ide_startstop_t service(struct ata_device *drive, struct request *rq); static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq) { struct ata_taskfile *args = rq->special; + unsigned long flags; ide__sti(); + + spin_lock_irqsave(drive->channel->lock, flags); + blkdev_dequeue_request(rq); drive->rq = NULL; end_that_request_last(rq); + + spin_unlock_irqrestore(drive->channel->lock, flags); + kfree(args); return ide_stopped; @@ -218,6 +225,8 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request * * and it must have reported a need for service (status has SERVICE_STAT set) * * Also, nIEN must be set as not to need protection against ide_dmaq_intr + * + * Channel lock should be held. */ static ide_startstop_t service(struct ata_device *drive, struct request *rq) { @@ -503,6 +512,8 @@ static int tcq_wait_dataphase(struct ata_device *drive) /* * Invoked from a SERVICE interrupt, command etc already known. Just need to * start the dma engine for this tag. + * + * Channel lock should be held. */ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq) { @@ -527,6 +538,8 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request * /* * Start a queued command from scratch. + * + * Channel lock should be held. */ ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq) { diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index d2275474c256..d8cdc878f961 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -223,15 +223,15 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq) } trm290_prepare_drive(drive, 1); /* select DMA xfer */ + outl(ch->dmatable_dma|reading|writing, ch->dma_base); drive->waiting_for_dma = 1; outw((count * 2) - 1, ch->dma_base+2); /* start DMA */ - if (drive->type != ATA_DISK) - return 0; - - ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + if (drive->type == ATA_DISK) { + ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); + outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + } return 0; } diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 8ffce483e12f..7b2f379e6e87 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -243,7 +243,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int u8 *scsi_buf; unsigned long flags; - if (!(rq->flags & REQ_SPECIAL)) { + if (!(rq->flags & REQ_PC)) { ide_end_request(drive, rq, uptodate); return 0; } @@ -293,6 +293,8 @@ static inline unsigned long get_timeout(struct atapi_packet_command *pc) */ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; struct Scsi_Host *host = drive->driver_data; idescsi_scsi_t *scsi = idescsi_private(host); u8 ireason; @@ -333,6 +335,8 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request temp = pc->actually_transferred + bcount; if ( temp > pc->request_transfer) { if (temp > pc->buffer_size) { + unsigned long flags; + struct ata_channel *ch = drive->channel; printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n"); temp = pc->buffer_size - pc->actually_transferred; if (temp) { @@ -346,7 +350,14 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request pc->actually_transferred += temp; pc->current_position += temp; atapi_discard_data(drive,bcount - temp); - ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } #ifdef DEBUG @@ -370,12 +381,21 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request pc->actually_transferred+=bcount; /* Update the current position */ pc->current_position+=bcount; - ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ + spin_unlock_irqrestore(ch->lock, flags); + return ide_started; } static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq) { + unsigned long flags; + struct ata_channel *ch = drive->channel; struct Scsi_Host *host = drive->driver_data; idescsi_scsi_t *scsi = idescsi_private(host); struct atapi_packet_command *pc = scsi->pc; @@ -391,7 +411,15 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); return ide_stopped; } - ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ + spin_unlock_irqrestore(ch->lock, flags); + atapi_write(drive, scsi->pc->c, 12); /* Send the actual packet */ return ide_started; } @@ -425,8 +453,18 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request set_bit(PC_DMA_IN_PROGRESS, &pc->flags); udma_start(drive, rq); } - if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - ide_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL); + if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { + unsigned long flags; + struct ata_channel *ch = drive->channel; + + /* FIXME: this locking should encompass the above register + * file access too. + */ + + spin_lock_irqsave(ch->lock, flags); + ata_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL); + spin_unlock_irqrestore(ch->lock, flags); + OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ return ide_started; } else { @@ -452,7 +490,7 @@ static ide_startstop_t idescsi_do_request(struct ata_device *drive, struct reque rq->current_nr_sectors); #endif - if (rq->flags & REQ_SPECIAL) { + if (rq->flags & REQ_PC) { return idescsi_issue_pc(drive, rq, (struct atapi_packet_command *) rq->special); } blk_dump_rq_flags(rq, "ide-scsi: unsup command"); @@ -667,7 +705,7 @@ static int idescsi_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) } memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_SPECIAL; + rq->flags = REQ_PC; rq->special = (char *) pc; rq->bio = idescsi_dma_bio (drive, pc); spin_unlock_irq(cmd->host->host_lock); diff --git a/include/linux/ide.h b/include/linux/ide.h index 52a0d9b28915..9ef57489ae9c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -213,6 +213,7 @@ void ide_setup_ports(hw_regs_t *hw, /* Currently only m68k, apus and m8xx need it */ #ifdef ATA_ARCH_ACK_INTR +extern int ide_irq_lock; # define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) #else # define ide_ack_intr(hwif) (1) @@ -603,11 +604,7 @@ extern int noautodma; extern int __ide_end_request(struct ata_device *, struct request *, int, unsigned int); extern int ide_end_request(struct ata_device *drive, struct request *, int); -/* - * This is used on exit from the driver, to designate the next irq handler - * and also to start the safety timer. - */ -extern void ide_set_handler(struct ata_device *drive, ata_handler_t handler, +extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler, unsigned long timeout, ata_expiry_t expiry); extern u8 ata_dump(struct ata_device *, struct request *, const char *); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 6a45e0eb97e5..ac3fc9409b2a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1111,6 +1111,7 @@ #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220 #define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB #define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230 -- cgit v1.2.3 From eada9464889e4dab0f67b9f7533ad8a926186fcf Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sat, 8 Jun 2002 21:51:57 -0700 Subject: [PATCH] 2.5.20 locks.h cleanup Since I have been looking in to the lcoking issues recently the following rather trivial gabrage code collection became obvious... - Remove "not yet used" code from 1995 in asm/locks.h. It's garbage. - Remove useless DEBUG_SPINLOCK code from generic spinlock.h code. Just compiling for SMP does the trick already. - Replace all usages of SPINLOCK_DEBUG with the now global CONFIG_DEBUG_SPINLOCK. --- arch/alpha/kernel/smc37c669.c | 66 ++------------------- arch/ppc/kernel/ppc_ksyms.c | 2 +- arch/ppc/lib/locks.c | 2 +- drivers/scsi/tmscsim.c | 6 +- include/asm-cris/locks.h | 133 ----------------------------------------- include/asm-i386/locks.h | 135 ------------------------------------------ include/asm-i386/spinlock.h | 28 +++------ include/asm-ppc/spinlock.h | 14 ++--- include/asm-x86_64/locks.h | 135 ------------------------------------------ include/asm-x86_64/spinlock.h | 26 +++----- include/linux/spinlock.h | 48 ++------------- 11 files changed, 35 insertions(+), 560 deletions(-) delete mode 100644 include/asm-cris/locks.h delete mode 100644 include/asm-i386/locks.h delete mode 100644 include/asm-x86_64/locks.h (limited to 'include/linux') diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c index 3ffb611f2ccf..8a817233a075 100644 --- a/arch/alpha/kernel/smc37c669.c +++ b/arch/alpha/kernel/smc37c669.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -1103,66 +1104,7 @@ static int SMC37c669_xlate_drq( unsigned int drq ); -#if 0 -/* -** External Data Declarations -*/ - -extern struct LOCK spl_atomic; - -/* -** External Function Prototype Declarations -*/ - -/* From kernel_alpha.mar */ -extern spinlock( - struct LOCK *spl -); - -extern spinunlock( - struct LOCK *spl -); - -/* From filesys.c */ -int allocinode( - char *name, - int can_create, - struct INODE **ipp -); - -extern int null_procedure( void ); - -int smcc669_init( void ); -int smcc669_open( struct FILE *fp, char *info, char *next, char *mode ); -int smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf ); -int smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf ); -int smcc669_close( struct FILE *fp ); - -struct DDB smc_ddb = { - "smc", /* how this routine wants to be called */ - smcc669_read, /* read routine */ - smcc669_write, /* write routine */ - smcc669_open, /* open routine */ - smcc669_close, /* close routine */ - null_procedure, /* name expansion routine */ - null_procedure, /* delete routine */ - null_procedure, /* create routine */ - null_procedure, /* setmode */ - null_procedure, /* validation routine */ - 0, /* class specific use */ - 1, /* allows information */ - 0, /* must be stacked */ - 0, /* is a flash update driver */ - 0, /* is a block device */ - 0, /* not seekable */ - 0, /* is an Ethernet device */ - 0, /* is a filesystem driver */ -}; -#endif - -#define spinlock(x) -#define spinunlock(x) - +static spinlock_t smc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; /* **++ @@ -2042,10 +1984,10 @@ static void __init SMC37c669_config_mode( ** mode. Therefore, a spinlock is placed around the two writes to ** guarantee that they complete uninterrupted. */ - spinlock( &spl_atomic ); + spin_lock(&smc_lock); wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); - spinunlock( &spl_atomic ); + spin_unlock(&smc_lock); } else { wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY ); diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 9232c0184416..4254a096759a 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -217,7 +217,7 @@ EXPORT_SYMBOL(__global_cli); EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_save_flags); EXPORT_SYMBOL(__global_restore_flags); -#ifdef SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK EXPORT_SYMBOL(_raw_spin_lock); EXPORT_SYMBOL(_raw_spin_unlock); EXPORT_SYMBOL(_raw_spin_trylock); diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c index 579bd69906f6..feb3b96ca478 100644 --- a/arch/ppc/lib/locks.c +++ b/arch/ppc/lib/locks.c @@ -16,7 +16,7 @@ #include #include -#ifdef SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK #undef INIT_STUCK #define INIT_STUCK 200000000 /*0xffffffff*/ diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index ea61de3cacb6..bd4e92ed97e7 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -254,8 +254,6 @@ * undef : traditional save_flags; cli; restore_flags; */ -//#define DEBUG_SPINLOCKS 2 /* Set to 0, 1 or 2 in include/linux/spinlock.h */ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) # include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) @@ -293,7 +291,7 @@ MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl); # if USE_SPINLOCKS == 3 /* both */ -# if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0 +# if defined (CONFIG_SMP) # define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; }; # else # define DC390_LOCKA_INIT @@ -322,7 +320,7 @@ MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl); # if USE_SPINLOCKS == 2 /* adapter specific locks */ -# if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0 +# if defined (CONFIG_SMP) # define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; }; # else # define DC390_LOCKA_INIT diff --git a/include/asm-cris/locks.h b/include/asm-cris/locks.h deleted file mode 100644 index a075e92bd7ed..000000000000 --- a/include/asm-cris/locks.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SMP locks primitives for building ix86 locks - * (not yet used). - * - * Alan Cox, alan@cymru.net, 1995 - */ - -/* - * This would be much easier but far less clear and easy - * to borrow for other processors if it was just assembler. - */ - -extern __inline__ void prim_spin_lock(struct spinlock *sp) -{ - int processor=smp_processor_id(); - - /* - * Grab the lock bit - */ - - while(lock_set_bit(0,&sp->lock)) - { - /* - * Failed, but that's cos we own it! - */ - - if(sp->cpu==processor) - { - sp->users++; - return 0; - } - /* - * Spin in the cache S state if possible - */ - while(sp->lock) - { - /* - * Wait for any invalidates to go off - */ - - if(smp_invalidate_needed&(1<spins++; - } - /* - * Someone wrote the line, we go 'I' and get - * the cache entry. Now try to regrab - */ - } - sp->users++;sp->cpu=processor; - return 1; -} - -/* - * Release a spin lock - */ - -extern __inline__ int prim_spin_unlock(struct spinlock *sp) -{ - /* This is safe. The decrement is still guarded by the lock. A multilock would - not be safe this way */ - if(!--sp->users) - { - lock_clear_bit(0,&sp->lock);sp->cpu= NO_PROC_ID; - return 1; - } - return 0; -} - - -/* - * Non blocking lock grab - */ - -extern __inline__ int prim_spin_lock_nb(struct spinlock *sp) -{ - if(lock_set_bit(0,&sp->lock)) - return 0; /* Locked already */ - sp->users++; - return 1; /* We got the lock */ -} - - -/* - * These wrap the locking primitives up for usage - */ - -extern __inline__ void spinlock(struct spinlock *sp) -{ - if(sp->prioritylock_order) - panic("lock order violation: %s (%d)\n", sp->name, current->lock_order); - if(prim_spin_lock(sp)) - { - /* - * We got a new lock. Update the priority chain - */ - sp->oldpri=current->lock_order; - current->lock_order=sp->priority; - } -} - -extern __inline__ void spinunlock(struct spinlock *sp) -{ - if(current->lock_order!=sp->priority) - panic("lock release order violation %s (%d)\n", sp->name, current->lock_order); - if(prim_spin_unlock(sp)) - { - /* - * Update the debugging lock priority chain. We dumped - * our last right to the lock. - */ - current->lock_order=sp->oldpri; - } -} - -extern __inline__ void spintestlock(struct spinlock *sp) -{ - /* - * We do no sanity checks, it's legal to optimistically - * get a lower lock. - */ - prim_spin_lock_nb(sp); -} - -extern __inline__ void spintestunlock(struct spinlock *sp) -{ - /* - * A testlock doesn't update the lock chain so we - * must not update it on free - */ - prim_spin_unlock(sp); -} diff --git a/include/asm-i386/locks.h b/include/asm-i386/locks.h deleted file mode 100644 index ffcab0afb658..000000000000 --- a/include/asm-i386/locks.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * SMP locks primitives for building ix86 locks - * (not yet used). - * - * Alan Cox, alan@redhat.com, 1995 - */ - -/* - * This would be much easier but far less clear and easy - * to borrow for other processors if it was just assembler. - */ - -static __inline__ void prim_spin_lock(struct spinlock *sp) -{ - int processor=smp_processor_id(); - - /* - * Grab the lock bit - */ - - while(lock_set_bit(0,&sp->lock)) - { - /* - * Failed, but that's cos we own it! - */ - - if(sp->cpu==processor) - { - sp->users++; - return 0; - } - /* - * Spin in the cache S state if possible - */ - while(sp->lock) - { - /* - * Wait for any invalidates to go off - */ - - if(smp_invalidate_needed&(1<spins++; - } - /* - * Someone wrote the line, we go 'I' and get - * the cache entry. Now try to regrab - */ - } - sp->users++;sp->cpu=processor; - return 1; -} - -/* - * Release a spin lock - */ - -static __inline__ int prim_spin_unlock(struct spinlock *sp) -{ - /* This is safe. The decrement is still guarded by the lock. A multilock would - not be safe this way */ - if(!--sp->users) - { - sp->cpu= NO_PROC_ID;lock_clear_bit(0,&sp->lock); - return 1; - } - return 0; -} - - -/* - * Non blocking lock grab - */ - -static __inline__ int prim_spin_lock_nb(struct spinlock *sp) -{ - if(lock_set_bit(0,&sp->lock)) - return 0; /* Locked already */ - sp->users++; - return 1; /* We got the lock */ -} - - -/* - * These wrap the locking primitives up for usage - */ - -static __inline__ void spinlock(struct spinlock *sp) -{ - if(sp->prioritylock_order) - panic("lock order violation: %s (%d)\n", sp->name, current->lock_order); - if(prim_spin_lock(sp)) - { - /* - * We got a new lock. Update the priority chain - */ - sp->oldpri=current->lock_order; - current->lock_order=sp->priority; - } -} - -static __inline__ void spinunlock(struct spinlock *sp) -{ - int pri; - if(current->lock_order!=sp->priority) - panic("lock release order violation %s (%d)\n", sp->name, current->lock_order); - pri=sp->oldpri; - if(prim_spin_unlock(sp)) - { - /* - * Update the debugging lock priority chain. We dumped - * our last right to the lock. - */ - current->lock_order=sp->pri; - } -} - -static __inline__ void spintestlock(struct spinlock *sp) -{ - /* - * We do no sanity checks, it's legal to optimistically - * get a lower lock. - */ - prim_spin_lock_nb(sp); -} - -static __inline__ void spintestunlock(struct spinlock *sp) -{ - /* - * A testlock doesn't update the lock chain so we - * must not update it on free - */ - prim_spin_unlock(sp); -} diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index 1a4b4879c358..678a64fed800 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -9,30 +9,20 @@ extern int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); -/* It seems that people are forgetting to - * initialize their spinlocks properly, tsk tsk. - * Remember to turn this off in 2.4. -ben - */ -#if defined(CONFIG_DEBUG_SPINLOCK) -#define SPINLOCK_DEBUG 1 -#else -#define SPINLOCK_DEBUG 0 -#endif - /* * Your basic SMP spinlocks, allowing only a single CPU anywhere */ typedef struct { volatile unsigned int lock; -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK unsigned magic; #endif } spinlock_t; #define SPINLOCK_MAGIC 0xdead4ead -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK #define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC #else #define SPINLOCK_MAGIC_INIT /* */ @@ -79,7 +69,7 @@ typedef struct { static inline void _raw_spin_unlock(spinlock_t *lock) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (lock->magic != SPINLOCK_MAGIC) BUG(); if (!spin_is_locked(lock)) @@ -100,7 +90,7 @@ static inline void _raw_spin_unlock(spinlock_t *lock) static inline void _raw_spin_unlock(spinlock_t *lock) { char oldval = 1; -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (lock->magic != SPINLOCK_MAGIC) BUG(); if (!spin_is_locked(lock)) @@ -125,7 +115,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock) static inline void _raw_spin_lock(spinlock_t *lock) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK __label__ here; here: if (lock->magic != SPINLOCK_MAGIC) { @@ -151,14 +141,14 @@ printk("eip: %p\n", &&here); */ typedef struct { volatile unsigned int lock; -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK unsigned magic; #endif } rwlock_t; #define RWLOCK_MAGIC 0xdeaf1eed -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK #define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC #else #define RWLOCK_MAGIC_INIT /* */ @@ -181,7 +171,7 @@ typedef struct { static inline void _raw_read_lock(rwlock_t *rw) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (rw->magic != RWLOCK_MAGIC) BUG(); #endif @@ -190,7 +180,7 @@ static inline void _raw_read_lock(rwlock_t *rw) static inline void _raw_write_lock(rwlock_t *rw) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (rw->magic != RWLOCK_MAGIC) BUG(); #endif diff --git a/include/asm-ppc/spinlock.h b/include/asm-ppc/spinlock.h index f5d454bc5275..b7dafa9a36a5 100644 --- a/include/asm-ppc/spinlock.h +++ b/include/asm-ppc/spinlock.h @@ -7,22 +7,20 @@ #include #include -#undef SPINLOCK_DEBUG - /* * Simple spin lock operations. */ typedef struct { volatile unsigned long lock; -#ifdef SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK volatile unsigned long owner_pc; volatile unsigned long owner_cpu; #endif } spinlock_t; #ifdef __KERNEL__ -#if SPINLOCK_DEBUG +#if CONFIG_DEBUG_SPINLOCK #define SPINLOCK_DEBUG_INIT , 0, 0 #else #define SPINLOCK_DEBUG_INIT /* */ @@ -34,7 +32,7 @@ typedef struct { #define spin_is_locked(x) ((x)->lock != 0) #define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) -#ifndef SPINLOCK_DEBUG +#ifndef CONFIG_DEBUG_SPINLOCK static inline void _raw_spin_lock(spinlock_t *lock) { @@ -88,12 +86,12 @@ extern unsigned long __spin_trylock(volatile unsigned long *lock); */ typedef struct { volatile unsigned long lock; -#ifdef SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK volatile unsigned long owner_pc; #endif } rwlock_t; -#if SPINLOCK_DEBUG +#if CONFIG_DEBUG_SPINLOCK #define RWLOCK_DEBUG_INIT , 0 #else #define RWLOCK_DEBUG_INIT /* */ @@ -102,7 +100,7 @@ typedef struct { #define RW_LOCK_UNLOCKED (rwlock_t) { 0 RWLOCK_DEBUG_INIT } #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0) -#ifndef SPINLOCK_DEBUG +#ifndef CONFIG_DEBUG_SPINLOCK static __inline__ void _raw_read_lock(rwlock_t *rw) { diff --git a/include/asm-x86_64/locks.h b/include/asm-x86_64/locks.h deleted file mode 100644 index 1cc171f9b600..000000000000 --- a/include/asm-x86_64/locks.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * SMP locks primitives for building ix86 locks - * (not yet used). - * - * Alan Cox, alan@redhat.com, 1995 - */ - -/* - * This would be much easier but far less clear and easy - * to borrow for other processors if it was just assembler. - */ - -extern __inline__ void prim_spin_lock(struct spinlock *sp) -{ - int processor=smp_processor_id(); - - /* - * Grab the lock bit - */ - - while(lock_set_bit(0,&sp->lock)) - { - /* - * Failed, but that's cos we own it! - */ - - if(sp->cpu==processor) - { - sp->users++; - return 0; - } - /* - * Spin in the cache S state if possible - */ - while(sp->lock) - { - /* - * Wait for any invalidates to go off - */ - - if(smp_invalidate_needed&(1<spins++; - } - /* - * Someone wrote the line, we go 'I' and get - * the cache entry. Now try to regrab - */ - } - sp->users++;sp->cpu=processor; - return 1; -} - -/* - * Release a spin lock - */ - -extern __inline__ int prim_spin_unlock(struct spinlock *sp) -{ - /* This is safe. The decrement is still guarded by the lock. A multilock would - not be safe this way */ - if(!--sp->users) - { - sp->cpu= NO_PROC_ID;lock_clear_bit(0,&sp->lock); - return 1; - } - return 0; -} - - -/* - * Non blocking lock grab - */ - -extern __inline__ int prim_spin_lock_nb(struct spinlock *sp) -{ - if(lock_set_bit(0,&sp->lock)) - return 0; /* Locked already */ - sp->users++; - return 1; /* We got the lock */ -} - - -/* - * These wrap the locking primitives up for usage - */ - -extern __inline__ void spinlock(struct spinlock *sp) -{ - if(sp->prioritylock_order) - panic("lock order violation: %s (%d)\n", sp->name, current->lock_order); - if(prim_spin_lock(sp)) - { - /* - * We got a new lock. Update the priority chain - */ - sp->oldpri=current->lock_order; - current->lock_order=sp->priority; - } -} - -extern __inline__ void spinunlock(struct spinlock *sp) -{ - int pri; - if(current->lock_order!=sp->priority) - panic("lock release order violation %s (%d)\n", sp->name, current->lock_order); - pri=sp->oldpri; - if(prim_spin_unlock(sp)) - { - /* - * Update the debugging lock priority chain. We dumped - * our last right to the lock. - */ - current->lock_order=sp->pri; - } -} - -extern __inline__ void spintestlock(struct spinlock *sp) -{ - /* - * We do no sanity checks, it's legal to optimistically - * get a lower lock. - */ - prim_spin_lock_nb(sp); -} - -extern __inline__ void spintestunlock(struct spinlock *sp) -{ - /* - * A testlock doesn't update the lock chain so we - * must not update it on free - */ - prim_spin_unlock(sp); -} diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h index b68101e609e1..6f1d71c65a68 100644 --- a/include/asm-x86_64/spinlock.h +++ b/include/asm-x86_64/spinlock.h @@ -9,30 +9,20 @@ extern int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); -/* It seems that people are forgetting to - * initialize their spinlocks properly, tsk tsk. - * Remember to turn this off in 2.4. -ben - */ -#if defined(CONFIG_DEBUG_SPINLOCK) -#define SPINLOCK_DEBUG 1 -#else -#define SPINLOCK_DEBUG 0 -#endif - /* * Your basic SMP spinlocks, allowing only a single CPU anywhere */ typedef struct { volatile unsigned int lock; -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK unsigned magic; #endif } spinlock_t; #define SPINLOCK_MAGIC 0xdead4ead -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK #define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC #else #define SPINLOCK_MAGIC_INIT /* */ @@ -82,7 +72,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock) static inline void _raw_spin_lock(spinlock_t *lock) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK __label__ here; here: if (lock->magic != SPINLOCK_MAGIC) { @@ -97,7 +87,7 @@ printk("eip: %p\n", &&here); static inline void _raw_spin_unlock(spinlock_t *lock) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (lock->magic != SPINLOCK_MAGIC) BUG(); if (!spin_is_locked(lock)) @@ -120,14 +110,14 @@ static inline void _raw_spin_unlock(spinlock_t *lock) */ typedef struct { volatile unsigned int lock; -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK unsigned magic; #endif } rwlock_t; #define RWLOCK_MAGIC 0xdeaf1eed -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK #define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC #else #define RWLOCK_MAGIC_INIT /* */ @@ -150,7 +140,7 @@ typedef struct { extern inline void _raw_read_lock(rwlock_t *rw) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (rw->magic != RWLOCK_MAGIC) BUG(); #endif @@ -159,7 +149,7 @@ extern inline void _raw_read_lock(rwlock_t *rw) static inline void _raw_write_lock(rwlock_t *rw) { -#if SPINLOCK_DEBUG +#ifdef CONFIG_DEBUG_SPINLOCK if (rw->magic != RWLOCK_MAGIC) BUG(); #endif diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index e46232e8e126..0e9f7247bc86 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -64,13 +64,9 @@ #elif !defined(spin_lock_init) /* !SMP and spin_lock_init not previously defined (e.g. by including asm/spinlock.h */ -#define DEBUG_SPINLOCKS 0 /* 0 == no debugging, 1 == maintain lock state, 2 == full debug */ - -#if (DEBUG_SPINLOCKS < 1) - #ifndef CONFIG_PREEMPT -#define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic) -#define ATOMIC_DEC_AND_LOCK +# define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic) +# define ATOMIC_DEC_AND_LOCK #endif /* @@ -80,10 +76,10 @@ */ #if (__GNUC__ > 2) typedef struct { } spinlock_t; - #define SPIN_LOCK_UNLOCKED (spinlock_t) { } +# define SPIN_LOCK_UNLOCKED (spinlock_t) { } #else typedef struct { int gcc_is_buggy; } spinlock_t; - #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } +# define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #endif #define spin_lock_init(lock) do { (void)(lock); } while(0) @@ -93,42 +89,6 @@ #define spin_unlock_wait(lock) do { (void)(lock); } while(0) #define _raw_spin_unlock(lock) do { (void)(lock); } while(0) -#elif (DEBUG_SPINLOCKS < 2) - -typedef struct { - volatile unsigned long lock; -} spinlock_t; -#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } - -#define spin_lock_init(x) do { (x)->lock = 0; } while (0) -#define spin_is_locked(lock) (test_bit(0,(lock))) -#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) - -#define spin_lock(x) do { (x)->lock = 1; } while (0) -#define spin_unlock_wait(x) do { } while (0) -#define spin_unlock(x) do { (x)->lock = 0; } while (0) - -#else /* (DEBUG_SPINLOCKS >= 2) */ - -typedef struct { - volatile unsigned long lock; - volatile unsigned int babble; - const char *module; -} spinlock_t; -#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 25, __BASE_FILE__ } - -#include - -#define spin_lock_init(x) do { (x)->lock = 0; } while (0) -#define spin_is_locked(lock) (test_bit(0,(lock))) -#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) - -#define spin_lock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0) -#define spin_unlock_wait(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0) -#define spin_unlock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0) - -#endif /* DEBUG_SPINLOCKS */ - /* * Read-write spinlocks, allowing multiple readers * but only one writer. -- cgit v1.2.3 From 3150c862b5b885c929d1300b9a39d4d3b76ba3df Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 8 Jun 2002 21:56:20 -0700 Subject: [PATCH] Fix more header file breakage Since namespace.h needs the contents of dcache, task struct and semaphores, it seems sensible to include these two files into namespace.h. For the future: If the task_struct in sched.h is split into its own include file, namespace.h could include this file, but namespace.h will also need asm/semaphore.h --- include/linux/namespace.h | 3 +++ kernel/fork.c | 1 + mm/vmalloc.c | 1 + 3 files changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/namespace.h b/include/linux/namespace.h index da92ede04064..1113fe62d6cd 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -2,6 +2,9 @@ #define _NAMESPACE_H_ #ifdef __KERNEL__ +#include +#include + struct namespace { atomic_t count; struct vfsmount * root; diff --git a/kernel/fork.c b/kernel/fork.c index a4f5a991e0a5..493139670d30 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/mm/vmalloc.c b/mm/vmalloc.c index a3082fa949ce..f95ebed746b0 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3