diff options
Diffstat (limited to 'drivers')
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 &= 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(®ister_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(®ister_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 */ |