summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/numa.c8
-rw-r--r--drivers/ata/Kconfig2
-rw-r--r--drivers/ata/ahci.c16
-rw-r--r--drivers/ata/ata_generic.c2
-rw-r--r--drivers/ata/ata_piix.c9
-rw-r--r--drivers/ata/libata-acpi.c10
-rw-r--r--drivers/ata/libata-core.c100
-rw-r--r--drivers/ata/libata-eh.c2
-rw-r--r--drivers/ata/libata-scsi.c45
-rw-r--r--drivers/ata/libata.h4
-rw-r--r--drivers/ata/pata_artop.c4
-rw-r--r--drivers/ata/pata_cmd640.c4
-rw-r--r--drivers/ata/pata_cmd64x.c2
-rw-r--r--drivers/ata/pata_cs5520.c2
-rw-r--r--drivers/ata/pata_cs5530.c2
-rw-r--r--drivers/ata/pata_cs5535.c2
-rw-r--r--drivers/ata/pata_cypress.c2
-rw-r--r--drivers/ata/pata_hpt366.c28
-rw-r--r--drivers/ata/pata_hpt37x.c10
-rw-r--r--drivers/ata/pata_hpt3x3.c2
-rw-r--r--drivers/ata/pata_isapnp.c2
-rw-r--r--drivers/ata/pata_it8213.c2
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c2
-rw-r--r--drivers/ata/pata_jmicron.c2
-rw-r--r--drivers/ata/pata_legacy.c2
-rw-r--r--drivers/ata/pata_platform.c2
-rw-r--r--drivers/ata/pata_qdi.c2
-rw-r--r--drivers/ata/pata_rz1000.c2
-rw-r--r--drivers/ata/pata_sc1200.c2
-rw-r--r--drivers/ata/pata_scc.c6
-rw-r--r--drivers/ata/pata_serverworks.c2
-rw-r--r--drivers/ata/pata_sl82c105.c2
-rw-r--r--drivers/ata/pata_winbond.c2
-rw-r--r--drivers/ata/pdc_adma.c2
-rw-r--r--drivers/ata/sata_inic162x.c2
-rw-r--r--drivers/ata/sata_mv.c2
-rw-r--r--drivers/ata/sata_nv.c24
-rw-r--r--drivers/ata/sata_qstor.c2
-rw-r--r--drivers/ata/sata_sil.c2
-rw-r--r--drivers/ata/sata_sil24.c5
-rw-r--r--drivers/ata/sata_sis.c2
-rw-r--r--drivers/ata/sata_svw.c2
-rw-r--r--drivers/ata/sata_sx4.c2
-rw-r--r--drivers/ata/sata_uli.c2
-rw-r--r--drivers/ata/sata_via.c4
-rw-r--r--drivers/ata/sata_vsc.c2
-rw-r--r--drivers/base/dmapool.c1
-rw-r--r--drivers/block/cciss.c45
-rw-r--r--drivers/char/agp/frontend.c1
-rw-r--r--drivers/char/agp/generic.c1
-rw-r--r--drivers/char/agp/via-agp.c6
-rw-r--r--drivers/char/hangcheck-timer.c2
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c134
-rw-r--r--drivers/char/watchdog/booke_wdt.c2
-rw-r--r--drivers/crypto/Kconfig4
-rw-r--r--drivers/firewire/fw-ohci.c1
-rw-r--r--drivers/ide/Kconfig15
-rw-r--r--drivers/ide/cris/ide-cris.c14
-rw-r--r--drivers/ide/ide-dma.c53
-rw-r--r--drivers/ide/ide-io.c1
-rw-r--r--drivers/ide/ide-lib.c12
-rw-r--r--drivers/ide/ide.c1
-rw-r--r--drivers/ide/pci/alim15x3.c69
-rw-r--r--drivers/ide/pci/cmd64x.c15
-rw-r--r--drivers/ide/pci/cs5530.c160
-rw-r--r--drivers/ide/pci/it821x.c21
-rw-r--r--drivers/ide/pci/pdc202xx_new.c29
-rw-r--r--drivers/ide/pci/pdc202xx_old.c184
-rw-r--r--drivers/ide/pci/sc1200.c161
-rw-r--r--drivers/ide/pci/scc_pata.c22
-rw-r--r--drivers/ide/pci/serverworks.c77
-rw-r--r--drivers/ide/pci/siimage.c24
-rw-r--r--drivers/ide/pci/sis5513.c85
-rw-r--r--drivers/ide/pci/sl82c105.c76
-rw-r--r--drivers/infiniband/core/cache.c1
-rw-r--r--drivers/infiniband/core/cm.c4
-rw-r--r--drivers/infiniband/core/cma.c106
-rw-r--r--drivers/infiniband/core/device.c136
-rw-r--r--drivers/infiniband/core/umem.c5
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c7
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c94
-rw-r--r--drivers/infiniband/hw/ehca/ehca_mrmw.c7
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c17
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c13
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6120.c7
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c7
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c12
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs_mcast.c16
-rw-r--r--drivers/infiniband/hw/mlx4/main.c1
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c181
-rw-r--r--drivers/infiniband/hw/mlx4/srq.c6
-rw-r--r--drivers/infiniband/hw/mlx4/user.h5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c160
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h49
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c214
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c87
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c40
-rw-r--r--drivers/input/joystick/Kconfig1
-rw-r--r--drivers/input/misc/Kconfig5
-rw-r--r--drivers/input/mouse/Kconfig1
-rw-r--r--drivers/input/tablet/Kconfig4
-rw-r--r--drivers/input/touchscreen/Kconfig1
-rw-r--r--drivers/isdn/icn/icn.c1
-rw-r--r--drivers/isdn/sc/message.c2
-rw-r--r--drivers/kvm/kvm.h1
-rw-r--r--drivers/kvm/kvm_main.c1
-rw-r--r--drivers/kvm/svm.c1
-rw-r--r--drivers/kvm/vmx.c1
-rw-r--r--drivers/macintosh/windfarm_core.c10
-rw-r--r--drivers/media/dvb/bt8xx/dst.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c15
-rw-r--r--drivers/media/video/cafe_ccic-regs.h6
-rw-r--r--drivers/media/video/cafe_ccic.c18
-rw-r--r--drivers/media/video/em28xx/Kconfig1
-rw-r--r--drivers/media/video/ivtv/Kconfig2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h8
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c12
-rw-r--r--drivers/media/video/ov7670.c21
-rw-r--r--drivers/media/video/tuner-simple.c10
-rw-r--r--drivers/mmc/card/block.c17
-rw-r--r--drivers/mmc/host/au1xmmc.c35
-rw-r--r--drivers/mmc/host/pxamci.c18
-rw-r--r--drivers/mmc/host/sdhci.c9
-rw-r--r--drivers/mtd/ubi/eba.c3
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/declance.c2
-rw-r--r--drivers/net/e1000/e1000.h4
-rw-r--r--drivers/net/e1000/e1000_main.c43
-rw-r--r--drivers/net/gianfar.c11
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.c3
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.h3
-rw-r--r--drivers/net/ibm_emac/ibm_emac_phy.c60
-rw-r--r--drivers/net/ibm_emac/ibm_emac_rgmii.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_rgmii.h2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_tah.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_tah.h2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_zmii.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_zmii.h2
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/ixgb/ixgb_main.c36
-rw-r--r--drivers/net/mlx4/alloc.c1
-rw-r--r--drivers/net/mlx4/eq.c1
-rw-r--r--drivers/net/mlx4/fw.c2
-rw-r--r--drivers/net/mlx4/icm.c1
-rw-r--r--drivers/net/mlx4/main.c2
-rw-r--r--drivers/net/mlx4/mlx4.h1
-rw-r--r--drivers/net/mlx4/reset.c1
-rw-r--r--drivers/net/netxen/netxen_nic_init.c2
-rw-r--r--drivers/net/pasemi_mac.c45
-rw-r--r--drivers/net/pasemi_mac.h4
-rw-r--r--drivers/net/sky2.c69
-rw-r--r--drivers/net/smc911x.c6
-rw-r--r--drivers/net/spider_net.c3
-rw-r--r--drivers/net/ucc_geth.c40
-rw-r--r--drivers/net/ucc_geth_mii.c9
-rw-r--r--drivers/net/ucc_geth_mii.h10
-rw-r--r--drivers/oprofile/buffer_sync.c1
-rw-r--r--drivers/parport/parport_pc.c1
-rw-r--r--drivers/pci/hotplug/ibmphp_hpc.c1
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c5
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h1
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/rtc-omap.c4
-rw-r--r--drivers/sbus/char/bbc_i2c.c1
-rw-r--r--drivers/sbus/char/display7seg.c1
-rw-r--r--drivers/scsi/Kconfig8
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c2
-rw-r--r--drivers/serial/8250.c21
-rw-r--r--drivers/serial/bfin_5xx.c125
-rw-r--r--drivers/serial/icom.c55
-rw-r--r--drivers/serial/serial_ks8695.c4
-rw-r--r--drivers/serial/sunhv.c280
-rw-r--r--drivers/spi/spi_bfin5xx.c152
-rw-r--r--drivers/spi/spidev.c2
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/console/vgacon.c9
187 files changed, 2201 insertions, 1820 deletions
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 8fcd6a15517f..a2efae8a4c4e 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -40,19 +40,19 @@ static nodemask_t nodes_found_map = NODE_MASK_NONE;
#define NID_INVAL -1
/* maps to convert between proximity domain and logical node ID */
-int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]
+static int pxm_to_node_map[MAX_PXM_DOMAINS]
= { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL };
-int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
+static int node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
-int __cpuinit pxm_to_node(int pxm)
+int pxm_to_node(int pxm)
{
if (pxm < 0)
return NID_INVAL;
return pxm_to_node_map[pxm];
}
-int __cpuinit node_to_pxm(int node)
+int node_to_pxm(int node)
{
if (node < 0)
return PXM_INVAL;
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ad1f59c1b3fc..b4a8d6030e48 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -132,7 +132,7 @@ config SATA_SIS
depends on PCI
select PATA_SIS
help
- This option enables support for SiS Serial ATA on
+ This option enables support for SiS Serial ATA on
SiS 964/965/966/180 and Parallel ATA on SiS 180.
The PATA support for SiS 180 requires additionally to
enable the PATA_SIS driver in the config.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1ae443d7ab92..7baeaffefe7a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -46,7 +46,7 @@
#include <linux/libata.h>
#define DRV_NAME "ahci"
-#define DRV_VERSION "2.1"
+#define DRV_VERSION "2.2"
enum {
@@ -170,10 +170,12 @@ enum {
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
+ AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_SKIP_D2H_BSY,
+ ATA_FLAG_SKIP_D2H_BSY |
+ ATA_FLAG_ACPI_SATA,
};
struct ahci_cmd_hdr {
@@ -353,7 +355,8 @@ static const struct ata_port_info ahci_port_info[] = {
/* board_ahci_sb600 */
{
.flags = AHCI_FLAG_COMMON |
- AHCI_FLAG_IGN_SERR_INTERNAL,
+ AHCI_FLAG_IGN_SERR_INTERNAL |
+ AHCI_FLAG_32BIT_ONLY,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
@@ -491,6 +494,13 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
+ /* some chips lie about 64bit support */
+ if ((cap & HOST_CAP_64) && (pi->flags & AHCI_FLAG_32BIT_ONLY)) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "controller can't do 64bit DMA, forcing 32bit\n");
+ cap &= ~HOST_CAP_64;
+ }
+
/* fixup zero port_map */
if (!port_map) {
port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1;
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index c3d753296bc6..7565f022bd69 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -26,7 +26,7 @@
#include <linux/libata.h>
#define DRV_NAME "ata_generic"
-#define DRV_VERSION "0.2.11"
+#define DRV_VERSION "0.2.12"
/*
* A generic parallel ATA driver using libata
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 13b6b1df2ac4..0458811010fd 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -155,7 +155,6 @@ struct piix_host_priv {
static int piix_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent);
static void piix_pata_error_handler(struct ata_port *ap);
-static void piix_sata_error_handler(struct ata_port *ap);
static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev);
@@ -364,7 +363,7 @@ static const struct ata_port_operations piix_sata_ops = {
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
- .error_handler = piix_sata_error_handler,
+ .error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_handler = ata_interrupt,
@@ -641,12 +640,6 @@ static void piix_pata_error_handler(struct ata_port *ap)
ata_std_postreset);
}
-static void piix_sata_error_handler(struct ata_port *ap)
-{
- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
- ata_std_postreset);
-}
-
/**
* piix_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index ed4138e24b0c..02236739b40f 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -321,7 +321,7 @@ static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
/* Don't continue if device has no _ADR method.
* _GTF is intended for known motherboard devices. */
- if (!(ap->cbl == ATA_CBL_SATA)) {
+ if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
if (err < 0) {
if (ata_msg_probe(ap))
@@ -343,7 +343,7 @@ static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
/* Get this drive's _ADR info. if not already known. */
if (!dev->obj_handle) {
- if (!(ap->cbl == ATA_CBL_SATA)) {
+ if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
/* get child objects of dev_handle == channel objects,
* + _their_ children == drive objects */
/* channel is ap->port_no */
@@ -528,7 +528,7 @@ static int do_drive_set_taskfiles(struct ata_device *dev,
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
__FUNCTION__, ap->port_no);
- if (libata_noacpi || !(ap->cbl == ATA_CBL_SATA))
+ if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA))
return 0;
if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
@@ -578,7 +578,7 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
* we should not run GTF on PATA devices since some
* PATA require execution of GTM/STM before GTF.
*/
- if (!(ap->cbl == ATA_CBL_SATA))
+ if (!(ap->flags & ATA_FLAG_ACPI_SATA))
return 0;
for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
@@ -641,7 +641,7 @@ int ata_acpi_push_id(struct ata_device *dev)
__FUNCTION__, dev->devno, ap->port_no);
/* Don't continue if not a SATA device. */
- if (!(ap->cbl == ATA_CBL_SATA)) {
+ if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG,
"%s: Not a SATA device\n", __FUNCTION__);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 4166407eb47c..a6de57e02047 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -59,7 +59,7 @@
#include "libata.h"
-#define DRV_VERSION "2.20" /* must be exactly four chars */
+#define DRV_VERSION "2.21" /* must be exactly four chars */
/* debounce timing parameters in msecs { interval, duration, timeout } */
@@ -101,12 +101,6 @@ int libata_noacpi = 1;
module_param_named(noacpi, libata_noacpi, int, 0444);
MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
-int ata_spindown_compat = 1;
-module_param_named(spindown_compat, ata_spindown_compat, int, 0644);
-MODULE_PARM_DESC(spindown_compat, "Enable backward compatible spindown "
- "behavior. Will be removed. More info can be found in "
- "Documentation/feature-removal-schedule.txt\n");
-
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
@@ -983,7 +977,7 @@ static u64 ata_hpa_resize(struct ata_device *dev)
{
u64 sectors = dev->n_sectors;
u64 hpa_sectors;
-
+
if (ata_id_has_lba48(dev->id))
hpa_sectors = ata_read_native_max_address_ext(dev);
else
@@ -1594,7 +1588,7 @@ unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
* Check if the current speed of the device requires IORDY. Used
* by various controllers for chip configuration.
*/
-
+
unsigned int ata_pio_need_iordy(const struct ata_device *adev)
{
/* Controller doesn't support IORDY. Probably a pointless check
@@ -1617,7 +1611,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
* Compute the highest mode possible if we are not using iordy. Return
* -1 if no iordy mode is available.
*/
-
+
static u32 ata_pio_mask_no_iordy(const struct ata_device *adev)
{
/* If we have no drive specific rule, then PIO 2 is non IORDY */
@@ -1919,7 +1913,6 @@ int ata_dev_configure(struct ata_device *dev)
snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
dev->n_sectors = ata_id_n_sectors(id);
- dev->n_sectors_boot = dev->n_sectors;
/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
@@ -2670,7 +2663,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
t->active += (t->cycle - (t->active + t->recover)) / 2;
t->recover = t->cycle - t->active;
}
-
+
/* In a few cases quantisation may produce enough errors to
leave t->cycle too low for the sum of active and recovery
if so we must correct this */
@@ -2900,9 +2893,6 @@ int ata_do_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
if (used_dma && (ap->host->flags & ATA_HOST_SIMPLEX))
ap->host->simplex_claimed = ap;
- /* step5: chip specific finalisation */
- if (ap->ops->post_set_mode)
- ap->ops->post_set_mode(ap);
out:
if (rc)
*r_failed_dev = dev;
@@ -3632,7 +3622,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
const u16 *old_id = dev->id;
unsigned char model[2][ATA_ID_PROD_LEN + 1];
unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
- u64 new_n_sectors;
if (dev->class != new_class) {
ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
@@ -3644,7 +3633,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1]));
ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0]));
ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
- new_n_sectors = ata_id_n_sectors(new_id);
if (strcmp(model[0], model[1])) {
ata_dev_printk(dev, KERN_INFO, "model number mismatch "
@@ -3658,25 +3646,12 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
return 0;
}
- if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
- ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
- "%llu != %llu\n",
- (unsigned long long)dev->n_sectors,
- (unsigned long long)new_n_sectors);
- /* Are we the boot time size - if so we appear to be the
- same disk at this point and our HPA got reapplied */
- if (ata_ignore_hpa && dev->n_sectors_boot == new_n_sectors
- && ata_id_hpa_enabled(new_id))
- return 1;
- return 0;
- }
-
return 1;
}
/**
- * ata_dev_revalidate - Revalidate ATA device
- * @dev: device to revalidate
+ * ata_dev_reread_id - Re-read IDENTIFY data
+ * @adev: target ATA device
* @readid_flags: read ID flags
*
* Re-read IDENTIFY page and make sure @dev is still attached to
@@ -3688,34 +3663,68 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
* RETURNS:
* 0 on success, negative errno otherwise
*/
-int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
+int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags)
{
unsigned int class = dev->class;
u16 *id = (void *)dev->ap->sector_buf;
int rc;
- if (!ata_dev_enabled(dev)) {
- rc = -ENODEV;
- goto fail;
- }
-
/* read ID data */
rc = ata_dev_read_id(dev, &class, readid_flags, id);
if (rc)
- goto fail;
+ return rc;
/* is the device still there? */
- if (!ata_dev_same_device(dev, class, id)) {
- rc = -ENODEV;
- goto fail;
- }
+ if (!ata_dev_same_device(dev, class, id))
+ return -ENODEV;
memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
+ return 0;
+}
+
+/**
+ * ata_dev_revalidate - Revalidate ATA device
+ * @dev: device to revalidate
+ * @readid_flags: read ID flags
+ *
+ * Re-read IDENTIFY page, make sure @dev is still attached to the
+ * port and reconfigure it according to the new IDENTIFY page.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, negative errno otherwise
+ */
+int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
+{
+ u64 n_sectors = dev->n_sectors;
+ int rc;
+
+ if (!ata_dev_enabled(dev))
+ return -ENODEV;
+
+ /* re-read ID */
+ rc = ata_dev_reread_id(dev, readid_flags);
+ if (rc)
+ goto fail;
/* configure device according to the new ID */
rc = ata_dev_configure(dev);
- if (rc == 0)
- return 0;
+ if (rc)
+ goto fail;
+
+ /* verify n_sectors hasn't changed */
+ if (dev->class == ATA_DEV_ATA && dev->n_sectors != n_sectors) {
+ ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+ "%llu != %llu\n",
+ (unsigned long long)n_sectors,
+ (unsigned long long)dev->n_sectors);
+ rc = -ENODEV;
+ goto fail;
+ }
+
+ return 0;
fail:
ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
@@ -3759,6 +3768,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
+ { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 5309c312f517..d8070989a39f 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1009,7 +1009,7 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
sense_buf[0] = 0x70;
sense_buf[2] = qc->result_tf.feature >> 4;
- /* some devices time out if garbage left in tf */
+ /* some devices time out if garbage left in tf */
ata_tf_init(dev, &tf);
memset(cdb, 0, ATAPI_CDB_LEN);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index dd81fa78cdcf..242c43eef807 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -893,6 +893,23 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
return queue_depth;
}
+/* XXX: for spindown warning */
+static void ata_delayed_done_timerfn(unsigned long arg)
+{
+ struct scsi_cmnd *scmd = (void *)arg;
+
+ scmd->scsi_done(scmd);
+}
+
+/* XXX: for spindown warning */
+static void ata_delayed_done(struct scsi_cmnd *scmd)
+{
+ static struct timer_list timer;
+
+ setup_timer(&timer, ata_delayed_done_timerfn, (unsigned long)scmd);
+ mod_timer(&timer, jiffies + 5 * HZ);
+}
+
/**
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
* @qc: Storage for translated ATA taskfile
@@ -949,22 +966,24 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
* removed. Read Documentation/feature-removal-schedule.txt
* for more info.
*/
- if (ata_spindown_compat &&
+ if ((qc->dev->flags & ATA_DFLAG_SPUNDOWN) &&
(system_state == SYSTEM_HALT ||
system_state == SYSTEM_POWER_OFF)) {
- static int warned = 0;
+ static unsigned long warned = 0;
- if (!warned) {
- spin_unlock_irq(qc->ap->lock);
+ if (!test_and_set_bit(0, &warned)) {
ata_dev_printk(qc->dev, KERN_WARNING,
"DISK MIGHT NOT BE SPUN DOWN PROPERLY. "
"UPDATE SHUTDOWN UTILITY\n");
ata_dev_printk(qc->dev, KERN_WARNING,
"For more info, visit "
"http://linux-ata.org/shutdown.html\n");
- warned = 1;
- ssleep(5);
- spin_lock_irq(qc->ap->lock);
+
+ /* ->scsi_done is not used, use it for
+ * delayed completion.
+ */
+ scmd->scsi_done = qc->scsidone;
+ qc->scsidone = ata_delayed_done;
}
scmd->result = SAM_STAT_GOOD;
return 1;
@@ -1375,6 +1394,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
}
}
+ /* XXX: track spindown state for spindown skipping and warning */
+ if (unlikely(qc->tf.command == ATA_CMD_STANDBY ||
+ qc->tf.command == ATA_CMD_STANDBYNOW1))
+ qc->dev->flags |= ATA_DFLAG_SPUNDOWN;
+ else if (likely(system_state != SYSTEM_HALT &&
+ system_state != SYSTEM_POWER_OFF))
+ qc->dev->flags &= ~ATA_DFLAG_SPUNDOWN;
+
if (need_sense && !ap->ops->error_handler)
ata_dump_status(ap->print_id, &qc->result_tf);
@@ -1488,14 +1515,14 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
early_finish:
ata_qc_free(qc);
- done(cmd);
+ qc->scsidone(cmd);
DPRINTK("EXIT - early finish (good or error)\n");
return 0;
err_did:
ata_qc_free(qc);
cmd->result = (DID_ERROR << 16);
- done(cmd);
+ qc->scsidone(cmd);
err_mem:
DPRINTK("EXIT - internal\n");
return 0;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 8b71b73a199c..5e2466658420 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -58,7 +58,6 @@ extern int atapi_enabled;
extern int atapi_dmadir;
extern int libata_fua;
extern int libata_noacpi;
-extern int ata_spindown_compat;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
@@ -76,7 +75,8 @@ extern unsigned ata_exec_internal_sg(struct ata_device *dev,
extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
unsigned int flags, u16 *id);
-extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags);
+extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
+extern int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags);
extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_port *ap);
extern int sata_set_spd_needed(struct ata_port *ap);
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 9861059dd673..7b4810c171b7 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -28,7 +28,7 @@
#include <linux/ata.h>
#define DRV_NAME "pata_artop"
-#define DRV_VERSION "0.4.2"
+#define DRV_VERSION "0.4.3"
/*
* The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -99,7 +99,7 @@ static int artop6260_pre_reset(struct ata_port *ap, unsigned long deadline)
*
* Identify the cable type for the ARTOp interface in question
*/
-
+
static int artop6260_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index ed00fa9d53be..31cbf8daa299 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -107,7 +107,7 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
} else {
/* Save the shared timings for channel, they will be loaded
- by qc_issue_prot. Reloading the setup time is expensive
+ by qc_issue_prot. Reloading the setup time is expensive
so we keep a merged one loaded */
pci_read_config_byte(pdev, ARTIM23, &reg);
reg &= 0x3F;
@@ -231,7 +231,7 @@ static void cmd640_hardware_init(struct pci_dev *pdev)
pci_write_config_byte(pdev, CMDTIM, 0);
/* 512 byte bursts (sector) */
pci_write_config_byte(pdev, BRST, 0x40);
- /*
+ /*
* A reporter a long time ago
* Had problems with the data fifo
* So don't run the risk
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 2a79b335cfcc..320a5b10aa98 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -31,7 +31,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_cmd64x"
-#define DRV_VERSION "0.2.2"
+#define DRV_VERSION "0.2.3"
/*
* CMD64x specific registers definition.
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 83bcc5b32597..1aabe15ad9d3 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -41,7 +41,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_cs5520"
-#define DRV_VERSION "0.6.4"
+#define DRV_VERSION "0.6.5"
struct pio_clocks
{
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 1b67923d7a4e..848f0309bf03 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -35,7 +35,7 @@
#include <linux/dmi.h>
#define DRV_NAME "pata_cs5530"
-#define DRV_VERSION "0.7.2"
+#define DRV_VERSION "0.7.3"
static void __iomem *cs5530_port_base(struct ata_port *ap)
{
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index f37d4cd812a1..aa3256fb9f7a 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -39,7 +39,7 @@
#include <asm/msr.h>
#define DRV_NAME "cs5535"
-#define DRV_VERSION "0.2.11"
+#define DRV_VERSION "0.2.12"
/*
* The Geode (Aka Athlon GX now) uses an internal MSR based
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index 27b9f29c01e3..d41a7691dd8e 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -18,7 +18,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_cypress"
-#define DRV_VERSION "0.1.4"
+#define DRV_VERSION "0.1.5"
/* here are the offset definitions for the registers */
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index c6c8a8bb06d0..0c9cb6090711 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -220,32 +220,6 @@ static int hpt36x_cable_detect(struct ata_port *ap)
return ATA_CBL_PATA80;
}
-static int hpt36x_pre_reset(struct ata_port *ap, unsigned long deadline)
-{
- static const struct pci_bits hpt36x_enable_bits[] = {
- { 0x50, 1, 0x04, 0x04 },
- { 0x54, 1, 0x04, 0x04 }
- };
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
- if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
- return -ENOENT;
-
- return ata_std_prereset(ap, deadline);
-}
-
-/**
- * hpt36x_error_handler - reset the hpt36x bus
- * @ap: ATA port to reset
- *
- * Perform the reset handling for the 366/368
- */
-
-static void hpt36x_error_handler(struct ata_port *ap)
-{
- ata_bmdma_drive_eh(ap, hpt36x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
/**
* hpt366_set_piomode - PIO setup
* @ap: ATA interface
@@ -351,7 +325,7 @@ static struct ata_port_operations hpt366_port_ops = {
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
- .error_handler = hpt36x_error_handler,
+ .error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = hpt36x_cable_detect,
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 5a0a410654e2..a54c17433eef 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -961,7 +961,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
u8 mcr1;
u32 freq;
int prefer_dpll = 1;
-
+
unsigned long iobase = pci_resource_start(dev, 4);
const struct hpt_chip *chip_table;
@@ -1055,7 +1055,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
*/
pci_write_config_byte(dev, 0x5b, 0x23);
-
+
/*
* HighPoint does this for HPT372A.
* NOTE: This register is only writeable via I/O space.
@@ -1088,7 +1088,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
* Turn the frequency check into a band and then find a timing
* table to match it.
*/
-
+
clock_slot = hpt37x_clock_slot(freq, chip_table->base);
if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) {
/*
@@ -1099,11 +1099,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
*/
unsigned int f_low, f_high;
int adjust;
-
+
clock_slot = 2;
if (port->udma_mask & 0xE0)
clock_slot = 3;
-
+
f_low = (MHz[clock_slot] * chip_table->base) / 192;
f_high = f_low + 2;
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index bbabe7902fbb..8ce5e23a5f75 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -23,7 +23,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x3"
-#define DRV_VERSION "0.4.2"
+#define DRV_VERSION "0.4.3"
/**
* hpt3x3_set_piomode - PIO setup
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index d042efdfbac4..1f647b648204 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -17,7 +17,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_isapnp"
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
static struct scsi_host_template isapnp_sht = {
.module = THIS_MODULE,
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index a769952646e1..95b0bb61788b 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -19,7 +19,7 @@
#include <linux/ata.h>
#define DRV_NAME "pata_it8213"
-#define DRV_VERSION "0.0.2"
+#define DRV_VERSION "0.0.3"
/**
* it8213_pre_reset - check for 40/80 pin
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index b994351fbcd0..8d2bc1e9e871 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -23,7 +23,7 @@
#include <scsi/scsi_host.h>
#define DRV_NAME "pata_ixp4xx_cf"
-#define DRV_VERSION "0.1.2"
+#define DRV_VERSION "0.1.3"
static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
{
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 8d799e87f752..2af7ff8256ca 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -19,7 +19,7 @@
#include <linux/ata.h>
#define DRV_NAME "pata_jmicron"
-#define DRV_VERSION "0.1.4"
+#define DRV_VERSION "0.1.5"
typedef enum {
PORT_PATA0 = 0,
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 707099291e01..edffc25d2d3f 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -64,7 +64,7 @@
#include <linux/platform_device.h>
#define DRV_NAME "pata_legacy"
-#define DRV_VERSION "0.5.4"
+#define DRV_VERSION "0.5.5"
#define NR_HOST 6
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 1f6384895a4f..cbb7866940d6 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -22,7 +22,7 @@
#include <linux/pata_platform.h>
#define DRV_NAME "pata_platform"
-#define DRV_VERSION "0.1.2"
+#define DRV_VERSION "1.0"
static int pio_mask = 1;
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index fb8c9e14b8d4..1998c19e8743 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -26,7 +26,7 @@
#include <linux/platform_device.h>
#define DRV_NAME "pata_qdi"
-#define DRV_VERSION "0.3.0"
+#define DRV_VERSION "0.3.1"
#define NR_HOST 4 /* Two 6580s */
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 2bfd7ef42af5..a3488b41ad26 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -21,7 +21,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_rz1000"
-#define DRV_VERSION "0.2.3"
+#define DRV_VERSION "0.2.4"
/**
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 225013ecf4b6..1233063ab9a8 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -40,7 +40,7 @@
#include <linux/libata.h>
#define DRV_NAME "sc1200"
-#define DRV_VERSION "0.2.4"
+#define DRV_VERSION "0.2.5"
#define SC1200_REV_A 0x00
#define SC1200_REV_B1 0x01
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index cca3aa225efe..aa138d211b09 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -43,7 +43,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_scc"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
@@ -864,10 +864,10 @@ static void scc_bmdma_freeze (struct ata_port *ap)
* @ap: ATA port to be reset
*/
-static int scc_pata_prereset (struct ata_port *ap)
+static int scc_pata_prereset (struct ata_port *ap, unsigned long deadline)
{
ap->cbl = ATA_CBL_PATA80;
- return ata_std_prereset(ap);
+ return ata_std_prereset(ap, deadline);
}
/**
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index dee6e211949d..1e8f421963c7 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -41,7 +41,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_serverworks"
-#define DRV_VERSION "0.4.0"
+#define DRV_VERSION "0.4.1"
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index f48491ad5f3a..e5aaec43694d 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -26,7 +26,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_sl82c105"
-#define DRV_VERSION "0.3.0"
+#define DRV_VERSION "0.3.1"
enum {
/*
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index cc4ad271afb5..83abfeca4057 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#define DRV_NAME "pata_winbond"
-#define DRV_VERSION "0.0.2"
+#define DRV_VERSION "0.0.3"
#define NR_HOST 4 /* Two winbond controllers, two channels each */
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 52b69530ab29..f12c2b6ac08e 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -44,7 +44,7 @@
#include <linux/libata.h>
#define DRV_NAME "pdc_adma"
-#define DRV_VERSION "0.05"
+#define DRV_VERSION "0.06"
/* macro to calculate base address for ATA regs */
#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40))
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index bda5e7747c21..2d80c9d95e95 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -28,7 +28,7 @@
#include <scsi/scsi_device.h>
#define DRV_NAME "sata_inic162x"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
enum {
MMIO_BAR = 5,
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index cb9b9ac12b4c..705a020e1597 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -35,7 +35,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "0.81"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 4cea3ef75226..adfa693db53d 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -49,7 +49,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_nv"
-#define DRV_VERSION "3.3"
+#define DRV_VERSION "3.4"
#define NV_ADMA_DMA_BOUNDARY 0xffffffffUL
@@ -229,7 +229,6 @@ struct nv_host_priv {
#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void nv_remove_one (struct pci_dev *pdev);
#ifdef CONFIG_PM
static int nv_pci_device_resume(struct pci_dev *pdev);
#endif
@@ -288,12 +287,6 @@ static const struct pci_device_id nv_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
- { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
- { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
{ } /* terminate list */
};
@@ -306,7 +299,7 @@ static struct pci_driver nv_pci_driver = {
.suspend = ata_pci_device_suspend,
.resume = nv_pci_device_resume,
#endif
- .remove = nv_remove_one,
+ .remove = ata_pci_remove_one,
};
static struct scsi_host_template nv_sht = {
@@ -809,7 +802,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
u16 status;
u32 gen_ctl;
u32 notifier, notifier_error;
-
+
/* if ADMA is disabled, use standard ata interrupt handler */
if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
@@ -970,7 +963,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
/* clear ADMA status */
writew(0xffff, mmio + NV_ADMA_STAT);
-
+
/* clear notifiers - note both ports need to be written with
something even though we are only clearing on one */
if (ap->port_no == 0) {
@@ -1613,15 +1606,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
IRQF_SHARED, ppi[0]->sht);
}
-static void nv_remove_one (struct pci_dev *pdev)
-{
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
- struct nv_host_priv *hpriv = host->private_data;
-
- ata_pci_remove_one(pdev);
- kfree(hpriv);
-}
-
#ifdef CONFIG_PM
static int nv_pci_device_resume(struct pci_dev *pdev)
{
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index f5a05de0093d..6688ccb66320 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -39,7 +39,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_qstor"
-#define DRV_VERSION "0.07"
+#define DRV_VERSION "0.08"
enum {
QS_MMIO_BAR = 4,
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index e8483aadd11b..a3b339bcf3cf 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -305,7 +305,7 @@ static int sil_set_mode (struct ata_port *ap, struct ata_device **r_failed)
u32 tmp, dev_mode[2];
unsigned int i;
int rc;
-
+
rc = ata_do_set_mode(ap, r_failed);
if (rc)
return rc;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index a69d78cd8e9b..0ddfae9911cd 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -30,7 +30,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_sil24"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "0.9"
/*
* Port request block (PRB) 32 bytes
@@ -237,7 +237,8 @@ enum {
/* host flags */
SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
- ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY,
+ ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY |
+ ATA_FLAG_ACPI_SATA,
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
IRQ_STAT_4PORTS = 0xf,
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index ee66c5fa7ac8..51d9251b0898 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -43,7 +43,7 @@
#include "sis.h"
#define DRV_NAME "sata_sis"
-#define DRV_VERSION "0.7"
+#define DRV_VERSION "0.8"
enum {
sis_180 = 0,
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 17246734fe76..bcb2cd8b063d 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -53,7 +53,7 @@
#endif /* CONFIG_PPC_OF */
#define DRV_NAME "sata_svw"
-#define DRV_VERSION "2.1"
+#define DRV_VERSION "2.2"
enum {
/* ap->flags bits */
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 3a4f44559d0a..2d14f3d56d92 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -44,7 +44,7 @@
#include "sata_promise.h"
#define DRV_NAME "sata_sx4"
-#define DRV_VERSION "0.10"
+#define DRV_VERSION "0.11"
enum {
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 006f5e352658..6815de7cca79 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -36,7 +36,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_uli"
-#define DRV_VERSION "1.1"
+#define DRV_VERSION "1.2"
enum {
uli_5289 = 0,
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index d105d2c189d2..01bba26d8d1a 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -46,7 +46,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_via"
-#define DRV_VERSION "2.1"
+#define DRV_VERSION "2.2"
enum board_ids_enum {
vt6420,
@@ -441,7 +441,7 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
return -ENOMEM;
}
- rc = pcim_iomap_regions(pdev, 0x1f, DRV_NAME);
+ rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
if (rc) {
dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap "
"PCI BARs (errno=%d)\n", rc);
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 80126f835d32..81330175fc89 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -47,7 +47,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_vsc"
-#define DRV_VERSION "2.1"
+#define DRV_VERSION "2.2"
enum {
VSC_MMIO_BAR = 0,
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 9406259754ad..91970e9bb05e 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -8,6 +8,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/poison.h>
+#include <linux/sched.h>
/*
* Pool allocator ... wraps the dma_alloc_coherent page allocator, so
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 370dfe1c422e..5acc6c44aead 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3469,13 +3469,39 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
return -1;
}
-static void cciss_remove_one(struct pci_dev *pdev)
+static void cciss_shutdown(struct pci_dev *pdev)
{
ctlr_info_t *tmp_ptr;
- int i, j;
+ int i;
char flush_buf[4];
int return_code;
+ tmp_ptr = pci_get_drvdata(pdev);
+ if (tmp_ptr == NULL)
+ return;
+ i = tmp_ptr->ctlr;
+ if (hba[i] == NULL)
+ return;
+
+ /* Turn board interrupts off and send the flush cache command */
+ /* sendcmd will turn off interrupt, and send the flush...
+ * To write all data in the battery backed cache to disks */
+ memset(flush_buf, 0, 4);
+ return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
+ TYPE_CMD);
+ if (return_code == IO_OK) {
+ printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
+ } else {
+ printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
+ }
+ free_irq(hba[i]->intr[2], hba[i]);
+}
+
+static void __devexit cciss_remove_one(struct pci_dev *pdev)
+{
+ ctlr_info_t *tmp_ptr;
+ int i, j;
+
if (pci_get_drvdata(pdev) == NULL) {
printk(KERN_ERR "cciss: Unable to remove device \n");
return;
@@ -3506,18 +3532,7 @@ static void cciss_remove_one(struct pci_dev *pdev)
cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
- /* Turn board interrupts off and send the flush cache command */
- /* sendcmd will turn off interrupt, and send the flush...
- * To write all data in the battery backed cache to disks */
- memset(flush_buf, 0, 4);
- return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
- TYPE_CMD);
- if (return_code == IO_OK) {
- printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
- } else {
- printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
- }
- free_irq(hba[i]->intr[2], hba[i]);
+ cciss_shutdown(pdev);
#ifdef CONFIG_PCI_MSI
if (hba[i]->msix_vector)
@@ -3550,7 +3565,7 @@ static struct pci_driver cciss_pci_driver = {
.probe = cciss_init_one,
.remove = __devexit_p(cciss_remove_one),
.id_table = cciss_pci_device_id, /* id_table */
- .shutdown = cciss_remove_one,
+ .shutdown = cciss_shutdown,
};
/*
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 679d7f972439..c7ed617aa7ff 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -37,6 +37,7 @@
#include <linux/agpgart.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include "agp.h"
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 45aeb917ec63..d535c406b319 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -37,6 +37,7 @@
#include <linux/vmalloc.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index a2bb4eccaab4..9aaf401a8975 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -384,9 +384,9 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_VIA_P4M800CE,
.chipset_name = "VT3314",
},
- /* CX700 */
+ /* VT3324 / CX700 */
{
- .device_id = PCI_DEVICE_ID_VIA_CX700,
+ .device_id = PCI_DEVICE_ID_VIA_VT3324,
.chipset_name = "CX700",
},
/* VT3336 */
@@ -540,7 +540,7 @@ static const struct pci_device_id agp_via_pci_table[] = {
ID(PCI_DEVICE_ID_VIA_83_87XX_1),
ID(PCI_DEVICE_ID_VIA_3296_0),
ID(PCI_DEVICE_ID_VIA_P4M800CE),
- ID(PCI_DEVICE_ID_VIA_CX700),
+ ID(PCI_DEVICE_ID_VIA_VT3324),
ID(PCI_DEVICE_ID_VIA_VT3336),
ID(PCI_DEVICE_ID_VIA_P4M890),
{ }
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index f0e7263dfcde..0e8ceea5ea78 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -48,7 +48,7 @@
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/sysrq.h>
-
+#include <linux/timer.h>
#define VERSION_STR "0.9.0"
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 147c12047cf3..41f78e2c158f 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -50,18 +50,10 @@
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ctype.h>
-#include <linux/delay.h>
#include <asm/atomic.h>
-#ifdef CONFIG_X86
-/* This is ugly, but I've determined that x86 is the only architecture
- that can reasonably support the IPMI NMI watchdog timeout at this
- time. If another architecture adds this capability somehow, it
- will have to be a somewhat different mechanism and I have no idea
- how it will work. So in the unlikely event that another
- architecture supports this, we can figure out a good generic
- mechanism for it at that time. */
-#define HAVE_DIE_NMI_POST
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/apic.h>
#endif
#define PFX "IPMI Watchdog: "
@@ -327,11 +319,6 @@ static unsigned char ipmi_version_minor;
/* If a pretimeout occurs, this is used to allow only one panic to happen. */
static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
-#ifdef HAVE_DIE_NMI_POST
-static int testing_nmi;
-static int nmi_handler_registered;
-#endif
-
static int ipmi_heartbeat(void);
static void panic_halt_ipmi_heartbeat(void);
@@ -373,10 +360,6 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
int hbnow = 0;
- /* These can be cleared as we are setting the timeout. */
- ipmi_start_timer_on_heartbeat = 0;
- pretimeout_since_last_heartbeat = 0;
-
data[0] = 0;
WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
@@ -451,12 +434,13 @@ static int ipmi_set_timeout(int do_heartbeat)
wait_for_completion(&set_timeout_wait);
- mutex_unlock(&set_timeout_lock);
-
if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
|| ((send_heartbeat_now)
&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
+ {
rv = ipmi_heartbeat();
+ }
+ mutex_unlock(&set_timeout_lock);
out:
return rv;
@@ -536,10 +520,12 @@ static int ipmi_heartbeat(void)
int rv;
struct ipmi_system_interface_addr addr;
- if (ipmi_ignore_heartbeat)
+ if (ipmi_ignore_heartbeat) {
return 0;
+ }
if (ipmi_start_timer_on_heartbeat) {
+ ipmi_start_timer_on_heartbeat = 0;
ipmi_watchdog_state = action_val;
return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
} else if (pretimeout_since_last_heartbeat) {
@@ -547,6 +533,7 @@ static int ipmi_heartbeat(void)
We don't want to set the action, though, we want to
leave that alone (thus it can't be combined with the
above operation. */
+ pretimeout_since_last_heartbeat = 0;
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
}
@@ -934,45 +921,6 @@ static void ipmi_register_watchdog(int ipmi_intf)
printk(KERN_CRIT PFX "Unable to register misc device\n");
}
-#ifdef HAVE_DIE_NMI_POST
- if (nmi_handler_registered) {
- int old_pretimeout = pretimeout;
- int old_timeout = timeout;
- int old_preop_val = preop_val;
-
- /* Set the pretimeout to go off in a second and give
- ourselves plenty of time to stop the timer. */
- ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
- preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
- pretimeout = 99;
- timeout = 100;
-
- testing_nmi = 1;
-
- rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
- if (rv) {
- printk(KERN_WARNING PFX "Error starting timer to"
- " test NMI: 0x%x. The NMI pretimeout will"
- " likely not work\n", rv);
- rv = 0;
- goto out_restore;
- }
-
- msleep(1500);
-
- if (testing_nmi != 2) {
- printk(KERN_WARNING PFX "IPMI NMI didn't seem to"
- " occur. The NMI pretimeout will"
- " likely not work\n");
- }
- out_restore:
- testing_nmi = 0;
- preop_val = old_preop_val;
- pretimeout = old_pretimeout;
- timeout = old_timeout;
- }
-#endif
-
out:
up_write(&register_sem);
@@ -982,10 +930,6 @@ static void ipmi_register_watchdog(int ipmi_intf)
ipmi_watchdog_state = action_val;
ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
printk(KERN_INFO PFX "Starting now!\n");
- } else {
- /* Stop the timer now. */
- ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
- ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
}
}
@@ -1022,28 +966,17 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
up_write(&register_sem);
}
-#ifdef HAVE_DIE_NMI_POST
+#ifdef HAVE_NMI_HANDLER
static int
-ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
+ipmi_nmi(void *dev_id, int cpu, int handled)
{
- if (val != DIE_NMI_POST)
- return NOTIFY_OK;
-
- if (testing_nmi) {
- testing_nmi = 2;
- return NOTIFY_STOP;
- }
-
/* If we are not expecting a timeout, ignore it. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
- return NOTIFY_OK;
-
- if (preaction_val != WDOG_PRETIMEOUT_NMI)
- return NOTIFY_OK;
+ return NOTIFY_DONE;
/* If no one else handled the NMI, we assume it was the IPMI
watchdog. */
- if (preop_val == WDOG_PREOP_PANIC) {
+ if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
/* On some machines, the heartbeat will give
an error and not work unless we re-enable
the timer. So do so. */
@@ -1052,12 +985,18 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
panic(PFX "pre-timeout");
}
- return NOTIFY_STOP;
+ return NOTIFY_DONE;
}
-static struct notifier_block ipmi_nmi_handler = {
- .notifier_call = ipmi_nmi
+static struct nmi_handler ipmi_nmi_handler =
+{
+ .link = LIST_HEAD_INIT(ipmi_nmi_handler.link),
+ .dev_name = "ipmi_watchdog",
+ .dev_id = NULL,
+ .handler = ipmi_nmi,
+ .priority = 0, /* Call us last. */
};
+int nmi_handler_registered;
#endif
static int wdog_reboot_handler(struct notifier_block *this,
@@ -1174,7 +1113,7 @@ static int preaction_op(const char *inval, char *outval)
preaction_val = WDOG_PRETIMEOUT_NONE;
else if (strcmp(inval, "pre_smi") == 0)
preaction_val = WDOG_PRETIMEOUT_SMI;
-#ifdef HAVE_DIE_NMI_POST
+#ifdef HAVE_NMI_HANDLER
else if (strcmp(inval, "pre_nmi") == 0)
preaction_val = WDOG_PRETIMEOUT_NMI;
#endif
@@ -1208,7 +1147,7 @@ static int preop_op(const char *inval, char *outval)
static void check_parms(void)
{
-#ifdef HAVE_DIE_NMI_POST
+#ifdef HAVE_NMI_HANDLER
int do_nmi = 0;
int rv;
@@ -1221,9 +1160,20 @@ static void check_parms(void)
preop_op("preop_none", NULL);
do_nmi = 0;
}
+#ifdef CONFIG_X86_LOCAL_APIC
+ if (nmi_watchdog == NMI_IO_APIC) {
+ printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
+ " mode (value is %d), that is incompatible"
+ " with using NMI in the IPMI watchdog."
+ " Disabling IPMI nmi pretimeout.\n",
+ nmi_watchdog);
+ preaction_val = WDOG_PRETIMEOUT_NONE;
+ do_nmi = 0;
+ }
+#endif
}
if (do_nmi && !nmi_handler_registered) {
- rv = register_die_notifier(&ipmi_nmi_handler);
+ rv = request_nmi(&ipmi_nmi_handler);
if (rv) {
printk(KERN_WARNING PFX
"Can't register nmi handler\n");
@@ -1231,7 +1181,7 @@ static void check_parms(void)
} else
nmi_handler_registered = 1;
} else if (!do_nmi && nmi_handler_registered) {
- unregister_die_notifier(&ipmi_nmi_handler);
+ release_nmi(&ipmi_nmi_handler);
nmi_handler_registered = 0;
}
#endif
@@ -1267,9 +1217,9 @@ static int __init ipmi_wdog_init(void)
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
-#ifdef HAVE_DIE_NMI_POST
- if (nmi_handler_registered)
- unregister_die_notifier(&ipmi_nmi_handler);
+#ifdef HAVE_NMI_HANDLER
+ if (preaction_val == WDOG_PRETIMEOUT_NMI)
+ release_nmi(&ipmi_nmi_handler);
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
&wdog_panic_notifier);
@@ -1288,9 +1238,9 @@ static void __exit ipmi_wdog_exit(void)
ipmi_smi_watcher_unregister(&smi_watcher);
ipmi_unregister_watchdog(watchdog_ifnum);
-#ifdef HAVE_DIE_NMI_POST
+#ifdef HAVE_NMI_HANDLER
if (nmi_handler_registered)
- unregister_die_notifier(&ipmi_nmi_handler);
+ release_nmi(&ipmi_nmi_handler);
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c
index 0e23f29f71ab..0f5c77ddd39d 100644
--- a/drivers/char/watchdog/booke_wdt.c
+++ b/drivers/char/watchdog/booke_wdt.c
@@ -24,7 +24,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-/* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot.
+/* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
* Also, the wdt_period sets the watchdog timer period timeout.
* For E500 cpus the wdt_period sets which bit changing from 0->1 will
* trigger a watchog timeout. This watchdog timeout will occur 3 times, the
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e678a33ea672..bb90cbd7ca51 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -1,10 +1,10 @@
menu "Hardware crypto devices"
config CRYPTO_DEV_PADLOCK
- bool "Support for VIA PadLock ACE"
+ tristate "Support for VIA PadLock ACE"
depends on X86_32
select CRYPTO_ALGAPI
- default y
+ default m
help
Some VIA processors come with an integrated crypto engine
(so called VIA PadLock ACE, Advanced Cryptography Engine)
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 1f5c70461b8b..c17342d3e6fd 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/dma-mapping.h>
+#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 9040809d2c25..b1a9b81c211f 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -4,13 +4,10 @@
# Andre Hedrick <andre@linux-ide.org>
#
-if BLOCK
-
-menu "ATA/ATAPI/MFM/RLL support"
- depends on HAS_IOMEM
-
-config IDE
+menuconfig IDE
tristate "ATA/ATAPI/MFM/RLL support"
+ depends on BLOCK
+ depends on HAS_IOMEM
---help---
If you say Y here, your kernel will be able to manage low cost mass
storage units such as ATA/(E)IDE and ATAPI units. The most common
@@ -1099,8 +1096,4 @@ config BLK_DEV_HD_ONLY
config BLK_DEV_HD
def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY
-endif
-
-endmenu
-
-endif
+endif # IDE
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index c04cb25a01ff..ca0341c05e55 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -1002,18 +1002,6 @@ static int cris_ide_build_dmatable (ide_drive_t *drive)
return 1; /* let the PIO routines handle this weirdness */
}
-static int cris_config_drive_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (!speed)
- return 0;
-
- speed_cris_ide(drive, speed);
-
- return ide_dma_enable(drive);
-}
-
/*
* cris_dma_intr() is the handler for disk read/write DMA interrupts
*/
@@ -1043,7 +1031,7 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive)
static int cris_dma_check(ide_drive_t *drive)
{
- if (ide_use_dma(drive) && cris_config_drive_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
return -1;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 5fe85191d49c..b77b7d138c49 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -670,41 +670,6 @@ int __ide_dma_good_drive (ide_drive_t *drive)
EXPORT_SYMBOL(__ide_dma_good_drive);
-int ide_use_dma(ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = drive->hwif;
-
- if ((id->capability & 1) == 0 || drive->autodma == 0)
- return 0;
-
- /* consult the list of known "bad" drives */
- if (__ide_dma_bad_drive(drive))
- return 0;
-
- /* capable of UltraDMA modes */
- if (id->field_valid & 4) {
- if (hwif->ultra_mask & id->dma_ultra)
- return 1;
- }
-
- /* capable of regular DMA modes */
- if (id->field_valid & 2) {
- if (hwif->mwdma_mask & id->dma_mword)
- return 1;
- if (hwif->swdma_mask & id->dma_1word)
- return 1;
- }
-
- /* consult the list of known "good" drives */
- if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
- return 1;
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(ide_use_dma);
-
static const u8 xfer_mode_bases[] = {
XFER_UDMA_0,
XFER_MW_DMA_0,
@@ -731,10 +696,12 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
mask &= 0x07;
break;
case XFER_MW_DMA_0:
- mask = id->dma_mword & hwif->mwdma_mask;
+ if (id->field_valid & 2)
+ mask = id->dma_mword & hwif->mwdma_mask;
break;
case XFER_SW_DMA_0:
- mask = id->dma_1word & hwif->swdma_mask;
+ if (id->field_valid & 2)
+ mask = id->dma_1word & hwif->swdma_mask;
break;
default:
BUG();
@@ -783,8 +750,11 @@ int ide_tune_dma(ide_drive_t *drive)
{
u8 speed;
- /* TODO: use only ide_max_dma_mode() */
- if (!ide_use_dma(drive))
+ if ((drive->id->capability & 1) == 0 || drive->autodma == 0)
+ return 0;
+
+ /* consult the list of known "bad" drives */
+ if (__ide_dma_bad_drive(drive))
return 0;
speed = ide_max_dma_mode(drive);
@@ -792,9 +762,10 @@ int ide_tune_dma(ide_drive_t *drive)
if (!speed)
return 0;
- drive->hwif->speedproc(drive, speed);
+ if (drive->hwif->speedproc(drive, speed))
+ return 0;
- return ide_dma_enable(drive);
+ return 1;
}
EXPORT_SYMBOL_GPL(ide_tune_dma);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 8e568143d90d..bfe8f1b712ba 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -223,6 +223,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
break;
if (drive->hwif->ide_dma_check == NULL)
break;
+ drive->hwif->dma_off_quietly(drive);
ide_set_dma(drive);
break;
}
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 3be3c69383f2..074bb32a4a40 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -111,18 +111,6 @@ u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
EXPORT_SYMBOL(ide_rate_filter);
-int ide_dma_enable (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- return ((int) ((((id->dma_ultra >> 8) & hwif->ultra_mask) ||
- ((id->dma_mword >> 8) & hwif->mwdma_mask) ||
- ((id->dma_1word >> 8) & hwif->swdma_mask)) ? 1 : 0));
-}
-
-EXPORT_SYMBOL(ide_dma_enable);
-
int ide_use_fast_pio(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index f2b547ff7722..6002713a20a1 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -910,6 +910,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
err = 0;
if (arg) {
+ hwif->dma_off_quietly(drive);
if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
err = -EIO;
} else
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 428efdae0c7b..27525ec2e19a 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -455,28 +455,6 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return (ide_config_drive_speed(drive, speed));
}
-
-/**
- * config_chipset_for_dma - set up DMA mode
- * @drive: drive to configure for
- *
- * Place a drive into DMA mode and tune the chipset for
- * the selected speed.
- *
- * Returns true if DMA mode can be used
- */
-
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (!(speed))
- return 0;
-
- (void) ali15x3_tune_chipset(drive, speed);
- return ide_dma_enable(drive);
-}
-
/**
* ali15x3_config_drive_for_dma - configure for DMA
* @drive: drive to configure
@@ -487,48 +465,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
- goto ata_pio;
-
drive->init_speed = 0;
- if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
- /* Consult the list of known "bad" drives */
- if (__ide_dma_bad_drive(drive))
- goto ata_pio;
- if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
- if (id->dma_ultra & hwif->ultra_mask) {
- /* Force if Capable UltraDMA */
- int dma = config_chipset_for_dma(drive);
- if ((id->field_valid & 2) && !dma)
- goto try_dma_modes;
- }
- } else if (id->field_valid & 2) {
-try_dma_modes:
- if ((id->dma_mword & hwif->mwdma_mask) ||
- (id->dma_1word & hwif->swdma_mask)) {
- /* Force if Capable regular DMA modes */
- if (!config_chipset_for_dma(drive))
- goto ata_pio;
- }
- } else if (__ide_dma_good_drive(drive) &&
- (id->eide_dma_time < 150)) {
- /* Consult the list of known "good" drives */
- if (!config_chipset_for_dma(drive))
- goto ata_pio;
- } else {
- goto ata_pio;
- }
- } else {
-ata_pio:
- hwif->tuneproc(drive, 255);
- return -1;
- }
+ if (ide_tune_dma(drive))
+ return 0;
- return 0;
+ ali15x3_tune_drive(drive, 255);
+
+ return -1;
}
/**
@@ -739,7 +683,8 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
return;
}
- hwif->atapi_dma = 1;
+ if (m5229_revision > 0x20)
+ hwif->atapi_dma = 1;
if (m5229_revision <= 0x20)
hwif->ultra_mask = 0x00; /* no udma */
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 61ea96b5555c..7c57dc696f52 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -352,22 +352,9 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed)
return ide_config_drive_speed(drive, speed);
}
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (!speed)
- return 0;
-
- if (cmd64x_tune_chipset(drive, speed))
- return 0;
-
- return ide_dma_enable(drive);
-}
-
static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
{
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
if (ide_use_fast_pio(drive))
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index b2d7c132ef4b..1eec1f308d16 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -1,10 +1,10 @@
/*
- * linux/drivers/ide/pci/cs5530.c Version 0.7 Sept 10, 2002
+ * linux/drivers/ide/pci/cs5530.c Version 0.73 Mar 10 2007
*
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
- * Ditto of GNU General Public License.
- *
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
+ *
* May be copied or modified under the terms of the GNU General Public License
*
* Development of this chipset driver was funded
@@ -62,6 +62,14 @@ static unsigned int cs5530_pio_timings[2][5] = {
#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
+static void cs5530_tunepio(ide_drive_t *drive, u8 pio)
+{
+ unsigned long basereg = CS5530_BASEREG(drive->hwif);
+ unsigned int format = (inl(basereg + 4) >> 31) & 1;
+
+ outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
+}
+
/**
* cs5530_tuneproc - select/set PIO modes
*
@@ -74,98 +82,78 @@ static unsigned int cs5530_pio_timings[2][5] = {
static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */
{
- ide_hwif_t *hwif = HWIF(drive);
- unsigned int format;
- unsigned long basereg = CS5530_BASEREG(hwif);
- static u8 modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
-
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
- if (!cs5530_set_xfer_mode(drive, modes[pio])) {
- format = (inl(basereg + 4) >> 31) & 1;
- outl(cs5530_pio_timings[format][pio],
- basereg+(drive->select.b.unit<<3));
+
+ if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
+ cs5530_tunepio(drive, pio);
+}
+
+/**
+ * cs5530_udma_filter - UDMA filter
+ * @drive: drive
+ *
+ * cs5530_udma_filter() does UDMA mask filtering for the given drive
+ * taking into the consideration capabilities of the mate device.
+ *
+ * The CS5530 specifies that two drives sharing a cable cannot mix
+ * UDMA/MDMA. It has to be one or the other, for the pair, though
+ * different timings can still be chosen for each drive. We could
+ * set the appropriate timing bits on the fly, but that might be
+ * a bit confusing. So, for now we statically handle this requirement
+ * by looking at our mate drive to see what it is capable of, before
+ * choosing a mode for our own drive.
+ *
+ * Note: This relies on the fact we never fail from UDMA to MWDMA2
+ * but instead drop to PIO.
+ */
+
+static u8 cs5530_udma_filter(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
+ struct hd_driveid *mateid = mate->id;
+ u8 mask = hwif->ultra_mask;
+
+ if (mate->present == 0)
+ goto out;
+
+ if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
+ if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+ goto out;
+ if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+ mask = 0;
}
+out:
+ return mask;
}
/**
- * cs5530_config_dma - select/set DMA and UDMA modes
+ * cs5530_config_dma - set DMA/UDMA mode
* @drive: drive to tune
*
- * cs5530_config_dma() handles selection/setting of DMA/UDMA modes
- * for both the chipset and drive. The CS5530 has limitations about
- * mixing DMA/UDMA on the same cable.
+ * cs5530_config_dma() handles setting of DMA/UDMA mode
+ * for both the chipset and drive.
*/
-
-static int cs5530_config_dma (ide_drive_t *drive)
+
+static int cs5530_config_dma(ide_drive_t *drive)
{
- int udma_ok = 1, mode = 0;
- ide_hwif_t *hwif = HWIF(drive);
- int unit = drive->select.b.unit;
- ide_drive_t *mate = &hwif->drives[unit^1];
- struct hd_driveid *id = drive->id;
- unsigned int reg, timings = 0;
- unsigned long basereg;
+ if (ide_tune_dma(drive))
+ return 0;
- /*
- * Default to DMA-off in case we run into trouble here.
- */
- hwif->dma_off_quietly(drive);
+ return 1;
+}
- /*
- * The CS5530 specifies that two drives sharing a cable cannot
- * mix UDMA/MDMA. It has to be one or the other, for the pair,
- * though different timings can still be chosen for each drive.
- * We could set the appropriate timing bits on the fly,
- * but that might be a bit confusing. So, for now we statically
- * handle this requirement by looking at our mate drive to see
- * what it is capable of, before choosing a mode for our own drive.
- *
- * Note: This relies on the fact we never fail from UDMA to MWDMA_2
- * but instead drop to PIO
- */
- if (mate->present) {
- struct hd_driveid *mateid = mate->id;
- if (mateid && (mateid->capability & 1) &&
- !__ide_dma_bad_drive(mate)) {
- if ((mateid->field_valid & 4) &&
- (mateid->dma_ultra & 7))
- udma_ok = 1;
- else if ((mateid->field_valid & 2) &&
- (mateid->dma_mword & 7))
- udma_ok = 0;
- else
- udma_ok = 1;
- }
- }
+static int cs5530_tune_chipset(ide_drive_t *drive, u8 mode)
+{
+ unsigned long basereg;
+ unsigned int reg, timings = 0;
- /*
- * Now see what the current drive is capable of,
- * selecting UDMA only if the mate said it was ok.
- */
- if (id && (id->capability & 1) && drive->autodma &&
- !__ide_dma_bad_drive(drive)) {
- if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
- if (id->dma_ultra & 4)
- mode = XFER_UDMA_2;
- else if (id->dma_ultra & 2)
- mode = XFER_UDMA_1;
- else if (id->dma_ultra & 1)
- mode = XFER_UDMA_0;
- }
- if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
- if (id->dma_mword & 4)
- mode = XFER_MW_DMA_2;
- else if (id->dma_mword & 2)
- mode = XFER_MW_DMA_1;
- else if (id->dma_mword & 1)
- mode = XFER_MW_DMA_0;
- }
- }
+ mode = ide_rate_filter(drive, mode);
/*
* Tell the drive to switch to the new mode; abort on failure.
*/
- if (!mode || cs5530_set_xfer_mode(drive, mode))
+ if (cs5530_set_xfer_mode(drive, mode))
return 1; /* failure */
/*
@@ -178,14 +166,21 @@ static int cs5530_config_dma (ide_drive_t *drive)
case XFER_MW_DMA_0: timings = 0x00077771; break;
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ cs5530_tunepio(drive, mode - XFER_PIO_0);
+ return 0;
default:
BUG();
break;
}
- basereg = CS5530_BASEREG(hwif);
+ basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */
timings |= reg & 0x80000000; /* preserve PIO format bit */
- if (unit == 0) { /* are we configuring drive0? */
+ if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */
outl(timings, basereg + 4); /* write drive0 config register */
} else {
if (timings & 0x00100000)
@@ -311,6 +306,8 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
hwif->serialized = hwif->mate->serialized = 1;
hwif->tuneproc = &cs5530_tuneproc;
+ hwif->speedproc = &cs5530_tune_chipset;
+
basereg = CS5530_BASEREG(hwif);
d0_timings = inl(basereg + 0);
if (CS5530_BAD_PIO(d0_timings)) {
@@ -332,6 +329,7 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
hwif->ultra_mask = 0x07;
hwif->mwdma_mask = 0x07;
+ hwif->udma_filter = cs5530_udma_filter;
hwif->ide_dma_check = &cs5530_config_dma;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 442f658c6ae7..5faaff87d580 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -464,25 +464,6 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
}
/**
- * config_chipset_for_dma - configure for DMA
- * @drive: drive to configure
- *
- * Called by the IDE layer when it wants the timings set up.
- */
-
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (speed == 0)
- return 0;
-
- it821x_tune_chipset(drive, speed);
-
- return ide_dma_enable(drive);
-}
-
-/**
* it821x_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up
*
@@ -494,7 +475,7 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int it821x_config_drive_for_dma (ide_drive_t *drive)
{
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
it821x_tuneproc(drive, 255);
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 65b1e124edf7..cc0bfdcf1f19 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -228,38 +228,11 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
return get_indexed_reg(hwif, 0x0b) & 0x04;
}
-static int config_chipset_for_dma(ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
- u8 speed;
-
- if (id->capability & 4) {
- /*
- * Set IORDY_EN & PREFETCH_EN (this seems to have
- * NO real effect since this register is reloaded
- * by hardware when the transfer mode is selected)
- */
- u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00;
-
- tmp = get_indexed_reg(hwif, 0x13 + adj);
- set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03);
- }
-
- speed = ide_max_dma_mode(drive);
-
- if (!speed)
- return 0;
-
- (void) hwif->speedproc(drive, speed);
- return ide_dma_enable(drive);
-}
-
static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
{
drive->init_speed = 0;
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
if (ide_use_fast_pio(drive))
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 7146fe3f6ba7..23844687deea 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -1,8 +1,9 @@
/*
- * linux/drivers/ide/pci/pdc202xx_old.c Version 0.36 Sept 11, 2002
+ * linux/drivers/ide/pci/pdc202xx_old.c Version 0.50 Mar 3, 2007
*
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006-2007 MontaVista Software, Inc.
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
* compiled into the kernel if you have more than one card installed.
@@ -60,45 +61,7 @@ static const char *pdc_quirk_drives[] = {
NULL
};
-/* A Register */
-#define SYNC_ERRDY_EN 0xC0
-
-#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */
-#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */
-#define IORDY_EN 0x20 /* PIO: IOREADY */
-#define PREFETCH_EN 0x10 /* PIO: PREFETCH */
-
-#define PA3 0x08 /* PIO"A" timing */
-#define PA2 0x04 /* PIO"A" timing */
-#define PA1 0x02 /* PIO"A" timing */
-#define PA0 0x01 /* PIO"A" timing */
-
-/* B Register */
-
-#define MB2 0x80 /* DMA"B" timing */
-#define MB1 0x40 /* DMA"B" timing */
-#define MB0 0x20 /* DMA"B" timing */
-
-#define PB4 0x10 /* PIO_FORCE 1:0 */
-
-#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */
-#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */
-#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */
-#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */
-
-/* C Register */
-#define IORDYp_NO_SPEED 0x4F
-#define SPEED_DIS 0x0F
-
-#define DMARQp 0x80
-#define IORDYp 0x40
-#define DMAR_EN 0x20
-#define DMAW_EN 0x10
-
-#define MC3 0x08 /* DMA"C" timing */
-#define MC2 0x04 /* DMA"C" timing */
-#define MC1 0x02 /* DMA"C" timing */
-#define MC0 0x01 /* DMA"C" timing */
+static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{
@@ -107,52 +70,25 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
u8 drive_pci = 0x60 + (drive->dn << 2);
u8 speed = ide_rate_filter(drive, xferspeed);
- u32 drive_conf;
- u8 AP, BP, CP, DP;
+ u8 AP = 0, BP = 0, CP = 0;
u8 TA = 0, TB = 0, TC = 0;
- if (drive->media != ide_disk &&
- drive->media != ide_cdrom && speed < XFER_SW_DMA_0)
- return -1;
-
+#if PDC202XX_DEBUG_DRIVE_INFO
+ u32 drive_conf = 0;
pci_read_config_dword(dev, drive_pci, &drive_conf);
- pci_read_config_byte(dev, (drive_pci), &AP);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
- pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
- pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
+#endif
- if (speed < XFER_SW_DMA_0) {
- if ((AP & 0x0F) || (BP & 0x07)) {
- /* clear PIO modes of lower 8421 bits of A Register */
- pci_write_config_byte(dev, (drive_pci), AP &~0x0F);
- pci_read_config_byte(dev, (drive_pci), &AP);
-
- /* clear PIO modes of lower 421 bits of B Register */
- pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-
- pci_read_config_byte(dev, (drive_pci), &AP);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
- }
- } else {
- if ((BP & 0xF0) && (CP & 0x0F)) {
- /* clear DMA modes of upper 842 bits of B Register */
- /* clear PIO forced mode upper 1 bit of B Register */
- pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-
- /* clear DMA modes of lower 8421 bits of C Register */
- pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);
- pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
- }
- }
+ /*
+ * TODO: do this once per channel
+ */
+ if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
+ pdc_old_disable_66MHz_clock(hwif);
- pci_read_config_byte(dev, (drive_pci), &AP);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
- pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+ pci_read_config_byte(dev, drive_pci, &AP);
+ pci_read_config_byte(dev, drive_pci + 1, &BP);
+ pci_read_config_byte(dev, drive_pci + 2, &CP);
switch(speed) {
- case XFER_UDMA_6: speed = XFER_UDMA_5;
case XFER_UDMA_5:
case XFER_UDMA_4: TB = 0x20; TC = 0x01; break;
case XFER_UDMA_2: TB = 0x20; TC = 0x01; break;
@@ -161,7 +97,7 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
case XFER_UDMA_0:
case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break;
case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break;
- case XFER_MW_DMA_0:
+ case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break;
case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break;
case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break;
case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break;
@@ -174,25 +110,39 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
}
if (speed < XFER_SW_DMA_0) {
- pci_write_config_byte(dev, (drive_pci), AP|TA);
- pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
+ /*
+ * preserve SYNC_INT / ERDDY_EN bits while clearing
+ * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
+ */
+ AP &= ~0x3f;
+ if (drive->id->capability & 4)
+ AP |= 0x20; /* set IORDY_EN bit */
+ if (drive->media == ide_disk)
+ AP |= 0x10; /* set Prefetch_EN bit */
+ /* clear PB[4:0] bits of register B */
+ BP &= ~0x1f;
+ pci_write_config_byte(dev, drive_pci, AP | TA);
+ pci_write_config_byte(dev, drive_pci + 1, BP | TB);
} else {
- pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
- pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
+ /* clear MB[2:0] bits of register B */
+ BP &= ~0xe0;
+ /* clear MC[3:0] bits of register C */
+ CP &= ~0x0f;
+ pci_write_config_byte(dev, drive_pci + 1, BP | TB);
+ pci_write_config_byte(dev, drive_pci + 2, CP | TC);
}
#if PDC202XX_DEBUG_DRIVE_INFO
printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
drive->name, ide_xfer_verbose(speed),
drive->dn, drive_conf);
- pci_read_config_dword(dev, drive_pci, &drive_conf);
+ pci_read_config_dword(dev, drive_pci, &drive_conf);
printk("0x%08x\n", drive_conf);
-#endif /* PDC202XX_DEBUG_DRIVE_INFO */
+#endif
- return (ide_config_drive_speed(drive, speed));
+ return ide_config_drive_speed(drive, speed);
}
-
static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
@@ -210,6 +160,8 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
* Set the control register to use the 66MHz system
* clock for UDMA 3/4/5 mode operation when necessary.
*
+ * FIXME: this register is shared by both channels, some locking is needed
+ *
* It may also be possible to leave the 66MHz clock on
* and readjust the timing parameters.
*/
@@ -229,65 +181,11 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
}
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- u32 drive_conf = 0;
- u8 drive_pci = 0x60 + (drive->dn << 2);
- u8 test1 = 0, test2 = 0, speed = -1;
- u8 AP = 0;
-
- if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
- pdc_old_disable_66MHz_clock(drive->hwif);
-
- drive_pci = 0x60 + (drive->dn << 2);
- pci_read_config_dword(dev, drive_pci, &drive_conf);
- if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
- goto chipset_is_set;
-
- pci_read_config_byte(dev, drive_pci, &test1);
- if (!(test1 & SYNC_ERRDY_EN)) {
- if (drive->select.b.unit & 0x01) {
- pci_read_config_byte(dev, drive_pci - 4, &test2);
- if ((test2 & SYNC_ERRDY_EN) &&
- !(test1 & SYNC_ERRDY_EN)) {
- pci_write_config_byte(dev, drive_pci,
- test1|SYNC_ERRDY_EN);
- }
- } else {
- pci_write_config_byte(dev, drive_pci,
- test1|SYNC_ERRDY_EN);
- }
- }
-
-chipset_is_set:
-
- pci_read_config_byte(dev, (drive_pci), &AP);
- if (id->capability & 4) /* IORDY_EN */
- pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN);
- pci_read_config_byte(dev, (drive_pci), &AP);
- if (drive->media == ide_disk) /* PREFETCH_EN */
- pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
-
- speed = ide_max_dma_mode(drive);
-
- if (!(speed)) {
- /* restore original pci-config space */
- pci_write_config_dword(dev, drive_pci, drive_conf);
- return 0;
- }
-
- (void) hwif->speedproc(drive, speed);
- return ide_dma_enable(drive);
-}
-
static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
{
drive->init_speed = 0;
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
if (ide_use_fast_pio(drive))
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index b5ae0c50e216..523363c93794 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -1,7 +1,9 @@
/*
- * linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003
+ * linux/drivers/ide/pci/sc1200.c Version 0.94 Mar 10 2007
*
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
+ *
* May be copied or modified under the terms of the GNU General Public License
*
* Development of this chipset driver was funded
@@ -93,64 +95,50 @@ static const unsigned int sc1200_pio_timings[4][5] =
*/
//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
-static int sc1200_autoselect_dma_mode (ide_drive_t *drive)
+static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
{
- int udma_ok = 1, mode = 0;
- ide_hwif_t *hwif = HWIF(drive);
- int unit = drive->select.b.unit;
- ide_drive_t *mate = &hwif->drives[unit^1];
- struct hd_driveid *id = drive->id;
-
- /*
- * The SC1200 specifies that two drives sharing a cable cannot
- * mix UDMA/MDMA. It has to be one or the other, for the pair,
- * though different timings can still be chosen for each drive.
- * We could set the appropriate timing bits on the fly,
- * but that might be a bit confusing. So, for now we statically
- * handle this requirement by looking at our mate drive to see
- * what it is capable of, before choosing a mode for our own drive.
- */
- if (mate->present) {
- struct hd_driveid *mateid = mate->id;
- if (mateid && (mateid->capability & 1) && !__ide_dma_bad_drive(mate)) {
- if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
- udma_ok = 1;
- else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
- udma_ok = 0;
- else
- udma_ok = 1;
- }
- }
- /*
- * Now see what the current drive is capable of,
- * selecting UDMA only if the mate said it was ok.
- */
- if (id && (id->capability & 1) && hwif->autodma && !__ide_dma_bad_drive(drive)) {
- if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
- if (id->dma_ultra & 4)
- mode = XFER_UDMA_2;
- else if (id->dma_ultra & 2)
- mode = XFER_UDMA_1;
- else if (id->dma_ultra & 1)
- mode = XFER_UDMA_0;
- }
- if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
- if (id->dma_mword & 4)
- mode = XFER_MW_DMA_2;
- else if (id->dma_mword & 2)
- mode = XFER_MW_DMA_1;
- else if (id->dma_mword & 1)
- mode = XFER_MW_DMA_0;
- }
- }
- return mode;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *pdev = hwif->pci_dev;
+ unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
+
+ pci_read_config_dword(pdev, basereg + 4, &format);
+ format = (format >> 31) & 1;
+ if (format)
+ format += sc1200_get_pci_clock();
+ pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3),
+ sc1200_pio_timings[format][pio]);
}
/*
- * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes
- * for both the chipset and drive.
+ * The SC1200 specifies that two drives sharing a cable cannot mix
+ * UDMA/MDMA. It has to be one or the other, for the pair, though
+ * different timings can still be chosen for each drive. We could
+ * set the appropriate timing bits on the fly, but that might be
+ * a bit confusing. So, for now we statically handle this requirement
+ * by looking at our mate drive to see what it is capable of, before
+ * choosing a mode for our own drive.
*/
-static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
+static u8 sc1200_udma_filter(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
+ struct hd_driveid *mateid = mate->id;
+ u8 mask = hwif->ultra_mask;
+
+ if (mate->present == 0)
+ goto out;
+
+ if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
+ if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+ goto out;
+ if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+ mask = 0;
+ }
+out:
+ return mask;
+}
+
+static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode)
{
ide_hwif_t *hwif = HWIF(drive);
int unit = drive->select.b.unit;
@@ -158,20 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
unsigned short pci_clock;
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
- /*
- * Default to DMA-off in case we run into trouble here.
- */
- hwif->dma_off_quietly(drive); /* turn off DMA while we fiddle */
- outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
+ mode = ide_rate_filter(drive, mode);
/*
* Tell the drive to switch to the new mode; abort on failure.
*/
- if (!mode || sc1200_set_xfer_mode(drive, mode)) {
+ if (sc1200_set_xfer_mode(drive, mode)) {
printk("SC1200: set xfer mode failure\n");
return 1; /* failure */
}
+ switch (mode) {
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ sc1200_tunepio(drive, mode - XFER_PIO_0);
+ return 0;
+ }
+
pci_clock = sc1200_get_pci_clock();
/*
@@ -224,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
case PCI_CLK_66: timings = 0x00015151; break;
}
break;
- }
-
- if (timings == 0) {
- printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock);
- return 1; /* failure */
+ default:
+ BUG();
+ break;
}
if (unit == 0) { /* are we configuring drive0? */
@@ -239,8 +231,6 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
}
- outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */
-
return 0; /* success */
}
@@ -250,7 +240,10 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
*/
static int sc1200_config_dma (ide_drive_t *drive)
{
- return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive));
+ if (ide_tune_dma(drive))
+ return 0;
+
+ return 1;
}
@@ -290,10 +283,11 @@ static int sc1200_ide_dma_end (ide_drive_t *drive)
static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int format;
- static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
int mode = -1;
+ /*
+ * bad abuse of ->tuneproc interface
+ */
switch (pio) {
case 200: mode = XFER_UDMA_0; break;
case 201: mode = XFER_UDMA_1; break;
@@ -304,20 +298,17 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au
}
if (mode != -1) {
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
- (void)sc1200_config_dma2(drive, mode);
+ hwif->dma_off_quietly(drive);
+ if (sc1200_tune_chipset(drive, mode) == 0)
+ hwif->dma_host_on(drive);
return;
}
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio);
- if (!sc1200_set_xfer_mode(drive, modes[pio])) {
- unsigned int basereg = hwif->channel ? 0x50 : 0x40;
- pci_read_config_dword (hwif->pci_dev, basereg+4, &format);
- format = (format >> 31) & 1;
- if (format)
- format += sc1200_get_pci_clock();
- pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]);
- }
+
+ if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
+ sc1200_tunepio(drive, pio);
}
#ifdef CONFIG_PM
@@ -438,12 +429,12 @@ static int sc1200_resume (struct pci_dev *dev)
for (d = 0; d < MAX_DRIVES; ++d) {
ide_drive_t *drive = &(hwif->drives[d]);
if (drive->present && !__ide_dma_bad_drive(drive)) {
- int was_using_dma = drive->using_dma;
+ int enable_dma = drive->using_dma;
hwif->dma_off_quietly(drive);
- sc1200_config_dma(drive);
- if (!was_using_dma && drive->using_dma) {
- hwif->dma_off_quietly(drive);
- }
+ if (sc1200_config_dma(drive))
+ enable_dma = 0;
+ if (enable_dma)
+ hwif->dma_host_on(drive);
}
}
}
@@ -461,11 +452,13 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
hwif->serialized = hwif->mate->serialized = 1;
hwif->autodma = 0;
if (hwif->dma_base) {
+ hwif->udma_filter = sc1200_udma_filter;
hwif->ide_dma_check = &sc1200_config_dma;
hwif->ide_dma_end = &sc1200_ide_dma_end;
if (!noautodma)
hwif->autodma = 1;
hwif->tuneproc = &sc1200_tuneproc;
+ hwif->speedproc = &sc1200_tune_chipset;
}
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x07;
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index cbf936325355..55bc0a32e34f 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -322,26 +322,6 @@ static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed)
}
/**
- * scc_config_chipset_for_dma - configure for DMA
- * @drive: drive to configure
- *
- * Called by scc_config_drive_for_dma().
- */
-
-static int scc_config_chipset_for_dma(ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (!speed)
- return 0;
-
- if (scc_tune_chipset(drive, speed))
- return 0;
-
- return ide_dma_enable(drive);
-}
-
-/**
* scc_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up
*
@@ -354,7 +334,7 @@ static int scc_config_chipset_for_dma(ide_drive_t *drive)
static int scc_config_drive_for_dma(ide_drive_t *drive)
{
- if (ide_use_dma(drive) && scc_config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
if (ide_use_fast_pio(drive))
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 2fa6d92d16cc..6234f806c6b5 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,9 +1,10 @@
/*
- * linux/drivers/ide/pci/serverworks.c Version 0.8 25 Ebr 2003
+ * linux/drivers/ide/pci/serverworks.c Version 0.9 Mar 4 2007
*
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
* Portions copyright (c) 2001 Sun Microsystems
*
*
@@ -136,19 +137,14 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- u8 speed;
- u8 pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+ u8 speed = ide_rate_filter(drive, xferspeed);
+ u8 pio = ide_get_best_pio_mode(drive, 255, 4, NULL);
u8 unit = (drive->select.b.unit & 0x01);
u8 csb5 = svwks_csb_check(dev);
u8 ultra_enable = 0, ultra_timing = 0;
u8 dma_timing = 0, pio_timing = 0;
u16 csb5_pio = 0;
- if (xferspeed == 255) /* PIO auto-tuning */
- speed = XFER_PIO_0 + pio;
- else
- speed = ide_rate_filter(drive, xferspeed);
-
/* If we are about to put a disk into UDMA mode we screwed up.
Our code assumes we never _ever_ do this on an OSB4 */
@@ -231,6 +227,9 @@ oem_setup_failed:
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
case XFER_MW_DMA_0:
+ /*
+ * TODO: always setup PIO mode so this won't be needed
+ */
pio_timing |= pio_modes[pio];
csb5_pio |= (pio << (4*drive->dn));
dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
@@ -242,6 +241,9 @@ oem_setup_failed:
case XFER_UDMA_2:
case XFER_UDMA_1:
case XFER_UDMA_0:
+ /*
+ * TODO: always setup PIO mode so this won't be needed
+ */
pio_timing |= pio_modes[pio];
csb5_pio |= (pio << (4*drive->dn));
dma_timing |= dma_modes[2];
@@ -262,72 +264,21 @@ oem_setup_failed:
return (ide_config_drive_speed(drive, speed));
}
-static void config_chipset_for_pio (ide_drive_t *drive)
-{
- u16 eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
- u16 xfer_pio = drive->id->eide_pio_modes;
- u8 timing, speed, pio;
-
- pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
-
- if (xfer_pio > 4)
- xfer_pio = 0;
-
- if (drive->id->eide_pio_iordy > 0)
- for (xfer_pio = 5;
- xfer_pio>0 &&
- drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
- xfer_pio--);
- else
- xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
- (drive->id->eide_pio_modes & 2) ? 0x04 :
- (drive->id->eide_pio_modes & 1) ? 0x03 :
- (drive->id->tPIO & 2) ? 0x02 :
- (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
-
- timing = (xfer_pio >= pio) ? xfer_pio : pio;
-
- switch(timing) {
- case 4: speed = XFER_PIO_4;break;
- case 3: speed = XFER_PIO_3;break;
- case 2: speed = XFER_PIO_2;break;
- case 1: speed = XFER_PIO_1;break;
- default:
- speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
- break;
- }
- (void) svwks_tune_chipset(drive, speed);
- drive->current_speed = speed;
-}
-
static void svwks_tune_drive (ide_drive_t *drive, u8 pio)
{
- if(pio == 255)
- (void) svwks_tune_chipset(drive, 255);
- else
- (void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio));
-}
-
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (!(speed))
- speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
-
- (void) svwks_tune_chipset(drive, speed);
- return ide_dma_enable(drive);
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+ (void)svwks_tune_chipset(drive, XFER_PIO_0 + pio);
}
static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
{
drive->init_speed = 0;
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
if (ide_use_fast_pio(drive))
- config_chipset_for_pio(drive);
+ svwks_tune_drive(drive, 255);
return -1;
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index d09e74c2996e..1a4444e7226a 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -375,28 +375,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
}
/**
- * config_chipset_for_dma - configure for DMA
- * @drive: drive to configure
- *
- * Called by the IDE layer when it wants the timings set up.
- * For the CMD680 we also need to set up the PIO timings and
- * enable DMA.
- */
-
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_max_dma_mode(drive);
-
- if (!speed)
- return 0;
-
- if (siimage_tune_chipset(drive, speed))
- return 0;
-
- return ide_dma_enable(drive);
-}
-
-/**
* siimage_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up
*
@@ -408,7 +386,7 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int siimage_config_drive_for_dma (ide_drive_t *drive)
{
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
if (ide_use_fast_pio(drive))
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 2bde1b92784a..bb6cc4aedd63 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,9 +1,11 @@
/*
- * linux/drivers/ide/pci/sis5513.c Version 0.16ac+vp Jun 18, 2003
+ * linux/drivers/ide/pci/sis5513.c Version 0.20 Mar 4, 2007
*
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
* Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
+ *
* May be copied or modified under the terms of the GNU General Public License
*
*
@@ -448,36 +450,15 @@ static void config_drive_art_rwp (ide_drive_t *drive)
pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
}
-
/* Set per-drive active and recovery time */
static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- u8 timing, drive_pci, test1, test2;
-
- u16 eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
- u16 xfer_pio = drive->id->eide_pio_modes;
+ u8 drive_pci, test1, test2;
config_drive_art_rwp(drive);
- pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
-
- if (xfer_pio> 4)
- xfer_pio = 0;
-
- if (drive->id->eide_pio_iordy > 0) {
- for (xfer_pio = 5;
- (xfer_pio > 0) &&
- (drive->id->eide_pio_iordy > eide_pio_timing[xfer_pio]);
- xfer_pio--);
- } else {
- xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
- (drive->id->eide_pio_modes & 2) ? 0x04 :
- (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio;
- }
-
- timing = (xfer_pio >= pio) ? xfer_pio : pio;
/* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */
drive_pci = 0x40;
@@ -500,17 +481,18 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
test1 &= ~0x0F;
test2 &= ~0x07;
- switch(timing) {
+ switch(pio) {
case 4: test1 |= 0x01; test2 |= 0x03; break;
case 3: test1 |= 0x03; test2 |= 0x03; break;
case 2: test1 |= 0x04; test2 |= 0x04; break;
case 1: test1 |= 0x07; test2 |= 0x06; break;
+ case 0: /* PIO0: register setting == X000 */
default: break;
}
pci_write_config_byte(dev, drive_pci, test1);
pci_write_config_byte(dev, drive_pci+1, test2);
} else if (chipset_family < ATA_133) {
- switch(timing) { /* active recovery
+ switch(pio) { /* active recovery
v v */
case 4: test1 = 0x30|0x01; break;
case 3: test1 = 0x30|0x03; break;
@@ -525,24 +507,28 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
pci_read_config_dword(dev, drive_pci, &test3);
test3 &= 0xc0c00fff;
if (test3 & 0x08) {
- test3 |= (unsigned long)ini_time_value[ATA_133][timing] << 12;
- test3 |= (unsigned long)act_time_value[ATA_133][timing] << 16;
- test3 |= (unsigned long)rco_time_value[ATA_133][timing] << 24;
+ test3 |= ini_time_value[ATA_133][pio] << 12;
+ test3 |= act_time_value[ATA_133][pio] << 16;
+ test3 |= rco_time_value[ATA_133][pio] << 24;
} else {
- test3 |= (unsigned long)ini_time_value[ATA_100][timing] << 12;
- test3 |= (unsigned long)act_time_value[ATA_100][timing] << 16;
- test3 |= (unsigned long)rco_time_value[ATA_100][timing] << 24;
+ test3 |= ini_time_value[ATA_100][pio] << 12;
+ test3 |= act_time_value[ATA_100][pio] << 16;
+ test3 |= rco_time_value[ATA_100][pio] << 24;
}
pci_write_config_dword(dev, drive_pci, test3);
}
}
-static int config_chipset_for_pio (ide_drive_t *drive, u8 pio)
+static int sis5513_tune_drive(ide_drive_t *drive, u8 pio)
{
- if (pio == 255)
- pio = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
config_art_rwp_pio(drive, pio);
- return ide_config_drive_speed(drive, XFER_PIO_0 + min_t(u8, pio, 4));
+ return ide_config_drive_speed(drive, XFER_PIO_0 + pio);
+}
+
+static void sis5513_tuneproc(ide_drive_t *drive, u8 pio)
+{
+ (void)sis5513_tune_drive(drive, pio);
}
static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed)
@@ -622,25 +608,26 @@ static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed)
case XFER_SW_DMA_1:
case XFER_SW_DMA_0:
break;
- case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4));
- case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3));
- case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2));
- case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1));
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
case XFER_PIO_0:
- default: return((int) config_chipset_for_pio(drive, 0));
+ return sis5513_tune_drive(drive, speed - XFER_PIO_0);
+ default:
+ BUG();
+ break;
}
- return ((int) ide_config_drive_speed(drive, speed));
-}
-
-static void sis5513_tune_drive (ide_drive_t *drive, u8 pio)
-{
- (void) config_chipset_for_pio(drive, pio);
+ return ide_config_drive_speed(drive, speed);
}
static int sis5513_config_xfer_rate(ide_drive_t *drive)
{
- config_art_rwp_pio(drive, 5);
+ /*
+ * TODO: always set PIO mode and remove this
+ */
+ sis5513_tuneproc(drive, 255);
drive->init_speed = 0;
@@ -648,7 +635,7 @@ static int sis5513_config_xfer_rate(ide_drive_t *drive)
return 0;
if (ide_use_fast_pio(drive))
- sis5513_tune_drive(drive, 5);
+ sis5513_tuneproc(drive, 255);
return -1;
}
@@ -836,7 +823,7 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
if (!hwif->irq)
hwif->irq = hwif->channel ? 15 : 14;
- hwif->tuneproc = &sis5513_tune_drive;
+ hwif->tuneproc = &sis5513_tuneproc;
hwif->speedproc = &sis5513_tune_chipset;
if (!(hwif->dma_base)) {
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index fe3b4b91f854..7c383d9cc472 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -82,7 +82,14 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio)
pio = ide_get_best_pio_mode(drive, pio, 5, &p);
- drive->drive_data = drv_ctrl = get_pio_timings(&p);
+ drv_ctrl = get_pio_timings(&p);
+
+ /*
+ * Store the PIO timings so that we can restore them
+ * in case DMA will be turned off...
+ */
+ drive->drive_data &= 0xffff0000;
+ drive->drive_data |= drv_ctrl;
if (!drive->using_dma) {
/*
@@ -100,17 +107,55 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio)
}
/*
- * Configure the drive for DMA.
- * We'll program the chipset only when DMA is actually turned on.
+ * Configure the drive and chipset for a new transfer speed.
*/
-static int config_for_dma(ide_drive_t *drive)
+static int sl82c105_tune_chipset(ide_drive_t *drive, u8 speed)
{
- DBG(("config_for_dma(drive:%s)\n", drive->name));
+ static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
+ u16 drv_ctrl;
- if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0)
- return 0;
+ DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
+ drive->name, ide_xfer_verbose(speed)));
- return ide_dma_enable(drive);
+ speed = ide_rate_filter(drive, speed);
+
+ switch (speed) {
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
+
+ /*
+ * Store the DMA timings so that we can actually program
+ * them when DMA will be turned on...
+ */
+ drive->drive_data &= 0x0000ffff;
+ drive->drive_data |= (unsigned long)drv_ctrl << 16;
+
+ /*
+ * If we are already using DMA, we just reprogram
+ * the drive control register.
+ */
+ if (drive->using_dma) {
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
+ int reg = 0x44 + drive->dn * 4;
+
+ pci_write_config_word(dev, reg, drv_ctrl);
+ }
+ break;
+ case XFER_PIO_5:
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ (void) sl82c105_tune_pio(drive, speed - XFER_PIO_0);
+ break;
+ default:
+ return -1;
+ }
+
+ return ide_config_drive_speed(drive, speed);
}
/*
@@ -120,7 +165,7 @@ static int sl82c105_ide_dma_check(ide_drive_t *drive)
{
DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name));
- if (ide_use_dma(drive) && config_for_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
return -1;
@@ -219,7 +264,7 @@ static int sl82c105_ide_dma_on(ide_drive_t *drive)
rc = __ide_dma_on(drive);
if (rc == 0) {
- pci_write_config_word(dev, reg, 0x0200);
+ pci_write_config_word(dev, reg, drive->drive_data >> 16);
printk(KERN_INFO "%s: DMA enabled\n", drive->name);
}
@@ -304,7 +349,7 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
/*
* The bridge should be part of the same device, but function 0.
*/
- bridge = pci_find_slot(dev->bus->number,
+ bridge = pci_get_bus_and_slot(dev->bus->number,
PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
if (!bridge)
return -1;
@@ -314,13 +359,15 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
*/
if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
- bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA)
+ bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) {
+ pci_dev_put(bridge);
return -1;
-
+ }
/*
* We need to find function 0's revision, not function 1
*/
pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
+ pci_dev_put(bridge);
return rev;
}
@@ -357,6 +404,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
hwif->tuneproc = &sl82c105_tune_drive;
+ hwif->speedproc = &sl82c105_tune_chipset;
hwif->selectproc = &sl82c105_selectproc;
hwif->resetproc = &sl82c105_resetproc;
@@ -388,7 +436,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
}
hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x04;
+ hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &sl82c105_ide_dma_check;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 558c9a0fc8b9..e85f7013de57 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -38,6 +38,7 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include <rdma/ib_cache.h>
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index eff591deeb46..e840434a96d8 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -306,7 +306,9 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
do {
spin_lock_irqsave(&cm.lock, flags);
ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
- next_id++, &id);
+ next_id, &id);
+ if (!ret)
+ next_id = ((unsigned) id + 1) & MAX_ID_MASK;
spin_unlock_irqrestore(&cm.lock, flags);
} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index fde92ce45153..2eb52b7a71da 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -346,12 +346,33 @@ static void cma_deref_id(struct rdma_id_private *id_priv)
complete(&id_priv->comp);
}
-static void cma_release_remove(struct rdma_id_private *id_priv)
+static int cma_disable_remove(struct rdma_id_private *id_priv,
+ enum cma_state state)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&id_priv->lock, flags);
+ if (id_priv->state == state) {
+ atomic_inc(&id_priv->dev_remove);
+ ret = 0;
+ } else
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&id_priv->lock, flags);
+ return ret;
+}
+
+static void cma_enable_remove(struct rdma_id_private *id_priv)
{
if (atomic_dec_and_test(&id_priv->dev_remove))
wake_up(&id_priv->wait_remove);
}
+static int cma_has_cm_dev(struct rdma_id_private *id_priv)
+{
+ return (id_priv->id.device && id_priv->cm_id.ib);
+}
+
struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
void *context, enum rdma_port_space ps)
{
@@ -884,9 +905,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
struct rdma_cm_event event;
int ret = 0;
- atomic_inc(&id_priv->dev_remove);
- if (!cma_comp(id_priv, CMA_CONNECT))
- goto out;
+ if (cma_disable_remove(id_priv, CMA_CONNECT))
+ return 0;
memset(&event, 0, sizeof event);
switch (ib_event->event) {
@@ -942,12 +962,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
/* Destroy the CM ID by returning a non-zero value. */
id_priv->cm_id.ib = NULL;
cma_exch(id_priv, CMA_DESTROYING);
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
rdma_destroy_id(&id_priv->id);
return ret;
}
out:
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
return ret;
}
@@ -1057,11 +1077,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
int offset, ret;
listen_id = cm_id->context;
- atomic_inc(&listen_id->dev_remove);
- if (!cma_comp(listen_id, CMA_LISTEN)) {
- ret = -ECONNABORTED;
- goto out;
- }
+ if (cma_disable_remove(listen_id, CMA_LISTEN))
+ return -ECONNABORTED;
memset(&event, 0, sizeof event);
offset = cma_user_data_offset(listen_id->id.ps);
@@ -1101,11 +1118,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
release_conn_id:
cma_exch(conn_id, CMA_DESTROYING);
- cma_release_remove(conn_id);
+ cma_enable_remove(conn_id);
rdma_destroy_id(&conn_id->id);
out:
- cma_release_remove(listen_id);
+ cma_enable_remove(listen_id);
return ret;
}
@@ -1171,9 +1188,10 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
struct sockaddr_in *sin;
int ret = 0;
- memset(&event, 0, sizeof event);
- atomic_inc(&id_priv->dev_remove);
+ if (cma_disable_remove(id_priv, CMA_CONNECT))
+ return 0;
+ memset(&event, 0, sizeof event);
switch (iw_event->event) {
case IW_CM_EVENT_CLOSE:
event.event = RDMA_CM_EVENT_DISCONNECTED;
@@ -1214,12 +1232,12 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
/* Destroy the CM ID by returning a non-zero value. */
id_priv->cm_id.iw = NULL;
cma_exch(id_priv, CMA_DESTROYING);
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
rdma_destroy_id(&id_priv->id);
return ret;
}
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
return ret;
}
@@ -1234,11 +1252,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
int ret;
listen_id = cm_id->context;
- atomic_inc(&listen_id->dev_remove);
- if (!cma_comp(listen_id, CMA_LISTEN)) {
- ret = -ECONNABORTED;
- goto out;
- }
+ if (cma_disable_remove(listen_id, CMA_LISTEN))
+ return -ECONNABORTED;
/* Create a new RDMA id for the new IW CM ID */
new_cm_id = rdma_create_id(listen_id->id.event_handler,
@@ -1255,13 +1270,13 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr);
if (!dev) {
ret = -EADDRNOTAVAIL;
- cma_release_remove(conn_id);
+ cma_enable_remove(conn_id);
rdma_destroy_id(new_cm_id);
goto out;
}
ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL);
if (ret) {
- cma_release_remove(conn_id);
+ cma_enable_remove(conn_id);
rdma_destroy_id(new_cm_id);
goto out;
}
@@ -1270,7 +1285,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
ret = cma_acquire_dev(conn_id);
mutex_unlock(&lock);
if (ret) {
- cma_release_remove(conn_id);
+ cma_enable_remove(conn_id);
rdma_destroy_id(new_cm_id);
goto out;
}
@@ -1293,14 +1308,14 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
/* User wants to destroy the CM ID */
conn_id->cm_id.iw = NULL;
cma_exch(conn_id, CMA_DESTROYING);
- cma_release_remove(conn_id);
+ cma_enable_remove(conn_id);
rdma_destroy_id(&conn_id->id);
}
out:
if (dev)
dev_put(dev);
- cma_release_remove(listen_id);
+ cma_enable_remove(listen_id);
return ret;
}
@@ -1519,7 +1534,7 @@ static void cma_work_handler(struct work_struct *_work)
destroy = 1;
}
out:
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
cma_deref_id(id_priv);
if (destroy)
rdma_destroy_id(&id_priv->id);
@@ -1711,13 +1726,13 @@ static void addr_handler(int status, struct sockaddr *src_addr,
if (id_priv->id.event_handler(&id_priv->id, &event)) {
cma_exch(id_priv, CMA_DESTROYING);
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
cma_deref_id(id_priv);
rdma_destroy_id(&id_priv->id);
return;
}
out:
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
cma_deref_id(id_priv);
}
@@ -2042,11 +2057,10 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
int ret = 0;
- memset(&event, 0, sizeof event);
- atomic_inc(&id_priv->dev_remove);
- if (!cma_comp(id_priv, CMA_CONNECT))
- goto out;
+ if (cma_disable_remove(id_priv, CMA_CONNECT))
+ return 0;
+ memset(&event, 0, sizeof event);
switch (ib_event->event) {
case IB_CM_SIDR_REQ_ERROR:
event.event = RDMA_CM_EVENT_UNREACHABLE;
@@ -2084,12 +2098,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
/* Destroy the CM ID by returning a non-zero value. */
id_priv->cm_id.ib = NULL;
cma_exch(id_priv, CMA_DESTROYING);
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
rdma_destroy_id(&id_priv->id);
return ret;
}
out:
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
return ret;
}
@@ -2413,7 +2427,7 @@ int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_comp(id_priv, CMA_CONNECT))
+ if (!cma_has_cm_dev(id_priv))
return -EINVAL;
switch (id->device->node_type) {
@@ -2435,7 +2449,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_comp(id_priv, CMA_CONNECT))
+ if (!cma_has_cm_dev(id_priv))
return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) {
@@ -2466,8 +2480,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (!cma_comp(id_priv, CMA_CONNECT) &&
- !cma_comp(id_priv, CMA_DISCONNECT))
+ if (!cma_has_cm_dev(id_priv))
return -EINVAL;
switch (rdma_node_get_transport(id->device->node_type)) {
@@ -2499,10 +2512,9 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
int ret;
id_priv = mc->id_priv;
- atomic_inc(&id_priv->dev_remove);
- if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
- !cma_comp(id_priv, CMA_ADDR_RESOLVED))
- goto out;
+ if (cma_disable_remove(id_priv, CMA_ADDR_BOUND) &&
+ cma_disable_remove(id_priv, CMA_ADDR_RESOLVED))
+ return 0;
if (!status && id_priv->id.qp)
status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
@@ -2524,12 +2536,12 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
ret = id_priv->id.event_handler(&id_priv->id, &event);
if (ret) {
cma_exch(id_priv, CMA_DESTROYING);
- cma_release_remove(id_priv);
+ cma_enable_remove(id_priv);
rdma_destroy_id(&id_priv->id);
return 0;
}
-out:
- cma_release_remove(id_priv);
+
+ cma_enable_remove(id_priv);
return 0;
}
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 592c90aa3183..3ada17c0f239 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include "core_priv.h"
@@ -149,6 +150,18 @@ static int alloc_name(char *name)
return 0;
}
+static int start_port(struct ib_device *device)
+{
+ return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
+}
+
+
+static int end_port(struct ib_device *device)
+{
+ return (device->node_type == RDMA_NODE_IB_SWITCH) ?
+ 0 : device->phys_port_cnt;
+}
+
/**
* ib_alloc_device - allocate an IB device struct
* @size:size of structure to allocate
@@ -208,6 +221,45 @@ static int add_client_context(struct ib_device *device, struct ib_client *client
return 0;
}
+static int read_port_table_lengths(struct ib_device *device)
+{
+ struct ib_port_attr *tprops = NULL;
+ int num_ports, ret = -ENOMEM;
+ u8 port_index;
+
+ tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
+ if (!tprops)
+ goto out;
+
+ num_ports = end_port(device) - start_port(device) + 1;
+
+ device->pkey_tbl_len = kmalloc(sizeof *device->pkey_tbl_len * num_ports,
+ GFP_KERNEL);
+ device->gid_tbl_len = kmalloc(sizeof *device->gid_tbl_len * num_ports,
+ GFP_KERNEL);
+ if (!device->pkey_tbl_len || !device->gid_tbl_len)
+ goto err;
+
+ for (port_index = 0; port_index < num_ports; ++port_index) {
+ ret = ib_query_port(device, port_index + start_port(device),
+ tprops);
+ if (ret)
+ goto err;
+ device->pkey_tbl_len[port_index] = tprops->pkey_tbl_len;
+ device->gid_tbl_len[port_index] = tprops->gid_tbl_len;
+ }
+
+ ret = 0;
+ goto out;
+
+err:
+ kfree(device->gid_tbl_len);
+ kfree(device->pkey_tbl_len);
+out:
+ kfree(tprops);
+ return ret;
+}
+
/**
* ib_register_device - Register an IB device with IB core
* @device:Device to register
@@ -239,10 +291,19 @@ int ib_register_device(struct ib_device *device)
spin_lock_init(&device->event_handler_lock);
spin_lock_init(&device->client_data_lock);
+ ret = read_port_table_lengths(device);
+ if (ret) {
+ printk(KERN_WARNING "Couldn't create table lengths cache for device %s\n",
+ device->name);
+ goto out;
+ }
+
ret = ib_device_register_sysfs(device);
if (ret) {
printk(KERN_WARNING "Couldn't register device %s with driver model\n",
device->name);
+ kfree(device->gid_tbl_len);
+ kfree(device->pkey_tbl_len);
goto out;
}
@@ -284,6 +345,9 @@ void ib_unregister_device(struct ib_device *device)
list_del(&device->core_list);
+ kfree(device->gid_tbl_len);
+ kfree(device->pkey_tbl_len);
+
mutex_unlock(&device_mutex);
spin_lock_irqsave(&device->client_data_lock, flags);
@@ -506,10 +570,7 @@ int ib_query_port(struct ib_device *device,
u8 port_num,
struct ib_port_attr *port_attr)
{
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
- if (port_num)
- return -EINVAL;
- } else if (port_num < 1 || port_num > device->phys_port_cnt)
+ if (port_num < start_port(device) || port_num > end_port(device))
return -EINVAL;
return device->query_port(device, port_num, port_attr);
@@ -581,10 +642,7 @@ int ib_modify_port(struct ib_device *device,
u8 port_num, int port_modify_mask,
struct ib_port_modify *port_modify)
{
- if (device->node_type == RDMA_NODE_IB_SWITCH) {
- if (port_num)
- return -EINVAL;
- } else if (port_num < 1 || port_num > device->phys_port_cnt)
+ if (port_num < start_port(device) || port_num > end_port(device))
return -EINVAL;
return device->modify_port(device, port_num, port_modify_mask,
@@ -592,6 +650,68 @@ int ib_modify_port(struct ib_device *device,
}
EXPORT_SYMBOL(ib_modify_port);
+/**
+ * ib_find_gid - Returns the port number and GID table index where
+ * a specified GID value occurs.
+ * @device: The device to query.
+ * @gid: The GID value to search for.
+ * @port_num: The port number of the device where the GID value was found.
+ * @index: The index into the GID table where the GID was found. This
+ * parameter may be NULL.
+ */
+int ib_find_gid(struct ib_device *device, union ib_gid *gid,
+ u8 *port_num, u16 *index)
+{
+ union ib_gid tmp_gid;
+ int ret, port, i;
+
+ for (port = start_port(device); port <= end_port(device); ++port) {
+ for (i = 0; i < device->gid_tbl_len[port - start_port(device)]; ++i) {
+ ret = ib_query_gid(device, port, i, &tmp_gid);
+ if (ret)
+ return ret;
+ if (!memcmp(&tmp_gid, gid, sizeof *gid)) {
+ *port_num = port;
+ if (index)
+ *index = i;
+ return 0;
+ }
+ }
+ }
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL(ib_find_gid);
+
+/**
+ * ib_find_pkey - Returns the PKey table index where a specified
+ * PKey value occurs.
+ * @device: The device to query.
+ * @port_num: The port number of the device to search for the PKey.
+ * @pkey: The PKey value to search for.
+ * @index: The index into the PKey table where the PKey was found.
+ */
+int ib_find_pkey(struct ib_device *device,
+ u8 port_num, u16 pkey, u16 *index)
+{
+ int ret, i;
+ u16 tmp_pkey;
+
+ for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) {
+ ret = ib_query_pkey(device, port_num, i, &tmp_pkey);
+ if (ret)
+ return ret;
+
+ if (pkey == tmp_pkey) {
+ *index = i;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL(ib_find_pkey);
+
static int __init ib_core_init(void)
{
int ret;
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index f32ca5fbb26b..b4aec5103c99 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -36,6 +36,7 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
+#include <linux/sched.h>
#include "uverbs.h"
@@ -209,8 +210,10 @@ void ib_umem_release(struct ib_umem *umem)
__ib_umem_release(umem->context->device, umem, 1);
mm = get_task_mm(current);
- if (!mm)
+ if (!mm) {
+ kfree(umem);
return;
+ }
diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index f64d42b08674..1d286d3cc2d5 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -277,6 +277,7 @@ void ehca_cleanup_mrmw_cache(void);
extern spinlock_t ehca_qp_idr_lock;
extern spinlock_t ehca_cq_idr_lock;
+extern spinlock_t hcall_lock;
extern struct idr ehca_qp_idr;
extern struct idr ehca_cq_idr;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 82dda2faf4d0..100329ba3343 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -517,12 +517,11 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
else {
struct ehca_cq *cq = eq->eqe_cache[i].cq;
comp_event_callback(cq);
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ spin_lock(&ehca_cq_idr_lock);
cq->nr_events--;
if (!cq->nr_events)
wake_up(&cq->wait_completion);
- spin_unlock_irqrestore(&ehca_cq_idr_lock,
- flags);
+ spin_unlock(&ehca_cq_idr_lock);
}
} else {
ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -711,6 +710,7 @@ static void destroy_comp_task(struct ehca_comp_pool *pool,
kthread_stop(task);
}
+#ifdef CONFIG_HOTPLUG_CPU
static void take_over_work(struct ehca_comp_pool *pool,
int cpu)
{
@@ -735,7 +735,6 @@ static void take_over_work(struct ehca_comp_pool *pool,
}
-#ifdef CONFIG_HOTPLUG_CPU
static int comp_pool_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index fe90e7454560..c3f99f33b49c 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0022");
+MODULE_VERSION("SVNEHCA_0023");
int ehca_open_aqp1 = 0;
int ehca_debug_level = 0;
@@ -62,7 +62,7 @@ int ehca_use_hp_mr = 0;
int ehca_port_act_time = 30;
int ehca_poll_all_eqs = 1;
int ehca_static_rate = -1;
-int ehca_scaling_code = 1;
+int ehca_scaling_code = 0;
module_param_named(open_aqp1, ehca_open_aqp1, int, 0);
module_param_named(debug_level, ehca_debug_level, int, 0);
@@ -98,6 +98,7 @@ MODULE_PARM_DESC(scaling_code,
spinlock_t ehca_qp_idr_lock;
spinlock_t ehca_cq_idr_lock;
+spinlock_t hcall_lock;
DEFINE_IDR(ehca_qp_idr);
DEFINE_IDR(ehca_cq_idr);
@@ -453,15 +454,14 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
ehca_show_debug_level, ehca_store_debug_level);
-void ehca_create_driver_sysfs(struct ibmebus_driver *drv)
-{
- driver_create_file(&drv->driver, &driver_attr_debug_level);
-}
+static struct attribute *ehca_drv_attrs[] = {
+ &driver_attr_debug_level.attr,
+ NULL
+};
-void ehca_remove_driver_sysfs(struct ibmebus_driver *drv)
-{
- driver_remove_file(&drv->driver, &driver_attr_debug_level);
-}
+static struct attribute_group ehca_drv_attr_grp = {
+ .attrs = ehca_drv_attrs
+};
#define EHCA_RESOURCE_ATTR(name) \
static ssize_t ehca_show_##name(struct device *dev, \
@@ -523,44 +523,28 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
}
static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
+static struct attribute *ehca_dev_attrs[] = {
+ &dev_attr_adapter_handle.attr,
+ &dev_attr_num_ports.attr,
+ &dev_attr_hw_ver.attr,
+ &dev_attr_max_eq.attr,
+ &dev_attr_cur_eq.attr,
+ &dev_attr_max_cq.attr,
+ &dev_attr_cur_cq.attr,
+ &dev_attr_max_qp.attr,
+ &dev_attr_cur_qp.attr,
+ &dev_attr_max_mr.attr,
+ &dev_attr_cur_mr.attr,
+ &dev_attr_max_mw.attr,
+ &dev_attr_cur_mw.attr,
+ &dev_attr_max_pd.attr,
+ &dev_attr_max_ah.attr,
+ NULL
+};
-void ehca_create_device_sysfs(struct ibmebus_dev *dev)
-{
- device_create_file(&dev->ofdev.dev, &dev_attr_adapter_handle);
- device_create_file(&dev->ofdev.dev, &dev_attr_num_ports);
- device_create_file(&dev->ofdev.dev, &dev_attr_hw_ver);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_eq);
- device_create_file(&dev->ofdev.dev, &dev_attr_cur_eq);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_cq);
- device_create_file(&dev->ofdev.dev, &dev_attr_cur_cq);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_qp);
- device_create_file(&dev->ofdev.dev, &dev_attr_cur_qp);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_mr);
- device_create_file(&dev->ofdev.dev, &dev_attr_cur_mr);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_mw);
- device_create_file(&dev->ofdev.dev, &dev_attr_cur_mw);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_pd);
- device_create_file(&dev->ofdev.dev, &dev_attr_max_ah);
-}
-
-void ehca_remove_device_sysfs(struct ibmebus_dev *dev)
-{
- device_remove_file(&dev->ofdev.dev, &dev_attr_adapter_handle);
- device_remove_file(&dev->ofdev.dev, &dev_attr_num_ports);
- device_remove_file(&dev->ofdev.dev, &dev_attr_hw_ver);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_eq);
- device_remove_file(&dev->ofdev.dev, &dev_attr_cur_eq);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_cq);
- device_remove_file(&dev->ofdev.dev, &dev_attr_cur_cq);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_qp);
- device_remove_file(&dev->ofdev.dev, &dev_attr_cur_qp);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_mr);
- device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mr);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_mw);
- device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mw);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_pd);
- device_remove_file(&dev->ofdev.dev, &dev_attr_max_ah);
-}
+static struct attribute_group ehca_dev_attr_grp = {
+ .attrs = ehca_dev_attrs
+};
static int __devinit ehca_probe(struct ibmebus_dev *dev,
const struct of_device_id *id)
@@ -668,7 +652,10 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
}
}
- ehca_create_device_sysfs(dev);
+ ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+ if (ret) /* only complain; we can live without attributes */
+ ehca_err(&shca->ib_device,
+ "Cannot create device attributes ret=%d", ret);
spin_lock(&shca_list_lock);
list_add(&shca->shca_list, &shca_list);
@@ -720,7 +707,7 @@ static int __devexit ehca_remove(struct ibmebus_dev *dev)
struct ehca_shca *shca = dev->ofdev.dev.driver_data;
int ret;
- ehca_remove_device_sysfs(dev);
+ sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
if (ehca_open_aqp1 == 1) {
int i;
@@ -812,11 +799,12 @@ int __init ehca_module_init(void)
int ret;
printk(KERN_INFO "eHCA Infiniband Device Driver "
- "(Rel.: SVNEHCA_0022)\n");
+ "(Rel.: SVNEHCA_0023)\n");
idr_init(&ehca_qp_idr);
idr_init(&ehca_cq_idr);
spin_lock_init(&ehca_qp_idr_lock);
spin_lock_init(&ehca_cq_idr_lock);
+ spin_lock_init(&hcall_lock);
INIT_LIST_HEAD(&shca_list);
spin_lock_init(&shca_list_lock);
@@ -838,7 +826,9 @@ int __init ehca_module_init(void)
goto module_init2;
}
- ehca_create_driver_sysfs(&ehca_driver);
+ ret = sysfs_create_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp);
+ if (ret) /* only complain; we can live without attributes */
+ ehca_gen_err("Cannot create driver attributes ret=%d", ret);
if (ehca_poll_all_eqs != 1) {
ehca_gen_err("WARNING!!!");
@@ -865,7 +855,7 @@ void __exit ehca_module_exit(void)
if (ehca_poll_all_eqs == 1)
del_timer_sync(&poll_eqs_timer);
- ehca_remove_driver_sysfs(&ehca_driver);
+ sysfs_remove_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp);
ibmebus_unregister_driver(&ehca_driver);
ehca_destroy_slab_caches();
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 84c5bb498563..add79bd44e39 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -2050,13 +2050,10 @@ int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc)
switch (hipz_rc) {
case H_SUCCESS: /* successful completion */
return 0;
- case H_ADAPTER_PARM: /* invalid adapter handle */
- case H_RT_PARM: /* invalid resource type */
case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
- case H_MLENGTH_PARM: /* invalid memory length */
- case H_MEM_ACCESS_PARM: /* invalid access controls */
case H_CONSTRAINED: /* resource constraint */
- return -EINVAL;
+ case H_NO_MEM:
+ return -ENOMEM;
case H_BUSY: /* long busy */
return -EBUSY;
default:
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index df0516f24379..b5bc787c77b6 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -523,6 +523,8 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
goto create_qp_exit1;
}
+ my_qp->ib_qp.qp_num = my_qp->real_qp_num;
+
switch (init_attr->qp_type) {
case IB_QPT_RC:
if (isdaqp == 0) {
@@ -568,7 +570,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr;
parms.act_nr_send_sges = init_attr->cap.max_send_sge;
parms.act_nr_recv_sges = init_attr->cap.max_recv_sge;
- my_qp->real_qp_num =
+ my_qp->ib_qp.qp_num =
(init_attr->qp_type == IB_QPT_SMI) ? 0 : 1;
}
@@ -595,7 +597,6 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
my_qp->ib_qp.recv_cq = init_attr->recv_cq;
my_qp->ib_qp.send_cq = init_attr->send_cq;
- my_qp->ib_qp.qp_num = my_qp->real_qp_num;
my_qp->ib_qp.qp_type = init_attr->qp_type;
my_qp->qp_type = init_attr->qp_type;
@@ -968,17 +969,21 @@ static int internal_modify_qp(struct ib_qp *ibqp,
((ehca_mult - 1) / ah_mult) : 0;
else
mqpcb->max_static_rate = 0;
-
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);
/*
+ * Always supply the GRH flag, even if it's zero, to give the
+ * hypervisor a clear "yes" or "no" instead of a "perhaps"
+ */
+ update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+
+ /*
* only if GRH is TRUE we might consider SOURCE_GID_IDX
* and DEST_GID otherwise phype will return H_ATTR_PARM!!!
*/
if (attr->ah_attr.ah_flags == IB_AH_GRH) {
- mqpcb->send_grh_flag = 1 << 31;
- update_mask |=
- EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+ mqpcb->send_grh_flag = 1;
+
mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index;
update_mask |=
EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index b564fcd3b282..7f0beec74f70 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -154,7 +154,8 @@ static long ehca_plpar_hcall9(unsigned long opcode,
unsigned long arg9)
{
long ret;
- int i, sleep_msecs;
+ int i, sleep_msecs, lock_is_set = 0;
+ unsigned long flags;
ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
"arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
@@ -162,10 +163,18 @@ static long ehca_plpar_hcall9(unsigned long opcode,
arg8, arg9);
for (i = 0; i < 5; i++) {
+ if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
+ spin_lock_irqsave(&hcall_lock, flags);
+ lock_is_set = 1;
+ }
+
ret = plpar_hcall9(opcode, outs,
arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9);
+ if (lock_is_set)
+ spin_unlock_irqrestore(&hcall_lock, flags);
+
if (H_IS_LONG_BUSY(ret)) {
sleep_msecs = get_longbusy_msecs(ret);
msleep_interruptible(sleep_msecs);
@@ -193,11 +202,11 @@ static long ehca_plpar_hcall9(unsigned long opcode,
opcode, ret, outs[0], outs[1], outs[2], outs[3],
outs[4], outs[5], outs[6], outs[7], outs[8]);
return ret;
-
}
return H_BUSY;
}
+
u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
struct ehca_pfeq *pfeq,
const u32 neq_control,
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index 1b9c30857754..4e2e3dfeb2c8 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -747,7 +747,6 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
static int ipath_pe_intconfig(struct ipath_devdata *dd)
{
- u64 val;
u32 chiprev;
/*
@@ -760,9 +759,9 @@ static int ipath_pe_intconfig(struct ipath_devdata *dd)
if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) {
/* Rev2+ reports extra errors via internal GPIO pins */
dd->ipath_flags |= IPATH_GPIO_ERRINTRS;
- val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
- val |= IPATH_GPIO_ERRINTR_MASK;
- ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+ dd->ipath_gpio_mask |= IPATH_GPIO_ERRINTR_MASK;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+ dd->ipath_gpio_mask);
}
return 0;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 45d033169c6e..a90d3b5699c4 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -1056,7 +1056,7 @@ irqreturn_t ipath_intr(int irq, void *data)
gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT);
chk0rcv = 1;
}
- if (unlikely(gpiostatus)) {
+ if (gpiostatus) {
/*
* Some unexpected bits remain. If they could have
* caused the interrupt, complain and clear.
@@ -1065,9 +1065,8 @@ irqreturn_t ipath_intr(int irq, void *data)
* GPIO interrupts, possibly on a "three strikes"
* basis.
*/
- u32 mask;
- mask = ipath_read_kreg32(
- dd, dd->ipath_kregs->kr_gpio_mask);
+ const u32 mask = (u32) dd->ipath_gpio_mask;
+
if (mask & gpiostatus) {
ipath_dbg("Unexpected GPIO IRQ bits %x\n",
gpiostatus & mask);
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index e900c2593f44..12194f3dd8cc 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -397,6 +397,8 @@ struct ipath_devdata {
unsigned long ipath_pioavailshadow[8];
/* shadow of kr_gpio_out, for rmw ops */
u64 ipath_gpio_out;
+ /* shadow the gpio mask register */
+ u64 ipath_gpio_mask;
/* kr_revision shadow */
u64 ipath_revision;
/*
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 12933e77c7e9..bb70845279b8 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1387,13 +1387,12 @@ static int enable_timer(struct ipath_devdata *dd)
* processing.
*/
if (dd->ipath_flags & IPATH_GPIO_INTR) {
- u64 val;
ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
0x2074076542310ULL);
/* Enable GPIO bit 2 interrupt */
- val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
- val |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
- ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+ dd->ipath_gpio_mask |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+ dd->ipath_gpio_mask);
}
init_timer(&dd->verbs_timer);
@@ -1412,8 +1411,9 @@ static int disable_timer(struct ipath_devdata *dd)
u64 val;
/* Disable GPIO bit 2 interrupt */
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
- val &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
- ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+ dd->ipath_gpio_mask &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+ dd->ipath_gpio_mask);
/*
* We might want to undo changes to debugportselect,
* but how?
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
index 085e28b939ec..dd691cfa5079 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
@@ -165,10 +165,9 @@ static int ipath_mcast_add(struct ipath_ibdev *dev,
{
struct rb_node **n = &mcast_tree.rb_node;
struct rb_node *pn = NULL;
- unsigned long flags;
int ret;
- spin_lock_irqsave(&mcast_lock, flags);
+ spin_lock_irq(&mcast_lock);
while (*n) {
struct ipath_mcast *tmcast;
@@ -228,7 +227,7 @@ static int ipath_mcast_add(struct ipath_ibdev *dev,
ret = 0;
bail:
- spin_unlock_irqrestore(&mcast_lock, flags);
+ spin_unlock_irq(&mcast_lock);
return ret;
}
@@ -289,17 +288,16 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
struct ipath_mcast *mcast = NULL;
struct ipath_mcast_qp *p, *tmp;
struct rb_node *n;
- unsigned long flags;
int last = 0;
int ret;
- spin_lock_irqsave(&mcast_lock, flags);
+ spin_lock_irq(&mcast_lock);
/* Find the GID in the mcast table. */
n = mcast_tree.rb_node;
while (1) {
if (n == NULL) {
- spin_unlock_irqrestore(&mcast_lock, flags);
+ spin_unlock_irq(&mcast_lock);
ret = -EINVAL;
goto bail;
}
@@ -334,7 +332,7 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
break;
}
- spin_unlock_irqrestore(&mcast_lock, flags);
+ spin_unlock_irq(&mcast_lock);
if (p) {
/*
@@ -348,9 +346,9 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
atomic_dec(&mcast->refcount);
wait_event(mcast->wait, !atomic_read(&mcast->refcount));
ipath_mcast_free(mcast);
- spin_lock(&dev->n_mcast_grps_lock);
+ spin_lock_irq(&dev->n_mcast_grps_lock);
dev->n_mcast_grps_allocated--;
- spin_unlock(&dev->n_mcast_grps_lock);
+ spin_unlock_irq(&dev->n_mcast_grps_lock);
}
ret = 0;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 688ecb4c39f3..402f3a20ec0a 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -489,6 +489,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->uar_map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
if (!ibdev->uar_map)
goto err_uar;
+ MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock);
INIT_LIST_HEAD(&ibdev->pgdir_list);
mutex_init(&ibdev->pgdir_mutex);
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 5cd706908450..a824bc5f79fd 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -188,14 +188,32 @@ static int send_wqe_overhead(enum ib_qp_type type)
}
}
-static int set_qp_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
- enum ib_qp_type type, struct mlx4_ib_qp *qp)
+static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ struct mlx4_ib_qp *qp)
{
- /* Sanity check QP size before proceeding */
+ /* Sanity check RQ size before proceeding */
+ if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
+ cap->max_recv_sge > dev->dev->caps.max_rq_sg)
+ return -EINVAL;
+
+ qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0;
+
+ qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge *
+ sizeof (struct mlx4_wqe_data_seg)));
+ qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg);
+
+ cap->max_recv_wr = qp->rq.max;
+ cap->max_recv_sge = qp->rq.max_gs;
+
+ return 0;
+}
+
+static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ enum ib_qp_type type, struct mlx4_ib_qp *qp)
+{
+ /* Sanity check SQ size before proceeding */
if (cap->max_send_wr > dev->dev->caps.max_wqes ||
- cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_send_sge > dev->dev->caps.max_sq_sg ||
- cap->max_recv_sge > dev->dev->caps.max_rq_sg ||
cap->max_inline_data + send_wqe_overhead(type) +
sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz)
return -EINVAL;
@@ -208,12 +226,7 @@ static int set_qp_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg)
return -EINVAL;
- qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0;
- qp->sq.max = cap->max_send_wr ? roundup_pow_of_two(cap->max_send_wr) : 0;
-
- qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge *
- sizeof (struct mlx4_wqe_data_seg)));
- qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg);
+ qp->sq.max = cap->max_send_wr ? roundup_pow_of_two(cap->max_send_wr) : 1;
qp->sq.wqe_shift = ilog2(roundup_pow_of_two(max(cap->max_send_sge *
sizeof (struct mlx4_wqe_data_seg),
@@ -233,16 +246,26 @@ static int set_qp_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
qp->sq.offset = 0;
}
- cap->max_send_wr = qp->sq.max;
- cap->max_recv_wr = qp->rq.max;
- cap->max_send_sge = qp->sq.max_gs;
- cap->max_recv_sge = qp->rq.max_gs;
+ cap->max_send_wr = qp->sq.max;
+ cap->max_send_sge = qp->sq.max_gs;
cap->max_inline_data = (1 << qp->sq.wqe_shift) - send_wqe_overhead(type) -
sizeof (struct mlx4_wqe_inline_seg);
return 0;
}
+static int set_user_sq_size(struct mlx4_ib_qp *qp,
+ struct mlx4_ib_create_qp *ucmd)
+{
+ qp->sq.max = 1 << ucmd->log_sq_bb_count;
+ qp->sq.wqe_shift = ucmd->log_sq_stride;
+
+ qp->buf_size = (qp->rq.max << qp->rq.wqe_shift) +
+ (qp->sq.max << qp->sq.wqe_shift);
+
+ return 0;
+}
+
static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
@@ -264,7 +287,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
qp->sq.head = 0;
qp->sq.tail = 0;
- err = set_qp_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+ err = set_rq_size(dev, &init_attr->cap, qp);
if (err)
goto err;
@@ -276,6 +299,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
goto err;
}
+ err = set_user_sq_size(qp, &ucmd);
+ if (err)
+ goto err;
+
qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
qp->buf_size, 0);
if (IS_ERR(qp->umem)) {
@@ -297,6 +324,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_mtt;
} else {
+ err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+ if (err)
+ goto err;
+
err = mlx4_ib_db_alloc(dev, &qp->db, 0);
if (err)
goto err;
@@ -573,7 +604,7 @@ static int to_mlx4_st(enum ib_qp_type type)
}
}
-static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, struct ib_qp_attr *attr,
+static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, const struct ib_qp_attr *attr,
int attr_mask)
{
u8 dest_rd_atomic;
@@ -603,7 +634,7 @@ static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, struct ib_qp_attr *att
return cpu_to_be32(hw_access_flags);
}
-static void store_sqp_attrs(struct mlx4_ib_sqp *sqp, struct ib_qp_attr *attr,
+static void store_sqp_attrs(struct mlx4_ib_sqp *sqp, const struct ib_qp_attr *attr,
int attr_mask)
{
if (attr_mask & IB_QP_PKEY_INDEX)
@@ -619,7 +650,7 @@ static void mlx4_set_sched(struct mlx4_qp_path *path, u8 port)
path->sched_queue = (path->sched_queue & 0xbf) | ((port - 1) << 6);
}
-static int mlx4_set_path(struct mlx4_ib_dev *dev, struct ib_ah_attr *ah,
+static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
struct mlx4_qp_path *path, u8 port)
{
path->grh_mylmc = ah->src_path_bits & 0x7f;
@@ -655,14 +686,14 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, struct ib_ah_attr *ah,
return 0;
}
-int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
- int attr_mask, struct ib_udata *udata)
+static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
+ const struct ib_qp_attr *attr, int attr_mask,
+ enum ib_qp_state cur_state, enum ib_qp_state new_state)
{
struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
struct mlx4_ib_qp *qp = to_mqp(ibqp);
struct mlx4_qp_context *context;
enum mlx4_qp_optpar optpar = 0;
- enum ib_qp_state cur_state, new_state;
int sqd_event;
int err = -EINVAL;
@@ -670,34 +701,6 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (!context)
return -ENOMEM;
- mutex_lock(&qp->mutex);
-
- cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
- new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
-
- if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
- goto out;
-
- if ((attr_mask & IB_QP_PKEY_INDEX) &&
- attr->pkey_index >= dev->dev->caps.pkey_table_len) {
- goto out;
- }
-
- if ((attr_mask & IB_QP_PORT) &&
- (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
- goto out;
- }
-
- if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
- attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
- goto out;
- }
-
- if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
- attr->max_dest_rd_atomic > 1 << dev->dev->caps.max_qp_dest_rdma) {
- goto out;
- }
-
context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |
(to_mlx4_st(ibqp->qp_type) << 16));
context->flags |= cpu_to_be32(1 << 8); /* DE? */
@@ -920,11 +923,84 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
}
out:
- mutex_unlock(&qp->mutex);
kfree(context);
return err;
}
+static const struct ib_qp_attr mlx4_ib_qp_attr = { .port_num = 1 };
+static const int mlx4_ib_qp_attr_mask_table[IB_QPT_UD + 1] = {
+ [IB_QPT_UD] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_QKEY),
+ [IB_QPT_UC] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_RC] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
+ IB_QP_QKEY),
+ [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
+ IB_QP_QKEY),
+};
+
+int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_udata *udata)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
+ struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ enum ib_qp_state cur_state, new_state;
+ int err = -EINVAL;
+
+ mutex_lock(&qp->mutex);
+
+ cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
+ new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+ if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
+ goto out;
+
+ if ((attr_mask & IB_QP_PKEY_INDEX) &&
+ attr->pkey_index >= dev->dev->caps.pkey_table_len) {
+ goto out;
+ }
+
+ if ((attr_mask & IB_QP_PORT) &&
+ (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
+ goto out;
+ }
+
+ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+ attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
+ goto out;
+ }
+
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+ attr->max_dest_rd_atomic > dev->dev->caps.max_qp_dest_rdma) {
+ goto out;
+ }
+
+ if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+ err = 0;
+ goto out;
+ }
+
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_ERR) {
+ err = __mlx4_ib_modify_qp(ibqp, &mlx4_ib_qp_attr,
+ mlx4_ib_qp_attr_mask_table[ibqp->qp_type],
+ IB_QPS_RESET, IB_QPS_INIT);
+ if (err)
+ goto out;
+ cur_state = IB_QPS_INIT;
+ }
+
+ err = __mlx4_ib_modify_qp(ibqp, attr, attr_mask, cur_state, new_state);
+
+out:
+ mutex_unlock(&qp->mutex);
+ return err;
+}
+
static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
void *wqe)
{
@@ -952,6 +1028,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
(be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20) & 0xff;
sqp->ud_header.grh.flow_label =
ah->av.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
+ sqp->ud_header.grh.hop_limit = ah->av.hop_limit;
ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.port_pd) >> 24,
ah->av.gid_index, &sqp->ud_header.grh.source_gid);
memcpy(sqp->ud_header.grh.destination_gid.raw,
@@ -1192,7 +1269,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
*/
wmb();
- if (wr->opcode < 0 || wr->opcode > ARRAY_SIZE(mlx4_ib_opcode)) {
+ if (wr->opcode < 0 || wr->opcode >= ARRAY_SIZE(mlx4_ib_opcode)) {
err = -EINVAL;
goto out;
}
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 42ab4a801d6a..12fac1c8989d 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -297,6 +297,12 @@ int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
break;
}
+ if (unlikely(srq->head == srq->tail)) {
+ err = -ENOMEM;
+ *bad_wr = wr;
+ break;
+ }
+
srq->wrid[srq->head] = wr->wr_id;
next = get_wqe(srq, srq->head);
diff --git a/drivers/infiniband/hw/mlx4/user.h b/drivers/infiniband/hw/mlx4/user.h
index 5b8eddc9fa83..88c72d56368b 100644
--- a/drivers/infiniband/hw/mlx4/user.h
+++ b/drivers/infiniband/hw/mlx4/user.h
@@ -39,7 +39,7 @@
* Increment this value if any changes that break userspace ABI
* compatibility are made.
*/
-#define MLX4_IB_UVERBS_ABI_VERSION 1
+#define MLX4_IB_UVERBS_ABI_VERSION 2
/*
* Make sure that all structs defined in this file remain laid out so
@@ -87,6 +87,9 @@ struct mlx4_ib_create_srq_resp {
struct mlx4_ib_create_qp {
__u64 buf_addr;
__u64 db_addr;
+ __u8 log_sq_bb_count;
+ __u8 log_sq_stride;
+ __u8 reserved[6];
};
#endif /* MLX4_IB_USER_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 27caf3b0648a..4b111a852ff6 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -279,6 +279,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
(be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff;
header->grh.flow_label =
ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff);
+ header->grh.hop_limit = ah->av->hop_limit;
ib_get_cached_gid(&dev->ib_dev,
be32_to_cpu(ah->av->port_pd) >> 24,
ah->av->gid_index % dev->limits.gid_table_len,
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 71314460b11e..38102520ffb3 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -37,6 +37,7 @@
#include <linux/completion.h>
#include <linux/pci.h>
#include <linux/errno.h>
+#include <linux/sched.h>
#include <asm/io.h>
#include <rdma/ib_mad.h>
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index cf0868f6e965..be6e1e03bdab 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -37,6 +37,7 @@
*/
#include <linux/hardirq.h>
+#include <linux/sched.h>
#include <asm/io.h>
@@ -284,7 +285,7 @@ void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
{
struct mthca_cqe *cqe;
u32 prod_index;
- int nfreed = 0;
+ int i, nfreed = 0;
spin_lock_irq(&cq->lock);
@@ -321,6 +322,8 @@ void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
}
if (nfreed) {
+ for (i = 0; i < nfreed; ++i)
+ set_cqe_hw(get_cqe(cq, (cq->cons_index + i) & cq->ibcq.cqe));
wmb();
cq->cons_index += nfreed;
update_cons_index(dev, cq, nfreed);
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 773145e29947..aa563e61de65 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -1250,12 +1250,14 @@ static void __mthca_remove_one(struct pci_dev *pdev)
int __mthca_restart_one(struct pci_dev *pdev)
{
struct mthca_dev *mdev;
+ int hca_type;
mdev = pci_get_drvdata(pdev);
if (!mdev)
return -ENODEV;
+ hca_type = mdev->hca_type;
__mthca_remove_one(pdev);
- return __mthca_init_one(pdev, mdev->hca_type);
+ return __mthca_init_one(pdev, hca_type);
}
static int __devinit mthca_init_one(struct pci_dev *pdev,
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 48f7c65e9aed..e61f3e626980 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -36,6 +36,7 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/sched.h>
#include <asm/page.h>
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index fee60c852d14..027664979fe2 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -37,6 +37,7 @@
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include <asm/io.h>
@@ -295,7 +296,7 @@ static int to_mthca_st(int transport)
}
}
-static void store_attrs(struct mthca_sqp *sqp, struct ib_qp_attr *attr,
+static void store_attrs(struct mthca_sqp *sqp, const struct ib_qp_attr *attr,
int attr_mask)
{
if (attr_mask & IB_QP_PKEY_INDEX)
@@ -327,7 +328,7 @@ static void init_port(struct mthca_dev *dev, int port)
mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
}
-static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr,
+static __be32 get_hw_access_flags(struct mthca_qp *qp, const struct ib_qp_attr *attr,
int attr_mask)
{
u8 dest_rd_atomic;
@@ -510,7 +511,7 @@ out:
return err;
}
-static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
+static int mthca_path_set(struct mthca_dev *dev, const struct ib_ah_attr *ah,
struct mthca_qp_path *path, u8 port)
{
path->g_mylmc = ah->src_path_bits & 0x7f;
@@ -538,12 +539,12 @@ static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
return 0;
}
-int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
- struct ib_udata *udata)
+static int __mthca_modify_qp(struct ib_qp *ibqp,
+ const struct ib_qp_attr *attr, int attr_mask,
+ enum ib_qp_state cur_state, enum ib_qp_state new_state)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
- enum ib_qp_state cur_state, new_state;
struct mthca_mailbox *mailbox;
struct mthca_qp_param *qp_param;
struct mthca_qp_context *qp_context;
@@ -551,60 +552,6 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
u8 status;
int err = -EINVAL;
- mutex_lock(&qp->mutex);
-
- if (attr_mask & IB_QP_CUR_STATE) {
- cur_state = attr->cur_qp_state;
- } else {
- spin_lock_irq(&qp->sq.lock);
- spin_lock(&qp->rq.lock);
- cur_state = qp->state;
- spin_unlock(&qp->rq.lock);
- spin_unlock_irq(&qp->sq.lock);
- }
-
- new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
-
- if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) {
- mthca_dbg(dev, "Bad QP transition (transport %d) "
- "%d->%d with attr 0x%08x\n",
- qp->transport, cur_state, new_state,
- attr_mask);
- goto out;
- }
-
- if (cur_state == new_state && cur_state == IB_QPS_RESET) {
- err = 0;
- goto out;
- }
-
- if ((attr_mask & IB_QP_PKEY_INDEX) &&
- attr->pkey_index >= dev->limits.pkey_table_len) {
- mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
- attr->pkey_index, dev->limits.pkey_table_len-1);
- goto out;
- }
-
- if ((attr_mask & IB_QP_PORT) &&
- (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
- mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
- goto out;
- }
-
- if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
- attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
- mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
- attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
- goto out;
- }
-
- if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
- attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
- mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
- attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
- goto out;
- }
-
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox)) {
err = PTR_ERR(mailbox);
@@ -891,6 +838,98 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
out_mailbox:
mthca_free_mailbox(dev, mailbox);
+out:
+ return err;
+}
+
+static const struct ib_qp_attr dummy_init_attr = { .port_num = 1 };
+static const int dummy_init_attr_mask[] = {
+ [IB_QPT_UD] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_QKEY),
+ [IB_QPT_UC] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_RC] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
+ IB_QP_QKEY),
+ [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
+ IB_QP_QKEY),
+};
+
+int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ struct ib_udata *udata)
+{
+ struct mthca_dev *dev = to_mdev(ibqp->device);
+ struct mthca_qp *qp = to_mqp(ibqp);
+ enum ib_qp_state cur_state, new_state;
+ int err = -EINVAL;
+
+ mutex_lock(&qp->mutex);
+ if (attr_mask & IB_QP_CUR_STATE) {
+ cur_state = attr->cur_qp_state;
+ } else {
+ spin_lock_irq(&qp->sq.lock);
+ spin_lock(&qp->rq.lock);
+ cur_state = qp->state;
+ spin_unlock(&qp->rq.lock);
+ spin_unlock_irq(&qp->sq.lock);
+ }
+
+ new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+ if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) {
+ mthca_dbg(dev, "Bad QP transition (transport %d) "
+ "%d->%d with attr 0x%08x\n",
+ qp->transport, cur_state, new_state,
+ attr_mask);
+ goto out;
+ }
+
+ if ((attr_mask & IB_QP_PKEY_INDEX) &&
+ attr->pkey_index >= dev->limits.pkey_table_len) {
+ mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
+ attr->pkey_index, dev->limits.pkey_table_len-1);
+ goto out;
+ }
+
+ if ((attr_mask & IB_QP_PORT) &&
+ (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
+ mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
+ goto out;
+ }
+
+ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+ attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
+ mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
+ attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
+ goto out;
+ }
+
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+ attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
+ mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
+ attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
+ goto out;
+ }
+
+ if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+ err = 0;
+ goto out;
+ }
+
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_ERR) {
+ err = __mthca_modify_qp(ibqp, &dummy_init_attr,
+ dummy_init_attr_mask[ibqp->qp_type],
+ IB_QPS_RESET, IB_QPS_INIT);
+ if (err)
+ goto out;
+ cur_state = IB_QPS_INIT;
+ }
+
+ err = __mthca_modify_qp(ibqp, attr, attr_mask, cur_state, new_state);
out:
mutex_unlock(&qp->mutex);
@@ -1862,6 +1901,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
dev->kar + MTHCA_RECEIVE_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ qp->rq.next_ind = ind;
qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
size0 = 0;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 61974b0296ca..b8f05a526673 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/sched.h>
#include <asm/io.h>
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 87310eeb6df0..a0b3782c7625 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -132,12 +132,46 @@ struct ipoib_cm_data {
__be32 mtu;
};
+/*
+ * Quoting 10.3.1 Queue Pair and EE Context States:
+ *
+ * Note, for QPs that are associated with an SRQ, the Consumer should take the
+ * QP through the Error State before invoking a Destroy QP or a Modify QP to the
+ * Reset State. The Consumer may invoke the Destroy QP without first performing
+ * a Modify QP to the Error State and waiting for the Affiliated Asynchronous
+ * Last WQE Reached Event. However, if the Consumer does not wait for the
+ * Affiliated Asynchronous Last WQE Reached Event, then WQE and Data Segment
+ * leakage may occur. Therefore, it is good programming practice to tear down a
+ * QP that is associated with an SRQ by using the following process:
+ *
+ * - Put the QP in the Error State
+ * - Wait for the Affiliated Asynchronous Last WQE Reached Event;
+ * - either:
+ * drain the CQ by invoking the Poll CQ verb and either wait for CQ
+ * to be empty or the number of Poll CQ operations has exceeded
+ * CQ capacity size;
+ * - or
+ * post another WR that completes on the same CQ and wait for this
+ * WR to return as a WC;
+ * - and then invoke a Destroy QP or Reset QP.
+ *
+ * We use the second option and wait for a completion on the
+ * rx_drain_qp before destroying QPs attached to our SRQ.
+ */
+
+enum ipoib_cm_state {
+ IPOIB_CM_RX_LIVE,
+ IPOIB_CM_RX_ERROR, /* Ignored by stale task */
+ IPOIB_CM_RX_FLUSH /* Last WQE Reached event observed */
+};
+
struct ipoib_cm_rx {
struct ib_cm_id *id;
struct ib_qp *qp;
struct list_head list;
struct net_device *dev;
unsigned long jiffies;
+ enum ipoib_cm_state state;
};
struct ipoib_cm_tx {
@@ -165,10 +199,16 @@ struct ipoib_cm_dev_priv {
struct ib_srq *srq;
struct ipoib_cm_rx_buf *srq_ring;
struct ib_cm_id *id;
- struct list_head passive_ids;
+ struct ib_qp *rx_drain_qp; /* generates WR described in 10.3.1 */
+ struct list_head passive_ids; /* state: LIVE */
+ struct list_head rx_error_list; /* state: ERROR */
+ struct list_head rx_flush_list; /* state: FLUSH, drain not started */
+ struct list_head rx_drain_list; /* state: FLUSH, drain started */
+ struct list_head rx_reap_list; /* state: FLUSH, drain done */
struct work_struct start_task;
struct work_struct reap_task;
struct work_struct skb_task;
+ struct work_struct rx_reap_task;
struct delayed_work stale_task;
struct sk_buff_head skb_queue;
struct list_head start_list;
@@ -201,15 +241,17 @@ struct ipoib_dev_priv {
struct list_head multicast_list;
struct rb_root multicast_tree;
- struct delayed_work pkey_task;
+ struct delayed_work pkey_poll_task;
struct delayed_work mcast_task;
struct work_struct flush_task;
struct work_struct restart_task;
struct delayed_work ah_reap_task;
+ struct work_struct pkey_event_task;
struct ib_device *ca;
u8 port;
u16 pkey;
+ u16 pkey_index;
struct ib_pd *pd;
struct ib_mr *mr;
struct ib_cq *cq;
@@ -333,12 +375,13 @@ struct ipoib_dev_priv *ipoib_intf_alloc(const char *format);
int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
void ipoib_ib_dev_flush(struct work_struct *work);
+void ipoib_pkey_event(struct work_struct *work);
void ipoib_ib_dev_cleanup(struct net_device *dev);
int ipoib_ib_dev_open(struct net_device *dev);
int ipoib_ib_dev_up(struct net_device *dev);
int ipoib_ib_dev_down(struct net_device *dev, int flush);
-int ipoib_ib_dev_stop(struct net_device *dev);
+int ipoib_ib_dev_stop(struct net_device *dev, int flush);
int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
void ipoib_dev_cleanup(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 785bc8505f2a..ffec794b7913 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -37,6 +37,7 @@
#include <net/dst.h>
#include <net/icmp.h>
#include <linux/icmpv6.h>
+#include <linux/delay.h>
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
static int data_debug_level;
@@ -62,6 +63,16 @@ struct ipoib_cm_id {
u32 remote_mtu;
};
+static struct ib_qp_attr ipoib_cm_err_attr = {
+ .qp_state = IB_QPS_ERR
+};
+
+#define IPOIB_CM_RX_DRAIN_WRID 0x7fffffff
+
+static struct ib_recv_wr ipoib_cm_rx_drain_wr = {
+ .wr_id = IPOIB_CM_RX_DRAIN_WRID
+};
+
static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
struct ib_cm_event *event);
@@ -150,11 +161,44 @@ partial_error:
return NULL;
}
+static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv* priv)
+{
+ struct ib_recv_wr *bad_wr;
+
+ /* rx_drain_qp send queue depth is 1, so
+ * make sure we have at most 1 outstanding WR. */
+ if (list_empty(&priv->cm.rx_flush_list) ||
+ !list_empty(&priv->cm.rx_drain_list))
+ return;
+
+ if (ib_post_recv(priv->cm.rx_drain_qp, &ipoib_cm_rx_drain_wr, &bad_wr))
+ ipoib_warn(priv, "failed to post rx_drain wr\n");
+
+ list_splice_init(&priv->cm.rx_flush_list, &priv->cm.rx_drain_list);
+}
+
+static void ipoib_cm_rx_event_handler(struct ib_event *event, void *ctx)
+{
+ struct ipoib_cm_rx *p = ctx;
+ struct ipoib_dev_priv *priv = netdev_priv(p->dev);
+ unsigned long flags;
+
+ if (event->event != IB_EVENT_QP_LAST_WQE_REACHED)
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ list_move(&p->list, &priv->cm.rx_flush_list);
+ p->state = IPOIB_CM_RX_FLUSH;
+ ipoib_cm_start_rx_drain(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
struct ipoib_cm_rx *p)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_init_attr attr = {
+ .event_handler = ipoib_cm_rx_event_handler,
.send_cq = priv->cq, /* does not matter, we never send anything */
.recv_cq = priv->cq,
.srq = priv->cm.srq,
@@ -256,11 +300,13 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
cm_id->context = p;
p->jiffies = jiffies;
+ p->state = IPOIB_CM_RX_LIVE;
spin_lock_irq(&priv->lock);
+ if (list_empty(&priv->cm.passive_ids))
+ queue_delayed_work(ipoib_workqueue,
+ &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
list_add(&p->list, &priv->cm.passive_ids);
spin_unlock_irq(&priv->lock);
- queue_delayed_work(ipoib_workqueue,
- &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
return 0;
err_rep:
@@ -276,7 +322,6 @@ static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
{
struct ipoib_cm_rx *p;
struct ipoib_dev_priv *priv;
- int ret;
switch (event->event) {
case IB_CM_REQ_RECEIVED:
@@ -288,20 +333,9 @@ static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
case IB_CM_REJ_RECEIVED:
p = cm_id->context;
priv = netdev_priv(p->dev);
- spin_lock_irq(&priv->lock);
- if (list_empty(&p->list))
- ret = 0; /* Connection is going away already. */
- else {
- list_del_init(&p->list);
- ret = -ECONNRESET;
- }
- spin_unlock_irq(&priv->lock);
- if (ret) {
- ib_destroy_qp(p->qp);
- kfree(p);
- return ret;
- }
- return 0;
+ if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE))
+ ipoib_warn(priv, "unable to move qp to error state\n");
+ /* Fall through */
default:
return 0;
}
@@ -353,8 +387,15 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
wr_id, wc->status);
if (unlikely(wr_id >= ipoib_recvq_size)) {
- ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n",
- wr_id, ipoib_recvq_size);
+ if (wr_id == (IPOIB_CM_RX_DRAIN_WRID & ~IPOIB_CM_OP_SRQ)) {
+ spin_lock_irqsave(&priv->lock, flags);
+ list_splice_init(&priv->cm.rx_drain_list, &priv->cm.rx_reap_list);
+ ipoib_cm_start_rx_drain(priv);
+ queue_work(ipoib_workqueue, &priv->cm.rx_reap_task);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ } else
+ ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n",
+ wr_id, ipoib_recvq_size);
return;
}
@@ -373,13 +414,11 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
spin_lock_irqsave(&priv->lock, flags);
p->jiffies = jiffies;
- /* Move this entry to list head, but do
- * not re-add it if it has been removed. */
- if (!list_empty(&p->list))
+ /* Move this entry to list head, but do not re-add it
+ * if it has been moved out of list. */
+ if (p->state == IPOIB_CM_RX_LIVE)
list_move(&p->list, &priv->cm.passive_ids);
spin_unlock_irqrestore(&priv->lock, flags);
- queue_delayed_work(ipoib_workqueue,
- &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
}
}
@@ -584,17 +623,43 @@ static void ipoib_cm_tx_completion(struct ib_cq *cq, void *tx_ptr)
int ipoib_cm_dev_open(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ib_qp_init_attr qp_init_attr = {
+ .send_cq = priv->cq, /* does not matter, we never send anything */
+ .recv_cq = priv->cq,
+ .cap.max_send_wr = 1, /* FIXME: 0 Seems not to work */
+ .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
+ .cap.max_recv_wr = 1,
+ .cap.max_recv_sge = 1, /* FIXME: 0 Seems not to work */
+ .sq_sig_type = IB_SIGNAL_ALL_WR,
+ .qp_type = IB_QPT_UC,
+ };
int ret;
if (!IPOIB_CM_SUPPORTED(dev->dev_addr))
return 0;
+ priv->cm.rx_drain_qp = ib_create_qp(priv->pd, &qp_init_attr);
+ if (IS_ERR(priv->cm.rx_drain_qp)) {
+ printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
+ ret = PTR_ERR(priv->cm.rx_drain_qp);
+ return ret;
+ }
+
+ /*
+ * We put the QP in error state directly. This way, a "flush
+ * error" WC will be immediately generated for each WR we post.
+ */
+ ret = ib_modify_qp(priv->cm.rx_drain_qp, &ipoib_cm_err_attr, IB_QP_STATE);
+ if (ret) {
+ ipoib_warn(priv, "failed to modify drain QP to error: %d\n", ret);
+ goto err_qp;
+ }
+
priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev);
if (IS_ERR(priv->cm.id)) {
printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
ret = PTR_ERR(priv->cm.id);
- priv->cm.id = NULL;
- return ret;
+ goto err_cm;
}
ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num),
@@ -602,35 +667,79 @@ int ipoib_cm_dev_open(struct net_device *dev)
if (ret) {
printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name,
IPOIB_CM_IETF_ID | priv->qp->qp_num);
- ib_destroy_cm_id(priv->cm.id);
- priv->cm.id = NULL;
- return ret;
+ goto err_listen;
}
+
return 0;
+
+err_listen:
+ ib_destroy_cm_id(priv->cm.id);
+err_cm:
+ priv->cm.id = NULL;
+err_qp:
+ ib_destroy_qp(priv->cm.rx_drain_qp);
+ return ret;
}
void ipoib_cm_dev_stop(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_cm_rx *p;
+ struct ipoib_cm_rx *p, *n;
+ unsigned long begin;
+ LIST_HEAD(list);
+ int ret;
if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id)
return;
ib_destroy_cm_id(priv->cm.id);
priv->cm.id = NULL;
+
spin_lock_irq(&priv->lock);
while (!list_empty(&priv->cm.passive_ids)) {
p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
- list_del_init(&p->list);
+ list_move(&p->list, &priv->cm.rx_error_list);
+ p->state = IPOIB_CM_RX_ERROR;
spin_unlock_irq(&priv->lock);
+ ret = ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE);
+ if (ret)
+ ipoib_warn(priv, "unable to move qp to error state: %d\n", ret);
+ spin_lock_irq(&priv->lock);
+ }
+
+ /* Wait for all RX to be drained */
+ begin = jiffies;
+
+ while (!list_empty(&priv->cm.rx_error_list) ||
+ !list_empty(&priv->cm.rx_flush_list) ||
+ !list_empty(&priv->cm.rx_drain_list)) {
+ if (!time_after(jiffies, begin + 5 * HZ)) {
+ ipoib_warn(priv, "RX drain timing out\n");
+
+ /*
+ * assume the HW is wedged and just free up everything.
+ */
+ list_splice_init(&priv->cm.rx_flush_list, &list);
+ list_splice_init(&priv->cm.rx_error_list, &list);
+ list_splice_init(&priv->cm.rx_drain_list, &list);
+ break;
+ }
+ spin_unlock_irq(&priv->lock);
+ msleep(1);
+ spin_lock_irq(&priv->lock);
+ }
+
+ list_splice_init(&priv->cm.rx_reap_list, &list);
+
+ spin_unlock_irq(&priv->lock);
+
+ list_for_each_entry_safe(p, n, &list, list) {
ib_destroy_cm_id(p->id);
ib_destroy_qp(p->qp);
kfree(p);
- spin_lock_irq(&priv->lock);
}
- spin_unlock_irq(&priv->lock);
+ ib_destroy_qp(priv->cm.rx_drain_qp);
cancel_delayed_work(&priv->cm.stale_task);
}
@@ -1080,26 +1189,50 @@ void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
queue_work(ipoib_workqueue, &priv->cm.skb_task);
}
+static void ipoib_cm_rx_reap(struct work_struct *work)
+{
+ struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+ cm.rx_reap_task);
+ struct ipoib_cm_rx *p, *n;
+ LIST_HEAD(list);
+
+ spin_lock_irq(&priv->lock);
+ list_splice_init(&priv->cm.rx_reap_list, &list);
+ spin_unlock_irq(&priv->lock);
+
+ list_for_each_entry_safe(p, n, &list, list) {
+ ib_destroy_cm_id(p->id);
+ ib_destroy_qp(p->qp);
+ kfree(p);
+ }
+}
+
static void ipoib_cm_stale_task(struct work_struct *work)
{
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
cm.stale_task.work);
struct ipoib_cm_rx *p;
+ int ret;
spin_lock_irq(&priv->lock);
while (!list_empty(&priv->cm.passive_ids)) {
- /* List if sorted by LRU, start from tail,
+ /* List is sorted by LRU, start from tail,
* stop when we see a recently used entry */
p = list_entry(priv->cm.passive_ids.prev, typeof(*p), list);
if (time_before_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
break;
- list_del_init(&p->list);
+ list_move(&p->list, &priv->cm.rx_error_list);
+ p->state = IPOIB_CM_RX_ERROR;
spin_unlock_irq(&priv->lock);
- ib_destroy_cm_id(p->id);
- ib_destroy_qp(p->qp);
- kfree(p);
+ ret = ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE);
+ if (ret)
+ ipoib_warn(priv, "unable to move qp to error state: %d\n", ret);
spin_lock_irq(&priv->lock);
}
+
+ if (!list_empty(&priv->cm.passive_ids))
+ queue_delayed_work(ipoib_workqueue,
+ &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
spin_unlock_irq(&priv->lock);
}
@@ -1161,9 +1294,14 @@ int ipoib_cm_dev_init(struct net_device *dev)
INIT_LIST_HEAD(&priv->cm.passive_ids);
INIT_LIST_HEAD(&priv->cm.reap_list);
INIT_LIST_HEAD(&priv->cm.start_list);
+ INIT_LIST_HEAD(&priv->cm.rx_error_list);
+ INIT_LIST_HEAD(&priv->cm.rx_flush_list);
+ INIT_LIST_HEAD(&priv->cm.rx_drain_list);
+ INIT_LIST_HEAD(&priv->cm.rx_reap_list);
INIT_WORK(&priv->cm.start_task, ipoib_cm_tx_start);
INIT_WORK(&priv->cm.reap_task, ipoib_cm_tx_reap);
INIT_WORK(&priv->cm.skb_task, ipoib_cm_skb_reap);
+ INIT_WORK(&priv->cm.rx_reap_task, ipoib_cm_rx_reap);
INIT_DELAYED_WORK(&priv->cm.stale_task, ipoib_cm_stale_task);
skb_queue_head_init(&priv->cm.skb_queue);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 68d72c6f7ffb..c1aad06eb4e9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -448,6 +448,13 @@ int ipoib_ib_dev_open(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
+ if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) {
+ ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey);
+ clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ return -1;
+ }
+ set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+
ret = ipoib_init_qp(dev);
if (ret) {
ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);
@@ -457,14 +464,14 @@ int ipoib_ib_dev_open(struct net_device *dev)
ret = ipoib_ib_post_receives(dev);
if (ret) {
ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
- ipoib_ib_dev_stop(dev);
+ ipoib_ib_dev_stop(dev, 1);
return -1;
}
ret = ipoib_cm_dev_open(dev);
if (ret) {
- ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
- ipoib_ib_dev_stop(dev);
+ ipoib_warn(priv, "ipoib_cm_dev_open returned %d\n", ret);
+ ipoib_ib_dev_stop(dev, 1);
return -1;
}
@@ -516,7 +523,7 @@ int ipoib_ib_dev_down(struct net_device *dev, int flush)
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
mutex_lock(&pkey_mutex);
set_bit(IPOIB_PKEY_STOP, &priv->flags);
- cancel_delayed_work(&priv->pkey_task);
+ cancel_delayed_work(&priv->pkey_poll_task);
mutex_unlock(&pkey_mutex);
if (flush)
flush_workqueue(ipoib_workqueue);
@@ -543,7 +550,7 @@ static int recvs_pending(struct net_device *dev)
return pending;
}
-int ipoib_ib_dev_stop(struct net_device *dev)
+int ipoib_ib_dev_stop(struct net_device *dev, int flush)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_attr qp_attr;
@@ -629,7 +636,8 @@ timeout:
/* Wait for all AHs to be reaped */
set_bit(IPOIB_STOP_REAPER, &priv->flags);
cancel_delayed_work(&priv->ah_reap_task);
- flush_workqueue(ipoib_workqueue);
+ if (flush)
+ flush_workqueue(ipoib_workqueue);
begin = jiffies;
@@ -673,13 +681,24 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
return 0;
}
-void ipoib_ib_dev_flush(struct work_struct *work)
+static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
{
- struct ipoib_dev_priv *cpriv, *priv =
- container_of(work, struct ipoib_dev_priv, flush_task);
+ struct ipoib_dev_priv *cpriv;
struct net_device *dev = priv->dev;
+ u16 new_index;
+
+ mutex_lock(&priv->vlan_mutex);
- if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) {
+ /*
+ * Flush any child interfaces too -- they might be up even if
+ * the parent is down.
+ */
+ list_for_each_entry(cpriv, &priv->child_intfs, list)
+ __ipoib_ib_dev_flush(cpriv, pkey_event);
+
+ mutex_unlock(&priv->vlan_mutex);
+
+ if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {
ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
return;
}
@@ -689,10 +708,32 @@ void ipoib_ib_dev_flush(struct work_struct *work)
return;
}
+ if (pkey_event) {
+ if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
+ clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ ipoib_ib_dev_down(dev, 0);
+ ipoib_pkey_dev_delay_open(dev);
+ return;
+ }
+ set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+
+ /* restart QP only if P_Key index is changed */
+ if (new_index == priv->pkey_index) {
+ ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
+ return;
+ }
+ priv->pkey_index = new_index;
+ }
+
ipoib_dbg(priv, "flushing\n");
ipoib_ib_dev_down(dev, 0);
+ if (pkey_event) {
+ ipoib_ib_dev_stop(dev, 0);
+ ipoib_ib_dev_open(dev);
+ }
+
/*
* The device could have been brought down between the start and when
* we get here, don't bring it back up if it's not configured up
@@ -701,14 +742,24 @@ void ipoib_ib_dev_flush(struct work_struct *work)
ipoib_ib_dev_up(dev);
ipoib_mcast_restart_task(&priv->restart_task);
}
+}
- mutex_lock(&priv->vlan_mutex);
+void ipoib_ib_dev_flush(struct work_struct *work)
+{
+ struct ipoib_dev_priv *priv =
+ container_of(work, struct ipoib_dev_priv, flush_task);
- /* Flush any child interfaces too */
- list_for_each_entry(cpriv, &priv->child_intfs, list)
- ipoib_ib_dev_flush(&cpriv->flush_task);
+ ipoib_dbg(priv, "Flushing %s\n", priv->dev->name);
+ __ipoib_ib_dev_flush(priv, 0);
+}
- mutex_unlock(&priv->vlan_mutex);
+void ipoib_pkey_event(struct work_struct *work)
+{
+ struct ipoib_dev_priv *priv =
+ container_of(work, struct ipoib_dev_priv, pkey_event_task);
+
+ ipoib_dbg(priv, "Flushing %s and restarting its QP\n", priv->dev->name);
+ __ipoib_ib_dev_flush(priv, 1);
}
void ipoib_ib_dev_cleanup(struct net_device *dev)
@@ -736,7 +787,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
void ipoib_pkey_poll(struct work_struct *work)
{
struct ipoib_dev_priv *priv =
- container_of(work, struct ipoib_dev_priv, pkey_task.work);
+ container_of(work, struct ipoib_dev_priv, pkey_poll_task.work);
struct net_device *dev = priv->dev;
ipoib_pkey_dev_check_presence(dev);
@@ -747,7 +798,7 @@ void ipoib_pkey_poll(struct work_struct *work)
mutex_lock(&pkey_mutex);
if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
queue_delayed_work(ipoib_workqueue,
- &priv->pkey_task,
+ &priv->pkey_poll_task,
HZ);
mutex_unlock(&pkey_mutex);
}
@@ -766,7 +817,7 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev)
mutex_lock(&pkey_mutex);
clear_bit(IPOIB_PKEY_STOP, &priv->flags);
queue_delayed_work(ipoib_workqueue,
- &priv->pkey_task,
+ &priv->pkey_poll_task,
HZ);
mutex_unlock(&pkey_mutex);
return 1;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 0a428f2b05c7..894b1dcdf3eb 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -107,7 +107,7 @@ int ipoib_open(struct net_device *dev)
return -EINVAL;
if (ipoib_ib_dev_up(dev)) {
- ipoib_ib_dev_stop(dev);
+ ipoib_ib_dev_stop(dev, 1);
return -EINVAL;
}
@@ -152,7 +152,7 @@ static int ipoib_stop(struct net_device *dev)
flush_workqueue(ipoib_workqueue);
ipoib_ib_dev_down(dev, 1);
- ipoib_ib_dev_stop(dev);
+ ipoib_ib_dev_stop(dev, 1);
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
struct ipoib_dev_priv *cpriv;
@@ -988,7 +988,8 @@ static void ipoib_setup(struct net_device *dev)
INIT_LIST_HEAD(&priv->dead_ahs);
INIT_LIST_HEAD(&priv->multicast_list);
- INIT_DELAYED_WORK(&priv->pkey_task, ipoib_pkey_poll);
+ INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
+ INIT_WORK(&priv->pkey_event_task, ipoib_pkey_event);
INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task);
INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush);
INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 54fbead4de01..aae367057a56 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -524,7 +524,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
return;
if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
- ipoib_warn(priv, "ib_gid_entry_get() failed\n");
+ ipoib_warn(priv, "ib_query_gid() failed\n");
else
memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 5c3c6a43a52b..982eb88e27ec 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -33,8 +33,6 @@
* $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <rdma/ib_cache.h>
-
#include "ipoib.h"
int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
@@ -49,7 +47,7 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
if (!qp_attr)
goto out;
- if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
+ if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
ret = -ENXIO;
goto out;
@@ -94,26 +92,16 @@ int ipoib_init_qp(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
- u16 pkey_index;
struct ib_qp_attr qp_attr;
int attr_mask;
- /*
- * Search through the port P_Key table for the requested pkey value.
- * The port has to be assigned to the respective IB partition in
- * advance.
- */
- ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index);
- if (ret) {
- clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
- return ret;
- }
- set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
+ return -1;
qp_attr.qp_state = IB_QPS_INIT;
qp_attr.qkey = 0;
qp_attr.port_num = priv->port;
- qp_attr.pkey_index = pkey_index;
+ qp_attr.pkey_index = priv->pkey_index;
attr_mask =
IB_QP_QKEY |
IB_QP_PORT |
@@ -185,7 +173,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
size = ipoib_sendq_size + ipoib_recvq_size + 1;
ret = ipoib_cm_dev_init(dev);
if (!ret)
- size += ipoib_recvq_size;
+ size += ipoib_recvq_size + 1 /* 1 extra for rx_drain_qp */;
priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
if (IS_ERR(priv->cq)) {
@@ -259,14 +247,18 @@ void ipoib_event(struct ib_event_handler *handler,
struct ipoib_dev_priv *priv =
container_of(handler, struct ipoib_dev_priv, event_handler);
- if ((record->event == IB_EVENT_PORT_ERR ||
- record->event == IB_EVENT_PKEY_CHANGE ||
- record->event == IB_EVENT_PORT_ACTIVE ||
- record->event == IB_EVENT_LID_CHANGE ||
- record->event == IB_EVENT_SM_CHANGE ||
- record->event == IB_EVENT_CLIENT_REREGISTER) &&
- record->element.port_num == priv->port) {
+ if (record->element.port_num != priv->port)
+ return;
+
+ if (record->event == IB_EVENT_PORT_ERR ||
+ record->event == IB_EVENT_PORT_ACTIVE ||
+ record->event == IB_EVENT_LID_CHANGE ||
+ record->event == IB_EVENT_SM_CHANGE ||
+ record->event == IB_EVENT_CLIENT_REREGISTER) {
ipoib_dbg(priv, "Port state change event\n");
queue_work(ipoib_workqueue, &priv->flush_task);
+ } else if (record->event == IB_EVENT_PKEY_CHANGE) {
+ ipoib_dbg(priv, "P_Key change event on port:%d\n", priv->port);
+ queue_work(ipoib_workqueue, &priv->pkey_event_task);
}
}
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 82f563e24fdb..b0023452ec90 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -255,6 +255,7 @@ config JOYSTICK_JOYDUMP
config JOYSTICK_XPAD
tristate "X-Box gamepad support"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the X-Box pad with your computer.
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 6013ace94d98..842a7b4d16f8 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -84,6 +84,7 @@ config INPUT_ATLAS_BTNS
config INPUT_ATI_REMOTE
tristate "ATI / X10 USB RF remote control"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
@@ -99,6 +100,7 @@ config INPUT_ATI_REMOTE
config INPUT_ATI_REMOTE2
tristate "ATI / Philips USB RF remote control"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use an ATI or Philips USB RF remote control.
@@ -114,6 +116,7 @@ config INPUT_ATI_REMOTE2
config INPUT_KEYSPAN_REMOTE
tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
depends on EXPERIMENTAL
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use a Keyspan DMR USB remote control.
@@ -128,6 +131,7 @@ config INPUT_KEYSPAN_REMOTE
config INPUT_POWERMATE
tristate "Griffin PowerMate and Contour Jog support"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use Griffin PowerMate or Contour Jog devices.
@@ -144,6 +148,7 @@ config INPUT_POWERMATE
config INPUT_YEALINK
tristate "Yealink usb-p1k voip phone"
depends EXPERIMENTAL
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to enable keyboard and LCD functions of the
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 2ccc114b3ff6..eb0167e9f0cb 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -111,6 +111,7 @@ config MOUSE_SERIAL
config MOUSE_APPLETOUCH
tristate "Apple USB Touchpad support"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use an Apple USB Touchpad.
diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
index 12dfb0eb3262..d371c0bdc0bd 100644
--- a/drivers/input/tablet/Kconfig
+++ b/drivers/input/tablet/Kconfig
@@ -13,6 +13,7 @@ if INPUT_TABLET
config TABLET_USB_ACECAD
tristate "Acecad Flair tablet support (USB)"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the USB version of the Acecad Flair
@@ -25,6 +26,7 @@ config TABLET_USB_ACECAD
config TABLET_USB_AIPTEK
tristate "Aiptek 6000U/8000U tablet support (USB)"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the USB version of the Aiptek 6000U
@@ -49,6 +51,7 @@ config TABLET_USB_GTCO
config TABLET_USB_KBTAB
tristate "KB Gear JamStudio tablet support (USB)"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the USB version of the KB Gear
@@ -61,6 +64,7 @@ config TABLET_USB_KBTAB
config TABLET_USB_WACOM
tristate "Wacom Intuos/Graphire tablet support (USB)"
+ depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the USB version of the Wacom Intuos
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 5e640aeb03cd..4f091800bfeb 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -166,6 +166,7 @@ config TOUCHSCREEN_UCB1400
config TOUCHSCREEN_USB_COMPOSITE
tristate "USB Touchscreen Driver"
+ depends on USB_ARCH_HAS_HCD
select USB
help
USB Touchscreen driver for:
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 1e699bcaba0f..82d957bde299 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -12,6 +12,7 @@
#include "icn.h"
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/sched.h>
static int portbase = ICN_BASEADDR;
static unsigned long membase = ICN_MEMADDR;
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index c5a307e3c496..0b4c4f15abdd 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -16,7 +16,7 @@
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
-
+#include <linux/sched.h>
#include "includes.h"
#include "hardware.h"
#include "message.h"
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 41634fde8e13..1c040d80c641 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -11,6 +11,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
+#include <asm/signal.h>
#include "vmx.h"
#include <linux/kvm.h>
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 0d892600ff00..da985b31b17e 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -40,6 +40,7 @@
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/mount.h>
+#include <linux/sched.h>
#include "x86_emulate.h"
#include "segment_descriptor.h"
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 9c15f32eea18..fa17d6d4f0cb 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -19,6 +19,7 @@
#include <linux/vmalloc.h>
#include <linux/highmem.h>
#include <linux/profile.h>
+#include <linux/sched.h>
#include <asm/desc.h>
#include "kvm_svm.h"
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 724db0027f00..e6e4d240b2a6 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -22,6 +22,7 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/profile.h>
+#include <linux/sched.h>
#include <asm/io.h>
#include <asm/desc.h>
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 192b26e97777..11ced17f438a 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -216,7 +216,10 @@ int wf_register_control(struct wf_control *new_ct)
new_ct->attr.attr.mode = 0644;
new_ct->attr.show = wf_show_control;
new_ct->attr.store = wf_store_control;
- device_create_file(&wf_platform_device.dev, &new_ct->attr);
+ if (device_create_file(&wf_platform_device.dev, &new_ct->attr))
+ printk(KERN_WARNING "windfarm: device_create_file failed"
+ " for %s\n", new_ct->name);
+ /* the subsystem still does useful work without the file */
DBG("wf: Registered control %s\n", new_ct->name);
@@ -326,7 +329,10 @@ int wf_register_sensor(struct wf_sensor *new_sr)
new_sr->attr.attr.mode = 0444;
new_sr->attr.show = wf_show_sensor;
new_sr->attr.store = NULL;
- device_create_file(&wf_platform_device.dev, &new_sr->attr);
+ if (device_create_file(&wf_platform_device.dev, &new_sr->attr))
+ printk(KERN_WARNING "windfarm: device_create_file failed"
+ " for %s\n", new_sr->name);
+ /* the subsystem still does useful work without the file */
DBG("wf: Registered sensor %s\n", new_sr->name);
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 0393a3d19920..e908e3cf1e50 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1721,9 +1721,6 @@ static void dst_release(struct dvb_frontend *fe)
symbol_put(dst_ca_attach);
#endif
}
-#ifdef CONFIG_DVB_CORE_ATTACH
- symbol_put(dst_attach);
-#endif
kfree(state);
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e23d8a0ea1d3..a9fa3337dd81 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -200,7 +200,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
{
struct dvb_device *dvbdev;
struct file_operations *dvbdevfops;
-
+ struct class_device *clsdev;
int id;
mutex_lock(&dvbdev_register_lock);
@@ -242,8 +242,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
- class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
+ clsdev = class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR,
+ nums2minor(adap->num, type, id)),
+ adap->device, "dvb%d.%s%d", adap->num,
+ dnames[type], id);
+ if (IS_ERR(clsdev)) {
+ printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+ __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+ return PTR_ERR(clsdev);
+ }
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -431,7 +438,7 @@ static void __exit exit_dvbdev(void)
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
}
-module_init(init_dvbdev);
+subsys_initcall(init_dvbdev);
module_exit(exit_dvbdev);
MODULE_DESCRIPTION("DVB Core Driver");
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h
index b2c22a0d6643..8e2a87cdc791 100644
--- a/drivers/media/video/cafe_ccic-regs.h
+++ b/drivers/media/video/cafe_ccic-regs.h
@@ -150,6 +150,12 @@
#define REG_GL_IMASK 0x300c /* Interrupt mask register */
#define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */
+#define REG_GL_FCR 0x3038 /* GPIO functional control register */
+#define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */
+#define REG_GL_GPIOR 0x315c /* GPIO register */
+#define GGPIO_OUT 0x80000 /* GPIO output */
+#define GGPIO_VAL 0x00008 /* Output pin value */
+
#define REG_LEN REG_GL_IMASK + 4
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 96254dbaf625..c08f650df423 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -775,6 +775,12 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam)
spin_lock_irqsave(&cam->dev_lock, flags);
cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
/*
+ * Part one of the sensor dance: turn the global
+ * GPIO signal on.
+ */
+ cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
+ cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL);
+ /*
* Put the sensor into operational mode (assumes OLPC-style
* wiring). Control 0 is reset - set to 1 to operate.
* Control 1 is power down, set to 0 to operate.
@@ -784,6 +790,7 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam)
cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
// mdelay(1); /* Enough? */
spin_unlock_irqrestore(&cam->dev_lock, flags);
+ msleep(5); /* Just to be sure */
}
static void cafe_ctlr_power_down(struct cafe_camera *cam)
@@ -792,6 +799,8 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam)
spin_lock_irqsave(&cam->dev_lock, flags);
cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
+ cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON);
+ cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT);
cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
spin_unlock_irqrestore(&cam->dev_lock, flags);
}
@@ -851,6 +860,7 @@ static int cafe_cam_init(struct cafe_camera *cam)
ret = 0;
cam->state = S_IDLE;
out:
+ cafe_ctlr_power_down(cam);
mutex_unlock(&cam->s_mutex);
return ret;
}
@@ -2103,10 +2113,16 @@ static int cafe_pci_probe(struct pci_dev *pdev,
ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
if (ret)
goto out_iounmap;
+ /*
+ * Initialize the controller and leave it powered up. It will
+ * stay that way until the sensor driver shows up.
+ */
cafe_ctlr_init(cam);
cafe_ctlr_power_up(cam);
/*
- * Set up I2C/SMBUS communications
+ * Set up I2C/SMBUS communications. We have to drop the mutex here
+ * because the sensor could attach in this call chain, leading to
+ * unsightly deadlocks.
*/
mutex_unlock(&cam->s_mutex); /* attach can deadlock */
ret = cafe_smbus_setup(cam);
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 3823b62da4a4..5b6a40371602 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -1,7 +1,6 @@
config VIDEO_EM28XX
tristate "Empia EM2800/2820/2840 USB video capture support"
depends on VIDEO_V4L1 && I2C
- select VIDEO_BUF
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
index e854f3f1b70f..1aaeaa02f158 100644
--- a/drivers/media/video/ivtv/Kconfig
+++ b/drivers/media/video/ivtv/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_IVTV
tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
- depends on VIDEO_V4L1 && VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL
select FW_LOADER
select VIDEO_TUNER
select VIDEO_TVEEPROM
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 9a412d6c6d06..552f04511ead 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -67,14 +67,6 @@
#include <media/ivtv.h>
-#ifdef CONFIG_LIRC_I2C
-# error "This driver is not compatible with the LIRC I2C kernel configuration option."
-#endif /* CONFIG_LIRC_I2C */
-
-#ifndef CONFIG_PCI
-# error "This driver requires kernel PCI support."
-#endif /* CONFIG_PCI */
-
#define IVTV_ENCODER_OFFSET 0x00000000
#define IVTV_ENCODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 794a6a02f82f..1989ec1cb973 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -362,8 +362,6 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
- fmt->fmt.pix.left = itv->main_rect.left;
- fmt->fmt.pix.top = itv->main_rect.top;
fmt->fmt.pix.width = itv->main_rect.width;
fmt->fmt.pix.height = itv->main_rect.height;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -402,8 +400,6 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- fmt->fmt.pix.left = 0;
- fmt->fmt.pix.top = 0;
fmt->fmt.pix.width = itv->params.width;
fmt->fmt.pix.height = itv->params.height;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -498,15 +494,13 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
field = fmt->fmt.pix.field;
- r.top = fmt->fmt.pix.top;
- r.left = fmt->fmt.pix.left;
+ r.top = 0;
+ r.left = 0;
r.width = fmt->fmt.pix.width;
r.height = fmt->fmt.pix.height;
ivtv_get_fmt(itv, streamtype, fmt);
if (itv->output_mode != OUT_UDMA_YUV) {
/* TODO: would setting the rect also be valid for this mode? */
- fmt->fmt.pix.top = r.top;
- fmt->fmt.pix.left = r.left;
fmt->fmt.pix.width = r.width;
fmt->fmt.pix.height = r.height;
}
@@ -1141,8 +1135,6 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
fb->fmt.pixelformat = itv->osd_pixelformat;
fb->fmt.width = itv->osd_rect.width;
fb->fmt.height = itv->osd_rect.height;
- fb->fmt.left = itv->osd_rect.left;
- fb->fmt.top = itv->osd_rect.top;
fb->base = (void *)itv->osd_video_pbase;
if (itv->osd_global_alpha_state)
fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 03bc369a9e49..3ceb8a6249dd 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -720,12 +720,22 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
struct ov7670_format_struct *ovfmt;
struct ov7670_win_size *wsize;
struct ov7670_info *info = i2c_get_clientdata(c);
- unsigned char com7;
+ unsigned char com7, clkrc;
ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize);
if (ret)
return ret;
/*
+ * HACK: if we're running rgb565 we need to grab then rewrite
+ * CLKRC. If we're *not*, however, then rewriting clkrc hoses
+ * the colors.
+ */
+ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
+ ret = ov7670_read(c, REG_CLKRC, &clkrc);
+ if (ret)
+ return ret;
+ }
+ /*
* COM7 is a pain in the ass, it doesn't like to be read then
* quickly written afterward. But we have everything we need
* to set it absolutely here, as long as the format-specific
@@ -744,7 +754,10 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
if (wsize->regs)
ret = ov7670_write_array(c, wsize->regs);
info->fmt = ovfmt;
- return 0;
+
+ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
+ ret = ov7670_write(c, REG_CLKRC, clkrc);
+ return ret;
}
/*
@@ -1267,7 +1280,9 @@ static int ov7670_attach(struct i2c_adapter *adapter)
ret = ov7670_detect(client);
if (ret)
goto out_free_info;
- i2c_attach_client(client);
+ ret = i2c_attach_client(client);
+ if (ret)
+ goto out_free_info;
return 0;
out_free_info:
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 1b9b0742f753..c40b92ce1fad 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -205,9 +205,13 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
/* 0x01 -> ??? no change ??? */
/* 0x02 -> PAL BDGHI / SECAM L */
/* 0x04 -> ??? PAL others / SECAM others ??? */
- cb &= ~0x02;
- if (t->std & V4L2_STD_SECAM)
- cb |= 0x02;
+ cb &= ~0x03;
+ if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
+ cb |= PHILIPS_MF_SET_PAL_L;
+ else if (t->std & V4L2_STD_SECAM_LC)
+ cb |= PHILIPS_MF_SET_PAL_L2;
+ else /* V4L2_STD_B|V4L2_STD_GH */
+ cb |= PHILIPS_MF_SET_BG;
break;
case TUNER_TEMIC_4046FM5:
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d24ab234394c..a7562f7fc0b3 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -45,8 +45,6 @@
*/
#define MMC_SHIFT 3
-static int major;
-
/*
* There is one mmc_blk_data per slot.
*/
@@ -466,7 +464,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
md->queue.issue_fn = mmc_blk_issue_rq;
md->queue.data = md;
- md->disk->major = major;
+ md->disk->major = MMC_BLOCK_MAJOR;
md->disk->first_minor = devidx << MMC_SHIFT;
md->disk->fops = &mmc_bdops;
md->disk->private_data = md;
@@ -634,14 +632,9 @@ static int __init mmc_blk_init(void)
{
int res = -ENOMEM;
- res = register_blkdev(major, "mmc");
- if (res < 0) {
- printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",
- major, res);
+ res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
+ if (res)
goto out;
- }
- if (major == 0)
- major = res;
return mmc_register_driver(&mmc_driver);
@@ -652,7 +645,7 @@ static int __init mmc_blk_init(void)
static void __exit mmc_blk_exit(void)
{
mmc_unregister_driver(&mmc_driver);
- unregister_blkdev(major, "mmc");
+ unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
}
module_init(mmc_blk_init);
@@ -661,5 +654,3 @@ module_exit(mmc_blk_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
-module_param(major, int, 0444);
-MODULE_PARM_DESC(major, "specify the major device number for MMC block driver");
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index b7156a4555b5..f967226d7505 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -187,9 +187,8 @@ static void au1xmmc_tasklet_finish(unsigned long param)
}
static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
- struct mmc_command *cmd)
+ struct mmc_command *cmd, unsigned int flags)
{
-
u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
switch (mmc_resp_type(cmd)) {
@@ -213,24 +212,16 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
return MMC_ERR_INVALID;
}
- switch(cmd->opcode) {
- case MMC_READ_SINGLE_BLOCK:
- case SD_APP_SEND_SCR:
- mmccmd |= SD_CMD_CT_2;
- break;
- case MMC_READ_MULTIPLE_BLOCK:
- mmccmd |= SD_CMD_CT_4;
- break;
- case MMC_WRITE_BLOCK:
- mmccmd |= SD_CMD_CT_1;
- break;
-
- case MMC_WRITE_MULTIPLE_BLOCK:
- mmccmd |= SD_CMD_CT_3;
- break;
- case MMC_STOP_TRANSMISSION:
- mmccmd |= SD_CMD_CT_7;
- break;
+ if (flags & MMC_DATA_READ) {
+ if (flags & MMC_DATA_MULTI)
+ mmccmd |= SD_CMD_CT_4;
+ else
+ mmccmd |= SD_CMD_CT_2;
+ } else if (flags & MMC_DATA_WRITE) {
+ if (flags & MMC_DATA_MULTI)
+ mmccmd |= SD_CMD_CT_3;
+ else
+ mmccmd |= SD_CMD_CT_1;
}
au_writel(cmd->arg, HOST_CMDARG(host));
@@ -665,6 +656,7 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
{
struct au1xmmc_host *host = mmc_priv(mmc);
+ unsigned int flags = 0;
int ret = MMC_ERR_NONE;
WARN_ON(irqs_disabled());
@@ -677,11 +669,12 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
if (mrq->data) {
FLUSH_FIFO(host);
+ flags = mrq->data->flags;
ret = au1xmmc_prepare_data(host, mrq->data);
}
if (ret == MMC_ERR_NONE)
- ret = au1xmmc_send_command(host, 0, mrq->cmd);
+ ret = au1xmmc_send_command(host, 0, mrq->cmd, flags);
if (ret != MMC_ERR_NONE) {
mrq->cmd->error = ret;
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index d97d3864b57f..f8985c508bb9 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -232,20 +232,14 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
/*
* workaround for erratum #42:
* Intel PXA27x Family Processor Specification Update Rev 001
+ * A bogus CRC error can appear if the msb of a 136 bit
+ * response is a one.
*/
- if (cmd->opcode == MMC_ALL_SEND_CID ||
- cmd->opcode == MMC_SEND_CSD ||
- cmd->opcode == MMC_SEND_CID) {
- /* a bogus CRC error can appear if the msb of
- the 15 byte response is a one */
- if ((cmd->resp[0] & 0x80000000) == 0)
- cmd->error = MMC_ERR_BADCRC;
- } else {
- pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode);
- }
-#else
- cmd->error = MMC_ERR_BADCRC;
+ if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) {
+ pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode);
+ } else
#endif
+ cmd->error = MMC_ERR_BADCRC;
}
pxamci_disable_irq(host, END_CMD_RES);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ff5bf73cdd25..a359efdd77eb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -963,6 +963,15 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
sdhci_transfer_pio(host);
+ /*
+ * We currently don't do anything fancy with DMA
+ * boundaries, but as we can't disable the feature
+ * we need to at least restart the transfer.
+ */
+ if (intmask & SDHCI_INT_DMA_END)
+ writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
+ host->ioaddr + SDHCI_DMA_ADDRESS);
+
if (intmask & SDHCI_INT_DATA_END)
sdhci_finish_data(host);
}
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 3dba5733ed1f..74002945b71b 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -940,9 +940,6 @@ static void ltree_entry_ctor(void *obj, struct kmem_cache *cache,
{
struct ltree_entry *le = obj;
- if (flags & SLAB_CTOR_CONSTRUCTOR)
- return;
-
le->users = 0;
init_rwsem(&le->mutex);
}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index fb99cd445504..c5baa197bc08 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2508,6 +2508,7 @@ config MLX4_CORE
config MLX4_DEBUG
bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED)
+ depends on MLX4_CORE
default y
---help---
This option causes debugging code to be compiled into the
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 95d854e2295c..b2577f40124e 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -932,8 +932,6 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Kick the lance: transmit now */
writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
- spin_unlock_irq(&lp->lock);
-
dev->trans_start = jiffies;
dev_kfree_skb(skb);
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index a9ea67e75c1b..16a6edfeba41 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -333,11 +333,9 @@ struct e1000_adapter {
struct e1000_tx_ring test_tx_ring;
struct e1000_rx_ring test_rx_ring;
-
int msg_enable;
-#ifdef CONFIG_PCI_MSI
boolean_t have_msi;
-#endif
+
/* to not mess up cache alignment, always add to the bottom */
boolean_t tso_force;
boolean_t smart_power_down; /* phy smart power down */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 637ae8f68791..cbc7febe9cdc 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -158,9 +158,7 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
static irqreturn_t e1000_intr(int irq, void *data);
-#ifdef CONFIG_PCI_MSI
static irqreturn_t e1000_intr_msi(int irq, void *data);
-#endif
static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring);
#ifdef CONFIG_E1000_NAPI
@@ -300,31 +298,26 @@ module_exit(e1000_exit_module);
static int e1000_request_irq(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int flags, err = 0;
+ void (*handler) = &e1000_intr;
+ int irq_flags = IRQF_SHARED;
+ int err;
- flags = IRQF_SHARED;
-#ifdef CONFIG_PCI_MSI
if (adapter->hw.mac_type >= e1000_82571) {
- adapter->have_msi = TRUE;
- if ((err = pci_enable_msi(adapter->pdev))) {
- DPRINTK(PROBE, ERR,
- "Unable to allocate MSI interrupt Error: %d\n", err);
- adapter->have_msi = FALSE;
+ adapter->have_msi = !pci_enable_msi(adapter->pdev);
+ if (adapter->have_msi) {
+ handler = &e1000_intr_msi;
+ irq_flags = 0;
}
}
- if (adapter->have_msi) {
- flags &= ~IRQF_SHARED;
- err = request_irq(adapter->pdev->irq, &e1000_intr_msi, flags,
- netdev->name, netdev);
- if (err)
- DPRINTK(PROBE, ERR,
- "Unable to allocate interrupt Error: %d\n", err);
- } else
-#endif
- if ((err = request_irq(adapter->pdev->irq, &e1000_intr, flags,
- netdev->name, netdev)))
+
+ err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
+ netdev);
+ if (err) {
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
DPRINTK(PROBE, ERR,
"Unable to allocate interrupt Error: %d\n", err);
+ }
return err;
}
@@ -335,10 +328,8 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
free_irq(adapter->pdev->irq, netdev);
-#ifdef CONFIG_PCI_MSI
if (adapter->have_msi)
pci_disable_msi(adapter->pdev);
-#endif
}
/**
@@ -1440,10 +1431,6 @@ e1000_open(struct net_device *netdev)
/* From here on the code is the same as e1000_up() */
clear_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
- netif_poll_enable(netdev);
-#endif
-
e1000_irq_enable(adapter);
/* fire a link status change interrupt to start the watchdog */
@@ -3744,7 +3731,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
-#ifdef CONFIG_PCI_MSI
/**
* e1000_intr_msi - Interrupt Handler
@@ -3810,7 +3796,6 @@ e1000_intr_msi(int irq, void *data)
return IRQ_HANDLED;
}
-#endif
/**
* e1000_intr - Interrupt Handler
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index b666a0cc0642..f5b3cba23fc5 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1025,6 +1025,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
+ /* The powerpc-specific eieio() is used, as wmb() has too strong
+ * semantics (it requires synchronization between cacheable and
+ * uncacheable mappings, which eieio doesn't provide and which we
+ * don't need), thus requiring a more expensive sync instruction. At
+ * some point, the set of architecture-independent barrier functions
+ * should be expanded to include weaker barriers.
+ */
+
+ eieio();
txbdp->status = status;
/* If this was the last BD in the ring, the next one */
@@ -1301,6 +1310,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
bdp->length = 0;
/* Mark the buffer empty */
+ eieio();
bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
return skb;
@@ -1484,6 +1494,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
bdp = priv->cur_rx;
while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
+ rmb();
skb = priv->rx_skbuff[priv->skb_currx];
if (!(bdp->status &
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 50035ebd4f52..f752e5fc65ba 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -926,7 +926,7 @@ static int emac_link_differs(struct ocp_enet_private *dev)
int duplex = r & EMAC_MR1_FDE ? DUPLEX_FULL : DUPLEX_HALF;
int speed, pause, asym_pause;
- if (r & (EMAC_MR1_MF_1000 | EMAC_MR1_MF_1000GPCS))
+ if (r & EMAC_MR1_MF_1000)
speed = SPEED_1000;
else if (r & EMAC_MR1_MF_100)
speed = SPEED_100;
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index 6c0f071e4052..cabd9846a5ee 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -59,8 +59,7 @@ int __init mal_register_commac(struct ibm_ocp_mal *mal,
return 0;
}
-void __exit mal_unregister_commac(struct ibm_ocp_mal *mal,
- struct mal_commac *commac)
+void mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
{
unsigned long flags;
local_irq_save(flags);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index 407d2acbf7c7..64bc338acc6c 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -223,8 +223,7 @@ void mal_exit(void) __exit;
int mal_register_commac(struct ibm_ocp_mal *mal,
struct mal_commac *commac) __init;
-void mal_unregister_commac(struct ibm_ocp_mal *mal,
- struct mal_commac *commac) __exit;
+void mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac);
int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel, unsigned long size);
/* Returns BD ring offset for a particular channel
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c
index 9074f76ee2bf..e57862b34cae 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.c
+++ b/drivers/net/ibm_emac/ibm_emac_phy.c
@@ -22,6 +22,7 @@
#include <asm/ocp.h>
+#include "ibm_emac_core.h"
#include "ibm_emac_phy.h"
static inline int phy_read(struct mii_phy *phy, int reg)
@@ -34,11 +35,39 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
phy->mdio_write(phy->dev, phy->address, reg, val);
}
-int mii_reset_phy(struct mii_phy *phy)
+/*
+ * polls MII_BMCR until BMCR_RESET bit clears or operation times out.
+ *
+ * returns:
+ * >= 0 => success, value in BMCR returned to caller
+ * -EBUSY => failure, RESET bit never cleared
+ * otherwise => failure, lower level PHY read failed
+ */
+static int mii_spin_reset_complete(struct mii_phy *phy)
{
int val;
int limit = 10000;
+ while (limit--) {
+ val = phy_read(phy, MII_BMCR);
+ if (val >= 0 && !(val & BMCR_RESET))
+ return val; /* success */
+ udelay(10);
+ }
+ if (val & BMCR_RESET)
+ val = -EBUSY;
+
+ if (net_ratelimit())
+ printk(KERN_ERR "emac%d: PHY reset timeout (%d)\n",
+ ((struct ocp_enet_private *)phy->dev->priv)->def->index,
+ val);
+ return val;
+}
+
+int mii_reset_phy(struct mii_phy *phy)
+{
+ int val;
+
val = phy_read(phy, MII_BMCR);
val &= ~BMCR_ISOLATE;
val |= BMCR_RESET;
@@ -46,16 +75,11 @@ int mii_reset_phy(struct mii_phy *phy)
udelay(300);
- while (limit--) {
- val = phy_read(phy, MII_BMCR);
- if (val >= 0 && (val & BMCR_RESET) == 0)
- break;
- udelay(10);
- }
- if ((val & BMCR_ISOLATE) && limit > 0)
+ val = mii_spin_reset_complete(phy);
+ if (val >= 0 && (val & BMCR_ISOLATE))
phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
- return limit <= 0;
+ return val < 0;
}
static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
@@ -102,8 +126,14 @@ static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
}
/* Start/Restart aneg */
- ctl = phy_read(phy, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ /* on some PHYs (e.g. National DP83843) a write to MII_ADVERTISE
+ * causes BMCR_RESET to be set on the next read of MII_BMCR, which
+ * if not checked for causes the PHY to be reset below */
+ ctl = mii_spin_reset_complete(phy);
+ if (ctl < 0)
+ return ctl;
+
+ ctl |= BMCR_ANENABLE | BMCR_ANRESTART;
phy_write(phy, MII_BMCR, ctl);
return 0;
@@ -118,13 +148,13 @@ static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
phy->duplex = fd;
phy->pause = phy->asym_pause = 0;
+ /* First reset the PHY */
+ mii_reset_phy(phy);
+
ctl = phy_read(phy, MII_BMCR);
if (ctl < 0)
return ctl;
- ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
-
- /* First reset the PHY */
- phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+ ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE | BMCR_SPEED1000);
/* Select speed & duplex */
switch (speed) {
diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.c b/drivers/net/ibm_emac/ibm_emac_rgmii.c
index 53d281cb9a16..9dbb5e5936c3 100644
--- a/drivers/net/ibm_emac/ibm_emac_rgmii.c
+++ b/drivers/net/ibm_emac/ibm_emac_rgmii.c
@@ -162,7 +162,7 @@ void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
out_be32(&dev->base->ssr, ssr);
}
-void __exit __rgmii_fini(struct ocp_device *ocpdev, int input)
+void __rgmii_fini(struct ocp_device *ocpdev, int input)
{
struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
BUG_ON(!dev || dev->users == 0);
diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.h b/drivers/net/ibm_emac/ibm_emac_rgmii.h
index 117ea486c2ca..971e45815c6c 100644
--- a/drivers/net/ibm_emac/ibm_emac_rgmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_rgmii.h
@@ -37,7 +37,7 @@ struct ibm_ocp_rgmii {
#ifdef CONFIG_IBM_EMAC_RGMII
int rgmii_attach(void *emac) __init;
-void __rgmii_fini(struct ocp_device *ocpdev, int input) __exit;
+void __rgmii_fini(struct ocp_device *ocpdev, int input);
static inline void rgmii_fini(struct ocp_device *ocpdev, int input)
{
if (ocpdev)
diff --git a/drivers/net/ibm_emac/ibm_emac_tah.c b/drivers/net/ibm_emac/ibm_emac_tah.c
index e287b451bb44..3c2d5ba522a1 100644
--- a/drivers/net/ibm_emac/ibm_emac_tah.c
+++ b/drivers/net/ibm_emac/ibm_emac_tah.c
@@ -63,7 +63,7 @@ int __init tah_attach(void *emac)
return 0;
}
-void __exit __tah_fini(struct ocp_device *ocpdev)
+void __tah_fini(struct ocp_device *ocpdev)
{
struct tah_regs *p = ocp_get_drvdata(ocpdev);
BUG_ON(!p);
diff --git a/drivers/net/ibm_emac/ibm_emac_tah.h b/drivers/net/ibm_emac/ibm_emac_tah.h
index 38153945a240..ccf64915e1e4 100644
--- a/drivers/net/ibm_emac/ibm_emac_tah.h
+++ b/drivers/net/ibm_emac/ibm_emac_tah.h
@@ -55,7 +55,7 @@ struct tah_regs {
#ifdef CONFIG_IBM_EMAC_TAH
int tah_attach(void *emac) __init;
-void __tah_fini(struct ocp_device *ocpdev) __exit;
+void __tah_fini(struct ocp_device *ocpdev);
static inline void tah_fini(struct ocp_device *ocpdev)
{
if (ocpdev)
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.c b/drivers/net/ibm_emac/ibm_emac_zmii.c
index 37dc8f342868..2c0fdb0cabff 100644
--- a/drivers/net/ibm_emac/ibm_emac_zmii.c
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.c
@@ -215,7 +215,7 @@ void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
out_be32(&dev->base->ssr, ssr);
}
-void __exit __zmii_fini(struct ocp_device *ocpdev, int input)
+void __zmii_fini(struct ocp_device *ocpdev, int input)
{
struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
BUG_ON(!dev || dev->users == 0);
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.h b/drivers/net/ibm_emac/ibm_emac_zmii.h
index 972e3a44a09f..fad6d8bf983a 100644
--- a/drivers/net/ibm_emac/ibm_emac_zmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.h
@@ -40,7 +40,7 @@ struct ibm_ocp_zmii {
#ifdef CONFIG_IBM_EMAC_ZMII
int zmii_attach(void *emac) __init;
-void __zmii_fini(struct ocp_device *ocpdev, int input) __exit;
+void __zmii_fini(struct ocp_device *ocpdev, int input);
static inline void zmii_fini(struct ocp_device *ocpdev, int input)
{
if (ocpdev)
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index c8e90861f869..3569d5b03388 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -193,8 +193,6 @@ struct ixgb_adapter {
u16 msg_enable;
struct ixgb_hw_stats stats;
uint32_t alloc_rx_buff_failed;
-#ifdef CONFIG_PCI_MSI
boolean_t have_msi;
-#endif
};
#endif /* _IXGB_H_ */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 6d2b059371f1..991c8833e23c 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -227,7 +227,7 @@ int
ixgb_up(struct ixgb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int err;
+ int err, irq_flags = IRQF_SHARED;
int max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
struct ixgb_hw *hw = &adapter->hw;
@@ -246,26 +246,21 @@ ixgb_up(struct ixgb_adapter *adapter)
/* disable interrupts and get the hardware into a known state */
IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
-#ifdef CONFIG_PCI_MSI
- {
- boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) &
- IXGB_STATUS_PCIX_MODE) ? TRUE : FALSE;
- adapter->have_msi = TRUE;
-
- if (!pcix)
- adapter->have_msi = FALSE;
- else if((err = pci_enable_msi(adapter->pdev))) {
- DPRINTK(PROBE, ERR,
- "Unable to allocate MSI interrupt Error: %d\n", err);
- adapter->have_msi = FALSE;
+ /* only enable MSI if bus is in PCI-X mode */
+ if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_PCIX_MODE) {
+ err = pci_enable_msi(adapter->pdev);
+ if (!err) {
+ adapter->have_msi = 1;
+ irq_flags = 0;
+ }
/* proceed to try to request regular interrupt */
}
- }
-#endif
- if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- netdev->name, netdev))) {
+ err = request_irq(adapter->pdev->irq, &ixgb_intr, irq_flags,
+ netdev->name, netdev);
+ if (err) {
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
DPRINTK(PROBE, ERR,
"Unable to allocate interrupt Error: %d\n", err);
return err;
@@ -307,11 +302,10 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
ixgb_irq_disable(adapter);
free_irq(adapter->pdev->irq, netdev);
-#ifdef CONFIG_PCI_MSI
- if(adapter->have_msi == TRUE)
+
+ if (adapter->have_msi)
pci_disable_msi(adapter->pdev);
-#endif
if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer);
#ifdef CONFIG_IXGB_NAPI
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index 9ffdb9d29da9..dfbd5809d744 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -33,6 +33,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/bitmap.h>
+#include <linux/dma-mapping.h>
#include "mlx4.h"
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index af016d0ea1c6..0f11adb8eb4a 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
#include <linux/mlx4/cmd.h>
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index c42717313663..cfa5cc072339 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -90,7 +90,7 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
int i;
mlx4_dbg(dev, "DEV_CAP flags:\n");
- for (i = 0; i < 32; ++i)
+ for (i = 0; i < ARRAY_SIZE(fname); ++i)
if (fname[i] && (flags & (1 << i)))
mlx4_dbg(dev, " %s\n", fname[i]);
}
diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c
index e96feaed6ed4..b7a4aa8476fb 100644
--- a/drivers/net/mlx4/icm.c
+++ b/drivers/net/mlx4/icm.c
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/errno.h>
+#include <linux/mm.h>
#include <linux/mlx4/cmd.h>
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 4debb024eaf9..20b8c0d3ced4 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -542,8 +542,6 @@ static int __devinit mlx4_setup_hca(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
- MLX4_INIT_DOORBELL_LOCK(&priv->doorbell_lock);
-
err = mlx4_init_uar_table(dev);
if (err) {
mlx4_err(dev, "Failed to initialize "
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 9befbae3d196..3d3b6d24d8d3 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -275,7 +275,6 @@ struct mlx4_priv {
struct mlx4_uar driver_uar;
void __iomem *kar;
- MLX4_DECLARE_DOORBELL_LOCK(doorbell_lock)
u32 rev_id;
char board_id[MLX4_BOARD_ID_LEN];
diff --git a/drivers/net/mlx4/reset.c b/drivers/net/mlx4/reset.c
index 51eef8492e93..e4dfd4b11a4a 100644
--- a/drivers/net/mlx4/reset.c
+++ b/drivers/net/mlx4/reset.c
@@ -35,6 +35,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include "mlx4.h"
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index cf0e96adfe44..a36892457761 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1216,7 +1216,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
/* Window = 1 */
writel(consumer,
NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[ctxid].
+ recv_crb_registers[adapter->portnum].
crb_rcv_status_consumer));
}
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index bc7f3dee6e5b..8d38425e46c3 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -85,6 +85,7 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
{
struct pci_dev *pdev = mac->pdev;
struct device_node *dn = pci_device_to_OF_node(pdev);
+ int len;
const u8 *maddr;
u8 addr[6];
@@ -94,9 +95,17 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
return -ENOENT;
}
- maddr = of_get_property(dn, "local-mac-address", NULL);
+ maddr = of_get_property(dn, "local-mac-address", &len);
+
+ if (maddr && len == 6) {
+ memcpy(mac->mac_addr, maddr, 6);
+ return 0;
+ }
+
+ /* Some old versions of firmware mistakenly uses mac-address
+ * (and as a string) instead of a byte array in local-mac-address.
+ */
- /* Fall back to mac-address for older firmware */
if (maddr == NULL)
maddr = of_get_property(dn, "mac-address", NULL);
@@ -106,6 +115,7 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
return -ENOENT;
}
+
if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
&addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
dev_warn(&pdev->dev,
@@ -113,7 +123,8 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
return -EINVAL;
}
- memcpy(mac->mac_addr, addr, sizeof(addr));
+ memcpy(mac->mac_addr, addr, 6);
+
return 0;
}
@@ -384,17 +395,14 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev)
static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
{
- unsigned int reg, stat;
+ unsigned int reg, pcnt;
/* Re-enable packet count interrupts: finally
* ack the packet count interrupt we got in rx_intr.
*/
- pci_read_config_dword(mac->iob_pdev,
- PAS_IOB_DMA_RXCH_STAT(mac->dma_rxch),
- &stat);
+ pcnt = *mac->rx_status & PAS_STATUS_PCNT_M;
- reg = PAS_IOB_DMA_RXCH_RESET_PCNT(stat & PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
- | PAS_IOB_DMA_RXCH_RESET_PINTC;
+ reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC;
pci_write_config_dword(mac->iob_pdev,
PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch),
@@ -403,14 +411,12 @@ static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
{
- unsigned int reg, stat;
+ unsigned int reg, pcnt;
/* Re-enable packet count interrupts */
- pci_read_config_dword(mac->iob_pdev,
- PAS_IOB_DMA_TXCH_STAT(mac->dma_txch), &stat);
+ pcnt = *mac->tx_status & PAS_STATUS_PCNT_M;
- reg = PAS_IOB_DMA_TXCH_RESET_PCNT(stat & PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
- | PAS_IOB_DMA_TXCH_RESET_PINTC;
+ reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
pci_write_config_dword(mac->iob_pdev,
PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
@@ -591,21 +597,24 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
{
struct net_device *dev = data;
struct pasemi_mac *mac = netdev_priv(dev);
- unsigned int reg;
+ unsigned int reg, pcnt;
if (!(*mac->tx_status & PAS_STATUS_CAUSE_M))
return IRQ_NONE;
pasemi_mac_clean_tx(mac);
- reg = PAS_IOB_DMA_TXCH_RESET_PINTC;
+ pcnt = *mac->tx_status & PAS_STATUS_PCNT_M;
+
+ reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
if (*mac->tx_status & PAS_STATUS_SOFT)
reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
if (*mac->tx_status & PAS_STATUS_ERROR)
reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
- pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch),
+ pci_write_config_dword(mac->iob_pdev,
+ PAS_IOB_DMA_TXCH_RESET(mac->dma_txch),
reg);
return IRQ_HANDLED;
@@ -974,6 +983,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
if (txring->next_to_clean - txring->next_to_use == TX_RING_SIZE) {
spin_unlock_irqrestore(&txring->lock, flags);
pasemi_mac_clean_tx(mac);
+ pasemi_mac_restart_tx_intr(mac);
spin_lock_irqsave(&txring->lock, flags);
if (txring->next_to_clean - txring->next_to_use ==
@@ -1210,6 +1220,7 @@ static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
static struct pci_device_id pasemi_mac_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) },
{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) },
+ { },
};
MODULE_DEVICE_TABLE(pci, pasemi_mac_pci_tbl);
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index 8bc0cea8b145..c29ee159c33d 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -341,7 +341,7 @@ enum {
PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
#define PAS_IOB_DMA_RXCH_RESET(i) (0x1500 + (i)*4)
#define PAS_IOB_DMA_RXCH_RESET_PCNT_M 0xffff0000
-#define PAS_IOB_DMA_RXCH_RESET_PCNT_S 0
+#define PAS_IOB_DMA_RXCH_RESET_PCNT_S 16
#define PAS_IOB_DMA_RXCH_RESET_PCNT(x) (((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \
PAS_IOB_DMA_RXCH_RESET_PCNT_M)
#define PAS_IOB_DMA_RXCH_RESET_PCNTRST 0x00000020
@@ -352,7 +352,7 @@ enum {
#define PAS_IOB_DMA_RXCH_RESET_PINTC 0x00000001
#define PAS_IOB_DMA_TXCH_RESET(i) (0x1600 + (i)*4)
#define PAS_IOB_DMA_TXCH_RESET_PCNT_M 0xffff0000
-#define PAS_IOB_DMA_TXCH_RESET_PCNT_S 0
+#define PAS_IOB_DMA_TXCH_RESET_PCNT_S 16
#define PAS_IOB_DMA_TXCH_RESET_PCNT(x) (((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \
PAS_IOB_DMA_TXCH_RESET_PCNT_M)
#define PAS_IOB_DMA_TXCH_RESET_PCNTRST 0x00000020
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 104e20456e6f..832fd69a0e59 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -40,7 +40,6 @@
#include <linux/if_vlan.h>
#include <linux/prefetch.h>
#include <linux/mii.h>
-#include <linux/dmi.h>
#include <asm/irq.h>
@@ -151,8 +150,6 @@ static const char *yukon2_name[] = {
"FE", /* 0xb7 */
};
-static int dmi_blacklisted;
-
/* Access to external PHY */
static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
{
@@ -307,10 +304,13 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
PHY_M_EC_MAC_S_MSK);
ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+ /* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */
if (hw->chip_id == CHIP_ID_YUKON_EC)
+ /* set downshift counter to 3x and enable downshift */
ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
else
- ectrl |= PHY_M_EC_M_DSC(2) | PHY_M_EC_S_DSC(3);
+ /* set master & slave downshift counter to 1x */
+ ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
}
@@ -327,10 +327,12 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
/* enable automatic crossover */
ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
+ /* downshift on PHY 88E1112 and 88E1149 is changed */
if (sky2->autoneg == AUTONEG_ENABLE
&& (hw->chip_id == CHIP_ID_YUKON_XL
|| hw->chip_id == CHIP_ID_YUKON_EC_U
|| hw->chip_id == CHIP_ID_YUKON_EX)) {
+ /* set downshift counter to 3x and enable downshift */
ctrl &= ~PHY_M_PC_DSC_MSK;
ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
}
@@ -842,10 +844,12 @@ static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2,
/* Update chip's next pointer */
static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
{
- q = Y2_QADDR(q, PREF_UNIT_PUT_IDX);
+ /* Make sure write' to descriptors are complete before we tell hardware */
wmb();
- sky2_write16(hw, q, idx);
- sky2_read16(hw, q);
+ sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
+
+ /* Synchronize I/O on since next processor may write to tail */
+ mmiowb();
}
@@ -977,6 +981,7 @@ stopped:
/* reset the Rx prefetch unit */
sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+ mmiowb();
}
/* Clean out receive buffer area, assumes receiver hardware stopped */
@@ -1196,7 +1201,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
}
/* Tell chip about available buffers */
- sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
+ sky2_put_idx(hw, rxq, sky2->rx_put);
return 0;
nomem:
sky2_rx_clean(sky2);
@@ -1538,6 +1543,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
}
sky2->tx_cons = idx;
+ smp_mb();
+
if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
netif_wake_queue(dev);
}
@@ -1577,13 +1584,6 @@ static int sky2_down(struct net_device *dev)
imask &= ~portirq_msk[port];
sky2_write32(hw, B0_IMSK, imask);
- /*
- * Both ports share the NAPI poll on port 0, so if necessary undo the
- * the disable that is done in dev_close.
- */
- if (sky2->port == 0 && hw->ports > 1)
- netif_poll_enable(dev);
-
sky2_gmac_reset(hw, port);
/* Stop transmitter */
@@ -2139,8 +2139,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
switch (le->opcode & ~HW_OWNER) {
case OP_RXSTAT:
skb = sky2_receive(dev, length, status);
- if (!skb)
+ if (unlikely(!skb)) {
+ sky2->net_stats.rx_dropped++;
goto force_update;
+ }
skb->protocol = eth_type_trans(skb, dev);
sky2->net_stats.rx_packets++;
@@ -2221,6 +2223,7 @@ force_update:
/* Fully processed status ring so clear irq */
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+ mmiowb();
exit_loop:
if (buf_write[0]) {
@@ -2341,6 +2344,12 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port)
printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n",
dev->name, status);
+ if (status & GM_IS_RX_CO_OV)
+ gma_read16(hw, port, GM_RX_IRQ_SRC);
+
+ if (status & GM_IS_TX_CO_OV)
+ gma_read16(hw, port, GM_TX_IRQ_SRC);
+
if (status & GM_IS_RX_FF_OR) {
++sky2->net_stats.rx_fifo_errors;
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
@@ -2439,6 +2448,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
if (work_done < work_limit) {
netif_rx_complete(dev0);
+ /* end of interrupt, re-enables also acts as I/O synchronization */
sky2_read32(hw, B0_Y2_SP_LISR);
return 0;
} else {
@@ -2534,17 +2544,6 @@ static int __devinit sky2_init(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
-
- /* Some Gigabyte motherboards have 88e8056 but cause problems
- * There is some unresolved hardware related problem that causes
- * descriptor errors and receive data corruption.
- */
- if (hw->chip_id == CHIP_ID_YUKON_EC_U && dmi_blacklisted) {
- dev_err(&hw->pdev->dev,
- "88E8056 on this motherboard not supported\n");
- return -EOPNOTSUPP;
- }
-
hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
hw->ports = 1;
t8 = sky2_read8(hw, B2_Y2_HW_RES);
@@ -3910,24 +3909,8 @@ static struct pci_driver sky2_driver = {
.shutdown = sky2_shutdown,
};
-static struct dmi_system_id __initdata broken_dmi_table[] = {
- {
- .ident = "Gigabyte 965P-S3",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."),
- DMI_MATCH(DMI_PRODUCT_NAME, "965P-S3"),
-
- },
- },
- { }
-};
-
static int __init sky2_init_module(void)
{
- /* Look for sick motherboards */
- if (dmi_check_system(broken_dmi_table))
- dmi_blacklisted = 1;
-
return pci_register_driver(&sky2_driver);
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 81f24847c963..db43e42bee35 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -77,7 +77,6 @@ static const char version[] =
#include <linux/skbuff.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include "smc911x.h"
@@ -2084,12 +2083,11 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr)
lp->ctl_rspeed = 100;
/* Grab the IRQ */
- retval = request_irq(dev->irq, &smc911x_interrupt, IRQF_SHARED, dev->name, dev);
+ retval = request_irq(dev->irq, &smc911x_interrupt,
+ IRQF_SHARED | IRQF_TRIGGER_FALLING, dev->name, dev);
if (retval)
goto err_out;
- set_irq_type(dev->irq, IRQT_FALLING);
-
#ifdef SMC_USE_DMA
lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq);
lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 108adbf5b5eb..c3964c3d89d9 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -430,7 +430,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
/* and we need to have it 128 byte aligned, therefore we allocate a
* bit more */
/* allocate an skb */
- descr->skb = dev_alloc_skb(bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
+ descr->skb = netdev_alloc_skb(card->netdev,
+ bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
if (!descr->skb) {
if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Not enough memory to allocate rx buffer\n");
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 0f667652fda9..c2ccbd098f53 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved.
*
* Author: Shlomi Gridish <gridish@freescale.com>
* Li Yang <leoli@freescale.com>
@@ -3737,21 +3737,21 @@ static int ucc_geth_close(struct net_device *dev)
const struct ethtool_ops ucc_geth_ethtool_ops = { };
-static phy_interface_t to_phy_interface(const char *interface_type)
+static phy_interface_t to_phy_interface(const char *phy_connection_type)
{
- if (strcasecmp(interface_type, "mii") == 0)
+ if (strcasecmp(phy_connection_type, "mii") == 0)
return PHY_INTERFACE_MODE_MII;
- if (strcasecmp(interface_type, "gmii") == 0)
+ if (strcasecmp(phy_connection_type, "gmii") == 0)
return PHY_INTERFACE_MODE_GMII;
- if (strcasecmp(interface_type, "tbi") == 0)
+ if (strcasecmp(phy_connection_type, "tbi") == 0)
return PHY_INTERFACE_MODE_TBI;
- if (strcasecmp(interface_type, "rmii") == 0)
+ if (strcasecmp(phy_connection_type, "rmii") == 0)
return PHY_INTERFACE_MODE_RMII;
- if (strcasecmp(interface_type, "rgmii") == 0)
+ if (strcasecmp(phy_connection_type, "rgmii") == 0)
return PHY_INTERFACE_MODE_RGMII;
- if (strcasecmp(interface_type, "rgmii-id") == 0)
+ if (strcasecmp(phy_connection_type, "rgmii-id") == 0)
return PHY_INTERFACE_MODE_RGMII_ID;
- if (strcasecmp(interface_type, "rtbi") == 0)
+ if (strcasecmp(phy_connection_type, "rtbi") == 0)
return PHY_INTERFACE_MODE_RTBI;
return PHY_INTERFACE_MODE_MII;
@@ -3819,29 +3819,21 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ug_info->phy_address = *prop;
/* get the phy interface type, or default to MII */
- prop = of_get_property(np, "interface-type", NULL);
+ prop = of_get_property(np, "phy-connection-type", NULL);
if (!prop) {
/* handle interface property present in old trees */
prop = of_get_property(phy, "interface", NULL);
- if (prop != NULL)
+ if (prop != NULL) {
phy_interface = enet_to_phy_interface[*prop];
- else
+ max_speed = enet_to_speed[*prop];
+ } else
phy_interface = PHY_INTERFACE_MODE_MII;
} else {
phy_interface = to_phy_interface((const char *)prop);
}
- /* get speed, or derive from interface */
- prop = of_get_property(np, "max-speed", NULL);
- if (!prop) {
- /* handle interface property present in old trees */
- prop = of_get_property(phy, "interface", NULL);
- if (prop != NULL)
- max_speed = enet_to_speed[*prop];
- } else {
- max_speed = *prop;
- }
- if (!max_speed) {
+ /* get speed, or derive from PHY interface */
+ if (max_speed == 0)
switch (phy_interface) {
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_RGMII:
@@ -3854,9 +3846,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
max_speed = SPEED_100;
break;
}
- }
if (max_speed == SPEED_1000) {
+ /* configure muram FIFOs for gigabit operation */
ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT;
ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT;
ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT;
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index 27a1ef3b7b06..f96966d4bcc2 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -1,12 +1,13 @@
/*
* drivers/net/ucc_geth_mii.c
*
- * Gianfar Ethernet Driver -- MIIM bus implementation
- * Provides Bus interface for MIIM regs
+ * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation
+ * Provides Bus interface for MII Management regs in the UCC register space
*
- * Author: Li Yang
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
*
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ * Authors: Li Yang <leoli@freescale.com>
+ * Kim Phillips <kim.phillips@freescale.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/drivers/net/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h
index 98430fe0bfc6..d83437039919 100644
--- a/drivers/net/ucc_geth_mii.h
+++ b/drivers/net/ucc_geth_mii.h
@@ -1,13 +1,13 @@
/*
* drivers/net/ucc_geth_mii.h
*
- * Gianfar Ethernet Driver -- MII Management Bus Implementation
- * Driver for the MDIO bus controller in the Gianfar register space
+ * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation
+ * Provides Bus interface for MII Management regs in the UCC register space
*
- * Author: Andy Fleming
- * Maintainer: Kumar Gala
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
*
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ * Authors: Li Yang <leoli@freescale.com>
+ * Kim Phillips <kim.phillips@freescale.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 78c2e6e4b42e..edd6de995726 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -26,6 +26,7 @@
#include <linux/profile.h>
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/sched.h>
#include "oprofile_stats.h"
#include "event_buffer.h"
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 02c0d52c9f76..7bfbad57879d 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -51,6 +51,7 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/pnp.h>
#include <linux/platform_device.h>
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index 46abaa8c41f1..d06ccb69e411 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -34,6 +34,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/mutex.h>
+#include <linux/sched.h>
#include "ibmphp.h"
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index 6c5be3ff578c..df076064a3e0 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -129,8 +129,9 @@ struct kobj_type ktype_dlpar_io = {
};
struct kset dlpar_io_kset = {
- .subsys = &pci_hotplug_slots_subsys,
- .kobj = {.name = DLPAR_KOBJ_NAME, .ktype=&ktype_dlpar_io,},
+ .kobj = {.name = DLPAR_KOBJ_NAME,
+ .ktype = &ktype_dlpar_io,
+ .parent = &pci_hotplug_slots_subsys.kobj},
.ktype = &ktype_dlpar_io,
};
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index bf655dbaf8e2..5cca394d5999 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -8,6 +8,7 @@
#ifndef _AERDRV_H_
#define _AERDRV_H_
+#include <linux/workqueue.h>
#include <linux/pcieport_if.h>
#include <linux/aer.h>
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 95ce8f49e382..4e4c10a7fd3a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -59,7 +59,7 @@ comment "RTC interfaces"
depends on RTC_CLASS
config RTC_INTF_SYSFS
- boolean "sysfs"
+ boolean "/sys/class/rtc/rtcN (sysfs)"
depends on RTC_CLASS && SYSFS
default RTC_CLASS
help
@@ -70,7 +70,7 @@ config RTC_INTF_SYSFS
will be called rtc-sysfs.
config RTC_INTF_PROC
- boolean "proc"
+ boolean "/proc/driver/rtc (procfs for rtc0)"
depends on RTC_CLASS && PROC_FS
default RTC_CLASS
help
@@ -82,7 +82,7 @@ config RTC_INTF_PROC
will be called rtc-proc.
config RTC_INTF_DEV
- boolean "dev"
+ boolean "/dev/rtcN (character devices)"
depends on RTC_CLASS
default RTC_CLASS
help
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 60a8a4bb8bd2..a2f84f169588 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -371,7 +371,7 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev)
goto fail;
}
platform_set_drvdata(pdev, rtc);
- dev_set_devdata(&rtc->dev, mem);
+ dev_set_drvdata(&rtc->dev, mem);
/* clear pending irqs, and set 1/second periodic,
* which we'll use instead of update irqs
@@ -453,7 +453,7 @@ static int __devexit omap_rtc_remove(struct platform_device *pdev)
free_irq(omap_rtc_timer, rtc);
free_irq(omap_rtc_alarm, rtc);
- release_resource(dev_get_devdata(&rtc->dev));
+ release_resource(dev_get_drvdata(&rtc->dev));
rtc_device_unregister(rtc);
return 0;
}
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 8410587348f1..178155bf9db6 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -18,6 +18,7 @@
#include <asm/ebus.h>
#include <asm/spitfire.h>
#include <asm/bbc.h>
+#include <asm/io.h>
#include "bbc_i2c.h"
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 2d14a29effe4..3279a1b6501d 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -20,6 +20,7 @@
#include <asm/ebus.h> /* EBus device */
#include <asm/oplib.h> /* OpenProm Library */
#include <asm/uaccess.h> /* put_/get_user */
+#include <asm/io.h>
#include <asm/display7seg.h>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index e62d23f65180..d28c14e23c32 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1757,6 +1757,14 @@ config SCSI_ESP_CORE
tristate "ESP Scsi Driver Core"
depends on SCSI
select SCSI_SPI_ATTRS
+ help
+ This is a core driver for NCR53c9x based scsi chipsets,
+ also known as "ESP" for Emulex Scsi Processor or
+ Enhanced Scsi Processor. This driver does not exist by
+ itself, there are front-end drivers which, when enabled,
+ select and enable this driver. One example is SCSI_SUNESP.
+ These front-end drivers provide probing, DMA, and register
+ access support for the core driver.
config SCSI_SUNESP
tristate "Sparc ESP Scsi Driver"
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index e075a52ac104..84d9c27133d4 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -14,7 +14,7 @@
*
* Common management module
*/
-
+#include <linux/sched.h>
#include "megaraid_mm.h"
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 48e259a0167d..c84dab083a85 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -894,7 +894,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
quot = serial_dl_read(up);
quot <<= 3;
- status1 = serial_in(up, 0x04); /* EXCR1 */
+ status1 = serial_in(up, 0x04); /* EXCR2 */
status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
serial_outp(up, 0x04, status1);
@@ -2617,7 +2617,22 @@ void serial8250_suspend_port(int line)
*/
void serial8250_resume_port(int line)
{
- uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
+ struct uart_8250_port *up = &serial8250_ports[line];
+
+ if (up->capabilities & UART_NATSEMI) {
+ unsigned char tmp;
+
+ /* Ensure it's still in high speed mode */
+ serial_outp(up, UART_LCR, 0xE0);
+
+ tmp = serial_in(up, 0x04); /* EXCR2 */
+ tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+ tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
+ serial_outp(up, 0x04, tmp);
+
+ serial_outp(up, UART_LCR, 0);
+ }
+ uart_resume_port(&serial8250_reg, &up->port);
}
/*
@@ -2694,7 +2709,7 @@ static int serial8250_resume(struct platform_device *dev)
struct uart_8250_port *up = &serial8250_ports[i];
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- uart_resume_port(&serial8250_reg, &up->port);
+ serial8250_resume_port(i);
}
return 0;
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 408390f93db9..787dc7168f3e 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -6,8 +6,6 @@
* Created:
* Description: Driver for blackfin 5xx serial ports
*
- * Rev: $Id: bfin_5xx.c,v 1.19 2006/09/24 02:33:53 aubrey Exp $
- *
* Modified:
* Copyright 2006 Analog Devices Inc.
*
@@ -152,7 +150,7 @@ static void local_put_char(struct bfin_serial_port *uart, char ch)
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
- struct tty_struct *tty = uart->port.info?uart->port.info->tty:0;
+ struct tty_struct *tty = uart->port.info->tty;
unsigned int status, ch, flg;
#ifdef BF533_FAMILY
static int in_break = 0;
@@ -173,8 +171,10 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
if (ch != 0) {
in_break = 0;
ch = UART_GET_CHAR(uart);
- }
- return;
+ if (bfin_revid() < 5)
+ return;
+ } else
+ return;
}
#endif
@@ -185,27 +185,32 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
uart->port.icount.brk++;
if (uart_handle_break(&uart->port))
goto ignore_char;
- flg = TTY_BREAK;
- } else if (status & PE) {
- flg = TTY_PARITY;
+ }
+ if (status & PE)
uart->port.icount.parity++;
- } else if (status & OE) {
- flg = TTY_OVERRUN;
+ if (status & OE)
uart->port.icount.overrun++;
- } else if (status & FE) {
- flg = TTY_FRAME;
+ if (status & FE)
uart->port.icount.frame++;
- } else
+
+ status &= uart->port.read_status_mask;
+
+ if (status & BI)
+ flg = TTY_BREAK;
+ else if (status & PE)
+ flg = TTY_PARITY;
+ else if (status & FE)
+ flg = TTY_FRAME;
+ else
flg = TTY_NORMAL;
if (uart_handle_sysrq_char(&uart->port, ch))
goto ignore_char;
- if (tty)
- uart_insert_char(&uart->port, status, 2, ch, flg);
-ignore_char:
- if (tty)
- tty_flip_buffer_push(tty);
+ uart_insert_char(&uart->port, status, OE, ch, flg);
+
+ ignore_char:
+ tty_flip_buffer_push(tty);
}
static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
@@ -240,24 +245,29 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
bfin_serial_stop_tx(&uart->port);
}
-static irqreturn_t bfin_serial_int(int irq, void *dev_id)
+static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
- unsigned short status;
spin_lock(&uart->port.lock);
- status = UART_GET_IIR(uart);
- do {
- if ((status & IIR_STATUS) == IIR_TX_READY)
- bfin_serial_tx_chars(uart);
- if ((status & IIR_STATUS) == IIR_RX_READY)
- bfin_serial_rx_chars(uart);
- status = UART_GET_IIR(uart);
- } while (status & (IIR_TX_READY | IIR_RX_READY));
+ while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
+ bfin_serial_rx_chars(uart);
spin_unlock(&uart->port.lock);
return IRQ_HANDLED;
}
+static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
+{
+ struct bfin_serial_port *uart = dev_id;
+
+ spin_lock(&uart->port.lock);
+ while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
+ bfin_serial_tx_chars(uart);
+ spin_unlock(&uart->port.lock);
+ return IRQ_HANDLED;
+}
+
+
static void bfin_serial_do_work(struct work_struct *work)
{
struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue);
@@ -319,7 +329,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
spin_unlock_irqrestore(&uart->port.lock, flags);
}
-static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart)
+static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
{
struct tty_struct *tty = uart->port.info->tty;
int i, flg, status;
@@ -331,25 +341,32 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart)
uart->port.icount.brk++;
if (uart_handle_break(&uart->port))
goto dma_ignore_char;
- flg = TTY_BREAK;
- } else if (status & PE) {
- flg = TTY_PARITY;
+ }
+ if (status & PE)
uart->port.icount.parity++;
- } else if (status & OE) {
- flg = TTY_OVERRUN;
+ if (status & OE)
uart->port.icount.overrun++;
- } else if (status & FE) {
- flg = TTY_FRAME;
+ if (status & FE)
uart->port.icount.frame++;
- } else
+
+ status &= uart->port.read_status_mask;
+
+ if (status & BI)
+ flg = TTY_BREAK;
+ else if (status & PE)
+ flg = TTY_PARITY;
+ else if (status & FE)
+ flg = TTY_FRAME;
+ else
flg = TTY_NORMAL;
for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) {
if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
goto dma_ignore_char;
- uart_insert_char(&uart->port, status, 2, uart->rx_dma_buf.buf[i], flg);
+ uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg);
}
-dma_ignore_char:
+
+ dma_ignore_char:
tty_flip_buffer_push(tty);
}
@@ -545,14 +562,14 @@ static int bfin_serial_startup(struct uart_port *port)
add_timer(&(uart->rx_dma_timer));
#else
if (request_irq
- (uart->port.irq, bfin_serial_int, IRQF_DISABLED,
+ (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
"BFIN_UART_RX", uart)) {
printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
return -EBUSY;
}
if (request_irq
- (uart->port.irq+1, bfin_serial_int, IRQF_DISABLED,
+ (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED,
"BFIN_UART_TX", uart)) {
printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");
free_irq(uart->port.irq, uart);
@@ -614,13 +631,27 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
lcr |= EPS;
}
- /* These controls are not implemented for this port */
- termios->c_iflag |= INPCK | BRKINT | PARMRK;
- termios->c_iflag &= ~(IGNPAR | IGNBRK);
+ port->read_status_mask = OE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= (FE | PE);
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= BI;
- /* These controls are not implemented for this port */
- termios->c_iflag |= INPCK | BRKINT | PARMRK;
- termios->c_iflag &= ~(IGNPAR | IGNBRK);
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= FE | PE;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= OE;
+ }
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud);
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 6202995e8211..9d3105b64a7a 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -69,33 +69,40 @@
static const struct pci_device_id icom_pci_table[] = {
{
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = ADAPTER_V1,
- },
+ .vendor = PCI_VENDOR_ID_IBM,
+ .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = ADAPTER_V1,
+ },
{
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
- .driver_data = ADAPTER_V2,
- },
+ .vendor = PCI_VENDOR_ID_IBM,
+ .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+ .subvendor = PCI_VENDOR_ID_IBM,
+ .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
+ .driver_data = ADAPTER_V2,
+ },
{
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
- .driver_data = ADAPTER_V2,
- },
+ .vendor = PCI_VENDOR_ID_IBM,
+ .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+ .subvendor = PCI_VENDOR_ID_IBM,
+ .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
+ .driver_data = ADAPTER_V2,
+ },
{
- .vendor = PCI_VENDOR_ID_IBM,
- .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
- .subvendor = PCI_VENDOR_ID_IBM,
- .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
- .driver_data = ADAPTER_V2,
- },
+ .vendor = PCI_VENDOR_ID_IBM,
+ .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+ .subvendor = PCI_VENDOR_ID_IBM,
+ .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
+ .driver_data = ADAPTER_V2,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_IBM,
+ .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+ .subvendor = PCI_VENDOR_ID_IBM,
+ .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE,
+ .driver_data = ADAPTER_V2,
+ },
{}
};
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
index c5346d677315..698763b28ddd 100644
--- a/drivers/serial/serial_ks8695.c
+++ b/drivers/serial/serial_ks8695.c
@@ -301,11 +301,11 @@ static int ks8695uart_startup(struct uart_port *port)
retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, IRQF_DISABLED, "UART LineStatus", port);
if (retval)
- return err_ls;
+ goto err_ls;
retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, IRQF_DISABLED, "UART ModemStatus", port);
if (retval)
- return err_ms;
+ goto err_ms;
return 0;
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 40d48566215c..96557e6dba60 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -1,6 +1,6 @@
/* sunhv.c: Serial driver for SUN4V hypervisor console.
*
- * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -35,57 +35,51 @@
#define CON_BREAK ((long)-1)
#define CON_HUP ((long)-2)
-static inline long hypervisor_con_getchar(long *status)
-{
- register unsigned long func asm("%o5");
- register unsigned long arg0 asm("%o0");
- register unsigned long arg1 asm("%o1");
-
- func = HV_FAST_CONS_GETCHAR;
- arg0 = 0;
- arg1 = 0;
- __asm__ __volatile__("ta %6"
- : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
- : "0" (func), "1" (arg0), "2" (arg1),
- "i" (HV_FAST_TRAP));
+#define IGNORE_BREAK 0x1
+#define IGNORE_ALL 0x2
- *status = arg0;
+static char *con_write_page;
+static char *con_read_page;
- return (long) arg1;
-}
+static int hung_up = 0;
-static inline long hypervisor_con_putchar(long ch)
+static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit)
{
- register unsigned long func asm("%o5");
- register unsigned long arg0 asm("%o0");
+ while (!uart_circ_empty(xmit)) {
+ long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
- func = HV_FAST_CONS_PUTCHAR;
- arg0 = ch;
- __asm__ __volatile__("ta %4"
- : "=&r" (func), "=&r" (arg0)
- : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP));
+ if (status != HV_EOK)
+ break;
- return (long) arg0;
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
}
-#define IGNORE_BREAK 0x1
-#define IGNORE_ALL 0x2
+static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit)
+{
+ while (!uart_circ_empty(xmit)) {
+ unsigned long ra = __pa(xmit->buf + xmit->tail);
+ unsigned long len, status, sent;
-static int hung_up = 0;
+ len = CIRC_CNT_TO_END(xmit->head, xmit->tail,
+ UART_XMIT_SIZE);
+ status = sun4v_con_write(ra, len, &sent);
+ if (status != HV_EOK)
+ break;
+ xmit->tail = (xmit->tail + sent) & (UART_XMIT_SIZE - 1);
+ port->icount.tx += sent;
+ }
+}
-static struct tty_struct *receive_chars(struct uart_port *port)
+static int receive_chars_getchar(struct uart_port *port, struct tty_struct *tty)
{
- struct tty_struct *tty = NULL;
int saw_console_brk = 0;
int limit = 10000;
- if (port->info != NULL) /* Unopened serial console */
- tty = port->info->tty;
-
while (limit-- > 0) {
long status;
- long c = hypervisor_con_getchar(&status);
- unsigned char flag;
+ long c = sun4v_con_getchar(&status);
if (status == HV_EWOULDBLOCK)
break;
@@ -110,27 +104,90 @@ static struct tty_struct *receive_chars(struct uart_port *port)
continue;
}
- flag = TTY_NORMAL;
port->icount.rx++;
- if (c == CON_BREAK) {
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- flag = TTY_BREAK;
- }
if (uart_handle_sysrq_char(port, c))
continue;
- if ((port->ignore_status_mask & IGNORE_ALL) ||
- ((port->ignore_status_mask & IGNORE_BREAK) &&
- (c == CON_BREAK)))
+ tty_insert_flip_char(tty, c, TTY_NORMAL);
+ }
+
+ return saw_console_brk;
+}
+
+static int receive_chars_read(struct uart_port *port, struct tty_struct *tty)
+{
+ int saw_console_brk = 0;
+ int limit = 10000;
+
+ while (limit-- > 0) {
+ unsigned long ra = __pa(con_read_page);
+ unsigned long bytes_read, i;
+ long stat = sun4v_con_read(ra, PAGE_SIZE, &bytes_read);
+
+ if (stat != HV_EOK) {
+ bytes_read = 0;
+
+ if (stat == CON_BREAK) {
+ if (uart_handle_break(port))
+ continue;
+ saw_console_brk = 1;
+ *con_read_page = 0;
+ bytes_read = 1;
+ } else if (stat == CON_HUP) {
+ hung_up = 1;
+ uart_handle_dcd_change(port, 0);
+ continue;
+ } else {
+ /* HV_EWOULDBLOCK, etc. */
+ break;
+ }
+ }
+
+ if (hung_up) {
+ hung_up = 0;
+ uart_handle_dcd_change(port, 1);
+ }
+
+ for (i = 0; i < bytes_read; i++)
+ uart_handle_sysrq_char(port, con_read_page[i]);
+
+ if (tty == NULL)
continue;
- tty_insert_flip_char(tty, c, flag);
+ port->icount.rx += bytes_read;
+
+ tty_insert_flip_string(tty, con_read_page, bytes_read);
}
- if (saw_console_brk)
+ return saw_console_brk;
+}
+
+struct sunhv_ops {
+ void (*transmit_chars)(struct uart_port *port, struct circ_buf *xmit);
+ int (*receive_chars)(struct uart_port *port, struct tty_struct *tty);
+};
+
+static struct sunhv_ops bychar_ops = {
+ .transmit_chars = transmit_chars_putchar,
+ .receive_chars = receive_chars_getchar,
+};
+
+static struct sunhv_ops bywrite_ops = {
+ .transmit_chars = transmit_chars_write,
+ .receive_chars = receive_chars_read,
+};
+
+static struct sunhv_ops *sunhv_ops = &bychar_ops;
+
+static struct tty_struct *receive_chars(struct uart_port *port)
+{
+ struct tty_struct *tty = NULL;
+
+ if (port->info != NULL) /* Unopened serial console */
+ tty = port->info->tty;
+
+ if (sunhv_ops->receive_chars(port, tty))
sun_do_break();
return tty;
@@ -147,15 +204,7 @@ static void transmit_chars(struct uart_port *port)
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return;
- while (!uart_circ_empty(xmit)) {
- long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
-
- if (status != HV_EOK)
- break;
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
+ sunhv_ops->transmit_chars(port, xmit);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
@@ -212,7 +261,7 @@ static void sunhv_start_tx(struct uart_port *port)
struct circ_buf *xmit = &port->info->xmit;
while (!uart_circ_empty(xmit)) {
- long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
+ long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
if (status != HV_EOK)
break;
@@ -231,9 +280,10 @@ static void sunhv_send_xchar(struct uart_port *port, char ch)
spin_lock_irqsave(&port->lock, flags);
while (limit-- > 0) {
- long status = hypervisor_con_putchar(ch);
+ long status = sun4v_con_putchar(ch);
if (status == HV_EOK)
break;
+ udelay(1);
}
spin_unlock_irqrestore(&port->lock, flags);
@@ -254,15 +304,15 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state)
{
if (break_state) {
unsigned long flags;
- int limit = 1000000;
+ int limit = 10000;
spin_lock_irqsave(&port->lock, flags);
while (limit-- > 0) {
- long status = hypervisor_con_putchar(CON_BREAK);
+ long status = sun4v_con_putchar(CON_BREAK);
if (status == HV_EOK)
break;
- udelay(2);
+ udelay(1);
}
spin_unlock_irqrestore(&port->lock, flags);
@@ -359,38 +409,99 @@ static struct uart_driver sunhv_reg = {
static struct uart_port *sunhv_port;
-static inline void sunhv_console_putchar(struct uart_port *port, char c)
+/* Copy 's' into the con_write_page, decoding "\n" into
+ * "\r\n" along the way. We have to return two lengths
+ * because the caller needs to know how much to advance
+ * 's' and also how many bytes to output via con_write_page.
+ */
+static int fill_con_write_page(const char *s, unsigned int n,
+ unsigned long *page_bytes)
{
+ const char *orig_s = s;
+ char *p = con_write_page;
+ int left = PAGE_SIZE;
+
+ while (n--) {
+ if (*s == '\n') {
+ if (left < 2)
+ break;
+ *p++ = '\r';
+ left--;
+ } else if (left < 1)
+ break;
+ *p++ = *s++;
+ left--;
+ }
+ *page_bytes = p - con_write_page;
+ return s - orig_s;
+}
+
+static void sunhv_console_write_paged(struct console *con, const char *s, unsigned n)
+{
+ struct uart_port *port = sunhv_port;
unsigned long flags;
- int limit = 1000000;
spin_lock_irqsave(&port->lock, flags);
+ while (n > 0) {
+ unsigned long ra = __pa(con_write_page);
+ unsigned long page_bytes;
+ unsigned int cpy = fill_con_write_page(s, n,
+ &page_bytes);
+
+ n -= cpy;
+ s += cpy;
+ while (page_bytes > 0) {
+ unsigned long written;
+ int limit = 1000000;
+
+ while (limit--) {
+ unsigned long stat;
+
+ stat = sun4v_con_write(ra, page_bytes,
+ &written);
+ if (stat == HV_EOK)
+ break;
+ udelay(1);
+ }
+ if (limit <= 0)
+ break;
+ page_bytes -= written;
+ ra += written;
+ }
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static inline void sunhv_console_putchar(struct uart_port *port, char c)
+{
+ int limit = 1000000;
while (limit-- > 0) {
- long status = hypervisor_con_putchar(c);
+ long status = sun4v_con_putchar(c);
if (status == HV_EOK)
break;
- udelay(2);
+ udelay(1);
}
-
- spin_unlock_irqrestore(&port->lock, flags);
}
-static void sunhv_console_write(struct console *con, const char *s, unsigned n)
+static void sunhv_console_write_bychar(struct console *con, const char *s, unsigned n)
{
struct uart_port *port = sunhv_port;
+ unsigned long flags;
int i;
+ spin_lock_irqsave(&port->lock, flags);
for (i = 0; i < n; i++) {
if (*s == '\n')
sunhv_console_putchar(port, '\r');
sunhv_console_putchar(port, *s++);
}
+ spin_unlock_irqrestore(&port->lock, flags);
}
static struct console sunhv_console = {
.name = "ttyHV",
- .write = sunhv_console_write,
+ .write = sunhv_console_write_bychar,
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
.index = -1,
@@ -410,6 +521,7 @@ static inline struct console *SUNHV_CONSOLE(void)
static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
{
struct uart_port *port;
+ unsigned long minor;
int err;
if (op->irqs[0] == 0xffffffff)
@@ -419,6 +531,22 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
if (unlikely(!port))
return -ENOMEM;
+ minor = 1;
+ if (sun4v_hvapi_register(HV_GRP_CORE, 1, &minor) == 0 &&
+ minor >= 1) {
+ err = -ENOMEM;
+ con_write_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!con_write_page)
+ goto out_free_port;
+
+ con_read_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!con_read_page)
+ goto out_free_con_write_page;
+
+ sunhv_console.write = sunhv_console_write_paged;
+ sunhv_ops = &bywrite_ops;
+ }
+
sunhv_port = port;
port->line = 0;
@@ -437,7 +565,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
err = uart_register_driver(&sunhv_reg);
if (err)
- goto out_free_port;
+ goto out_free_con_read_page;
sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
sunserial_current_minor += 1;
@@ -463,6 +591,12 @@ out_unregister_driver:
sunserial_current_minor -= 1;
uart_unregister_driver(&sunhv_reg);
+out_free_con_read_page:
+ kfree(con_read_page);
+
+out_free_con_write_page:
+ kfree(con_write_page);
+
out_free_port:
kfree(port);
sunhv_port = NULL;
@@ -493,6 +627,10 @@ static struct of_device_id hv_match[] = {
.name = "console",
.compatible = "qcn",
},
+ {
+ .name = "console",
+ .compatible = "SUNW,sun4v-console",
+ },
{},
};
MODULE_DEVICE_TABLE(of, hv_match);
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index ce3c0ce2316e..7d2d9ec6cac3 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -126,7 +126,7 @@ struct chip_data {
u8 chip_select_num;
u8 n_bytes;
- u32 width; /* 0 or 1 */
+ u8 width; /* 0 or 1 */
u8 enable_dma;
u8 bits_per_word; /* 8 or 16 */
u8 cs_change_per_word;
@@ -136,7 +136,7 @@ struct chip_data {
void (*duplex) (struct driver_data *);
};
-void bfin_spi_enable(struct driver_data *drv_data)
+static void bfin_spi_enable(struct driver_data *drv_data)
{
u16 cr;
@@ -145,7 +145,7 @@ void bfin_spi_enable(struct driver_data *drv_data)
SSYNC();
}
-void bfin_spi_disable(struct driver_data *drv_data)
+static void bfin_spi_disable(struct driver_data *drv_data)
{
u16 cr;
@@ -163,9 +163,6 @@ static u16 hz_to_spi_baud(u32 speed_hz)
if ((sclk % (2 * speed_hz)) > 0)
spi_baud++;
- pr_debug("sclk = %ld, speed_hz = %d, spi_baud = %d\n", sclk, speed_hz,
- spi_baud);
-
return spi_baud;
}
@@ -190,11 +187,12 @@ static void restore_state(struct driver_data *drv_data)
/* Clear status and disable clock */
write_STAT(BIT_STAT_CLR);
bfin_spi_disable(drv_data);
- pr_debug("restoring spi ctl state\n");
+ dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
#if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
- pr_debug("chip select number is %d\n", chip->chip_select_num);
-
+ dev_dbg(&drv_data->pdev->dev,
+ "chip select number is %d\n", chip->chip_select_num);
+
switch (chip->chip_select_num) {
case 1:
bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00);
@@ -280,7 +278,8 @@ static void null_reader(struct driver_data *drv_data)
static void u8_writer(struct driver_data *drv_data)
{
- pr_debug("cr8-s is 0x%x\n", read_STAT());
+ dev_dbg(&drv_data->pdev->dev,
+ "cr8-s is 0x%x\n", read_STAT());
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u8 *) (drv_data->tx));
while (read_STAT() & BIT_STAT_TXS)
@@ -318,7 +317,8 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
static void u8_reader(struct driver_data *drv_data)
{
- pr_debug("cr-8 is 0x%x\n", read_STAT());
+ dev_dbg(&drv_data->pdev->dev,
+ "cr-8 is 0x%x\n", read_STAT());
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(0xFFFF);
@@ -404,7 +404,9 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
static void u16_writer(struct driver_data *drv_data)
{
- pr_debug("cr16 is 0x%x\n", read_STAT());
+ dev_dbg(&drv_data->pdev->dev,
+ "cr16 is 0x%x\n", read_STAT());
+
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u16 *) (drv_data->tx));
while ((read_STAT() & BIT_STAT_TXS))
@@ -442,7 +444,8 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
static void u16_reader(struct driver_data *drv_data)
{
- pr_debug("cr-16 is 0x%x\n", read_STAT());
+ dev_dbg(&drv_data->pdev->dev,
+ "cr-16 is 0x%x\n", read_STAT());
dummy_read();
while (drv_data->rx < (drv_data->rx_end - 2)) {
@@ -571,12 +574,12 @@ static void giveback(struct driver_data *drv_data)
msg->complete(msg->context);
}
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
{
struct driver_data *drv_data = (struct driver_data *)dev_id;
struct spi_message *msg = drv_data->cur_msg;
- pr_debug("in dma_irq_handler\n");
+ dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
clear_dma_irqstat(CH_SPI);
/*
@@ -604,7 +607,9 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
tasklet_schedule(&drv_data->pump_transfers);
/* free the irq handler before next transfer */
- pr_debug("disable dma channel irq%d\n", CH_SPI);
+ dev_dbg(&drv_data->pdev->dev,
+ "disable dma channel irq%d\n",
+ CH_SPI);
dma_disable_irq(CH_SPI);
return IRQ_HANDLED;
@@ -617,7 +622,8 @@ static void pump_transfers(unsigned long data)
struct spi_transfer *transfer = NULL;
struct spi_transfer *previous = NULL;
struct chip_data *chip = NULL;
- u16 cr, width, dma_width, dma_config;
+ u8 width;
+ u16 cr, dma_width, dma_config;
u32 tranf_success = 1;
/* Get current state information */
@@ -662,8 +668,8 @@ static void pump_transfers(unsigned long data)
if (transfer->tx_buf != NULL) {
drv_data->tx = (void *)transfer->tx_buf;
drv_data->tx_end = drv_data->tx + transfer->len;
- pr_debug("tx_buf is %p, tx_end is %p\n", transfer->tx_buf,
- drv_data->tx_end);
+ dev_dbg(&drv_data->pdev->dev, "tx_buf is %p, tx_end is %p\n",
+ transfer->tx_buf, drv_data->tx_end);
} else {
drv_data->tx = NULL;
}
@@ -671,8 +677,8 @@ static void pump_transfers(unsigned long data)
if (transfer->rx_buf != NULL) {
drv_data->rx = transfer->rx_buf;
drv_data->rx_end = drv_data->rx + transfer->len;
- pr_debug("rx_buf is %p, rx_end is %p\n", transfer->rx_buf,
- drv_data->rx_end);
+ dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n",
+ transfer->rx_buf, drv_data->rx_end);
} else {
drv_data->rx = NULL;
}
@@ -690,9 +696,9 @@ static void pump_transfers(unsigned long data)
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
- pr_debug
- ("transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
- drv_data->write, chip->write, null_writer);
+ dev_dbg(&drv_data->pdev->dev,
+ "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
+ drv_data->write, chip->write, null_writer);
/* speed and width has been set on per message */
message->state = RUNNING_STATE;
@@ -706,8 +712,9 @@ static void pump_transfers(unsigned long data)
}
write_FLAG(chip->flag);
- pr_debug("now pumping a transfer: width is %d, len is %d\n", width,
- transfer->len);
+ dev_dbg(&drv_data->pdev->dev,
+ "now pumping a transfer: width is %d, len is %d\n",
+ width, transfer->len);
/*
* Try to map dma buffer and do a dma transfer if
@@ -722,7 +729,7 @@ static void pump_transfers(unsigned long data)
bfin_spi_disable(drv_data);
/* config dma channel */
- pr_debug("doing dma transfer\n");
+ dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
if (width == CFG_SPI_WORDSIZE16) {
set_dma_x_count(CH_SPI, drv_data->len);
set_dma_x_modify(CH_SPI, 2);
@@ -738,7 +745,8 @@ static void pump_transfers(unsigned long data)
/* dirty hack for autobuffer DMA mode */
if (drv_data->tx_dma == 0xFFFF) {
- pr_debug("doing autobuffer DMA out.\n");
+ dev_dbg(&drv_data->pdev->dev,
+ "doing autobuffer DMA out.\n");
/* no irq in autobuffer mode */
dma_config =
@@ -758,7 +766,7 @@ static void pump_transfers(unsigned long data)
/* In dma mode, rx or tx must be NULL in one transfer */
if (drv_data->rx != NULL) {
/* set transfer mode, and enable SPI */
- pr_debug("doing DMA in.\n");
+ dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
/* disable SPI before write to TDBR */
write_CTRL(cr & ~BIT_CTL_ENABLE);
@@ -781,7 +789,7 @@ static void pump_transfers(unsigned long data)
/* set transfer mode, and enable SPI */
write_CTRL(cr);
} else if (drv_data->tx != NULL) {
- pr_debug("doing DMA out.\n");
+ dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
/* start dma */
dma_enable_irq(CH_SPI);
@@ -796,7 +804,7 @@ static void pump_transfers(unsigned long data)
}
} else {
/* IO mode write then read */
- pr_debug("doing IO transfer\n");
+ dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
write_STAT(BIT_STAT_CLR);
@@ -804,11 +812,11 @@ static void pump_transfers(unsigned long data)
/* full duplex mode */
BUG_ON((drv_data->tx_end - drv_data->tx) !=
(drv_data->rx_end - drv_data->rx));
- cr = (read_CTRL() & (~BIT_CTL_TIMOD)); /* clear the TIMOD bits */
- cr |=
- CFG_SPI_WRITE | (width << 8) | (CFG_SPI_ENABLE <<
- 14);
- pr_debug("IO duplex: cr is 0x%x\n", cr);
+ cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+ cr |= CFG_SPI_WRITE | (width << 8) |
+ (CFG_SPI_ENABLE << 14);
+ dev_dbg(&drv_data->pdev->dev,
+ "IO duplex: cr is 0x%x\n", cr);
write_CTRL(cr);
SSYNC();
@@ -819,11 +827,11 @@ static void pump_transfers(unsigned long data)
tranf_success = 0;
} else if (drv_data->tx != NULL) {
/* write only half duplex */
- cr = (read_CTRL() & (~BIT_CTL_TIMOD)); /* clear the TIMOD bits */
- cr |=
- CFG_SPI_WRITE | (width << 8) | (CFG_SPI_ENABLE <<
- 14);
- pr_debug("IO write: cr is 0x%x\n", cr);
+ cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+ cr |= CFG_SPI_WRITE | (width << 8) |
+ (CFG_SPI_ENABLE << 14);
+ dev_dbg(&drv_data->pdev->dev,
+ "IO write: cr is 0x%x\n", cr);
write_CTRL(cr);
SSYNC();
@@ -834,11 +842,11 @@ static void pump_transfers(unsigned long data)
tranf_success = 0;
} else if (drv_data->rx != NULL) {
/* read only half duplex */
- cr = (read_CTRL() & (~BIT_CTL_TIMOD)); /* cleare the TIMOD bits */
- cr |=
- CFG_SPI_READ | (width << 8) | (CFG_SPI_ENABLE <<
- 14);
- pr_debug("IO read: cr is 0x%x\n", cr);
+ cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+ cr |= CFG_SPI_READ | (width << 8) |
+ (CFG_SPI_ENABLE << 14);
+ dev_dbg(&drv_data->pdev->dev,
+ "IO read: cr is 0x%x\n", cr);
write_CTRL(cr);
SSYNC();
@@ -849,7 +857,8 @@ static void pump_transfers(unsigned long data)
}
if (!tranf_success) {
- pr_debug("IO write error!\n");
+ dev_dbg(&drv_data->pdev->dev,
+ "IO write error!\n");
message->state = ERROR_STATE;
} else {
/* Update total byte transfered */
@@ -899,11 +908,14 @@ static void pump_messages(struct work_struct *work)
/* Setup the SSP using the per chip configuration */
drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
restore_state(drv_data);
- pr_debug
- ("got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
- drv_data->cur_chip->baud, drv_data->cur_chip->flag,
- drv_data->cur_chip->ctl_reg);
- pr_debug("the first transfer len is %d\n", drv_data->cur_transfer->len);
+ dev_dbg(&drv_data->pdev->dev,
+ "got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
+ drv_data->cur_chip->baud, drv_data->cur_chip->flag,
+ drv_data->cur_chip->ctl_reg);
+
+ dev_dbg(&drv_data->pdev->dev,
+ "the first transfer len is %d\n",
+ drv_data->cur_transfer->len);
/* Mark as busy and launch transfers */
tasklet_schedule(&drv_data->pump_transfers);
@@ -932,7 +944,7 @@ static int transfer(struct spi_device *spi, struct spi_message *msg)
msg->status = -EINPROGRESS;
msg->state = START_STATE;
- pr_debug("adding an msg in transfer() \n");
+ dev_dbg(&spi->dev, "adding an msg in transfer() \n");
list_add_tail(&msg->queue, &drv_data->queue);
if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
@@ -1002,13 +1014,13 @@ static int setup(struct spi_device *spi)
if (chip->enable_dma && !dma_requested) {
/* register dma irq handler */
if (request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) {
- pr_debug
- ("Unable to request BlackFin SPI DMA channel\n");
+ dev_dbg(&spi->dev,
+ "Unable to request BlackFin SPI DMA channel\n");
return -ENODEV;
}
if (set_dma_callback(CH_SPI, (void *)dma_irq_handler, drv_data)
< 0) {
- pr_debug("Unable to set dma callback\n");
+ dev_dbg(&spi->dev, "Unable to set dma callback\n");
return -EPERM;
}
dma_disable_irq(CH_SPI);
@@ -1054,9 +1066,9 @@ static int setup(struct spi_device *spi)
return -ENODEV;
}
- pr_debug("setup spi chip %s, width is %d, dma is %d,",
+ dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d,",
spi->modalias, chip->width, chip->enable_dma);
- pr_debug("ctl_reg is 0x%x, flag_reg is 0x%x\n",
+ dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
chip->ctl_reg, chip->flag);
spi_set_ctldata(spi, chip);
@@ -1068,7 +1080,7 @@ static int setup(struct spi_device *spi)
* callback for spi framework.
* clean driver specific data
*/
-static void cleanup(const struct spi_device *spi)
+static void cleanup(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
@@ -1207,7 +1219,7 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "problem registering spi master\n");
goto out_error_queue_alloc;
}
- pr_debug("controller probe successfully\n");
+ dev_dbg(&pdev->dev, "controller probe successfully\n");
return status;
out_error_queue_alloc:
@@ -1287,27 +1299,23 @@ static int bfin5xx_spi_resume(struct platform_device *pdev)
#endif /* CONFIG_PM */
static struct platform_driver bfin5xx_spi_driver = {
- .driver = {
- .name = "bfin-spi-master",
- .bus = &platform_bus_type,
- .owner = THIS_MODULE,
- },
- .probe = bfin5xx_spi_probe,
- .remove = __devexit_p(bfin5xx_spi_remove),
- .suspend = bfin5xx_spi_suspend,
- .resume = bfin5xx_spi_resume,
+ .driver = {
+ .name = "bfin-spi-master",
+ .owner = THIS_MODULE,
+ },
+ .suspend = bfin5xx_spi_suspend,
+ .resume = bfin5xx_spi_resume,
+ .remove = __devexit_p(bfin5xx_spi_remove),
};
static int __init bfin5xx_spi_init(void)
{
- return platform_driver_register(&bfin5xx_spi_driver);
+ return platform_driver_probe(&bfin5xx_spi_driver, bfin5xx_spi_probe);
}
-
module_init(bfin5xx_spi_init);
static void __exit bfin5xx_spi_exit(void)
{
platform_driver_unregister(&bfin5xx_spi_driver);
}
-
module_exit(bfin5xx_spi_exit);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index c0a6dce800a3..225d6b2f82dd 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -484,7 +484,7 @@ static int spidev_probe(struct spi_device *spi)
* Reusing minors is fine so long as udev or mdev is working.
*/
mutex_lock(&device_list_lock);
- minor = find_first_zero_bit(minors, ARRAY_SIZE(minors));
+ minor = find_first_zero_bit(minors, N_SPI_MINORS);
if (minor < N_SPI_MINORS) {
spidev->dev.parent = &spi->dev;
spidev->dev.class = &spidev_class;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index eebcb708cff1..4d7485fa553f 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1535,7 +1535,7 @@ config FB_LEO
config FB_XVR500
bool "Sun XVR-500 3DLABS Wildcat support"
- depends on FB && PCI && SPARC64
+ depends on (FB = y) && PCI && SPARC64
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1548,7 +1548,7 @@ config FB_XVR500
config FB_XVR2500
bool "Sun XVR-2500 3DLABS Wildcat support"
- depends on FB && PCI && SPARC64
+ depends on (FB = y) && PCI && SPARC64
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 2460b82a1d93..f46fe95f69fb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -368,9 +368,14 @@ static const char *vgacon_startup(void)
#endif
}
+ /* SCREEN_INFO initialized? */
+ if ((ORIG_VIDEO_MODE == 0) &&
+ (ORIG_VIDEO_LINES == 0) &&
+ (ORIG_VIDEO_COLS == 0))
+ goto no_vga;
+
/* VGA16 modes are not handled by VGACON */
- if ((ORIG_VIDEO_MODE == 0x00) || /* SCREEN_INFO not initialized */
- (ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */
+ if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */
(ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */
(ORIG_VIDEO_MODE == 0x10) || /* 640x350/4 */
(ORIG_VIDEO_MODE == 0x12) || /* 640x480/4 */