aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2004-08-02 06:08:40 -0400
committerLen Brown <len.brown@intel.com>2004-08-02 06:08:40 -0400
commitec3b036720858caae7951be6d5dfa70e3071eb8b (patch)
treef5516210ff25363865d804c3eaf478085e0f9922 /drivers
parent023a2af5c04653827d36d4c9892e029cd83914cf (diff)
parent81fd00e2e58911325c794b6f98d683ecb7db2b04 (diff)
downloadhistory-ec3b036720858caae7951be6d5dfa70e3071eb8b.tar.gz
Merge intel.com:/home/lenb/bk/linux-2.6.8
into intel.com:/home/lenb/src/linux-acpi-test-2.6.8
Diffstat (limited to 'drivers')
-rw-r--r--drivers/atm/fore200e.c4
-rw-r--r--drivers/atm/iphase.h2
-rw-r--r--drivers/block/Kconfig7
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/bluetooth/hci_usb.c5
-rw-r--r--drivers/cdrom/aztcd.c2
-rw-r--r--drivers/cdrom/cdrom.c5
-rw-r--r--drivers/cdrom/optcd.c2
-rw-r--r--drivers/cdrom/sbpcd.c2
-rw-r--r--drivers/cdrom/sbpcd.h2
-rw-r--r--drivers/char/Kconfig16
-rw-r--r--drivers/char/README.scc2
-rw-r--r--drivers/char/hpet.c20
-rw-r--r--drivers/char/specialix.c2
-rw-r--r--drivers/ide/pci/hpt366.c239
-rw-r--r--drivers/ieee1394/dv1394.c2
-rw-r--r--drivers/isdn/hardware/eicon/platform.h7
-rw-r--r--drivers/isdn/hisax/callc.c2
-rw-r--r--drivers/isdn/hisax/config.c2
-rw-r--r--drivers/isdn/hisax/diva.c2
-rw-r--r--drivers/isdn/hisax/elsa.c2
-rw-r--r--drivers/isdn/hisax/hfc_pci.c2
-rw-r--r--drivers/isdn/hisax/isac.c2
-rw-r--r--drivers/isdn/hisax/isdnl1.c2
-rw-r--r--drivers/isdn/hisax/isdnl2.c2
-rw-r--r--drivers/isdn/hisax/isdnl3.c2
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c2
-rw-r--r--drivers/isdn/hisax/l3dss1.c2
-rw-r--r--drivers/isdn/hisax/tei.c2
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.c4
-rw-r--r--drivers/macintosh/Kconfig9
-rw-r--r--drivers/macintosh/ans-lcd.c11
-rw-r--r--drivers/macintosh/mediabay.c1
-rw-r--r--drivers/media/dvb/frontends/alps_tdlb7.c10
-rw-r--r--drivers/media/dvb/frontends/sp887x.c9
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c10
-rw-r--r--drivers/net/bonding/bond_main.c10
-rw-r--r--drivers/net/dummy.c10
-rw-r--r--drivers/net/hamradio/scc.c2
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--drivers/net/tg3.c18
-rw-r--r--drivers/net/tlan.c2
-rw-r--r--drivers/net/wireless/arlan.h1
-rw-r--r--drivers/net/wireless/prism54/isl_38xx.c2
-rw-r--r--drivers/pci/Kconfig19
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/msi.c878
-rw-r--r--drivers/pci/msi.h3
-rw-r--r--drivers/pcmcia/sa1100_generic.c4
-rw-r--r--drivers/scsi/aha152x.c2
-rw-r--r--drivers/scsi/fdomain.c4
-rw-r--r--drivers/scsi/pcmcia/Kconfig2
-rw-r--r--drivers/scsi/tmscsim.c2
-rw-r--r--drivers/usb/media/ov511.c2
-rw-r--r--drivers/usb/misc/tiglusb.c2
55 files changed, 828 insertions, 538 deletions
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index e33b5357ec5ecc..b2f13752cb5189 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -110,8 +110,8 @@
#endif
-extern const struct atmdev_ops fore200e_ops;
-extern const struct fore200e_bus fore200e_bus[];
+static const struct atmdev_ops fore200e_ops;
+static const struct fore200e_bus fore200e_bus[];
static struct fore200e* fore200e_boards = NULL;
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h
index 92e514c79c4845..9da028683bb8a6 100644
--- a/drivers/atm/iphase.h
+++ b/drivers/atm/iphase.h
@@ -68,8 +68,6 @@
#define IF_IADBG_SUNI_STAT 0x02000000 // suni statistics
#define IF_IADBG_RESET 0x04000000
-extern unsigned int IADebugFlag;
-
#define IF_IADBG(f) if (IADebugFlag & (f))
#ifdef CONFIG_ATM_IA_DEBUG /* Debug build */
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index afb9d4391a7a6e..c44f27f24847b7 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -33,6 +33,13 @@ config BLK_DEV_SWIM_IOP
Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
floppy controller on the Macintosh IIfx and Quadra 900/950.
+config MAC_FLOPPY
+ tristate "Support for PowerMac floppy"
+ depends on PPC_PMAC && !PPC_PMAC64
+ help
+ If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
+ floppy controller, say Y here. Most commonly found in PowerMacs.
+
config BLK_DEV_PS2
tristate "PS/2 ESDI hard disk support"
depends on MCA && MCA_LEGACY
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 7e37bdb44d0a23..5bf390d1b5ff88 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4190,7 +4190,7 @@ static int __init floppy_setup(char *str)
printk("\n");
} else
DPRINT("botched floppy option\n");
- DPRINT("Read linux/Documentation/floppy.txt\n");
+ DPRINT("Read Documentation/floppy.txt\n");
return 0;
}
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index e12d4c85eae440..9babb21df10c0c 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -65,7 +65,7 @@
#define URB_ZERO_PACKET 0
#endif
-#define VERSION "2.6"
+#define VERSION "2.7"
static struct usb_driver hci_usb_driver;
@@ -98,6 +98,9 @@ static struct usb_device_id blacklist_ids[] = {
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET },
+ /* ISSC Bluetooth Adapter v3.1 */
+ { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
+
/* Digianswer device */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index 97ab1b33fb650c..b6a14c80e23791 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -129,7 +129,7 @@
Werner Zimmermann, August 8, 1995
V1.70 Multisession support now is completed, but there is still not
enough testing done. If you can test it, please contact me. For
- details please read /usr/src/linux/Documentation/cdrom/aztcd
+ details please read Documentation/cdrom/aztcd
Werner Zimmermann, August 19, 1995
V1.80 Modification to suit the new kernel boot procedure introduced
with kernel 1.3.33. Will definitely not work with older kernels.
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 5a08b536444c7d..4c271524ea6480 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1921,6 +1921,8 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
struct packet_command cgc;
int nr, ret;
+ cdi->last_sense = 0;
+
memset(&cgc, 0, sizeof(cgc));
/*
@@ -1972,6 +1974,8 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!q)
return -ENXIO;
+ cdi->last_sense = 0;
+
while (nframes) {
nr = nframes;
if (cdi->cdda_method == CDDA_BPC_SINGLE)
@@ -2019,6 +2023,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
nframes -= nr;
lba += nr;
+ ubuf += len;
}
return ret;
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index 62e2d11b382963..caaeb724a3424f 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -964,7 +964,7 @@ static int update_toc(void)
#endif /* MULTISESSION */
if (disk_info.multi)
printk(KERN_WARNING "optcd: Multisession support experimental, "
- "see linux/Documentation/cdrom/optcd\n");
+ "see Documentation/cdrom/optcd\n");
DEBUG((DEBUG_TOC, "exiting update_toc"));
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index cd33f63b97cd0d..a2475c6bb183e3 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -5715,7 +5715,7 @@ int __init sbpcd_init(void)
if (port_index>0)
{
- msg(DBG_INF, "You should read linux/Documentation/cdrom/sbpcd\n");
+ msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
}
check_datarate();
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
index 16a0208a259874..2f2225f13c6f04 100644
--- a/drivers/cdrom/sbpcd.h
+++ b/drivers/cdrom/sbpcd.h
@@ -5,7 +5,7 @@
/*
* Attention! This file contains user-serviceable parts!
* I recommend to make use of it...
- * If you feel helpless, look into linux/Documentation/cdrom/sbpcd
+ * If you feel helpless, look into Documentation/cdrom/sbpcd
* (good idea anyway, at least before mailing me).
*
* The definitions for the first controller can get overridden by
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 60c50c2eb1af16..37e06735107522 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -976,14 +976,18 @@ config HPET_RTC_IRQ
is assumed the platform called hpet_alloc with the RTC IRQ values for
the HPET timers.
-config HPET_NOMMAP
- bool "HPET - Control mmap capability."
- default n
+config HPET_MMAP
+ bool "Allow mmap of HPET"
+ default y
depends on HPET
help
- If you say Y here, then the mmap interface for the HPET driver returns ENOSYS.
- Some hardware implementations might not want all the memory in the page the
- HPET control registers reside to be exposed.
+ If you say Y here, user applications will be able to mmap
+ the HPET registers.
+
+ In some hardware implementations, the page containing HPET
+ registers may also contain other things that shouldn't be
+ exposed to the user. If this applies to your hardware,
+ say N here.
config MAX_RAW_DEVS
int "Maximum number of RAW devices to support (1-8192)"
diff --git a/drivers/char/README.scc b/drivers/char/README.scc
index 8837d8a5dd08e7..90fa4b8aed10a3 100644
--- a/drivers/char/README.scc
+++ b/drivers/char/README.scc
@@ -2,4 +2,4 @@ The z8530drv is now a network device driver, you can find it in
../net/scc.c
A subset of the documentation is in
- ../../Documentation/networking/z8530drv.txt
+ Documentation/networking/z8530drv.txt
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 36d9d2876b1606..5e8c472446ef08 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -1,8 +1,14 @@
/*
* Intel & MS High Precision Event Timer Implementation.
- * Contributors:
+ *
+ * Copyright (C) 2003 Intel Corporation
* Venki Pallipadi
- * Bob Picco
+ * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
+ * Bob Picco <robert.picco@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
#include <linux/config.h>
@@ -250,9 +256,7 @@ static unsigned int hpet_poll(struct file *file, poll_table * wait)
static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
{
-#ifdef CONFIG_HPET_NOMMAP
- return -ENOSYS;
-#else
+#ifdef CONFIG_HPET_MMAP
struct hpet_dev *devp;
unsigned long addr;
@@ -276,6 +280,8 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
}
return 0;
+#else
+ return -ENOSYS;
#endif
}
@@ -901,14 +907,10 @@ static acpi_status __init hpet_resources(struct acpi_resource *res, void *data)
hdp->hd_nirqs = irqp->number_of_interrupts;
for (i = 0; i < hdp->hd_nirqs; i++)
-#ifdef CONFIG_IA64
hdp->hd_irq[i] =
acpi_register_gsi(irqp->interrupts[i],
irqp->edge_level,
irqp->active_high_low);
-#else
- hdp->hd_irq[i] = irqp->interrupts[i];
-#endif
}
}
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index de456d01ccea2f..0d3763dc6a50b8 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -72,7 +72,7 @@
/*
* There is a bunch of documentation about the card, jumpers, config
* settings, restrictions, cables, device names and numbers in
- * ../../Documentation/specialix.txt
+ * Documentation/specialix.txt
*/
#include <linux/config.h>
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 6c25d34b89390b..5f5bc3b6e8bc59 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,8 +1,9 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 0.34 Sept 17, 2002
+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
+ * Portions Copyright (C) 2003 Red Hat Inc
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
* Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
@@ -39,6 +40,13 @@
* Reset the hpt366 on error, reset on dma
* Fix disabling Fast Interrupt hpt366.
* Mike Waychison <crlf@sun.com>
+ *
+ * Added support for 372N clocking and clock switching. The 372N needs
+ * different clocks on read/write. This requires overloading rw_disk and
+ * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
+ * keeping me sane.
+ * Alan Cox <alan@redhat.com>
+ *
*/
@@ -168,6 +176,9 @@ static u32 hpt_revision (struct pci_dev *dev)
class_rev &= 0xff;
switch(dev->device) {
+ /* Remap new 372N onto 372 */
+ case PCI_DEVICE_ID_TTI_HPT372N:
+ class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
case PCI_DEVICE_ID_TTI_HPT374:
class_rev = PCI_DEVICE_ID_TTI_HPT374; break;
case PCI_DEVICE_ID_TTI_HPT371:
@@ -217,6 +228,11 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive)
return mode;
}
+/*
+ * Note for the future; the SATA hpt37x we must set
+ * either PIO or UDMA modes 0,4,5
+ */
+
static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
@@ -672,6 +688,69 @@ static int hpt374_ide_dma_end (ide_drive_t *drive)
return __ide_dma_end(drive);
}
+/**
+ * hpt372n_set_clock - perform clock switching dance
+ * @drive: Drive to switch
+ * @mode: Switching mode (0x21 for write, 0x23 otherwise)
+ *
+ * Switch the DPLL clock on the HPT372N devices. This is a
+ * right mess.
+ */
+
+static void hpt372n_set_clock(ide_drive_t *drive, int mode)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+
+ /* FIXME: should we check for DMA active and BUG() */
+ /* Tristate the bus */
+ outb(0x80, hwif->dma_base+0x73);
+ outb(0x80, hwif->dma_base+0x77);
+
+ /* Switch clock and reset channels */
+ outb(mode, hwif->dma_base+0x7B);
+ outb(0xC0, hwif->dma_base+0x79);
+
+ /* Reset state machines */
+ outb(0x37, hwif->dma_base+0x70);
+ outb(0x37, hwif->dma_base+0x74);
+
+ /* Complete reset */
+ outb(0x00, hwif->dma_base+0x79);
+
+ /* Reconnect channels to bus */
+ outb(0x00, hwif->dma_base+0x73);
+ outb(0x00, hwif->dma_base+0x77);
+}
+
+/**
+ * hpt372n_rw_disk - wrapper for I/O
+ * @drive: drive for command
+ * @rq: block request structure
+ * @block: block number
+ *
+ * This is called when a disk I/O is issued to the 372N instead
+ * of the default functionality. We need it because of the clock
+ * switching
+ *
+ */
+
+static ide_startstop_t hpt372n_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
+{
+ int wantclock;
+
+ if(rq_data_dir(rq) == READ)
+ wantclock = 0x21;
+ else
+ wantclock = 0x23;
+
+ if(HWIF(drive)->config_data != wantclock)
+ {
+ hpt372n_set_clock(drive, wantclock);
+ HWIF(drive)->config_data = wantclock;
+ }
+ return __ide_do_rw_disk(drive, rq, block);
+}
+
/*
* Since SUN Cobalt is attempting to do this operation, I should disclose
* this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
@@ -793,13 +872,23 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
u16 freq;
u32 pll;
u8 reg5bh;
-
-#if 1
u8 reg5ah = 0;
+ unsigned long dmabase = pci_resource_start(dev, 4);
+ u8 did, rid;
+ int is_372n = 0;
+
pci_read_config_byte(dev, 0x5a, &reg5ah);
/* interrupt force enable */
pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
-#endif
+
+ if(dmabase)
+ {
+ did = inb(dmabase + 0x22);
+ rid = inb(dmabase + 0x28);
+
+ if((did == 4 && rid == 6) || (did == 5 && rid > 1))
+ is_372n = 1;
+ }
/*
* default to pci clock. make sure MA15/16 are set to output
@@ -810,47 +899,86 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
/*
* set up the PLL. we need to adjust it so that it's stable.
* freq = Tpll * 192 / Tpci
+ *
+ * Todo. For non x86 should probably check the dword is
+ * set to 0xABCDExxx indicating the BIOS saved f_CNT
*/
pci_read_config_word(dev, 0x78, &freq);
freq &= 0x1FF;
- if (freq < 0xa0) {
- pll = F_LOW_PCI_33;
- if (hpt_minimum_revision(dev,8))
- pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
- else if (hpt_minimum_revision(dev,5))
- pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);
- else if (hpt_minimum_revision(dev,4))
- pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);
+
+ /*
+ * The 372N uses different PCI clock information and has
+ * some other complications
+ * On PCI33 timing we must clock switch
+ * On PCI66 timing we must NOT use the PCI clock
+ *
+ * Currently we always set up the PLL for the 372N
+ */
+
+ pci_set_drvdata(dev, NULL);
+
+ if(is_372n)
+ {
+ printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
+ if(freq < 0x55)
+ pll = F_LOW_PCI_33;
+ else if(freq < 0x70)
+ pll = F_LOW_PCI_40;
+ else if(freq < 0x7F)
+ pll = F_LOW_PCI_50;
else
- pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
- printk("HPT37X: using 33MHz PCI clock\n");
- } else if (freq < 0xb0) {
- pll = F_LOW_PCI_40;
- } else if (freq < 0xc8) {
- pll = F_LOW_PCI_50;
- if (hpt_minimum_revision(dev,8))
- pci_set_drvdata(dev, NULL);
- else if (hpt_minimum_revision(dev,5))
- pci_set_drvdata(dev, (void *) fifty_base_hpt372);
- else if (hpt_minimum_revision(dev,4))
- pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+ pll = F_LOW_PCI_66;
+
+ printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll);
+
+ /* We always use the pll not the PCI clock on 372N */
+ }
+ else
+ {
+ if(freq < 0x9C)
+ pll = F_LOW_PCI_33;
+ else if(freq < 0xb0)
+ pll = F_LOW_PCI_40;
+ else if(freq <0xc8)
+ pll = F_LOW_PCI_50;
else
- pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
- printk("HPT37X: using 50MHz PCI clock\n");
- } else {
- pll = F_LOW_PCI_66;
- if (hpt_minimum_revision(dev,8))
- {
- printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
- pci_set_drvdata(dev, NULL);
+ pll = F_LOW_PCI_66;
+
+ if (pll == F_LOW_PCI_33) {
+ if (hpt_minimum_revision(dev,8))
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);
+ else
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
+ printk("HPT37X: using 33MHz PCI clock\n");
+ } else if (pll == F_LOW_PCI_40) {
+ /* Unsupported */
+ } else if (pll == F_LOW_PCI_50) {
+ if (hpt_minimum_revision(dev,8))
+ pci_set_drvdata(dev, NULL);
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+ else
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+ printk("HPT37X: using 50MHz PCI clock\n");
+ } else {
+ if (hpt_minimum_revision(dev,8))
+ {
+ printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
+ }
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a);
+ else
+ pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
+ printk("HPT37X: using 66MHz PCI clock\n");
}
- else if (hpt_minimum_revision(dev,5))
- pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
- else if (hpt_minimum_revision(dev,4))
- pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a);
- else
- pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
- printk("HPT37X: using 66MHz PCI clock\n");
}
/*
@@ -863,6 +991,11 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
if (pci_get_drvdata(dev))
goto init_hpt37X_done;
+ if (hpt_minimum_revision(dev,8))
+ {
+ printk(KERN_ERR "HPT374: Only 33MHz PCI timings are supported.\n");
+ return -EOPNOTSUPP;
+ }
/*
* adjust PLL based upon PCI clock, enable it, and wait for
* stabilization.
@@ -1000,12 +1133,27 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
-
+ u8 did, rid;
+ unsigned long dmabase = hwif->dma_base;
+ int is_372n = 0;
+
+ if(dmabase)
+ {
+ did = inb(dmabase + 0x22);
+ rid = inb(dmabase + 0x28);
+
+ if((did == 4 && rid == 6) || (did == 5 && rid > 1))
+ is_372n = 1;
+ }
+
hwif->tuneproc = &hpt3xx_tune_drive;
hwif->speedproc = &hpt3xx_tune_chipset;
hwif->quirkproc = &hpt3xx_quirkproc;
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
+
+ if(is_372n)
+ hwif->rw_disk = &hpt372n_rw_disk;
/*
* The HPT37x uses the CBLID pins as outputs for MA15/MA16
@@ -1179,7 +1327,8 @@ static void __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d
u8 pin1 = 0, pin2 = 0;
unsigned int class_rev;
char *chipset_names[] = {"HPT366", "HPT366", "HPT368",
- "HPT370", "HPT370A", "HPT372"};
+ "HPT370", "HPT370A", "HPT372",
+ "HPT372N" };
if (PCI_FUNC(dev->devfn) & 1)
return;
@@ -1187,9 +1336,14 @@ static void __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
- strcpy(d->name, chipset_names[class_rev]);
+ if(dev->device == PCI_DEVICE_ID_TTI_HPT372N)
+ class_rev = 6;
+
+ if(class_rev <= 6)
+ d->name = chipset_names[class_rev];
switch(class_rev) {
+ case 6:
case 5:
case 4:
case 3: ide_setup_pci_device(dev, d);
@@ -1243,6 +1397,7 @@ static struct pci_device_id hpt366_pci_tbl[] = {
{ PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
{ PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
{ PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+ { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 0282df04047061..ecf6830b3b51e3 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -1322,7 +1322,7 @@ static unsigned int dv1394_poll(struct file *file, struct poll_table_struct *wai
static int dv1394_fasync(int fd, struct file *file, int on)
{
/* I just copied this code verbatim from Alan Cox's mouse driver example
- (linux/Documentation/DocBook/) */
+ (Documentation/DocBook/) */
struct video_card *video = file_to_video_card(file);
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
index c38f8718d8c51b..31299feb766088 100644
--- a/drivers/isdn/hardware/eicon/platform.h
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -1,4 +1,4 @@
-/* $Id: platform.h,v 1.37 2004/03/20 17:44:29 armin Exp $
+/* $Id: platform.h,v 1.37.4.1 2004/07/28 14:47:21 armin Exp $
*
* platform.h
*
@@ -214,10 +214,7 @@ void diva_os_free_message_buffer(diva_os_message_buffer_s *dmb);
*/
static __inline__ void diva_os_sleep(dword mSec)
{
- unsigned long timeout = HZ * mSec / 1000 + 1;
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(timeout);
+ msleep(mSec);
}
static __inline__ void diva_os_wait(dword mSec)
{
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 6b2623af12393e..04065ab2610f9f 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -7,7 +7,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* based on the teles driver from Jan den Ouden
*
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index b920679e8eb277..26bb71d96b38a2 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -8,7 +8,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* based on the teles driver from Jan den Ouden
*
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 843ed75f82c2ea..2b54e7d6fb98cc 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -9,7 +9,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Eicon Technology for documents and information
*
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 8b6da9ea4cb4ac..b336781296a5ce 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -9,7 +9,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Elsa GmbH for documents and information
*
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index c058ccbc51f17f..20042fda89a5fc 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -11,7 +11,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
*/
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 270df3bd551b24..20b9499529528c 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -9,7 +9,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
*/
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index 35536661b027d6..4d08d27f14995b 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -10,7 +10,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Jan den Ouden
* Fritz Elfert
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index da87f1ee623821..d311b5fbf89501 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -8,7 +8,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Jan den Ouden
* Fritz Elfert
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 5145948dc4a6d6..f571b5d18e91f4 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -8,7 +8,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Jan den Ouden
* Fritz Elfert
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index 23547749478e7c..d6c1c8f8329d86 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -9,7 +9,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
*/
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index 092634c03a1467..ec92308c1efc75 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -12,7 +12,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Jan den Ouden
* Fritz Elfert
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index 6056ac1d767326..082726db39855c 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -8,7 +8,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
- * ../../../Documentation/isdn/HiSax.cert
+ * Documentation/isdn/HiSax.cert
*
* Thanks to Jan den Ouden
* Fritz Elfert
diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c
index ee2071b061cd1f..da1d2fb9fc8dd5 100644
--- a/drivers/isdn/i4l/isdn_x25iface.c
+++ b/drivers/isdn/i4l/isdn_x25iface.c
@@ -8,7 +8,7 @@
* stuff needed to support the Linux X.25 PLP code on top of devices that
* can provide a lab_b service using the concap_proto mechanism.
* This module supports a network interface wich provides lapb_sematics
- * -- as defined in ../../Documentation/networking/x25-iface.txt -- to
+ * -- as defined in Documentation/networking/x25-iface.txt -- to
* the upper layer and assumes that the lower layer provides a reliable
* data link service by means of the concap_device_ops callbacks.
*
@@ -270,7 +270,7 @@ int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
}
/* process a frame handed over to us from linux network layer. First byte
- semantics as defined in ../../Documentation/networking/x25-iface.txt
+ semantics as defined in Documentation/networking/x25-iface.txt
*/
int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
{
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 80b5a8200c726d..f87ed85539d5f1 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -118,13 +118,6 @@ config PMAC_BACKLIGHT
events; also, the PowerBook button device will be enabled so you can
change the screen brightness.
-config MAC_FLOPPY
- bool "Support for PowerMac floppy"
- depends on PPC_PMAC && !PPC_PMAC64
- help
- If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
- floppy controller, say Y here. Most commonly found in PowerMacs.
-
config MAC_SERIAL
tristate "Support for PowerMac serial ports (OBSOLETE DRIVER)"
depends on PPC_PMAC && BROKEN
@@ -191,7 +184,7 @@ config THERM_PM72
G5 machines.
config ANSLCD
- bool "Support for ANS LCD display"
+ tristate "Support for ANS LCD display"
depends on ADB_CUDA && PPC_PMAC
endmenu
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index c4b82b5a88dc56..0e130f598a7909 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -136,7 +136,7 @@ const char anslcd_logo[] = "********************" /* Line #1 */
"* Welcome to *" /* Line #2 */
"********************"; /* Line #4 */
-int __init
+static int __init
anslcd_init(void)
{
int a;
@@ -173,5 +173,12 @@ anslcd_init(void)
return 0;
}
-__initcall(anslcd_init);
+static void __exit
+anslcd_exit(void)
+{
+ misc_deregister(&anslcd_dev);
+ iounmap(anslcd_ptr);
+}
+module_init(anslcd_init);
+module_exit(anslcd_exit);
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 67af530004aac7..aa0719775e477f 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -435,6 +435,7 @@ int __pmac check_media_bay(struct device_node *which_bay, int what)
#endif /* CONFIG_BLK_DEV_IDE */
return -ENODEV;
}
+EXPORT_SYMBOL(check_media_bay);
int __pmac check_media_bay_by_base(unsigned long base, int what)
{
diff --git a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c
index 64d95f2f88c95b..cf165f2d576704 100644
--- a/drivers/media/dvb/frontends/alps_tdlb7.c
+++ b/drivers/media/dvb/frontends/alps_tdlb7.c
@@ -28,8 +28,6 @@
*/
-
-#define __KERNEL_SYSCALLS__
#include <linux/module.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
@@ -151,13 +149,13 @@ static int sp8870_read_firmware_file (const char *fn, char **fp)
loff_t filesize;
char *dp;
- fd = open(fn, 0, 0);
+ fd = sys_open(fn, 0, 0);
if (fd == -1) {
printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
return -EIO;
}
- filesize = lseek(fd, 0L, 2);
+ filesize = sys_lseek(fd, 0L, 2);
if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
sys_close(fd);
@@ -171,8 +169,8 @@ static int sp8870_read_firmware_file (const char *fn, char **fp)
return -EIO;
}
- lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
- if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
+ sys_lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
+ if (sys_read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
vfree(dp);
sys_close(fd);
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 3b3a73bb00d737..53ebf4a69b07e2 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -12,7 +12,6 @@
next 0x4000 loaded. This may change in future versions.
*/
-#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
@@ -211,13 +210,13 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
// Load the firmware
set_fs(get_ds());
- fd = open(sp887x_firmware, 0, 0);
+ fd = sys_open(sp887x_firmware, 0, 0);
if (fd < 0) {
printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__,
sp887x_firmware);
return -EIO;
}
- filesize = lseek(fd, 0L, 2);
+ filesize = sys_lseek(fd, 0L, 2);
if (filesize <= 0) {
printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__,
sp887x_firmware);
@@ -239,8 +238,8 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
// read it!
// read the first 16384 bytes from the file
// ignore the first 10 bytes
- lseek(fd, 10, 0);
- if (read(fd, firmware, fw_size) != fw_size) {
+ sys_lseek(fd, 10, 0);
+ if (sys_read(fd, firmware, fw_size) != fw_size) {
printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__);
vfree(firmware);
sys_close(fd);
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 76a6027dbdb61a..28dc299a8cd5ad 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -32,7 +32,6 @@
*/
-#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
@@ -40,7 +39,6 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/fs.h>
-#include <linux/unistd.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/syscalls.h>
@@ -399,13 +397,13 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
// Load the firmware
set_fs(get_ds());
- fd = open(tda1004x_firmware, 0, 0);
+ fd = sys_open(tda1004x_firmware, 0, 0);
if (fd < 0) {
printk("%s: Unable to open firmware %s\n", __FUNCTION__,
tda1004x_firmware);
return -EIO;
}
- filesize = lseek(fd, 0L, 2);
+ filesize = sys_lseek(fd, 0L, 2);
if (filesize <= 0) {
printk("%s: Firmware %s is empty\n", __FUNCTION__,
tda1004x_firmware);
@@ -436,8 +434,8 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
}
// read it!
- lseek(fd, fw_offset, 0);
- if (read(fd, firmware, fw_size) != fw_size) {
+ sys_lseek(fd, fw_offset, 0);
+ if (sys_read(fd, firmware, fw_size) != fw_size) {
printk("%s: Failed to read firmware\n", __FUNCTION__);
vfree(firmware);
sys_close(fd);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6e57c143423081..6917b665b65a48 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4214,13 +4214,6 @@ out:
return 0;
}
-#ifdef CONFIG_NET_FASTROUTE
-static int bond_accept_fastpath(struct net_device *bond_dev, struct dst_entry *dst)
-{
- return -1;
-}
-#endif
-
/*------------------------- Device initialization ---------------------------*/
/*
@@ -4294,9 +4287,6 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
bond_set_mode_ops(bond_dev, bond->params.mode);
bond_dev->destructor = free_netdev;
-#ifdef CONFIG_NET_FASTROUTE
- bond_dev->accept_fastpath = bond_accept_fastpath;
-#endif
/* Initialize the device options */
bond_dev->tx_queue_len = 0;
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index fc0a851a93f977..7e15c51afd435d 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -57,13 +57,6 @@ static void set_multicast_list(struct net_device *dev)
{
}
-#ifdef CONFIG_NET_FASTROUTE
-static int dummy_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-{
- return -1;
-}
-#endif
-
static void __init dummy_setup(struct net_device *dev)
{
/* Initialize the device structure. */
@@ -71,9 +64,6 @@ static void __init dummy_setup(struct net_device *dev)
dev->hard_start_xmit = dummy_xmit;
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = dummy_set_address;
-#ifdef CONFIG_NET_FASTROUTE
- dev->accept_fastpath = dummy_accept_fastpath;
-#endif
/* Fill in device structure with ethernet-generic values. */
ether_setup(dev);
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index f7fc3b9c0a5ce3..2049556d1764f4 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -7,7 +7,7 @@
* ------------------
*
* You can find a subset of the documentation in
- * linux/Documentation/networking/z8530drv.txt.
+ * Documentation/networking/z8530drv.txt.
*/
/*
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index f79e9ab1c5325d..64b35cc250c982 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -79,6 +79,8 @@
#define PPPOE_HASH_BITS 4
#define PPPOE_HASH_SIZE (1<<PPPOE_HASH_BITS)
+static struct ppp_channel_ops pppoe_chan_ops;
+
static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index e5b49ebf6a3e03..0e46154729d4b2 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3635,9 +3635,25 @@ static int tg3_chip_reset(struct tg3 *tp)
/* restore 5701 hardware bug workaround flag */
tp->tg3_flags = flags_save;
+ /* Unfortunately, we have to delay before the PCI read back.
+ * Some 575X chips even will not respond to a PCI cfg access
+ * when the reset command is given to the chip.
+ *
+ * How do these hardware designers expect things to work
+ * properly if the PCI write is posted for a long period
+ * of time? It is always necessary to have some method by
+ * which a register read back can occur to push the write
+ * out which does the reset.
+ *
+ * For most tg3 variants the trick below was working.
+ * Ho hum...
+ */
+ udelay(120);
+
/* Flush PCI posted writes. The normal MMIO registers
* are inaccessible at this time so this is the only
- * way to make this reliably. I tried to use indirect
+ * way to make this reliably (actually, this is no longer
+ * the case, see above). I tried to use indirect
* register read/write but this upset some 5701 variants.
*/
pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 44d21edef3c489..6454331093e67b 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -212,7 +212,7 @@ MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
/* Define this to enable Link beat monitoring */
#undef MONITOR
-/* Turn on debugging. See linux/Documentation/networking/tlan.txt for details */
+/* Turn on debugging. See Documentation/networking/tlan.txt for details */
static int debug;
static int bbuf;
diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h
index eacf37fdd26b3f..a48af699c9c563 100644
--- a/drivers/net/wireless/arlan.h
+++ b/drivers/net/wireless/arlan.h
@@ -52,7 +52,6 @@ extern int arlan_debug;
extern int arlan_entry_debug;
extern int arlan_exit_debug;
extern int testMemory;
-extern const char* arlan_version;
extern int arlan_command(struct net_device * dev, int command);
#define SIDUNKNOWN -1
diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
index dd50660379043a..3ee31021f1b054 100644
--- a/drivers/net/wireless/prism54/isl_38xx.c
+++ b/drivers/net/wireless/prism54/isl_38xx.c
@@ -18,8 +18,6 @@
*
*/
-#define __KERNEL_SYSCALLS__
-
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 03681b915a5653..929012e60815a5 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -1,22 +1,15 @@
#
# PCI configuration
#
-config PCI_USE_VECTOR
- bool "Vector-based interrupt indexing (MSI)"
+config PCI_MSI
+ bool "Message Signaled Interrupts (MSI and MSI-X)"
depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
default n
help
- This replaces the current existing IRQ-based index interrupt scheme
- with the vector-base index scheme. The advantages of vector base
- over IRQ base are listed below:
- 1) Support MSI implementation.
- 2) Support future IOxAPIC hotplug
-
- Note that this allows the device drivers to enable MSI, Message
- Signaled Interrupt, on all MSI capable device functions detected.
- Message Signal Interrupt enables an MSI-capable hardware device to
- send an inbound Memory Write on its PCI bus instead of asserting
- IRQ signal on device IRQ pin.
+ This allows device drivers to enable MSI (Message Signaled
+ Interrupts). Message Signaled Interrupts enable a device to
+ generate an interrupt using an inbound Memory Write on its
+ PCI bus instead of asserting a device IRQ pin.
If you don't know what to do here, say N.
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 260b12b34779ee..377c7238c4cc30 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -26,7 +26,7 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_USE_VECTOR) += msi.o
+obj-$(CONFIG_PCI_MSI) += msi.o
# Cardbus & CompactPCI use setup-bus
obj-$(CONFIG_HOTPLUG) += setup-bus.o
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 35c73b9769e07f..d4c89d73e16dda 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -64,15 +64,13 @@ static void msi_set_mask_bit(unsigned int vector, int flag)
case PCI_CAP_ID_MSI:
{
int pos;
- unsigned int mask_bits;
+ u32 mask_bits;
pos = entry->mask_base;
- entry->dev->bus->ops->read(entry->dev->bus, entry->dev->devfn,
- pos, 4, &mask_bits);
+ pci_read_config_dword(entry->dev, pos, &mask_bits);
mask_bits &= ~(1);
mask_bits |= flag;
- entry->dev->bus->ops->write(entry->dev->bus, entry->dev->devfn,
- pos, 4, mask_bits);
+ pci_write_config_dword(entry->dev, pos, mask_bits);
break;
}
case PCI_CAP_ID_MSIX:
@@ -105,15 +103,13 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
return;
- entry->dev->bus->ops->read(entry->dev->bus, entry->dev->devfn,
- msi_lower_address_reg(pos), 4,
+ pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
&address.lo_address.value);
address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) <<
MSI_TARGET_CPU_SHIFT);
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
- entry->dev->bus->ops->write(entry->dev->bus, entry->dev->devfn,
- msi_lower_address_reg(pos), 4,
+ pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
address.lo_address.value);
break;
}
@@ -158,13 +154,25 @@ static void unmask_MSI_irq(unsigned int vector)
static unsigned int startup_msi_irq_wo_maskbit(unsigned int vector)
{
+ struct msi_desc *entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msi_lock, flags);
+ entry = msi_desc[vector];
+ if (!entry || !entry->dev) {
+ spin_unlock_irqrestore(&msi_lock, flags);
+ return 0;
+ }
+ entry->msi_attrib.state = 1; /* Mark it active */
+ spin_unlock_irqrestore(&msi_lock, flags);
+
return 0; /* never anything pending */
}
-static void pci_disable_msi(unsigned int vector);
+static void release_msi(unsigned int vector);
static void shutdown_msi_irq(unsigned int vector)
{
- pci_disable_msi(vector);
+ release_msi(vector);
}
#define shutdown_msi_irq_wo_maskbit shutdown_msi_irq
@@ -179,6 +187,18 @@ static void end_msi_irq_wo_maskbit(unsigned int vector)
static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
{
+ struct msi_desc *entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msi_lock, flags);
+ entry = msi_desc[vector];
+ if (!entry || !entry->dev) {
+ spin_unlock_irqrestore(&msi_lock, flags);
+ return 0;
+ }
+ entry->msi_attrib.state = 1; /* Mark it active */
+ spin_unlock_irqrestore(&msi_lock, flags);
+
unmask_MSI_irq(vector);
return 0; /* never anything pending */
}
@@ -200,7 +220,7 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
* which implement the MSI-X Capability Structure.
*/
static struct hw_interrupt_type msix_irq_type = {
- .typename = "PCI MSI-X",
+ .typename = "PCI-MSI-X",
.startup = startup_msi_irq_w_maskbit,
.shutdown = shutdown_msi_irq_w_maskbit,
.enable = enable_msi_irq_w_maskbit,
@@ -216,7 +236,7 @@ static struct hw_interrupt_type msix_irq_type = {
* Mask-and-Pending Bits.
*/
static struct hw_interrupt_type msi_irq_w_maskbit_type = {
- .typename = "PCI MSI",
+ .typename = "PCI-MSI",
.startup = startup_msi_irq_w_maskbit,
.shutdown = shutdown_msi_irq_w_maskbit,
.enable = enable_msi_irq_w_maskbit,
@@ -232,7 +252,7 @@ static struct hw_interrupt_type msi_irq_w_maskbit_type = {
* Mask-and-Pending Bits.
*/
static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
- .typename = "PCI MSI",
+ .typename = "PCI-MSI",
.startup = startup_msi_irq_wo_maskbit,
.shutdown = shutdown_msi_irq_wo_maskbit,
.enable = enable_msi_irq_wo_maskbit,
@@ -265,6 +285,7 @@ static void msi_address_init(struct msg_address *msi_address)
msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT);
}
+static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
static int assign_msi_vector(void)
{
static int new_vector_avail = 1;
@@ -278,6 +299,8 @@ static int assign_msi_vector(void)
spin_lock_irqsave(&msi_lock, flags);
if (!new_vector_avail) {
+ int free_vector = 0;
+
/*
* vector_irq[] = -1 indicates that this specific vector is:
* - assigned for MSI (since MSI have no associated IRQ) or
@@ -294,13 +317,34 @@ static int assign_msi_vector(void)
for (vector = FIRST_DEVICE_VECTOR; vector < NR_IRQS; vector++) {
if (vector_irq[vector] != 0)
continue;
- vector_irq[vector] = -1;
- nr_released_vectors--;
+ free_vector = vector;
+ if (!msi_desc[vector])
+ break;
+ else
+ continue;
+ }
+ if (!free_vector) {
spin_unlock_irqrestore(&msi_lock, flags);
- return vector;
+ return -EBUSY;
}
+ vector_irq[free_vector] = -1;
+ nr_released_vectors--;
spin_unlock_irqrestore(&msi_lock, flags);
- return -EBUSY;
+ if (msi_desc[free_vector] != NULL) {
+ struct pci_dev *dev;
+ int tail;
+
+ /* free all linked vectors before re-assign */
+ do {
+ spin_lock_irqsave(&msi_lock, flags);
+ dev = msi_desc[free_vector]->dev;
+ tail = msi_desc[free_vector]->link.tail;
+ spin_unlock_irqrestore(&msi_lock, flags);
+ msi_free_vector(dev, tail, 1);
+ } while (free_vector != tail);
+ }
+
+ return free_vector;
}
vector = assign_irq_vector(AUTO_ASSIGN);
last_alloc_vector = vector;
@@ -333,6 +377,15 @@ static int msi_init(void)
printk(KERN_INFO "WARNING: MSI INIT FAILURE\n");
return status;
}
+ last_alloc_vector = assign_irq_vector(AUTO_ASSIGN);
+ if (last_alloc_vector < 0) {
+ pci_msi_enable = 0;
+ printk(KERN_INFO "WARNING: ALL VECTORS ARE BUSY\n");
+ status = -EBUSY;
+ return status;
+ }
+ vector_irq[last_alloc_vector] = 0;
+ nr_released_vectors++;
printk(KERN_INFO "MSI INIT SUCCESS\n");
return status;
@@ -383,55 +436,49 @@ static void irq_handler_init(int cap_id, int pos, int mask)
static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
{
- u32 control;
+ u16 control;
- dev->bus->ops->read(dev->bus, dev->devfn,
- msi_control_reg(pos), 2, &control);
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
if (type == PCI_CAP_ID_MSI) {
/* Set enabled bits to single MSI & enable MSI_enable bit */
msi_enable(control, 1);
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_control_reg(pos), 2, control);
+ pci_write_config_word(dev, msi_control_reg(pos), control);
} else {
msix_enable(control);
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_control_reg(pos), 2, control);
+ pci_write_config_word(dev, msi_control_reg(pos), control);
}
if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
/* PCI Express Endpoint device detected */
- u32 cmd;
- dev->bus->ops->read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
+ u16 cmd;
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_INTX_DISABLE;
- dev->bus->ops->write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
{
- u32 control;
+ u16 control;
- dev->bus->ops->read(dev->bus, dev->devfn,
- msi_control_reg(pos), 2, &control);
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
if (type == PCI_CAP_ID_MSI) {
/* Set enabled bits to single MSI & enable MSI_enable bit */
msi_disable(control);
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_control_reg(pos), 2, control);
+ pci_write_config_word(dev, msi_control_reg(pos), control);
} else {
msix_disable(control);
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_control_reg(pos), 2, control);
+ pci_write_config_word(dev, msi_control_reg(pos), control);
}
if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
/* PCI Express Endpoint device detected */
- u32 cmd;
- dev->bus->ops->read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
+ u16 cmd;
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd &= ~PCI_COMMAND_INTX_DISABLE;
- dev->bus->ops->write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
-static int msi_lookup_vector(struct pci_dev *dev)
+static int msi_lookup_vector(struct pci_dev *dev, int type)
{
int vector;
unsigned long flags;
@@ -439,11 +486,11 @@ static int msi_lookup_vector(struct pci_dev *dev)
spin_lock_irqsave(&msi_lock, flags);
for (vector = FIRST_DEVICE_VECTOR; vector < NR_IRQS; vector++) {
if (!msi_desc[vector] || msi_desc[vector]->dev != dev ||
- msi_desc[vector]->msi_attrib.entry_nr ||
+ msi_desc[vector]->msi_attrib.type != type ||
msi_desc[vector]->msi_attrib.default_vector != dev->irq)
- continue; /* not entry 0, skip */
+ continue;
spin_unlock_irqrestore(&msi_lock, flags);
- /* This pre-assigned entry-0 MSI vector for this device
+ /* This pre-assigned MSI vector for this device
already exits. Override dev->irq with this vector */
dev->irq = vector;
return 0;
@@ -458,10 +505,9 @@ void pci_scan_msi_device(struct pci_dev *dev)
if (!dev)
return;
- if (pci_find_capability(dev, PCI_CAP_ID_MSIX) > 0) {
- nr_reserved_vectors++;
+ if (pci_find_capability(dev, PCI_CAP_ID_MSIX) > 0)
nr_msix_devices++;
- } else if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0)
+ else if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0)
nr_reserved_vectors++;
}
@@ -480,22 +526,10 @@ static int msi_capability_init(struct pci_dev *dev)
struct msg_address address;
struct msg_data data;
int pos, vector;
- u32 control;
+ u16 control;
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (!pos)
- return -EINVAL;
-
- dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos),
- 2, &control);
- if (control & PCI_MSI_FLAGS_ENABLE)
- return 0;
-
- if (!msi_lookup_vector(dev)) {
- /* Lookup Sucess */
- enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
- return 0;
- }
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
/* MSI Entry Initialization */
if (!(entry = alloc_msi_entry()))
return -ENOMEM;
@@ -504,11 +538,14 @@ static int msi_capability_init(struct pci_dev *dev)
kmem_cache_free(msi_cachep, entry);
return -EBUSY;
}
+ entry->link.head = vector;
+ entry->link.tail = vector;
entry->msi_attrib.type = PCI_CAP_ID_MSI;
+ entry->msi_attrib.state = 0; /* Mark it not active */
entry->msi_attrib.entry_nr = 0;
entry->msi_attrib.maskbit = is_mask_bit_support(control);
- entry->msi_attrib.default_vector = dev->irq;
- dev->irq = vector; /* save default pre-assigned ioapic vector */
+ entry->msi_attrib.default_vector = dev->irq; /* Save IOAPIC IRQ */
+ dev->irq = vector;
entry->dev = dev;
if (is_mask_bit_support(control)) {
entry->mask_base = msi_mask_bits_reg(pos,
@@ -521,27 +558,27 @@ static int msi_capability_init(struct pci_dev *dev)
msi_data_init(&data, vector);
entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- dev->bus->ops->write(dev->bus, dev->devfn, msi_lower_address_reg(pos),
- 4, address.lo_address.value);
+ pci_write_config_dword(dev, msi_lower_address_reg(pos),
+ address.lo_address.value);
if (is_64bit_address(control)) {
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_upper_address_reg(pos), 4, address.hi_address);
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_data_reg(pos, 1), 2, *((u32*)&data));
+ pci_write_config_dword(dev,
+ msi_upper_address_reg(pos), address.hi_address);
+ pci_write_config_word(dev,
+ msi_data_reg(pos, 1), *((u32*)&data));
} else
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_data_reg(pos, 0), 2, *((u32*)&data));
+ pci_write_config_word(dev,
+ msi_data_reg(pos, 0), *((u32*)&data));
if (entry->msi_attrib.maskbit) {
unsigned int maskbits, temp;
/* All MSIs are unmasked by default, Mask them all */
- dev->bus->ops->read(dev->bus, dev->devfn,
- msi_mask_bits_reg(pos, is_64bit_address(control)), 4,
+ pci_read_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
&maskbits);
temp = (1 << multi_msi_capable(control));
temp = ((temp - 1) & ~temp);
maskbits |= temp;
- dev->bus->ops->write(dev->bus, dev->devfn,
- msi_mask_bits_reg(pos, is_64bit_address(control)), 4,
+ pci_write_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
maskbits);
}
attach_msi_entry(entry, vector);
@@ -556,238 +593,219 @@ static int msi_capability_init(struct pci_dev *dev)
* @dev: pointer to the pci_dev data structure of MSI-X device function
*
* Setup the MSI-X capability structure of device funtion with a
- * single MSI-X vector. A return of zero indicates the successful setup
- * of an entry zero with the new MSI-X vector or non-zero for otherwise.
- * To request for additional MSI-X vectors, the device drivers are
- * required to utilize the following supported APIs:
- * 1) msi_alloc_vectors(...) for requesting one or more MSI-X vectors
- * 2) msi_free_vectors(...) for releasing one or more MSI-X vectors
- * back to PCI subsystem before calling free_irq(...)
+ * single MSI-X vector. A return of zero indicates the successful setup of
+ * requested MSI-X entries with allocated vectors or non-zero for otherwise.
**/
-static int msix_capability_init(struct pci_dev *dev)
+static int msix_capability_init(struct pci_dev *dev,
+ struct msix_entry *entries, int nvec)
{
- struct msi_desc *entry;
+ struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
struct msg_address address;
struct msg_data data;
- int vector = 0, pos, dev_msi_cap, i;
+ int vector, pos, i, j, nr_entries, temp = 0;
u32 phys_addr, table_offset;
- u32 control;
+ u16 control;
u8 bir;
void *base;
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- if (!pos)
- return -EINVAL;
-
/* Request & Map MSI-X table region */
- dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2,
- &control);
- if (control & PCI_MSIX_FLAGS_ENABLE)
- return 0;
-
- if (!msi_lookup_vector(dev)) {
- /* Lookup Sucess */
- enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
- return 0;
- }
-
- dev_msi_cap = multi_msix_capable(control);
- dev->bus->ops->read(dev->bus, dev->devfn,
- msix_table_offset_reg(pos), 4, &table_offset);
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ nr_entries = multi_msix_capable(control);
+ pci_read_config_dword(dev, msix_table_offset_reg(pos),
+ &table_offset);
bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
phys_addr = pci_resource_start (dev, bir);
phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
if (!request_mem_region(phys_addr,
- dev_msi_cap * PCI_MSIX_ENTRY_SIZE,
- "MSI-X iomap Failure"))
+ nr_entries * PCI_MSIX_ENTRY_SIZE,
+ "MSI-X vector table"))
return -ENOMEM;
- base = ioremap_nocache(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
- if (base == NULL)
- goto free_region;
- /* MSI Entry Initialization */
- entry = alloc_msi_entry();
- if (!entry)
- goto free_iomap;
- if ((vector = get_msi_vector(dev)) < 0)
- goto free_entry;
+ base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
+ if (base == NULL) {
+ release_mem_region(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
+ return -ENOMEM;
+ }
+ /* MSI-X Table Initialization */
+ for (i = 0; i < nvec; i++) {
+ entry = alloc_msi_entry();
+ if (!entry)
+ break;
+ if ((vector = get_msi_vector(dev)) < 0)
+ break;
- entry->msi_attrib.type = PCI_CAP_ID_MSIX;
- entry->msi_attrib.entry_nr = 0;
- entry->msi_attrib.maskbit = 1;
- entry->msi_attrib.default_vector = dev->irq;
- dev->irq = vector; /* save default pre-assigned ioapic vector */
- entry->dev = dev;
- entry->mask_base = (unsigned long)base;
- /* Replace with MSI handler */
- irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
- /* Configure MSI-X capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- writel(address.lo_address.value, base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
- writel(address.hi_address, base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
- writel(*(u32*)&data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
- /* Initialize all entries from 1 up to 0 */
- for (i = 1; i < dev_msi_cap; i++) {
- writel(0, base + i * PCI_MSIX_ENTRY_SIZE +
+ j = entries[i].entry;
+ entries[i].vector = vector;
+ entry->msi_attrib.type = PCI_CAP_ID_MSIX;
+ entry->msi_attrib.state = 0; /* Mark it not active */
+ entry->msi_attrib.entry_nr = j;
+ entry->msi_attrib.maskbit = 1;
+ entry->msi_attrib.default_vector = dev->irq;
+ entry->dev = dev;
+ entry->mask_base = (unsigned long)base;
+ if (!head) {
+ entry->link.head = vector;
+ entry->link.tail = vector;
+ head = entry;
+ } else {
+ entry->link.head = temp;
+ entry->link.tail = tail->link.tail;
+ tail->link.tail = vector;
+ head->link.head = vector;
+ }
+ temp = vector;
+ tail = entry;
+ /* Replace with MSI-X handler */
+ irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
+ /* Configure MSI-X capability structure */
+ msi_address_init(&address);
+ msi_data_init(&data, vector);
+ entry->msi_attrib.current_cpu =
+ ((address.lo_address.u.dest_id >>
+ MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+ writel(address.lo_address.value,
+ base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
- writel(0, base + i * PCI_MSIX_ENTRY_SIZE +
+ writel(address.hi_address,
+ base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
- writel(0, base + i * PCI_MSIX_ENTRY_SIZE +
+ writel(*(u32*)&data,
+ base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_DATA_OFFSET);
+ attach_msi_entry(entry, vector);
}
- attach_msi_entry(entry, vector);
- /* Set MSI enabled bits */
+ if (i != nvec) {
+ i--;
+ for (; i >= 0; i--) {
+ vector = (entries + i)->vector;
+ msi_free_vector(dev, vector, 0);
+ (entries + i)->vector = 0;
+ }
+ return -EBUSY;
+ }
+ /* Set MSI-X enabled bits */
enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
return 0;
-
-free_entry:
- kmem_cache_free(msi_cachep, entry);
-free_iomap:
- iounmap(base);
-free_region:
- release_mem_region(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
-
- return ((vector < 0) ? -EBUSY : -ENOMEM);
}
/**
- * pci_enable_msi - configure device's MSI(X) capability structure
- * @dev: pointer to the pci_dev data structure of MSI(X) device function
+ * pci_enable_msi - configure device's MSI capability structure
+ * @dev: pointer to the pci_dev data structure of MSI device function
*
- * Setup the MSI/MSI-X capability structure of device function with
- * a single MSI(X) vector upon its software driver call to request for
- * MSI(X) mode enabled on its hardware device function. A return of zero
- * indicates the successful setup of an entry zero with the new MSI(X)
+ * Setup the MSI capability structure of device function with
+ * a single MSI vector upon its software driver call to request for
+ * MSI mode enabled on its hardware device function. A return of zero
+ * indicates the successful setup of an entry zero with the new MSI
* vector or non-zero for otherwise.
**/
int pci_enable_msi(struct pci_dev* dev)
{
- int status = -EINVAL;
+ int pos, temp = dev->irq, status = -EINVAL;
+ u16 control;
if (!pci_msi_enable || !dev)
return status;
- if (msi_init() < 0)
- return -ENOMEM;
+ if ((status = msi_init()) < 0)
+ return status;
- if ((status = msix_capability_init(dev)) == -EINVAL)
- status = msi_capability_init(dev);
- if (!status)
- nr_reserved_vectors--;
+ if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
+ return -EINVAL;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (control & PCI_MSI_FLAGS_ENABLE)
+ return 0; /* Already in MSI mode */
+
+ if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
+ /* Lookup Sucess */
+ unsigned long flags;
+
+ spin_lock_irqsave(&msi_lock, flags);
+ if (!vector_irq[dev->irq]) {
+ msi_desc[dev->irq]->msi_attrib.state = 0;
+ vector_irq[dev->irq] = -1;
+ nr_released_vectors--;
+ spin_unlock_irqrestore(&msi_lock, flags);
+ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+ return 0;
+ }
+ spin_unlock_irqrestore(&msi_lock, flags);
+ dev->irq = temp;
+ }
+ /* Check whether driver already requested for MSI-X vectors */
+ if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
+ !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+ printk(KERN_INFO "Can't enable MSI. Device already had MSI-X vectors assigned\n");
+ dev->irq = temp;
+ return -EINVAL;
+ }
+ status = msi_capability_init(dev);
+ if (!status) {
+ if (!pos)
+ nr_reserved_vectors--; /* Only MSI capable */
+ else if (nr_msix_devices > 0)
+ nr_msix_devices--; /* Both MSI and MSI-X capable,
+ but choose enabling MSI */
+ }
return status;
}
-static int msi_free_vector(struct pci_dev* dev, int vector);
-static void pci_disable_msi(unsigned int vector)
+void pci_disable_msi(struct pci_dev* dev)
{
- int head, tail, type, default_vector;
struct msi_desc *entry;
- struct pci_dev *dev;
+ int pos, default_vector;
+ u16 control;
unsigned long flags;
+ if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI)))
+ return;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (!(control & PCI_MSI_FLAGS_ENABLE))
+ return;
+
spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[vector];
- if (!entry || !entry->dev) {
+ entry = msi_desc[dev->irq];
+ if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
spin_unlock_irqrestore(&msi_lock, flags);
return;
}
- dev = entry->dev;
- type = entry->msi_attrib.type;
- head = entry->link.head;
- tail = entry->link.tail;
- default_vector = entry->msi_attrib.default_vector;
- spin_unlock_irqrestore(&msi_lock, flags);
-
- disable_msi_mode(dev, pci_find_capability(dev, type), type);
- /* Restore dev->irq to its default pin-assertion vector */
- dev->irq = default_vector;
- if (type == PCI_CAP_ID_MSIX && head != tail) {
- /* Bad driver, which do not call msi_free_vectors before exit.
- We must do a cleanup here */
- while (1) {
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[vector];
- head = entry->link.head;
- tail = entry->link.tail;
- spin_unlock_irqrestore(&msi_lock, flags);
- if (tail == head)
- break;
- if (msi_free_vector(dev, entry->link.tail))
- break;
- }
+ if (entry->msi_attrib.state) {
+ spin_unlock_irqrestore(&msi_lock, flags);
+ printk(KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on vector->%d\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+ dev->irq);
+ BUG_ON(entry->msi_attrib.state > 0);
+ } else {
+ vector_irq[dev->irq] = 0; /* free it */
+ nr_released_vectors++;
+ default_vector = entry->msi_attrib.default_vector;
+ spin_unlock_irqrestore(&msi_lock, flags);
+ /* Restore dev->irq to its default pin-assertion vector */
+ dev->irq = default_vector;
+ disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
+ PCI_CAP_ID_MSI);
}
}
-static int msi_alloc_vector(struct pci_dev* dev, int head)
+static void release_msi(unsigned int vector)
{
struct msi_desc *entry;
- struct msg_address address;
- struct msg_data data;
- int i, offset, pos, dev_msi_cap, vector;
- u32 low_address, control;
- unsigned long base = 0L;
unsigned long flags;
spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[dev->irq];
- if (!entry) {
- spin_unlock_irqrestore(&msi_lock, flags);
- return -EINVAL;
- }
- base = entry->mask_base;
+ entry = msi_desc[vector];
+ if (entry && entry->dev)
+ entry->msi_attrib.state = 0; /* Mark it not active */
spin_unlock_irqrestore(&msi_lock, flags);
-
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos),
- 2, &control);
- dev_msi_cap = multi_msix_capable(control);
- for (i = 1; i < dev_msi_cap; i++) {
- if (!(low_address = readl(base + i * PCI_MSIX_ENTRY_SIZE)))
- break;
- }
- if (i >= dev_msi_cap)
- return -EINVAL;
-
- /* MSI Entry Initialization */
- if (!(entry = alloc_msi_entry()))
- return -ENOMEM;
-
- if ((vector = get_new_vector()) < 0) {
- kmem_cache_free(msi_cachep, entry);
- return vector;
- }
- entry->msi_attrib.type = PCI_CAP_ID_MSIX;
- entry->msi_attrib.entry_nr = i;
- entry->msi_attrib.maskbit = 1;
- entry->dev = dev;
- entry->link.head = head;
- entry->mask_base = base;
- irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
- /* Configure MSI-X capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
- writel(address.lo_address.value, base + offset +
- PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
- writel(address.hi_address, base + offset +
- PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
- writel(*(u32*)&data, base + offset + PCI_MSIX_ENTRY_DATA_OFFSET);
- writel(1, base + offset + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
- attach_msi_entry(entry, vector);
-
- return vector;
}
-static int msi_free_vector(struct pci_dev* dev, int vector)
+static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
{
struct msi_desc *entry;
- int entry_nr, type;
+ int head, entry_nr, type;
unsigned long base = 0L;
unsigned long flags;
@@ -799,66 +817,177 @@ static int msi_free_vector(struct pci_dev* dev, int vector)
}
type = entry->msi_attrib.type;
entry_nr = entry->msi_attrib.entry_nr;
+ head = entry->link.head;
base = entry->mask_base;
- if (entry->link.tail != entry->link.head) {
- msi_desc[entry->link.head]->link.tail = entry->link.tail;
- if (entry->link.tail)
- msi_desc[entry->link.tail]->link.head = entry->link.head;
- }
+ msi_desc[entry->link.head]->link.tail = entry->link.tail;
+ msi_desc[entry->link.tail]->link.head = entry->link.head;
entry->dev = NULL;
- vector_irq[vector] = 0;
- nr_released_vectors++;
+ if (!reassign) {
+ vector_irq[vector] = 0;
+ nr_released_vectors++;
+ }
msi_desc[vector] = NULL;
spin_unlock_irqrestore(&msi_lock, flags);
kmem_cache_free(msi_cachep, entry);
+
if (type == PCI_CAP_ID_MSIX) {
- int offset;
+ if (!reassign)
+ writel(1, base +
+ entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+
+ if (head == vector) {
+ /*
+ * Detect last MSI-X vector to be released.
+ * Release the MSI-X memory-mapped table.
+ */
+ int pos, nr_entries;
+ u32 phys_addr, table_offset;
+ u16 control;
+ u8 bir;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ pci_read_config_word(dev, msi_control_reg(pos),
+ &control);
+ nr_entries = multi_msix_capable(control);
+ pci_read_config_dword(dev, msix_table_offset_reg(pos),
+ &table_offset);
+ bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+ phys_addr = pci_resource_start (dev, bir);
+ phys_addr += (u32)(table_offset &
+ ~PCI_MSIX_FLAGS_BIRMASK);
+ iounmap((void*)base);
+ release_mem_region(phys_addr,
+ nr_entries * PCI_MSIX_ENTRY_SIZE);
+ }
+ }
- offset = entry_nr * PCI_MSIX_ENTRY_SIZE;
- writel(1, base + offset + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
- writel(0, base + offset + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+ return 0;
+}
+
+static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
+{
+ int vector = head, tail = 0;
+ int i = 0, j = 0, nr_entries = 0;
+ unsigned long base = 0L;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msi_lock, flags);
+ while (head != tail) {
+ nr_entries++;
+ tail = msi_desc[vector]->link.tail;
+ if (entries[0].entry == msi_desc[vector]->msi_attrib.entry_nr)
+ j = vector;
+ vector = tail;
}
+ if (*nvec > nr_entries) {
+ spin_unlock_irqrestore(&msi_lock, flags);
+ *nvec = nr_entries;
+ return -EINVAL;
+ }
+ vector = ((j > 0) ? j : head);
+ for (i = 0; i < *nvec; i++) {
+ j = msi_desc[vector]->msi_attrib.entry_nr;
+ msi_desc[vector]->msi_attrib.state = 0; /* Mark it not active */
+ vector_irq[vector] = -1; /* Mark it busy */
+ nr_released_vectors--;
+ entries[i].vector = vector;
+ if (j != (entries + i)->entry) {
+ base = msi_desc[vector]->mask_base;
+ msi_desc[vector]->msi_attrib.entry_nr =
+ (entries + i)->entry;
+ writel( readl(base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET), base +
+ (entries + i)->entry * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+ writel( readl(base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET), base +
+ (entries + i)->entry * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+ writel( (readl(base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_DATA_OFFSET) & 0xff00) | vector,
+ base + (entries+i)->entry*PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_DATA_OFFSET);
+ }
+ vector = msi_desc[vector]->link.tail;
+ }
+ spin_unlock_irqrestore(&msi_lock, flags);
return 0;
}
/**
- * msi_alloc_vectors - allocate additional MSI-X vectors
+ * pci_enable_msix - configure device's MSI-X capability structure
* @dev: pointer to the pci_dev data structure of MSI-X device function
- * @vector: pointer to an array of new allocated MSI-X vectors
+ * @data: pointer to an array of MSI-X entries
* @nvec: number of MSI-X vectors requested for allocation by device driver
*
- * Allocate additional MSI-X vectors requested by device driver. A
- * return of zero indicates the successful setup of MSI-X capability
- * structure with new allocated MSI-X vectors or non-zero for otherwise.
+ * Setup the MSI-X capability structure of device function with the number
+ * of requested vectors upon its software driver call to request for
+ * MSI-X mode enabled on its hardware device function. A return of zero
+ * indicates the successful configuration of MSI-X capability structure
+ * with new allocated MSI-X vectors. A return of < 0 indicates a failure.
+ * Or a return of > 0 indicates that driver request is exceeding the number
+ * of vectors available. Driver should use the returned value to re-send
+ * its request.
**/
-int msi_alloc_vectors(struct pci_dev* dev, int *vector, int nvec)
+int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
{
- struct msi_desc *entry;
- int i, head, pos, vec, free_vectors, alloc_vectors;
- int *vectors = (int *)vector;
- u32 control;
+ int status, pos, nr_entries, free_vectors;
+ int i, j, temp;
+ u16 control;
unsigned long flags;
- if (!pci_msi_enable || !dev)
+ if (!pci_msi_enable || !dev || !entries)
return -EINVAL;
+ if ((status = msi_init()) < 0)
+ return status;
+
if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
return -EINVAL;
- dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2, &control);
- if (nvec > multi_msix_capable(control))
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (control & PCI_MSIX_FLAGS_ENABLE)
+ return -EINVAL; /* Already in MSI-X mode */
+
+ nr_entries = multi_msix_capable(control);
+ if (nvec > nr_entries)
return -EINVAL;
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[dev->irq];
- if (!entry || entry->dev != dev || /* legal call */
- entry->msi_attrib.type != PCI_CAP_ID_MSIX || /* must be MSI-X */
- entry->link.head != entry->link.tail) { /* already multi */
- spin_unlock_irqrestore(&msi_lock, flags);
+ /* Check for any invalid entries */
+ for (i = 0; i < nvec; i++) {
+ if (entries[i].entry >= nr_entries)
+ return -EINVAL; /* invalid entry */
+ for (j = i + 1; j < nvec; j++) {
+ if (entries[i].entry == entries[j].entry)
+ return -EINVAL; /* duplicate entry */
+ }
+ }
+ temp = dev->irq;
+ if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+ /* Lookup Sucess */
+ nr_entries = nvec;
+ /* Reroute MSI-X table */
+ if (reroute_msix_table(dev->irq, entries, &nr_entries)) {
+ /* #requested > #previous-assigned */
+ dev->irq = temp;
+ return nr_entries;
+ }
+ dev->irq = temp;
+ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+ return 0;
+ }
+ /* Check whether driver already requested for MSI vector */
+ if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 &&
+ !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
+ printk(KERN_INFO "Can't enable MSI-X. Device already had MSI vector assigned\n");
+ dev->irq = temp;
return -EINVAL;
}
+
+ spin_lock_irqsave(&msi_lock, flags);
/*
* msi_lock is provided to ensure that enough vectors resources are
* available before granting.
@@ -874,71 +1003,65 @@ int msi_alloc_vectors(struct pci_dev* dev, int *vector, int nvec)
free_vectors /= nr_msix_devices;
spin_unlock_irqrestore(&msi_lock, flags);
- if (nvec > free_vectors)
- return -EBUSY;
-
- alloc_vectors = 0;
- head = dev->irq;
- for (i = 0; i < nvec; i++) {
- if ((vec = msi_alloc_vector(dev, head)) < 0)
- break;
- *(vectors + i) = vec;
- head = vec;
- alloc_vectors++;
- }
- if (alloc_vectors != nvec) {
- for (i = 0; i < alloc_vectors; i++) {
- vec = *(vectors + i);
- msi_free_vector(dev, vec);
- }
- spin_lock_irqsave(&msi_lock, flags);
- msi_desc[dev->irq]->link.tail = msi_desc[dev->irq]->link.head;
- spin_unlock_irqrestore(&msi_lock, flags);
- return -EBUSY;
+ if (nvec > free_vectors) {
+ if (free_vectors > 0)
+ return free_vectors;
+ else
+ return -EBUSY;
}
- if (nr_msix_devices > 0)
+
+ status = msix_capability_init(dev, entries, nvec);
+ if (!status && nr_msix_devices > 0)
nr_msix_devices--;
- return 0;
+ return status;
}
-/**
- * msi_free_vectors - reclaim MSI-X vectors to unused state
- * @dev: pointer to the pci_dev data structure of MSI-X device function
- * @vector: pointer to an array of released MSI-X vectors
- * @nvec: number of MSI-X vectors requested for release by device driver
- *
- * Reclaim MSI-X vectors released by device driver to unused state,
- * which may be used later on. A return of zero indicates the
- * success or non-zero for otherwise. Device driver should call this
- * before calling function free_irq.
- **/
-int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec)
+void pci_disable_msix(struct pci_dev* dev)
{
- struct msi_desc *entry;
- int i;
- unsigned long flags;
+ int pos, temp;
+ u16 control;
- if (!pci_msi_enable)
- return -EINVAL;
+ if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
+ return;
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[dev->irq];
- if (!entry || entry->dev != dev ||
- entry->msi_attrib.type != PCI_CAP_ID_MSIX ||
- entry->link.head == entry->link.tail) { /* Nothing to free */
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (!(control & PCI_MSIX_FLAGS_ENABLE))
+ return;
+
+ temp = dev->irq;
+ if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+ int state, vector, head, tail = 0, warning = 0;
+ unsigned long flags;
+
+ vector = head = dev->irq;
+ spin_lock_irqsave(&msi_lock, flags);
+ while (head != tail) {
+ state = msi_desc[vector]->msi_attrib.state;
+ if (state)
+ warning = 1;
+ else {
+ vector_irq[vector] = 0; /* free it */
+ nr_released_vectors++;
+ }
+ tail = msi_desc[vector]->link.tail;
+ vector = tail;
+ }
spin_unlock_irqrestore(&msi_lock, flags);
- return -EINVAL;
- }
- spin_unlock_irqrestore(&msi_lock, flags);
+ if (warning) {
+ dev->irq = temp;
+ printk(KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on all vectors\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn));
+ BUG_ON(warning > 0);
+ } else {
+ dev->irq = temp;
+ disable_msi_mode(dev,
+ pci_find_capability(dev, PCI_CAP_ID_MSIX),
+ PCI_CAP_ID_MSIX);
- for (i = 0; i < nvec; i++) {
- if (*(vector + i) == dev->irq)
- continue;/* Don't free entry 0 if mistaken by driver */
- msi_free_vector(dev, *(vector + i));
+ }
}
-
- return 0;
}
/**
@@ -952,62 +1075,73 @@ int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec)
**/
void msi_remove_pci_irq_vectors(struct pci_dev* dev)
{
- struct msi_desc *entry;
- int type, temp;
+ int state, pos, temp;
unsigned long flags;
if (!pci_msi_enable || !dev)
return;
- if (!pci_find_capability(dev, PCI_CAP_ID_MSI)) {
- if (!pci_find_capability(dev, PCI_CAP_ID_MSIX))
- return;
- }
- temp = dev->irq;
- if (msi_lookup_vector(dev))
- return;
-
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[dev->irq];
- if (!entry || entry->dev != dev) {
+ temp = dev->irq; /* Save IOAPIC IRQ */
+ if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 &&
+ !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
+ spin_lock_irqsave(&msi_lock, flags);
+ state = msi_desc[dev->irq]->msi_attrib.state;
spin_unlock_irqrestore(&msi_lock, flags);
- return;
+ if (state) {
+ printk(KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on vector->%d\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), dev->irq);
+ BUG_ON(state > 0);
+ } else /* Release MSI vector assigned to this device */
+ msi_free_vector(dev, dev->irq, 0);
+ dev->irq = temp; /* Restore IOAPIC IRQ */
}
- type = entry->msi_attrib.type;
- spin_unlock_irqrestore(&msi_lock, flags);
+ if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 &&
+ !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+ int vector, head, tail = 0, warning = 0;
+ unsigned long base = 0L;
- msi_free_vector(dev, dev->irq);
- if (type == PCI_CAP_ID_MSIX) {
- int i, pos, dev_msi_cap;
- u32 phys_addr, table_offset;
- u32 control;
- u8 bir;
-
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2, &control);
- dev_msi_cap = multi_msix_capable(control);
- dev->bus->ops->read(dev->bus, dev->devfn,
- msix_table_offset_reg(pos), 4, &table_offset);
- bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
- phys_addr = pci_resource_start (dev, bir);
- phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
- for (i = FIRST_DEVICE_VECTOR; i < NR_IRQS; i++) {
+ vector = head = dev->irq;
+ while (head != tail) {
spin_lock_irqsave(&msi_lock, flags);
- if (!msi_desc[i] || msi_desc[i]->dev != dev) {
- spin_unlock_irqrestore(&msi_lock, flags);
- continue;
- }
+ state = msi_desc[vector]->msi_attrib.state;
+ tail = msi_desc[vector]->link.tail;
+ base = msi_desc[vector]->mask_base;
spin_unlock_irqrestore(&msi_lock, flags);
- msi_free_vector(dev, i);
+ if (state)
+ warning = 1;
+ else if (vector != head) /* Release MSI-X vector */
+ msi_free_vector(dev, vector, 0);
+ vector = tail;
+ }
+ msi_free_vector(dev, vector, 0);
+ if (warning) {
+ /* Force to release the MSI-X memory-mapped table */
+ u32 phys_addr, table_offset;
+ u16 control;
+ u8 bir;
+
+ pci_read_config_word(dev, msi_control_reg(pos),
+ &control);
+ pci_read_config_dword(dev, msix_table_offset_reg(pos),
+ &table_offset);
+ bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+ phys_addr = pci_resource_start (dev, bir);
+ phys_addr += (u32)(table_offset &
+ ~PCI_MSIX_FLAGS_BIRMASK);
+ iounmap((void*)base);
+ release_mem_region(phys_addr, PCI_MSIX_ENTRY_SIZE *
+ multi_msix_capable(control));
+ printk(KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on all vectors\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn));
+ BUG_ON(warning > 0);
}
- writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
- iounmap((void*)entry->mask_base);
- release_mem_region(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
+ dev->irq = temp; /* Restore IOAPIC IRQ */
}
- dev->irq = temp;
- nr_reserved_vectors++;
}
EXPORT_SYMBOL(pci_enable_msi);
-EXPORT_SYMBOL(msi_alloc_vectors);
-EXPORT_SYMBOL(msi_free_vectors);
+EXPORT_SYMBOL(pci_disable_msi);
+EXPORT_SYMBOL(pci_enable_msix);
+EXPORT_SYMBOL(pci_disable_msix);
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 524504fdd4f015..3a7a5285439306 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -140,7 +140,8 @@ struct msi_desc {
struct {
__u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
__u8 maskbit : 1; /* mask-pending bit supported ? */
- __u8 reserved: 2; /* reserved */
+ __u8 state : 1; /* {0: free, 1: busy} */
+ __u8 reserved: 1; /* reserved */
__u8 entry_nr; /* specific enabled entry */
__u8 default_vector; /* default pre-assigned vector */
__u8 current_cpu; /* current destination cpu */
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index ceeed4fb4f1126..0efa9c6e730adc 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -29,10 +29,6 @@
file under either the MPL or the GPL.
======================================================================*/
-/*
- * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
- * on the low-level kernel interface.
- */
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index d9d363a9e2e17d..d11f86948afe2f 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1386,7 +1386,7 @@ static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev
"aha152x: unable to verify geometry for disk with >1GB.\n"
" Using default translation. Please verify yourself.\n"
" Perhaps you need to enable extended translation in the driver.\n"
- " See /usr/src/linux/Documentation/scsi/aha152x.txt for details.\n");
+ " See Documentation/scsi/aha152x.txt for details.\n");
}
} else {
info_array[0] = info[0];
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 3b749ddd0c0949..6529f0c557724e 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -681,6 +681,7 @@ static int fdomain_get_irq( int base )
static int fdomain_isa_detect( int *irq, int *iobase )
{
+#ifndef PCMCIA
int i, j;
int base = 0xdeadbeef;
int flag = 0;
@@ -786,6 +787,9 @@ static int fdomain_isa_detect( int *irq, int *iobase )
*iobase = base;
return 1; /* success */
+#else
+ return 0;
+#endif
}
/* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index b7d208e60886eb..df52190f4d94e0 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -17,7 +17,7 @@ config PCMCIA_AHA152X
config PCMCIA_FDOMAIN
tristate "Future Domain PCMCIA support"
- depends on m && ISA
+ depends on m
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
adapter to your computer.
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 239d5c0e580f71..1b324b8002e941 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -1215,7 +1215,7 @@ static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, stru
pdev = pACB->pdev;
pci_read_config_word(pdev, PCI_STATUS, &pstat);
printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
- printk ("DC390: In case of driver trouble read linux/Documentation/scsi/tmscsim.txt\n");
+ printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
}
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 51a39a31417af8..529a2de54fec22 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -16,7 +16,7 @@
* Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt.
*
- * Please see the file: linux/Documentation/usb/ov511.txt
+ * Please see the file: Documentation/usb/ov511.txt
* and the website at: http://alpha.dyndns.org/ov511
* for more info.
*
diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
index 471873b0c1e324..51717375a8c0db 100644
--- a/drivers/usb/misc/tiglusb.c
+++ b/drivers/usb/misc/tiglusb.c
@@ -10,7 +10,7 @@
*
* Based on dabusb.c, printer.c & scanner.c
*
- * Please see the file: linux/Documentation/usb/SilverLink.txt
+ * Please see the file: Documentation/usb/silverlink.txt
* and the website at: http://lpg.ticalc.org/prj_usb/
* for more info.
*