diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-14 18:24:00 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-14 18:24:00 +0200 |
commit | 83bd6998b04fc1bb7280b14f16b2bdbdc07c914b (patch) | |
tree | af1bbe2bac5752b69b1ac58bf5d822c735da439b /drivers/char | |
parent | e7250b8ae3870f37f660c2f65cafcaba85e3bfd3 (diff) | |
parent | adee14b2e1557d0a8559f29681732d05a89dfc35 (diff) |
Merge commit 'v2.6.27-rc6' into timers/hpet
Diffstat (limited to 'drivers/char')
41 files changed, 350 insertions, 1429 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d0ac944e169..caff85149b9 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -8,7 +8,7 @@ config VT bool "Virtual terminal" if EMBEDDED depends on !S390 select INPUT - default y if !VIOCONS + default y ---help--- If you say Y here, you will get support for terminal devices with display and keyboard devices. These are called "virtual" because you diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 8a161c30e1d..6850f6da757 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -55,7 +55,6 @@ obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_MMTIMER) += mmtimer.o -obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_IBM_BSR) += bsr.o diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 81e14bea54b..4bada0e8b81 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -148,6 +148,9 @@ struct agp_bridge_data { char minor_version; struct list_head list; u32 apbase_config; + /* list of agp_memory mapped to the aperture */ + struct list_head mapped_list; + spinlock_t mapped_lock; }; #define KB(x) ((x) * 1024) diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 1ffb381130c..31dcd9142d5 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -110,7 +110,8 @@ static int ali_configure(void) nlvm_addr+= agp_bridge->gart_bus_addr; nlvm_addr|=(agp_bridge->gart_bus_addr>>12); - printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr); + dev_info(&agp_bridge->dev->dev, "nlvm top &base = %8x\n", + nlvm_addr); } #endif @@ -315,8 +316,8 @@ static int __devinit agp_ali_probe(struct pci_dev *pdev, goto found; } - printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x)\n", - pdev->device); + dev_err(&pdev->dev, "unsupported ALi chipset [%04x/%04x])\n", + pdev->vendor, pdev->device); return -ENODEV; @@ -361,8 +362,7 @@ found: bridge->driver = &ali_generic_bridge; } - printk(KERN_INFO PFX "Detected ALi %s chipset\n", - devs[j].chipset_name); + dev_info(&pdev->dev, "ALi %s chipset\n", devs[j].chipset_name); /* Fill in the mode register */ pci_read_config_dword(pdev, diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 39a0718bc61..e280531843b 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -419,8 +419,8 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, return -ENODEV; j = ent - agp_amdk7_pci_table; - printk(KERN_INFO PFX "Detected AMD %s chipset\n", - amd_agp_device_ids[j].chipset_name); + dev_info(&pdev->dev, "AMD %s chipset\n", + amd_agp_device_ids[j].chipset_name); bridge = agp_alloc_bridge(); if (!bridge) @@ -442,7 +442,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, while (!cap_ptr) { gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard); if (!gfxcard) { - printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n"); + dev_info(&pdev->dev, "no AGP VGA controller\n"); return -ENODEV; } cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP); @@ -453,7 +453,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, (if necessary at all). */ if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) { agp_bridge->flags |= AGP_ERRATA_1X; - printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n"); + dev_info(&pdev->dev, "AMD 751 chipset with NVidia GeForce; forcing 1X due to errata\n"); } pci_dev_put(gfxcard); } @@ -469,7 +469,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, agp_bridge->flags = AGP_ERRATA_FASTWRITES; agp_bridge->flags |= AGP_ERRATA_SBA; agp_bridge->flags |= AGP_ERRATA_1X; - printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n"); + dev_info(&pdev->dev, "AMD 761 chipset with errata; disabling AGP fast writes & SBA and forcing to 1X\n"); } } diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 481ffe87c71..7495c522d8e 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -34,6 +34,7 @@ static struct resource *aperture_resource; static int __initdata agp_try_unsupported = 1; +static int agp_bridges_found; static void amd64_tlbflush(struct agp_memory *temp) { @@ -293,12 +294,13 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, * so let double check that order, and lets trust the AMD NB settings */ if (order >=0 && aper + (32ULL<<(20 + order)) > 0x100000000ULL) { - printk(KERN_INFO "Aperture size %u MB is not right, using settings from NB\n", - 32 << order); + dev_info(&agp->dev, "aperture size %u MB is not right, using settings from NB\n", + 32 << order); order = nb_order; } - printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); + dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n", + aper, 32 << order); if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) return -1; @@ -319,10 +321,10 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) for (i = 0; i < num_k8_northbridges; i++) { struct pci_dev *dev = k8_northbridges[i]; if (fix_northbridge(dev, pdev, cap_ptr) < 0) { - printk(KERN_ERR PFX "No usable aperture found.\n"); + dev_err(&dev->dev, "no usable aperture found\n"); #ifdef __x86_64__ /* should port this to i386 */ - printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n"); + dev_err(&dev->dev, "consider rebooting with iommu=memaper=2 to get a good aperture\n"); #endif return -1; } @@ -345,14 +347,14 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data default: revstring="??"; break; } - printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); + dev_info(&pdev->dev, "AMD 8151 AGP Bridge rev %s\n", revstring); /* * Work around errata. * Chips before B2 stepping incorrectly reporting v3.5 */ if (pdev->revision < 0x13) { - printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); + dev_info(&pdev->dev, "correcting AGP revision (reports 3.5, is really 3.0)\n"); bridge->major_version = 3; bridge->minor_version = 0; } @@ -375,11 +377,11 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) struct pci_dev *dev1; int i; unsigned size = amd64_fetch_size(); - printk(KERN_INFO "Setting up ULi AGP.\n"); + + dev_info(&pdev->dev, "setting up ULi AGP\n"); dev1 = pci_get_slot (pdev->bus,PCI_DEVFN(0,0)); if (dev1 == NULL) { - printk(KERN_INFO PFX "Detected a ULi chipset, " - "but could not fine the secondary device.\n"); + dev_info(&pdev->dev, "can't find ULi secondary device\n"); return -ENODEV; } @@ -388,7 +390,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) break; if (i == ARRAY_SIZE(uli_sizes)) { - printk(KERN_INFO PFX "No ULi size found for %d\n", size); + dev_info(&pdev->dev, "no ULi size found for %d\n", size); return -ENODEV; } @@ -433,13 +435,11 @@ static int nforce3_agp_init(struct pci_dev *pdev) int i; unsigned size = amd64_fetch_size(); - printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); + dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); dev1 = pci_get_slot(pdev->bus, PCI_DEVFN(11, 0)); if (dev1 == NULL) { - printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " - "nForce3 chipset, but could not find " - "the secondary device.\n"); + dev_info(&pdev->dev, "can't find Nforce3 secondary device\n"); return -ENODEV; } @@ -448,7 +448,7 @@ static int nforce3_agp_init(struct pci_dev *pdev) break; if (i == ARRAY_SIZE(nforce3_sizes)) { - printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); + dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); return -ENODEV; } @@ -462,7 +462,7 @@ static int nforce3_agp_init(struct pci_dev *pdev) /* if x86-64 aperture base is beyond 4G, exit here */ if ( (apbase & 0x7fff) >> (32 - 25) ) { - printk(KERN_INFO PFX "aperture base > 4G\n"); + dev_info(&pdev->dev, "aperture base > 4G\n"); return -ENODEV; } @@ -489,6 +489,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, { struct agp_bridge_data *bridge; u8 cap_ptr; + int err; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) @@ -504,7 +505,8 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, pdev->device == PCI_DEVICE_ID_AMD_8151_0) { amd8151_init(pdev, bridge); } else { - printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn); + dev_info(&pdev->dev, "AGP bridge [%04x/%04x]\n", + pdev->vendor, pdev->device); } bridge->driver = &amd_8151_driver; @@ -536,7 +538,12 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, } pci_set_drvdata(pdev, bridge); - return agp_add_bridge(bridge); + err = agp_add_bridge(bridge); + if (err < 0) + return err; + + agp_bridges_found++; + return 0; } static void __devexit agp_amd64_remove(struct pci_dev *pdev) @@ -713,7 +720,11 @@ int __init agp_amd64_init(void) if (agp_off) return -EINVAL; - if (pci_register_driver(&agp_amd64_pci_driver) < 0) { + err = pci_register_driver(&agp_amd64_pci_driver); + if (err < 0) + return err; + + if (agp_bridges_found == 0) { struct pci_dev *dev; if (!agp_try_unsupported && !agp_try_unsupported_boot) { printk(KERN_INFO PFX "No supported AGP bridge found.\n"); diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 3a4566c0d84..6ecbcafb34b 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -486,8 +486,8 @@ static int __devinit agp_ati_probe(struct pci_dev *pdev, goto found; } - printk(KERN_ERR PFX - "Unsupported Ati chipset (device id: %04x)\n", pdev->device); + dev_err(&pdev->dev, "unsupported Ati chipset [%04x/%04x])\n", + pdev->vendor, pdev->device); return -ENODEV; found: @@ -500,8 +500,7 @@ found: bridge->driver = &ati_generic_bridge; - printk(KERN_INFO PFX "Detected Ati %s chipset\n", - devs[j].chipset_name); + dev_info(&pdev->dev, "Ati %s chipset\n", devs[j].chipset_name); /* Fill in the mode register */ pci_read_config_dword(pdev, diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 1ec87104e68..3a3cc03d401 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -144,7 +144,8 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) void *addr = bridge->driver->agp_alloc_page(bridge); if (!addr) { - printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); + dev_err(&bridge->dev->dev, + "can't get memory for scratch page\n"); return -ENOMEM; } @@ -155,13 +156,13 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) size_value = bridge->driver->fetch_size(); if (size_value == 0) { - printk(KERN_ERR PFX "unable to determine aperture size.\n"); + dev_err(&bridge->dev->dev, "can't determine aperture size\n"); rc = -EINVAL; goto err_out; } if (bridge->driver->create_gatt_table(bridge)) { - printk(KERN_ERR PFX - "unable to get memory for graphics translation table.\n"); + dev_err(&bridge->dev->dev, + "can't get memory for graphics translation table\n"); rc = -ENOMEM; goto err_out; } @@ -169,7 +170,8 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) bridge->key_list = vmalloc(PAGE_SIZE * 4); if (bridge->key_list == NULL) { - printk(KERN_ERR PFX "error allocating memory for key lists.\n"); + dev_err(&bridge->dev->dev, + "can't allocate memory for key lists\n"); rc = -ENOMEM; goto err_out; } @@ -179,10 +181,12 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) memset(bridge->key_list, 0, PAGE_SIZE * 4); if (bridge->driver->configure()) { - printk(KERN_ERR PFX "error configuring host chipset.\n"); + dev_err(&bridge->dev->dev, "error configuring host chipset\n"); rc = -EINVAL; goto err_out; } + INIT_LIST_HEAD(&bridge->mapped_list); + spin_lock_init(&bridge->mapped_lock); return 0; @@ -269,25 +273,27 @@ int agp_add_bridge(struct agp_bridge_data *bridge) /* Grab reference on the chipset driver. */ if (!try_module_get(bridge->driver->owner)) { - printk (KERN_INFO PFX "Couldn't lock chipset driver.\n"); + dev_info(&bridge->dev->dev, "can't lock chipset driver\n"); return -EINVAL; } error = agp_backend_initialize(bridge); if (error) { - printk (KERN_INFO PFX "agp_backend_initialize() failed.\n"); + dev_info(&bridge->dev->dev, + "agp_backend_initialize() failed\n"); goto err_out; } if (list_empty(&agp_bridges)) { error = agp_frontend_initialize(); if (error) { - printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n"); + dev_info(&bridge->dev->dev, + "agp_frontend_initialize() failed\n"); goto frontend_err; } - printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n", - bridge->driver->fetch_size(), bridge->gart_bus_addr); + dev_info(&bridge->dev->dev, "AGP aperture is %dM @ 0x%lx\n", + bridge->driver->fetch_size(), bridge->gart_bus_addr); } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index eaa1a355bb3..118dbde25dc 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -429,6 +429,10 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) curr->is_bound = true; curr->pg_start = pg_start; + spin_lock(&agp_bridge->mapped_lock); + list_add(&curr->mapped_list, &agp_bridge->mapped_list); + spin_unlock(&agp_bridge->mapped_lock); + return 0; } EXPORT_SYMBOL(agp_bind_memory); @@ -461,10 +465,34 @@ int agp_unbind_memory(struct agp_memory *curr) curr->is_bound = false; curr->pg_start = 0; + spin_lock(&curr->bridge->mapped_lock); + list_del(&curr->mapped_list); + spin_unlock(&curr->bridge->mapped_lock); return 0; } EXPORT_SYMBOL(agp_unbind_memory); +/** + * agp_rebind_emmory - Rewrite the entire GATT, useful on resume + */ +int agp_rebind_memory(void) +{ + struct agp_memory *curr; + int ret_val = 0; + + spin_lock(&agp_bridge->mapped_lock); + list_for_each_entry(curr, &agp_bridge->mapped_list, mapped_list) { + ret_val = curr->bridge->driver->insert_memory(curr, + curr->pg_start, + curr->type); + if (ret_val != 0) + break; + } + spin_unlock(&agp_bridge->mapped_lock); + return ret_val; +} +EXPORT_SYMBOL(agp_rebind_memory); + /* End - Routines for handling swapping of agp_memory into the GATT */ @@ -771,8 +799,8 @@ void agp_device_command(u32 bridge_agpstat, bool agp_v3) if (!agp) continue; - printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n", - agp_v3 ? 3 : 2, pci_name(device), mode); + dev_info(&device->dev, "putting AGP V%d device into %dx mode\n", + agp_v3 ? 3 : 2, mode); pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat); } } @@ -800,10 +828,8 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) get_agp_version(agp_bridge); - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", - agp_bridge->major_version, - agp_bridge->minor_version, - pci_name(agp_bridge->dev)); + dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n", + agp_bridge->major_version, agp_bridge->minor_version); pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat); @@ -832,8 +858,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) pci_write_config_dword(bridge->dev, bridge->capndx+AGPCTRL, temp); - printk(KERN_INFO PFX "Device is in legacy mode," - " falling back to 2.x\n"); + dev_info(&bridge->dev->dev, "bridge is in legacy mode, falling back to 2.x\n"); } } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index df702642ab8..016fdf0623a 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -32,8 +32,8 @@ #define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2 #define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0 #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 -#define PCI_DEVICE_ID_INTEL_IGD_HB 0x2A40 -#define PCI_DEVICE_ID_INTEL_IGD_IG 0x2A42 +#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 +#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_IGD_E_HB 0x2E00 #define PCI_DEVICE_ID_INTEL_IGD_E_IG 0x2E02 #define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10 @@ -55,7 +55,7 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ @@ -161,7 +161,7 @@ static int intel_i810_fetch_size(void) values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { - printk(KERN_WARNING PFX "i810 is disabled\n"); + dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n"); return 0; } if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { @@ -193,7 +193,8 @@ static int intel_i810_configure(void) intel_private.registers = ioremap(temp, 128 * 4096); if (!intel_private.registers) { - printk(KERN_ERR PFX "Unable to remap memory.\n"); + dev_err(&intel_private.pcidev->dev, + "can't remap memory\n"); return -ENOMEM; } } @@ -201,7 +202,8 @@ static int intel_i810_configure(void) if ((readl(intel_private.registers+I810_DRAM_CTL) & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { /* This will need to be dynamically assigned */ - printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); + dev_info(&intel_private.pcidev->dev, + "detected 4MB dedicated video ram\n"); intel_private.num_dcache_entries = 1024; } pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); @@ -500,8 +502,8 @@ static void intel_i830_init_gtt_entries(void) size = 1024 + 512; break; default: - printk(KERN_INFO PFX "Unknown page table size, " - "assuming 512KB\n"); + dev_info(&intel_private.pcidev->dev, + "unknown page table size, assuming 512KB\n"); size = 512; } size += 4; /* add in BIOS popup space */ @@ -515,8 +517,8 @@ static void intel_i830_init_gtt_entries(void) size = 2048; break; default: - printk(KERN_INFO PFX "Unknown page table size 0x%x, " - "assuming 512KB\n", + dev_info(&agp_bridge->dev->dev, + "unknown page table size 0x%x, assuming 512KB\n", (gmch_ctrl & G33_PGETBL_SIZE_MASK)); size = 512; } @@ -627,11 +629,11 @@ static void intel_i830_init_gtt_entries(void) } } if (gtt_entries > 0) - printk(KERN_INFO PFX "Detected %dK %s memory.\n", + dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", gtt_entries / KB(1), local ? "local" : "stolen"); else - printk(KERN_INFO PFX - "No pre-allocated video memory detected.\n"); + dev_info(&agp_bridge->dev->dev, + "no pre-allocated video memory detected\n"); gtt_entries /= KB(4); intel_private.gtt_entries = gtt_entries; @@ -801,10 +803,12 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, num_entries = A_SIZE_FIX(temp)->num_entries; if (pg_start < intel_private.gtt_entries) { - printk(KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n", - pg_start, intel_private.gtt_entries); + dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, + "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", + pg_start, intel_private.gtt_entries); - printk(KERN_INFO PFX "Trying to insert into local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to insert into local/stolen memory\n"); goto out_err; } @@ -851,7 +855,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start, return 0; if (pg_start < intel_private.gtt_entries) { - printk(KERN_INFO PFX "Trying to disable local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to disable local/stolen memory\n"); return -EINVAL; } @@ -957,7 +962,7 @@ static void intel_i9xx_setup_flush(void) if (intel_private.ifp_resource.start) { intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); if (!intel_private.i9xx_flush_page) - printk(KERN_INFO "unable to ioremap flush page - no chipset flushing"); + dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); } } @@ -1028,10 +1033,12 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, num_entries = A_SIZE_FIX(temp)->num_entries; if (pg_start < intel_private.gtt_entries) { - printk(KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n", - pg_start, intel_private.gtt_entries); + dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, + "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", + pg_start, intel_private.gtt_entries); - printk(KERN_INFO PFX "Trying to insert into local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to insert into local/stolen memory\n"); goto out_err; } @@ -1078,7 +1085,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, return 0; if (pg_start < intel_private.gtt_entries) { - printk(KERN_INFO PFX "Trying to disable local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to disable local/stolen memory\n"); return -EINVAL; } @@ -1182,7 +1190,7 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) { switch (agp_bridge->dev->device) { - case PCI_DEVICE_ID_INTEL_IGD_HB: + case PCI_DEVICE_ID_INTEL_GM45_HB: case PCI_DEVICE_ID_INTEL_IGD_E_HB: case PCI_DEVICE_ID_INTEL_Q45_HB: case PCI_DEVICE_ID_INTEL_G45_HB: @@ -1379,7 +1387,7 @@ static int intel_815_configure(void) /* the Intel 815 chipset spec. says that bits 29-31 in the * ATTBASE register are reserved -> try not to write them */ if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) { - printk(KERN_EMERG PFX "gatt bus addr too high"); + dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high"); return -EINVAL; } @@ -2117,8 +2125,8 @@ static const struct intel_driver_description { NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", NULL, &intel_g33_driver }, - { PCI_DEVICE_ID_INTEL_IGD_HB, PCI_DEVICE_ID_INTEL_IGD_IG, 0, - "Intel Integrated Graphics Device", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, + "Mobile Intel? GM45 Express", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, "Intel Integrated Graphics Device", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0, @@ -2163,8 +2171,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, if (intel_agp_chipsets[i].name == NULL) { if (cap_ptr) - printk(KERN_WARNING PFX "Unsupported Intel chipset" - "(device id: %04x)\n", pdev->device); + dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n", + pdev->vendor, pdev->device); agp_put_bridge(bridge); return -ENODEV; } @@ -2172,9 +2180,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, if (bridge->driver == NULL) { /* bridge has no AGP and no IGD detected */ if (cap_ptr) - printk(KERN_WARNING PFX "Failed to find bridge device " - "(chip_id: %04x)\n", - intel_agp_chipsets[i].gmch_chip_id); + dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n", + intel_agp_chipsets[i].gmch_chip_id); agp_put_bridge(bridge); return -ENODEV; } @@ -2183,8 +2190,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, bridge->capndx = cap_ptr; bridge->dev_private_data = &intel_private; - printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", - intel_agp_chipsets[i].name); + dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); /* * The following fixes the case where the BIOS has "forgotten" to @@ -2194,7 +2200,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, r = &pdev->resource[0]; if (!r->start && r->end) { if (pci_assign_resource(pdev, 0)) { - printk(KERN_ERR PFX "could not assign resource 0\n"); + dev_err(&pdev->dev, "can't assign resource 0\n"); agp_put_bridge(bridge); return -ENODEV; } @@ -2206,7 +2212,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, * 20030610 - hamish@zot.org */ if (pci_enable_device(pdev)) { - printk(KERN_ERR PFX "Unable to Enable PCI device\n"); + dev_err(&pdev->dev, "can't enable PCI device\n"); agp_put_bridge(bridge); return -ENODEV; } @@ -2238,6 +2244,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) static int agp_intel_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + int ret_val; pci_restore_state(pdev); @@ -2265,6 +2272,10 @@ static int agp_intel_resume(struct pci_dev *pdev) else if (bridge->driver == &intel_i965_driver) intel_i915_configure(); + ret_val = agp_rebind_memory(); + if (ret_val != 0) + return ret_val; + return 0; } #endif @@ -2315,7 +2326,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_G33_HB), ID(PCI_DEVICE_ID_INTEL_Q35_HB), ID(PCI_DEVICE_ID_INTEL_Q33_HB), - ID(PCI_DEVICE_ID_INTEL_IGD_HB), + ID(PCI_DEVICE_ID_INTEL_GM45_HB), ID(PCI_DEVICE_ID_INTEL_IGD_E_HB), ID(PCI_DEVICE_ID_INTEL_Q45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB), diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c index 3f9ccde6237..c73385cc4b8 100644 --- a/drivers/char/agp/isoch.c +++ b/drivers/char/agp/isoch.c @@ -153,7 +153,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, /* Check if this configuration has any chance of working */ if (tot_bw > target.maxbw) { - printk(KERN_ERR PFX "isochronous bandwidth required " + dev_err(&td->dev, "isochronous bandwidth required " "by AGP 3.0 devices exceeds that which is supported by " "the AGP 3.0 bridge!\n"); ret = -ENODEV; @@ -188,7 +188,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, /* Exit if the minimal ISOCH_N allocation among the masters is more * than the target can handle. */ if (tot_n > target.n) { - printk(KERN_ERR PFX "number of isochronous " + dev_err(&td->dev, "number of isochronous " "transactions per period required by AGP 3.0 devices " "exceeds that which is supported by the AGP 3.0 " "bridge!\n"); @@ -229,7 +229,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, /* Exit if the minimal RQ needs of the masters exceeds what the target * can provide. */ if (tot_rq > rq_isoch) { - printk(KERN_ERR PFX "number of request queue slots " + dev_err(&td->dev, "number of request queue slots " "required by the isochronous bandwidth requested by " "AGP 3.0 devices exceeds the number provided by the " "AGP 3.0 bridge!\n"); @@ -359,8 +359,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) case 0x0001: /* Unclassified device */ /* Don't know what this is, but log it for investigation. */ if (mcapndx != 0) { - printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n", - dev->vendor, dev->device); + dev_info(&td->dev, "wacky, found unclassified AGP device %s [%04x/%04x]\n", + pci_name(dev), + dev->vendor, dev->device); } continue; @@ -407,17 +408,18 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) } if (mcapndx == 0) { - printk(KERN_ERR PFX "woah! Non-AGP device " - "found on the secondary bus of an AGP 3.5 bridge!\n"); + dev_err(&td->dev, "woah! Non-AGP device %s on " + "secondary bus of AGP 3.5 bridge!\n", + pci_name(dev)); ret = -ENODEV; goto free_and_exit; } mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; if (mmajor < 3) { - printk(KERN_ERR PFX "woah! AGP 2.0 device " - "found on the secondary bus of an AGP 3.5 " - "bridge operating with AGP 3.0 electricals!\n"); + dev_err(&td->dev, "woah! AGP 2.0 device %s on " + "secondary bus of AGP 3.5 bridge operating " + "with AGP 3.0 electricals!\n", pci_name(dev)); ret = -ENODEV; goto free_and_exit; } @@ -427,10 +429,10 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) pci_read_config_dword(dev, cur->capndx+AGPSTAT, &mstatus); if (((mstatus >> 3) & 0x1) == 0) { - printk(KERN_ERR PFX "woah! AGP 3.x device " - "not operating in AGP 3.x mode found on the " - "secondary bus of an AGP 3.5 bridge operating " - "with AGP 3.0 electricals!\n"); + dev_err(&td->dev, "woah! AGP 3.x device %s not " + "operating in AGP 3.x mode on secondary bus " + "of AGP 3.5 bridge operating with AGP 3.0 " + "electricals!\n", pci_name(dev)); ret = -ENODEV; goto free_and_exit; } @@ -444,9 +446,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) if (isoch) { ret = agp_3_5_isochronous_node_enable(bridge, dev_list, ndevs); if (ret) { - printk(KERN_INFO PFX "Something bad happened setting " - "up isochronous xfers. Falling back to " - "non-isochronous xfer mode.\n"); + dev_info(&td->dev, "something bad happened setting " + "up isochronous xfers; falling back to " + "non-isochronous xfer mode\n"); } else { goto free_and_exit; } @@ -466,4 +468,3 @@ free_and_exit: get_out: return ret; } - diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index b6791846809..2587ef96a96 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -79,10 +79,8 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) u32 command; int rate; - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", - agp_bridge->major_version, - agp_bridge->minor_version, - pci_name(agp_bridge->dev)); + dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n", + agp_bridge->major_version, agp_bridge->minor_version); pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); command = agp_collect_device_status(bridge, mode, command); @@ -94,8 +92,8 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) if (!agp) continue; - printk(KERN_INFO PFX "Putting AGP V3 device at %s into %dx mode\n", - pci_name(device), rate); + dev_info(&agp_bridge->dev->dev, "putting AGP V3 device at %s into %dx mode\n", + pci_name(device), rate); pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); @@ -105,7 +103,7 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) * cannot be configured */ if (device->device == bridge->dev->device) { - printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); + dev_info(&agp_bridge->dev->dev, "SiS delay workaround: giving bridge time to recover\n"); msleep(10); } } @@ -190,7 +188,8 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev, return -ENODEV; - printk(KERN_INFO PFX "Detected SiS chipset - id:%i\n", pdev->device); + dev_info(&pdev->dev, "SiS chipset [%04x/%04x]\n", + pdev->vendor, pdev->device); bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; @@ -242,7 +241,7 @@ static struct pci_device_id agp_sis_pci_table[] = { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_5591_AGP, + .device = PCI_DEVICE_ID_SI_5591, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 0e054c13449..2fb27fe4c10 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -241,7 +241,8 @@ static void serverworks_tlbflush(struct agp_memory *temp) while (readb(serverworks_private.registers+SVWRKS_POSTFLUSH) == 1) { cpu_relax(); if (time_after(jiffies, timeout)) { - printk(KERN_ERR PFX "TLB post flush took more than 3 seconds\n"); + dev_err(&serverworks_private.svrwrks_dev->dev, + "TLB post flush took more than 3 seconds\n"); break; } } @@ -251,7 +252,8 @@ static void serverworks_tlbflush(struct agp_memory *temp) while (readl(serverworks_private.registers+SVWRKS_DIRFLUSH) == 1) { cpu_relax(); if (time_after(jiffies, timeout)) { - printk(KERN_ERR PFX "TLB Dir flush took more than 3 seconds\n"); + dev_err(&serverworks_private.svrwrks_dev->dev, + "TLB Dir flush took more than 3 seconds\n"); break; } } @@ -271,7 +273,7 @@ static int serverworks_configure(void) temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); serverworks_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); if (!serverworks_private.registers) { - printk (KERN_ERR PFX "Unable to ioremap() memory.\n"); + dev_err(&agp_bridge->dev->dev, "can't ioremap(%#x)\n", temp); return -ENOMEM; } @@ -451,7 +453,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, switch (pdev->device) { case 0x0006: - printk (KERN_ERR PFX "ServerWorks CNB20HE is unsupported due to lack of documentation.\n"); + dev_err(&pdev->dev, "ServerWorks CNB20HE is unsupported due to lack of documentation\n"); return -ENODEV; case PCI_DEVICE_ID_SERVERWORKS_HE: @@ -461,8 +463,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, default: if (cap_ptr) - printk(KERN_ERR PFX "Unsupported Serverworks chipset " - "(device id: %04x)\n", pdev->device); + dev_err(&pdev->dev, "unsupported Serverworks chipset " + "[%04x/%04x]\n", pdev->vendor, pdev->device); return -ENODEV; } @@ -470,8 +472,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); if (!bridge_dev) { - printk(KERN_INFO PFX "Detected a Serverworks chipset " - "but could not find the secondary device.\n"); + dev_info(&pdev->dev, "can't find secondary device\n"); return -ENODEV; } @@ -482,8 +483,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2); if (temp2 != 0) { - printk(KERN_INFO PFX "Detected 64 bit aperture address, " - "but top bits are not zero. Disabling agp\n"); + dev_info(&pdev->dev, "64 bit aperture address, " + "but top bits are not zero; disabling AGP\n"); return -ENODEV; } serverworks_private.mm_addr_ofs = 0x18; @@ -495,8 +496,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs + 4, &temp2); if (temp2 != 0) { - printk(KERN_INFO PFX "Detected 64 bit MMIO address, " - "but top bits are not zero. Disabling agp\n"); + dev_info(&pdev->dev, "64 bit MMIO address, but top " + "bits are not zero; disabling AGP\n"); return -ENODEV; } } diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index d2fa3cfca02..eef72709ec5 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -46,8 +46,8 @@ static int uninorth_fetch_size(void) break; if (i == agp_bridge->driver->num_aperture_sizes) { - printk(KERN_ERR PFX "Invalid aperture size, using" - " default\n"); + dev_err(&agp_bridge->dev->dev, "invalid aperture size, " + "using default\n"); size = 0; aperture = NULL; } @@ -108,8 +108,8 @@ static int uninorth_configure(void) current_size = A_SIZE_32(agp_bridge->current_size); - printk(KERN_INFO PFX "configuring for size idx: %d\n", - current_size->size_value); + dev_info(&agp_bridge->dev->dev, "configuring for size idx: %d\n", + current_size->size_value); /* aperture size and gatt addr */ pci_write_config_dword(agp_bridge->dev, @@ -197,8 +197,9 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) gp = (u32 *) &agp_bridge->gatt_table[pg_start]; for (i = 0; i < mem->page_count; ++i) { if (gp[i]) { - printk("u3_insert_memory: entry 0x%x occupied (%x)\n", - i, gp[i]); + dev_info(&agp_bridge->dev->dev, + "u3_insert_memory: entry 0x%x occupied (%x)\n", + i, gp[i]); return -EBUSY; } } @@ -276,8 +277,8 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode) &scratch); } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000); if ((scratch & PCI_AGP_COMMAND_AGP) == 0) - printk(KERN_ERR PFX "failed to write UniNorth AGP" - " command register\n"); + dev_err(&bridge->dev->dev, "can't write UniNorth AGP " + "command register\n"); if (uninorth_rev >= 0x30) { /* This is an AGP V3 */ @@ -330,8 +331,8 @@ static int agp_uninorth_suspend(struct pci_dev *pdev) pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd); if (!(cmd & PCI_AGP_COMMAND_AGP)) continue; - printk("uninorth-agp: disabling AGP on device %s\n", - pci_name(device)); + dev_info(&pdev->dev, "disabling AGP on device %s\n", + pci_name(device)); cmd &= ~PCI_AGP_COMMAND_AGP; pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd); } @@ -341,8 +342,7 @@ static int agp_uninorth_suspend(struct pci_dev *pdev) pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd); bridge->dev_private_data = (void *)(long)cmd; if (cmd & PCI_AGP_COMMAND_AGP) { - printk("uninorth-agp: disabling AGP on bridge %s\n", - pci_name(pdev)); + dev_info(&pdev->dev, "disabling AGP on bridge\n"); cmd &= ~PCI_AGP_COMMAND_AGP; pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd); } @@ -591,14 +591,14 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, /* probe for known chipsets */ for (j = 0; devs[j].chipset_name != NULL; ++j) { if (pdev->device == devs[j].device_id) { - printk(KERN_INFO PFX "Detected Apple %s chipset\n", - devs[j].chipset_name); + dev_info(&pdev->dev, "Apple %s chipset\n", + devs[j].chipset_name); goto found; } } - printk(KERN_ERR PFX "Unsupported Apple chipset (device id: %04x).\n", - pdev->device); + dev_err(&pdev->dev, "unsupported Apple chipset [%04x/%04x]\n", + pdev->vendor, pdev->device); return -ENODEV; found: diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 3530ff417a5..6e763e3f5a8 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1254,7 +1254,7 @@ static int rs_break(struct tty_struct *tty, int break_state) unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_break")) - return; + return -EINVAL; local_irq_save(flags); if (break_state == -1) diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 34275c6f1da..74e9cd81b5b 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -10,7 +10,7 @@ #include <linux/init.h> #include <linux/smp_lock.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/uaccess.h> #include <asm/therm.h> diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 67fbd7aab5d..34d15d54823 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -37,7 +37,6 @@ #include <linux/rtc.h> #include <linux/proc_fs.h> #include <linux/efi.h> -#include <linux/smp_lock.h> #include <linux/uaccess.h> #include <asm/system.h> diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 02aac104842..fd64137b1ab 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -322,11 +322,10 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) hp->tty = tty; - if (hp->ops->notifier_add) - rc = hp->ops->notifier_add(hp, hp->data); - spin_unlock_irqrestore(&hp->lock, flags); + if (hp->ops->notifier_add) + rc = hp->ops->notifier_add(hp, hp->data); /* * If the notifier fails we return an error. The tty layer diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index d9ce1091562..9790201718a 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h @@ -6,7 +6,7 @@ * Ryan S. Arnold <rsa@us.ibm.com> * * hvc_console header information: - * moved here from include/asm-powerpc/hvconsole.h + * moved here from arch/powerpc/include/asm/hvconsole.h * and drivers/char/hvc_console.c * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 786d518e947..473d9b14439 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -114,7 +114,7 @@ * the hvcs_final_close() function in order to get it out of the spinlock. * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from - * include/asm-powerpc/hvcserver.h + * arch/powerepc/include/asm/hvcserver.h * * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to * prevent possible lockup with realtime scheduling as similarily pointed out by diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c index bab43ca32ac..263567f5f39 100644 --- a/drivers/char/hw_random/ixp4xx-rng.c +++ b/drivers/char/hw_random/ixp4xx-rng.c @@ -23,7 +23,7 @@ #include <linux/hw_random.h> #include <asm/io.h> -#include <asm/hardware.h> +#include <mach/hardware.h> static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer) diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index f7feae4ebb5..128202e18fc 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c @@ -31,6 +31,7 @@ #include <asm/io.h> #include <asm/msr.h> #include <asm/cpufeature.h> +#include <asm/i387.h> #define PFX KBUILD_MODNAME ": " @@ -67,16 +68,23 @@ enum { * Another possible performance boost may come from simply buffering * until we have 4 bytes, thus returning a u32 at a time, * instead of the current u8-at-a-time. + * + * Padlock instructions can generate a spurious DNA fault, so + * we have to call them in the context of irq_ts_save/restore() */ static inline u32 xstore(u32 *addr, u32 edx_in) { u32 eax_out; + int ts_state; + + ts_state = irq_ts_save(); asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" :"=m"(*addr), "=a"(eax_out) :"D"(addr), "d"(edx_in)); + irq_ts_restore(ts_state); return eax_out; } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 192688344ed..8e8afb6141f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -66,8 +66,8 @@ #include <linux/ctype.h> #ifdef CONFIG_PPC_OF -#include <asm/of_device.h> -#include <asm/of_platform.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> #endif #define PFX "ipmi_si: " @@ -2695,15 +2695,13 @@ static __devinit void default_find_bmc(void) for (i = 0; ; i++) { if (!ipmi_defaults[i].port) break; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return; - #ifdef CONFIG_PPC_MERGE if (check_legacy_ioport(ipmi_defaults[i].port)) continue; #endif + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return; info->addr_source = NULL; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index e30575e8764..b638403e8e9 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1612,8 +1612,10 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) switch (cmd) { case MOXA_GET_MAJOR: - printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl %x, fix " - "your userspace\n", current->comm, cmd); + if (printk_ratelimit()) + printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl " + "%x (GET_MAJOR), fix your userspace\n", + current->comm, cmd); return put_user(ttymajor, (int __user *)argp); case MOXA_CHKPORTENABLE: diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index b1414507997..3a23e7694d5 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -29,7 +29,6 @@ #include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/uaccess.h> -#include <linux/version.h> #include "tty.h" #include "network.h" diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index d1fceabe3ae..c240562c218 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -232,7 +232,6 @@ typedef struct _mgslpc_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -459,13 +458,11 @@ static int ttymajor=0; static int debug_level = 0; static int maxframe[MAX_DEVICE_COUNT] = {0,}; -static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1}; module_param(break_on_load, bool, 0); module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); MODULE_LICENSE("GPL"); @@ -2915,7 +2912,6 @@ static void mgslpc_add_device(MGSLPC_INFO *info) if (info->line < MAX_DEVICE_COUNT) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } mgslpc_device_count++; diff --git a/drivers/char/random.c b/drivers/char/random.c index e0d0e371909..7ce1ac4baa6 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -407,7 +407,7 @@ struct entropy_store { /* read-write data: */ spinlock_t lock; unsigned add_ptr; - int entropy_count; + int entropy_count; /* Must at no time exceed ->POOLBITS! */ int input_rotate; }; @@ -520,6 +520,7 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) static void credit_entropy_bits(struct entropy_store *r, int nbits) { unsigned long flags; + int entropy_count; if (!nbits) return; @@ -527,20 +528,20 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits) spin_lock_irqsave(&r->lock, flags); DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); - r->entropy_count += nbits; - if (r->entropy_count < 0) { + entropy_count = r->entropy_count; + entropy_count += nbits; + if (entropy_count < 0) { DEBUG_ENT("negative entropy/overflow\n"); - r->entropy_count = 0; - } else if (r->entropy_count > r->poolinfo->POOLBITS) - r->entropy_count = r->poolinfo->POOLBITS; + entropy_count = 0; + } else if (entropy_count > r->poolinfo->POOLBITS) + entropy_count = r->poolinfo->POOLBITS; + r->entropy_count = entropy_count; /* should we wake readers? */ - if (r == &input_pool && - r->entropy_count >= random_read_wakeup_thresh) { + if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { wake_up_interruptible(&random_read_wait); kill_fasync(&fasync, SIGIO, POLL_IN); } - spin_unlock_irqrestore(&r->lock, flags); } @@ -1571,6 +1572,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) return half_md4_transform(hash, keyptr->secret); } +EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index d9799e2bcfb..f53d4d00faf 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -78,7 +78,6 @@ #include <linux/wait.h> #include <linux/bcd.h> #include <linux/delay.h> -#include <linux/smp_lock.h> #include <linux/uaccess.h> #include <asm/current.h> diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ef6706f0906..500f5176b6b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -304,7 +304,6 @@ struct mgsl_struct { /* generic HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -868,7 +867,6 @@ static int irq[MAX_ISA_DEVICES]; static int dma[MAX_ISA_DEVICES]; static int debug_level; static int maxframe[MAX_TOTAL_DEVICES]; -static int dosyncppp[MAX_TOTAL_DEVICES]; static int txdmabufs[MAX_TOTAL_DEVICES]; static int txholdbufs[MAX_TOTAL_DEVICES]; @@ -879,7 +877,6 @@ module_param_array(irq, int, NULL, 0); module_param_array(dma, int, NULL, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); module_param_array(txdmabufs, int, NULL, 0); module_param_array(txholdbufs, int, NULL, 0); @@ -4258,7 +4255,6 @@ static void mgsl_add_device( struct mgsl_struct *info ) if (info->line < MAX_TOTAL_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; if (txdmabufs[info->line]) { info->num_tx_dma_buffers = txdmabufs[info->line]; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 3e9058993e4..08911ed6649 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -47,7 +47,6 @@ #include <linux/module.h> -#include <linux/version.h> #include <linux/errno.h> #include <linux/signal.h> #include <linux/sched.h> @@ -128,17 +127,14 @@ static int slgt_device_count; static int ttymajor; static int debug_level; static int maxframe[MAX_DEVICES]; -static int dosyncppp[MAX_DEVICES]; module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); -MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable"); /* * tty support and callbacks @@ -349,7 +345,6 @@ struct slgt_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC struct net_device *netdev; @@ -3405,7 +3400,6 @@ static void add_device(struct slgt_info *info) if (info->line < MAX_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } slgt_device_count++; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index c0490cbd0db..6bdb44f7bec 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -270,7 +270,6 @@ typedef struct _synclinkmp_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -469,13 +468,11 @@ static int ttymajor = 0; */ static int debug_level = 0; static int maxframe[MAX_DEVICES] = {0,}; -static int dosyncppp[MAX_DEVICES] = {0,}; module_param(break_on_load, bool, 0); module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); static char *driver_name = "SyncLink MultiPort driver"; static char *driver_version = "$Revision: 4.38 $"; @@ -3752,7 +3749,6 @@ static void add_device(SLMP_INFO *info) if (info->line < MAX_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } synclinkmp_device_count++; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e1b46bc7e43..daeb8f76697 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1161,8 +1161,8 @@ void disassociate_ctty(int on_exit) tty = get_current_tty(); if (tty) { tty_pgrp = get_pid(tty->pgrp); - mutex_unlock(&tty_mutex); lock_kernel(); + mutex_unlock(&tty_mutex); /* XXX: here we race, there is nothing protecting tty */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); @@ -2496,45 +2496,26 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) } /** - * tiocswinsz - implement window size set ioctl - * @tty; tty - * @arg: user buffer for result - * - * Copies the user idea of the window size to the kernel. Traditionally - * this is just advisory information but for the Linux console it - * actually has driver level meaning and triggers a VC resize. + * tty_do_resize - resize event + * @tty: tty being resized + * @real_tty: real tty (not the same as tty if using a pty/tty pair) + * @rows: rows (character) + * @cols: cols (character) * - * Locking: - * Called function use the console_sem is used to ensure we do - * not try and resize the console twice at once. - * The tty->termios_mutex is used to ensure we don't double - * resize and get confused. Lock order - tty->termios_mutex before - * console sem + * Update the termios variables and send the neccessary signals to + * peform a terminal resize correctly */ -static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, - struct winsize __user *arg) +int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, + struct winsize *ws) { - struct winsize tmp_ws; struct pid *pgrp, *rpgrp; unsigned long flags; - if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) - return -EFAULT; - - mutex_lock(&tty->termios_mutex); - if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) + /* For a PTY we need to lock the tty side */ + mutex_lock(&real_tty->termios_mutex); + if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; - -#ifdef CONFIG_VT - if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) { - if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col, - tmp_ws.ws_row)) { - mutex_unlock(&tty->termios_mutex); - return -ENXIO; - } - } -#endif /* Get the PID values and reference them so we can avoid holding the tty ctrl lock while sending signals */ spin_lock_irqsave(&tty->ctrl_lock, flags); @@ -2550,14 +2531,42 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, put_pid(pgrp); put_pid(rpgrp); - tty->winsize = tmp_ws; - real_tty->winsize = tmp_ws; + tty->winsize = *ws; + real_tty->winsize = *ws; done: - mutex_unlock(&tty->termios_mutex); + mutex_unlock(&real_tty->termios_mutex); return 0; } /** + * tiocswinsz - implement window size set ioctl + * @tty; tty + * @arg: user buffer for result + * + * Copies the user idea of the window size to the kernel. Traditionally + * this is just advisory information but for the Linux console it + * actually has driver level meaning and triggers a VC resize. + * + * Locking: + * Driver dependant. The default do_resize method takes the + * tty termios mutex and ctrl_lock. The console takes its own lock + * then calls into the default method. + */ + +static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, + struct winsize __user *arg) +{ + struct winsize tmp_ws; + if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) + return -EFAULT; + + if (tty->ops->resize) + return tty->ops->resize(tty, real_tty, &tmp_ws); + else + return tty_do_resize(tty, real_tty, &tmp_ws); +} + +/** * tioccons - allow admin to move logical console * @file: the file to become console * diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index ea9fc5d03b9..bf34e459742 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -937,12 +937,14 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, return 0; #endif case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, + /* FIXME: for correctness we may need to take the termios + lock here - review */ + return put_user(C_CLOCAL(real_tty) ? 1 : 0, (int __user *)arg); case TIOCSSOFTCAR: if (get_user(arg, (unsigned int __user *) arg)) return -EFAULT; - return tty_change_softcar(tty, arg); + return tty_change_softcar(real_tty, arg); default: return -ENOIOCTLCMD; } diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 241cbdea65a..f307f135cbf 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -169,7 +169,7 @@ static int tty_ldisc_get(int disc, struct tty_ldisc *ld) if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; err = tty_ldisc_try_get(disc, ld); - if (err == -EAGAIN) { + if (err < 0) { request_module("tty-ldisc-%d", disc); err = tty_ldisc_try_get(disc, ld); } diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c deleted file mode 100644 index 65fb848e1cc..00000000000 --- a/drivers/char/viocons.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* -*- linux-c -*- - * - * drivers/char/viocons.c - * - * iSeries Virtual Terminal - * - * Authors: Dave Boutcher <boutcher@us.ibm.com> - * Ryan Arnold <ryanarn@us.ibm.com> - * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell - * - * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation - * - * 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 Free Software Foundation; either version 2 of the - * License, or (at your option) anyu later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/kernel.h> -#include <linux/proc_fs.h> -#include <linux/errno.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/console.h> -#include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/init.h> -#include <linux/wait.h> -#include <linux/spinlock.h> -#include <asm/ioctls.h> -#include <linux/kd.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/sysrq.h> - -#include <asm/firmware.h> -#include <asm/iseries/vio.h> -#include <asm/iseries/hv_lp_event.h> -#include <asm/iseries/hv_call_event.h> -#include <asm/iseries/hv_lp_config.h> -#include <asm/iseries/hv_call.h> - -#ifdef CONFIG_VT -#error You must turn off CONFIG_VT to use CONFIG_VIOCONS -#endif - -#define VIOTTY_MAGIC (0x0DCB) -#define VTTY_PORTS 10 - -#define VIOCONS_KERN_WARN KERN_WARNING "viocons: " -#define VIOCONS_KERN_INFO KERN_INFO "viocons: " - -static DEFINE_SPINLOCK(consolelock); -static DEFINE_SPINLOCK(consoleloglock); - -static int vio_sysrq_pressed; - -#define VIOCHAR_NUM_BUF 16 - -/* - * Our port information. We store a pointer to one entry in the - * tty_driver_data - */ -static struct port_info { - int magic; - struct tty_struct *tty; - HvLpIndex lp; - u8 vcons; - u64 seq; /* sequence number of last HV send */ - u64 ack; /* last ack from HV */ -/* - * When we get writes faster than we can send it to the partition, - * buffer the data here. Note that used is a bit map of used buffers. - * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume - * it is a multiple of unsigned long - */ - unsigned long used; - u8 *buffer[VIOCHAR_NUM_BUF]; - int bufferBytes[VIOCHAR_NUM_BUF]; - int curbuf; - int bufferOverflow; - int overflowMessage; -} port_info[VTTY_PORTS]; - -#define viochar_is_console(pi) ((pi) == &port_info[0]) -#define viochar_port(pi) ((pi) - &port_info[0]) - -static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp); - -static struct tty_driver *viotty_driver; - -static void hvlog(char *fmt, ...) -{ - int i; - unsigned long flags; - va_list args; - static char buf[256]; - - spin_lock_irqsave(&consoleloglock, flags); - va_start(args, fmt); - i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); - va_end(args); - buf[i++] = '\r'; - HvCall_writeLogBuffer(buf, i); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -static void hvlogOutput(const char *buf, int count) -{ - unsigned long flags; - int begin; - int index; - static const char cr = '\r'; - - begin = 0; - spin_lock_irqsave(&consoleloglock, flags); - for (index = 0; index < count; index++) { - if (buf[index] == '\n') { - /* - * Start right after the last '\n' or at the zeroth - * array position and output the number of characters - * including the newline. - */ - HvCall_writeLogBuffer(&buf[begin], index - begin + 1); - begin = index + 1; - HvCall_writeLogBuffer(&cr, 1); - } - } - if ((index - begin) > 0) - HvCall_writeLogBuffer(&buf[begin], index - begin); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -/* - * Make sure we're pointing to a valid port_info structure. Shamelessly - * plagerized from serial.c - */ -static inline int viotty_paranoia_check(struct port_info *pi, - char *name, const char *routine) -{ - static const char *bad_pi_addr = VIOCONS_KERN_WARN - "warning: bad address for port_info struct (%s) in %s\n"; - static const char *badmagic = VIOCONS_KERN_WARN - "warning: bad magic number for port_info struct (%s) in %s\n"; - - if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) { - printk(bad_pi_addr, name, routine); - return 1; - } - if (pi->magic != VIOTTY_MAGIC) { - printk(badmagic, name, routine); - return 1; - } - return 0; -} - -/* - * Add data to our pending-send buffers. - * - * NOTE: Don't use printk in here because it gets nastily recursive. - * hvlog can be used to log to the hypervisor buffer - */ -static int buffer_add(struct port_info *pi, const char *buf, size_t len) -{ - size_t bleft; - size_t curlen; - const char *curbuf; - int nextbuf; - - curbuf = buf; - bleft = len; - while (bleft > 0) { - /* - * If there is no space left in the current buffer, we have - * filled everything up, so return. If we filled the previous - * buffer we would already have moved to the next one. - */ - if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { - hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n"); - pi->bufferOverflow++; - pi->overflowMessage = 1; - break; - } - - /* - * Turn on the "used" bit for this buffer. If it's already on, - * that's fine. - */ - set_bit(pi->curbuf, &pi->used); - - /* - * See if this buffer has been allocated. If not, allocate it. - */ - if (pi->buffer[pi->curbuf] == NULL) { - pi->buffer[pi->curbuf] = - kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC); - if (pi->buffer[pi->curbuf] == NULL) { - hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.", - pi->curbuf); - break; - } - } - - /* Figure out how much we can copy into this buffer. */ - if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf])) - curlen = bleft; - else - curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]; - - /* Copy the data into the buffer. */ - memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf], - curbuf, curlen); - - pi->bufferBytes[pi->curbuf] += curlen; - curbuf += curlen; - bleft -= curlen; - - /* - * Now see if we've filled this buffer. If not then - * we'll try to use it again later. If we've filled it - * up then we'll advance the curbuf to the next in the - * circular queue. - */ - if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { - nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; - /* - * Move to the next buffer if it hasn't been used yet - */ - if (test_bit(nextbuf, &pi->used) == 0) - pi->curbuf = nextbuf; - } - } - return len - bleft; -} - -/* - * Send pending data - * - * NOTE: Don't use printk in here because it gets nastily recursive. - * hvlog can be used to log to the hypervisor buffer - */ -static void send_buffers(struct port_info *pi) -{ - HvLpEvent_Rc hvrc; - int nextbuf; - struct viocharlpevent *viochar; - unsigned long flags; - - spin_lock_irqsave(&consolelock, flags); - - viochar = (struct viocharlpevent *) - vio_get_event_buffer(viomajorsubtype_chario); - - /* Make sure we got a buffer */ - if (viochar == NULL) { - hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers()."); - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - if (pi->used == 0) { - hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n"); - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - /* - * curbuf points to the buffer we're filling. We want to - * start sending AFTER this one. - */ - nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; - - /* - * Loop until we find a buffer with the used bit on - */ - while (test_bit(nextbuf, &pi->used) == 0) - nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; - - initDataEvent(viochar, pi->lp); - - /* - * While we have buffers with data, and our send window - * is open, send them - */ - while ((test_bit(nextbuf, &pi->used)) && - ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - viochar->len = pi->bufferBytes[nextbuf]; - viochar->event.xCorrelationToken = pi->seq++; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + viochar->len; - - memcpy(viochar->data, pi->buffer[nextbuf], viochar->len); - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) { - /* - * MUST unlock the spinlock before doing a printk - */ - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - - printk(VIOCONS_KERN_WARN - "error sending event! return code %d\n", - (int)hvrc); - return; - } - - /* - * clear the used bit, zero the number of bytes in - * this buffer, and move to the next buffer - */ - clear_bit(nextbuf, &pi->used); - pi->bufferBytes[nextbuf] = 0; - nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; - } - - /* - * If we have emptied all the buffers, start at 0 again. - * this will re-use any allocated buffers - */ - if (pi->used == 0) { - pi->curbuf = 0; - - if (pi->overflowMessage) - pi->overflowMessage = 0; - - if (pi->tty) { - tty_wakeup(pi->tty); - } - } - - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); -} - -/* - * Our internal writer. Gets called both from the console device and - * the tty device. the tty pointer will be NULL if called from the console. - * Return total number of bytes "written". - * - * NOTE: Don't use printk in here because it gets nastily recursive. hvlog - * can be used to log to the hypervisor buffer - */ -static int internal_write(struct port_info *pi, const char *buf, size_t len) -{ - HvLpEvent_Rc hvrc; - size_t bleft; - size_t curlen; - const char *curbuf; - unsigned long flags; - struct viocharlpevent *viochar; - - /* - * Write to the hvlog of inbound data are now done prior to - * calling internal_write() since internal_write() is only called in - * the event that an lp event path is active, which isn't the case for - * logging attempts prior to console initialization. - * - * If there is already data queued for this port, send it prior to - * attempting to send any new data. - */ - if (pi->used) - send_buffers(pi); - - spin_lock_irqsave(&consolelock, flags); - - viochar = vio_get_event_buffer(viomajorsubtype_chario); - if (viochar == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - hvlog("\n\rviocons: Can't get vio buffer in internal_write()."); - return -EAGAIN; - } - initDataEvent(viochar, pi->lp); - - curbuf = buf; - bleft = len; - - while ((bleft > 0) && (pi->used == 0) && - ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - if (bleft > VIOCHAR_MAX_DATA) - curlen = VIOCHAR_MAX_DATA; - else - curlen = bleft; - - viochar->event.xCorrelationToken = pi->seq++; - memcpy(viochar->data, curbuf, curlen); - viochar->len = curlen; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + curlen; - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) { - hvlog("viocons: error sending event! %d\n", (int)hvrc); - goto out; - } - curbuf += curlen; - bleft -= curlen; - } - - /* If we didn't send it all, buffer as much of it as we can. */ - if (bleft > 0) - bleft -= buffer_add(pi, curbuf, bleft); -out: - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - return len - bleft; -} - -static struct port_info *get_port_data(struct tty_struct *tty) -{ - unsigned long flags; - struct port_info *pi; - - spin_lock_irqsave(&consolelock, flags); - if (tty) { - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, - "get_port_data")) { - pi = NULL; - } - } else - /* - * If this is the console device, use the lp from - * the first port entry - */ - pi = &port_info[0]; - spin_unlock_irqrestore(&consolelock, flags); - return pi; -} - -/* - * Initialize the common fields in a charLpEvent - */ -static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) -{ - struct HvLpEvent *hev = &viochar->event; - - memset(viochar, 0, sizeof(struct viocharlpevent)); - - hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | - HV_LP_EVENT_INT; - hev->xType = HvLpEvent_Type_VirtualIo; - hev->xSubtype = viomajorsubtype_chario | viochardata; - hev->xSourceLp = HvLpConfig_getLpIndex(); - hev->xTargetLp = lp; - hev->xSizeMinus1 = sizeof(struct viocharlpevent); - hev->xSourceInstanceId = viopath_sourceinst(lp); - hev->xTargetInstanceId = viopath_targetinst(lp); -} - -/* - * early console device write - */ -static void viocons_write_early(struct console *co, const char *s, unsigned count) -{ - hvlogOutput(s, count); -} - -/* - * console device write - */ -static void viocons_write(struct console *co, const char *s, unsigned count) -{ - int index; - int begin; - struct port_info *pi; - - static const char cr = '\r'; - - /* - * Check port data first because the target LP might be valid but - * simply not active, in which case we want to hvlog the output. - */ - pi = get_port_data(NULL); - if (pi == NULL) { - hvlog("\n\rviocons_write: unable to get port data."); - return; - } - - hvlogOutput(s, count); - - if (!viopath_isactive(pi->lp)) - return; - - /* - * Any newline character found will cause a - * carriage return character to be emitted as well. - */ - begin = 0; - for (index = 0; index < count; index++) { - if (s[index] == '\n') { - /* - * Newline found. Print everything up to and - * including the newline - */ - internal_write(pi, &s[begin], index - begin + 1); - begin = index + 1; - /* Emit a carriage return as well */ - internal_write(pi, &cr, 1); - } - } - - /* If any characters left to write, write them now */ - if ((index - begin) > 0) - internal_write(pi, &s[begin], index - begin); -} - -/* - * Work out the device associate with this console - */ -static struct tty_driver *viocons_device(struct console *c, int *index) -{ - *index = c->index; - return viotty_driver; -} - -/* - * console device I/O methods - */ -static struct console viocons_early = { - .name = "viocons", - .write = viocons_write_early, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static struct console viocons = { - .name = "viocons", - .write = viocons_write, - .device = viocons_device, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * TTY Open method - */ -static int viotty_open(struct tty_struct *tty, struct file *filp) -{ - int port; - unsigned long flags; - struct port_info *pi; - - port = tty->index; - - if ((port < 0) || (port >= VTTY_PORTS)) - return -ENODEV; - - spin_lock_irqsave(&consolelock, flags); - - pi = &port_info[port]; - /* If some other TTY is already connected here, reject the open */ - if ((pi->tty) && (pi->tty != tty)) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN - "attempt to open device twice from different ttys\n"); - return -EBUSY; - } - tty->driver_data = pi; - pi->tty = tty; - spin_unlock_irqrestore(&consolelock, flags); - - return 0; -} - -/* - * TTY Close method - */ -static void viotty_close(struct tty_struct *tty, struct file *filp) -{ - unsigned long flags; - struct port_info *pi; - - spin_lock_irqsave(&consolelock, flags); - pi = (struct port_info *)tty->driver_data; - - if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - if (tty->count == 1) - pi->tty = NULL; - spin_unlock_irqrestore(&consolelock, flags); -} - -/* - * TTY Write method - */ -static int viotty_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct port_info *pi; - - pi = get_port_data(tty); - if (pi == NULL) { - hvlog("\n\rviotty_write: no port data."); - return -ENODEV; - } - - if (viochar_is_console(pi)) - hvlogOutput(buf, count); - - /* - * If the path to this LP is closed, don't bother doing anything more. - * just dump the data on the floor and return count. For some reason - * some user level programs will attempt to probe available tty's and - * they'll attempt a viotty_write on an invalid port which maps to an - * invalid target lp. If this is the case then ignore the - * viotty_write call and, since the viopath isn't active to this - * partition, return count. - */ - if (!viopath_isactive(pi->lp)) - return count; - - return internal_write(pi, buf, count); -} - -/* - * TTY put_char method - */ -static int viotty_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct port_info *pi; - - pi = get_port_data(tty); - if (pi == NULL) - return 0; - - /* This will append '\r' as well if the char is '\n' */ - if (viochar_is_console(pi)) - hvlogOutput(&ch, 1); - - if (viopath_isactive(pi->lp)) - internal_write(pi, &ch, 1); - return 1; -} - -/* - * TTY write_room method - */ -static int viotty_write_room(struct tty_struct *tty) -{ - int i; - int room = 0; - struct port_info *pi; - unsigned long flags; - - spin_lock_irqsave(&consolelock, flags); - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) { - spin_unlock_irqrestore(&consolelock, flags); - return 0; - } - - /* If no buffers are used, return the max size. */ - if (pi->used == 0) { - spin_unlock_irqrestore(&consolelock, flags); - return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF; - } - - /* - * We retain the spinlock because we want to get an accurate - * count and it can change on us between each operation if we - * don't hold the spinlock. - */ - for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++) - room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]); - spin_unlock_irqrestore(&consolelock, flags); - - if (room > VIOCHAR_MAX_DATA) - room = VIOCHAR_MAX_DATA; - return room; -} - -/* - * TTY chars_in_buffer method - */ -static int viotty_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - -static int viotty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - /* - * the ioctls below read/set the flags usually shown in the leds - * don't use them - they will go away without warning - */ - case KDGETLED: - case KDGKBLED: - return put_user(0, (char *)arg); - - case KDSKBLED: - return 0; - } - /* FIXME: WTF is this being called for ??? */ - lock_kernel(); - ret = n_tty_ioctl(tty, file, cmd, arg); - unlock_kernel(); - return ret; -} - -/* - * Handle an open charLpEvent. Could be either interrupt or ack - */ -static void vioHandleOpenEvent(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - struct port_info *pi; - int reject = 0; - - if (hvlpevent_is_ack(event)) { - if (port >= VTTY_PORTS) - return; - - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - pi = &port_info[port]; - if (event->xRc == HvLpEvent_Rc_Good) { - pi->seq = pi->ack = 0; - /* - * This line allows connections from the primary - * partition but once one is connected from the - * primary partition nothing short of a reboot - * of linux will allow access from the hosting - * partition again without a required iSeries fix. - */ - pi->lp = event->xTargetLp; - } - - spin_unlock_irqrestore(&consolelock, flags); - if (event->xRc != HvLpEvent_Rc_Good) - printk(VIOCONS_KERN_WARN - "handle_open_event: event->xRc == (%d).\n", - event->xRc); - - if (event->xCorrelationToken != 0) { - atomic_t *aptr= (atomic_t *)event->xCorrelationToken; - atomic_set(aptr, 1); - } else - printk(VIOCONS_KERN_WARN - "weird...got open ack without atomic\n"); - return; - } - - /* This had better require an ack, otherwise complain */ - if (!hvlpevent_need_ack(event)) { - printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - /* Make sure this is a good virtual tty */ - if (port >= VTTY_PORTS) { - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - /* - * Flag state here since we can't printk while holding - * a spinlock. - */ - reject = 1; - } else { - pi = &port_info[port]; - if ((pi->lp != HvLpIndexInvalid) && - (pi->lp != event->xSourceLp)) { - /* - * If this is tty is already connected to a different - * partition, fail. - */ - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - reject = 2; - } else { - pi->lp = event->xSourceLp; - event->xRc = HvLpEvent_Rc_Good; - cevent->subtype_result_code = viorc_good; - pi->seq = pi->ack = 0; - reject = 0; - } - } - - spin_unlock_irqrestore(&consolelock, flags); - - if (reject == 1) - printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n"); - else if (reject == 2) - printk(VIOCONS_KERN_WARN - "open rejected: console in exclusive use by another partition.\n"); - - /* Return the acknowledgement */ - HvCallEvent_ackLpEvent(event); -} - -/* - * Handle a close charLpEvent. This should ONLY be an Interrupt because the - * virtual console should never actually issue a close event to the hypervisor - * because the virtual console never goes away. A close event coming from the - * hypervisor simply means that there are no client consoles connected to the - * virtual console. - * - * Regardless of the number of connections masqueraded on the other side of - * the hypervisor ONLY ONE close event should be called to accompany the ONE - * open event that is called. The close event should ONLY be called when NO - * MORE connections (masqueraded or not) exist on the other side of the - * hypervisor. - */ -static void vioHandleCloseEvent(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - - if (hvlpevent_is_int(event)) { - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN - "close message from invalid virtual device.\n"); - return; - } - - /* For closes, just mark the console partition invalid */ - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - if (port_info[port].lp == event->xSourceLp) - port_info[port].lp = HvLpIndexInvalid; - - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp); - } else - printk(VIOCONS_KERN_WARN - "got unexpected close acknowlegement\n"); -} - -/* - * Handle a config charLpEvent. Could be either interrupt or ack - */ -static void vioHandleConfig(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - - HvCall_writeLogBuffer(cevent->data, cevent->len); - - if (cevent->data[0] == 0x01) - printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n", - cevent->data[1], cevent->data[2], - cevent->data[3], cevent->data[4]); - else - printk(VIOCONS_KERN_WARN "unknown config event\n"); -} - -/* - * Handle a data charLpEvent. - */ -static void vioHandleData(struct HvLpEvent *event) -{ - struct tty_struct *tty; - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - struct port_info *pi; - int index; - int num_pushed; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n", - port); - return; - } - - /* - * Hold the spinlock so that we don't take an interrupt that - * changes tty between the time we fetch the port_info - * pointer and the time we paranoia check. - */ - spin_lock_irqsave(&consolelock, flags); - pi = &port_info[port]; - - /* - * Change 05/01/2003 - Ryan Arnold: If a partition other than - * the current exclusive partition tries to send us data - * events then just drop them on the floor because we don't - * want his stinking data. He isn't authorized to receive - * data because he wasn't the first one to get the console, - * therefore he shouldn't be allowed to send data either. - * This will work without an iSeries fix. - */ - if (pi->lp != event->xSourceLp) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - tty = pi->tty; - if (tty == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n", - port); - return; - } - - if (tty->magic != TTY_MAGIC) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN "tty bad magic\n"); - return; - } - - /* - * Just to be paranoid, make sure the tty points back to this port - */ - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - spin_unlock_irqrestore(&consolelock, flags); - - /* - * Change 07/21/2003 - Ryan Arnold: functionality added to - * support sysrq utilizing ^O as the sysrq key. The sysrq - * functionality will only work if built into the kernel and - * then only if sysrq is enabled through the proc filesystem. - */ - num_pushed = 0; - for (index = 0; index < cevent->len; index++) { - /* - * Will be optimized away if !CONFIG_MAGIC_SYSRQ: - */ - if (sysrq_on()) { - /* 0x0f is the ascii character for ^O */ - if (cevent->data[index] == '\x0f') { - vio_sysrq_pressed = 1; - /* - * continue because we don't want to add - * the sysrq key into the data string. - */ - continue; - } else if (vio_sysrq_pressed) { - handle_sysrq(cevent->data[index], tty); - vio_sysrq_pressed = 0; - /* - * continue because we don't want to add - * the sysrq sequence into the data string. - */ - continue; - } - } - /* - * The sysrq sequence isn't included in this check if - * sysrq is enabled and compiled into the kernel because - * the sequence will never get inserted into the buffer. - * Don't attempt to copy more data into the buffer than we - * have room for because it would fail without indication. - */ - if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) { - printk(VIOCONS_KERN_WARN "input buffer overflow!\n"); - break; - } - num_pushed++; - } - - if (num_pushed) - tty_flip_buffer_push(tty); -} - -/* - * Handle an ack charLpEvent. - */ -static void vioHandleAck(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - unsigned long flags; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN "data on invalid virtual device\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - port_info[port].ack = event->xCorrelationToken; - spin_unlock_irqrestore(&consolelock, flags); - - if (port_info[port].used) - send_buffers(&port_info[port]); -} - -/* - * Handle charLpEvents and route to the appropriate routine - */ -static void vioHandleCharEvent(struct HvLpEvent *event) -{ - int charminor; - - if (event == NULL) - return; - - charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; - switch (charminor) { - case viocharopen: - vioHandleOpenEvent(event); - break; - case viocharclose: - vioHandleCloseEvent(event); - break; - case viochardata: - vioHandleData(event); - break; - case viocharack: - vioHandleAck(event); - break; - case viocharconfig: - vioHandleConfig(event); - break; - default: - if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { - event->xRc = HvLpEvent_Rc_InvalidSubtype; - HvCallEvent_ackLpEvent(event); - } - } -} - -/* - * Send an open event - */ -static int send_open(HvLpIndex remoteLp, void *sem) -{ - return HvCallEvent_signalLpEventFast(remoteLp, - HvLpEvent_Type_VirtualIo, - viomajorsubtype_chario | viocharopen, - HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, - viopath_sourceinst(remoteLp), - viopath_targetinst(remoteLp), - (u64)(unsigned long)sem, VIOVERSION << 16, - 0, 0, 0, 0); -} - -static const struct tty_operations serial_ops = { - .open = viotty_open, - .close = viotty_close, - .write = viotty_write, - .put_char = viotty_put_char, - .write_room = viotty_write_room, - .chars_in_buffer = viotty_chars_in_buffer, - .ioctl = viotty_ioctl, -}; - -static int __init viocons_init2(void) -{ - atomic_t wait_flag; - int rc; - - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - - /* +2 for fudge */ - rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), - viomajorsubtype_chario, VIOCHAR_WINDOW + 2); - if (rc) - printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc); - - if (viopath_hostLp == HvLpIndexInvalid) - vio_set_hostlp(); - - /* - * And if the primary is not the same as the hosting LP, open to the - * hosting lp - */ - if ((viopath_hostLp != HvLpIndexInvalid) && - (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) { - printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n", - viopath_hostLp); - rc = viopath_open(viopath_hostLp, viomajorsubtype_chario, - VIOCHAR_WINDOW + 2); /* +2 for fudge */ - if (rc) - printk(VIOCONS_KERN_WARN - "error opening to partition %d: %d\n", - viopath_hostLp, rc); - } - - if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0) - printk(VIOCONS_KERN_WARN - "error seting handler for console events!\n"); - - /* - * First, try to open the console to the hosting lp. - * Wait on a semaphore for the response. - */ - atomic_set(&wait_flag, 0); - if ((viopath_isactive(viopath_hostLp)) && - (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) { - printk(VIOCONS_KERN_INFO "hosting partition %d\n", - viopath_hostLp); - while (atomic_read(&wait_flag) == 0) - mb(); - atomic_set(&wait_flag, 0); - } - - /* - * If we don't have an active console, try the primary - */ - if ((!viopath_isactive(port_info[0].lp)) && - (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) && - (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag) - == 0)) { - printk(VIOCONS_KERN_INFO "opening console to primary partition\n"); - while (atomic_read(&wait_flag) == 0) - mb(); - } - - /* Initialize the tty_driver structure */ - viotty_driver = alloc_tty_driver(VTTY_PORTS); - viotty_driver->owner = THIS_MODULE; - viotty_driver->driver_name = "vioconsole"; - viotty_driver->name = "tty"; - viotty_driver->name_base = 1; - viotty_driver->major = TTY_MAJOR; - viotty_driver->minor_start = 1; - viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE; - viotty_driver->subtype = 1; - viotty_driver->init_termios = tty_std_termios; - viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; - tty_set_operations(viotty_driver, &serial_ops); - - if (tty_register_driver(viotty_driver)) { - printk(VIOCONS_KERN_WARN "couldn't register console driver\n"); - put_tty_driver(viotty_driver); - viotty_driver = NULL; - } - - unregister_console(&viocons_early); - register_console(&viocons); - - return 0; -} - -static int __init viocons_init(void) -{ - int i; - - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - - printk(VIOCONS_KERN_INFO "registering console\n"); - for (i = 0; i < VTTY_PORTS; i++) { - port_info[i].lp = HvLpIndexInvalid; - port_info[i].magic = VIOTTY_MAGIC; - } - HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437); - add_preferred_console("viocons", 0, NULL); - register_console(&viocons_early); - return 0; -} - -console_initcall(viocons_init); -module_init(viocons_init2); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 82a51f38a54..60359c36091 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -803,7 +803,25 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, */ #define VC_RESIZE_MAXCOL (32767) #define VC_RESIZE_MAXROW (32767) -int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) + +/** + * vc_do_resize - resizing method for the tty + * @tty: tty being resized + * @real_tty: real tty (different to tty if a pty/tty pair) + * @vc: virtual console private data + * @cols: columns + * @lines: lines + * + * Resize a virtual console, clipping according to the actual constraints. + * If the caller passes a tty structure then update the termios winsize + * information and perform any neccessary signal handling. + * + * Caller must hold the console semaphore. Takes the termios mutex and + * ctrl_lock of the tty IFF a tty is passed. + */ + +static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, + struct vc_data *vc, unsigned int cols, unsigned int lines) { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned int old_cols, old_rows, old_row_size, old_screen_size; @@ -907,26 +925,15 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) gotoxy(vc, vc->vc_x, vc->vc_y); save_cur(vc); - if (vc->vc_tty) { - struct winsize ws, *cws = &vc->vc_tty->winsize; - struct pid *pgrp = NULL; - + if (tty) { + /* Rewrite the requested winsize data with the actual + resulting sizes */ + struct winsize ws; memset(&ws, 0, sizeof(ws)); ws.ws_row = vc->vc_rows; ws.ws_col = vc->vc_cols; ws.ws_ypixel = vc->vc_scan_lines; - - mutex_lock(&vc->vc_tty->termios_mutex); - spin_lock_irq(&vc->vc_tty->ctrl_lock); - if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) - pgrp = get_pid(vc->vc_tty->pgrp); - spin_unlock_irq(&vc->vc_tty->ctrl_lock); - if (pgrp) { - kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1); - put_pid(pgrp); - } - *cws = ws; - mutex_unlock(&vc->vc_tty->termios_mutex); + tty_do_resize(tty, real_tty, &ws); } if (CON_IS_VISIBLE(vc)) @@ -934,14 +941,47 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) return err; } -int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) +/** + * vc_resize - resize a VT + * @vc: virtual console + * @cols: columns + * @rows: rows + * + * Resize a virtual console as seen from the console end of things. We + * use the common vc_do_resize methods to update the structures. The + * caller must hold the console sem to protect console internals and + * vc->vc_tty + */ + +int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) +{ + return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows); +} + +/** + * vt_resize - resize a VT + * @tty: tty to resize + * @real_tty: tty if a pty/tty pair + * @ws: winsize attributes + * + * Resize a virtual terminal. This is called by the tty layer as we + * register our own handler for resizing. The mutual helper does all + * the actual work. + * + * Takes the console sem and the called methods then take the tty + * termios_mutex and the tty ctrl_lock in that order. + */ + +int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty, + struct winsize *ws) { - int rc; + struct vc_data *vc = tty->driver_data; + int ret; acquire_console_sem(); - rc = vc_resize(vc, cols, lines); + ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row); release_console_sem(); - return rc; + return ret; } void vc_deallocate(unsigned int currcons) @@ -2909,6 +2949,7 @@ static const struct tty_operations con_ops = { .start = con_start, .throttle = con_throttle, .unthrottle = con_unthrottle, + .resize = vt_resize, }; int __init vty_init(void) @@ -4063,7 +4104,6 @@ EXPORT_SYMBOL(default_blu); EXPORT_SYMBOL(update_region); EXPORT_SYMBOL(redraw_screen); EXPORT_SYMBOL(vc_resize); -EXPORT_SYMBOL(vc_lock_resize); EXPORT_SYMBOL(fg_console); EXPORT_SYMBOL(console_blank_hook); EXPORT_SYMBOL(console_blanked); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 3211afd9d57..c904e9ad4a7 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -947,14 +947,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, get_user(cc, &vtsizes->v_cols)) ret = -EFAULT; else { + acquire_console_sem(); for (i = 0; i < MAX_NR_CONSOLES; i++) { vc = vc_cons[i].d; if (vc) { vc->vc_resize_user = 1; - vc_lock_resize(vc_cons[i].d, cc, ll); + vc_resize(vc_cons[i].d, cc, ll); } } + release_console_sem(); } break; } diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index c5b1840906b..8b0252bf06e 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/cdev.h> -#include <linux/version.h> #include <linux/platform_device.h> #include <asm/io.h> diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index ffabd3ba2bd..62bda453c90 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/cdev.h> -#include <linux/version.h> #include <linux/platform_device.h> #include <asm/io.h> diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 8bfee5fb722..278c9857bcf 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -74,7 +74,6 @@ * currently programmed in the FPGA. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index 1f9c8b082db..24d0d9b938f 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/cdev.h> -#include <linux/version.h> #include <linux/platform_device.h> #include <asm/io.h> |