diff options
Diffstat (limited to 'drivers/char')
68 files changed, 2200 insertions, 1296 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 72bedad6bf8c..3bb6fa3930be 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -53,7 +53,7 @@ source "drivers/tty/serial/Kconfig" config TTY_PRINTK bool "TTY driver to output user messages via printk" - depends on EXPERT + depends on EXPERT && TTY default n ---help--- If you say Y here, the support for writing user messages (i.e. @@ -159,7 +159,7 @@ source "drivers/tty/hvc/Kconfig" config VIRTIO_CONSOLE tristate "Virtio console" - depends on VIRTIO + depends on VIRTIO && TTY select HVC_DRIVER help Virtio console for use with lguest and other hypervisors. @@ -392,6 +392,7 @@ config XILINX_HWICAP config R3964 tristate "Siemens R3964 line discipline" + depends on TTY ---help--- This driver allows synchronous communication with devices using the Siemens R3964 packet protocol. Unless you are dealing with special @@ -439,7 +440,7 @@ source "drivers/char/pcmcia/Kconfig" config MWAVE tristate "ACP Modem (Mwave) support" - depends on X86 + depends on X86 && TTY select SERIAL_8250 ---help--- The ACP modem (Mwave) for Linux is a WinModem. It is composed of a diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index fd793519ea2b..443cd6751ca2 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -249,7 +249,7 @@ static const struct agp_bridge_driver ali_m1541_bridge = { }; -static struct agp_device_ids ali_agp_device_ids[] __devinitdata = +static struct agp_device_ids ali_agp_device_ids[] = { { .device_id = PCI_DEVICE_ID_AL_M1541, @@ -299,8 +299,7 @@ static struct agp_device_ids ali_agp_device_ids[] __devinitdata = { }, /* dummy final entry, always present */ }; -static int __devinit agp_ali_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_device_ids *devs = ali_agp_device_ids; struct agp_bridge_data *bridge; @@ -374,7 +373,7 @@ found: return agp_add_bridge(bridge); } -static void __devexit agp_ali_remove(struct pci_dev *pdev) +static void agp_ali_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index f7e88787af97..779f0ab845a9 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -388,7 +388,7 @@ static const struct agp_bridge_driver amd_irongate_driver = { .agp_type_to_mask_type = agp_generic_type_to_mask_type, }; -static struct agp_device_ids amd_agp_device_ids[] __devinitdata = +static struct agp_device_ids amd_agp_device_ids[] = { { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006, @@ -405,8 +405,8 @@ static struct agp_device_ids amd_agp_device_ids[] __devinitdata = { }, /* dummy final entry, always present */ }; -static int __devinit agp_amdk7_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_amdk7_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; @@ -480,7 +480,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_amdk7_remove(struct pci_dev *pdev) +static void agp_amdk7_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 444f8b6ab411..d79d692d05b8 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -240,7 +240,7 @@ static const struct agp_bridge_driver amd_8151_driver = { }; /* Some basic sanity checks for the aperture. */ -static int __devinit agp_aperture_valid(u64 aper, u32 size) +static int agp_aperture_valid(u64 aper, u32 size) { if (!aperture_valid(aper, size, 32*1024*1024)) return 0; @@ -267,8 +267,7 @@ static int __devinit agp_aperture_valid(u64 aper, u32 size) * to allocate that much memory. But at least error out cleanly instead of * crashing. */ -static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, - u16 cap) +static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap) { u32 aper_low, aper_hi; u64 aper, nb_aper; @@ -326,7 +325,7 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, return 0; } -static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) +static int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) { int i; @@ -352,7 +351,7 @@ static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) } /* Handle AMD 8151 quirks */ -static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) +static void amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) { char *revstring; @@ -390,7 +389,7 @@ static const struct aper_size_info_32 uli_sizes[7] = {8, 2048, 1, 4}, {4, 1024, 0, 3} }; -static int __devinit uli_agp_init(struct pci_dev *pdev) +static int uli_agp_init(struct pci_dev *pdev) { u32 httfea,baseaddr,enuscr; struct pci_dev *dev1; @@ -513,8 +512,8 @@ put: return ret; } -static int __devinit agp_amd64_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_amd64_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; @@ -579,7 +578,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, return 0; } -static void __devexit agp_amd64_remove(struct pci_dev *pdev) +static void agp_amd64_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index dc30e2243494..0628d7b65c71 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -445,7 +445,7 @@ static const struct agp_bridge_driver ati_generic_bridge = { }; -static struct agp_device_ids ati_agp_device_ids[] __devinitdata = +static struct agp_device_ids ati_agp_device_ids[] = { { .device_id = PCI_DEVICE_ID_ATI_RS100, @@ -490,8 +490,7 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata = { }, /* dummy final entry, always present */ }; -static int __devinit agp_ati_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_device_ids *devs = ati_agp_device_ids; struct agp_bridge_data *bridge; @@ -533,7 +532,7 @@ found: return agp_add_bridge(bridge); } -static void __devexit agp_ati_remove(struct pci_dev *pdev) +static void agp_ati_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index d607f53d8afc..6974d5032053 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -343,8 +343,8 @@ static const struct agp_bridge_driver efficeon_driver = { .agp_type_to_mask_type = agp_generic_type_to_mask_type, }; -static int __devinit agp_efficeon_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_efficeon_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; @@ -407,7 +407,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_efficeon_remove(struct pci_dev *pdev) +static void agp_efficeon_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 75b763cb3ea1..15b240ea4848 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -587,8 +587,8 @@ const struct agp_bridge_driver intel_i460_driver = { .cant_use_aperture = true, }; -static int __devinit agp_intel_i460_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_intel_i460_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; @@ -611,7 +611,7 @@ static int __devinit agp_intel_i460_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_intel_i460_remove(struct pci_dev *pdev) +static void agp_intel_i460_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); @@ -637,7 +637,7 @@ static struct pci_driver agp_intel_i460_pci_driver = { .name = "agpgart-intel-i460", .id_table = agp_intel_i460_pci_table, .probe = agp_intel_i460_probe, - .remove = __devexit_p(agp_intel_i460_remove), + .remove = agp_intel_i460_remove, }; static int __init agp_intel_i460_init(void) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index b130df0a1958..a426ee1f57a6 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -732,8 +732,8 @@ static const struct intel_agp_driver_description { { 0, NULL, NULL } }; -static int __devinit agp_intel_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_intel_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr = 0; @@ -819,7 +819,7 @@ found_gmch: return err; } -static void __devexit agp_intel_remove(struct pci_dev *pdev) +static void agp_intel_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); @@ -912,7 +912,7 @@ static struct pci_driver agp_intel_pci_driver = { .name = "agpgart-intel", .id_table = agp_intel_pci_table, .probe = agp_intel_probe, - .remove = __devexit_p(agp_intel_remove), + .remove = agp_intel_remove, #ifdef CONFIG_PM .resume = agp_intel_resume, #endif diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 6ec0fff79bc2..1042c1b90376 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -62,12 +62,6 @@ #define I810_PTE_LOCAL 0x00000002 #define I810_PTE_VALID 0x00000001 #define I830_PTE_SYSTEM_CACHED 0x00000006 -/* GT PTE cache control fields */ -#define GEN6_PTE_UNCACHED 0x00000002 -#define HSW_PTE_UNCACHED 0x00000000 -#define GEN6_PTE_LLC 0x00000004 -#define GEN6_PTE_LLC_MLC 0x00000006 -#define GEN6_PTE_GFDT 0x00000008 #define I810_SMRAM_MISCC 0x70 #define I810_GFX_MEM_WIN_SIZE 0x00010000 @@ -97,7 +91,6 @@ #define G4x_GMCH_SIZE_VT_2M (G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN) #define GFX_FLSH_CNTL 0x2170 /* 915+ */ -#define GFX_FLSH_CNTL_VLV 0x101008 #define I810_DRAM_CTL 0x3000 #define I810_DRAM_ROW_0 0x00000001 @@ -148,29 +141,6 @@ #define INTEL_I7505_AGPCTRL 0x70 #define INTEL_I7505_MCHCFG 0x50 -#define SNB_GMCH_CTRL 0x50 -#define SNB_GMCH_GMS_STOLEN_MASK 0xF8 -#define SNB_GMCH_GMS_STOLEN_32M (1 << 3) -#define SNB_GMCH_GMS_STOLEN_64M (2 << 3) -#define SNB_GMCH_GMS_STOLEN_96M (3 << 3) -#define SNB_GMCH_GMS_STOLEN_128M (4 << 3) -#define SNB_GMCH_GMS_STOLEN_160M (5 << 3) -#define SNB_GMCH_GMS_STOLEN_192M (6 << 3) -#define SNB_GMCH_GMS_STOLEN_224M (7 << 3) -#define SNB_GMCH_GMS_STOLEN_256M (8 << 3) -#define SNB_GMCH_GMS_STOLEN_288M (9 << 3) -#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3) -#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3) -#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3) -#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3) -#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3) -#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3) -#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3) -#define SNB_GTT_SIZE_0M (0 << 8) -#define SNB_GTT_SIZE_1M (1 << 8) -#define SNB_GTT_SIZE_2M (2 << 8) -#define SNB_GTT_SIZE_MASK (3 << 8) - /* pci devices ids */ #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a @@ -219,66 +189,5 @@ #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB 0x0150 /* Desktop */ -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG 0x0152 -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG 0x0162 -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB 0x0154 /* Mobile */ -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG 0x0156 -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG 0x0166 -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */ -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A -#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A -#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB 0x0F00 /* VLV1 */ -#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG 0x0F30 -#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */ -#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG 0x0402 -#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG 0x0412 -#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG 0x0422 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */ -#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG 0x0406 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG 0x0416 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG 0x0426 -#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */ -#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG 0x040a -#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG 0x041a -#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG 0x042a -#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG 0x0C02 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG 0x0C12 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG 0x0C22 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG 0x0C06 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG 0x0C16 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG 0x0C26 -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG 0x0C0A -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG 0x0C1A -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG 0x0C2A -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG 0x0A02 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG 0x0A12 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG 0x0A22 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG 0x0A06 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG 0x0A16 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG 0x0A26 -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG 0x0A0A -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG 0x0A1A -#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG 0x0A2A -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG 0x0D12 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG 0x0D22 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG 0x0D32 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG 0x0D16 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG 0x0D26 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG 0x0D36 -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG 0x0D1A -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG 0x0D2A -#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG 0x0D3A #endif diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 38390f7c6ab6..b8e2014cb9cb 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -60,7 +60,6 @@ struct intel_gtt_driver { }; static struct _intel_private { - struct intel_gtt base; const struct intel_gtt_driver *driver; struct pci_dev *pcidev; /* device one */ struct pci_dev *bridge_dev; @@ -75,7 +74,18 @@ static struct _intel_private { struct resource ifp_resource; int resource_valid; struct page *scratch_page; + phys_addr_t scratch_page_dma; int refcount; + /* Whether i915 needs to use the dmar apis or not. */ + unsigned int needs_dmar : 1; + phys_addr_t gma_bus_addr; + /* Size of memory reserved for graphics by the BIOS */ + unsigned int stolen_size; + /* Total number of gtt entries. */ + unsigned int gtt_total_entries; + /* Part of the gtt that is mappable by the cpu, for those chips where + * this is not the full gtt. */ + unsigned int gtt_mappable_entries; } intel_private; #define INTEL_GTT_GEN intel_private.driver->gen @@ -291,15 +301,15 @@ static int intel_gtt_setup_scratch_page(void) get_page(page); set_pages_uc(page, 1); - if (intel_private.base.needs_dmar) { + if (intel_private.needs_dmar) { dma_addr = pci_map_page(intel_private.pcidev, page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) return -EINVAL; - intel_private.base.scratch_page_dma = dma_addr; + intel_private.scratch_page_dma = dma_addr; } else - intel_private.base.scratch_page_dma = page_to_phys(page); + intel_private.scratch_page_dma = page_to_phys(page); intel_private.scratch_page = page; @@ -367,62 +377,6 @@ static unsigned int intel_gtt_stolen_size(void) stolen_size = 0; break; } - } else if (INTEL_GTT_GEN == 6) { - /* - * SandyBridge has new memory control reg at 0x50.w - */ - u16 snb_gmch_ctl; - pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); - switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { - case SNB_GMCH_GMS_STOLEN_32M: - stolen_size = MB(32); - break; - case SNB_GMCH_GMS_STOLEN_64M: - stolen_size = MB(64); - break; - case SNB_GMCH_GMS_STOLEN_96M: - stolen_size = MB(96); - break; - case SNB_GMCH_GMS_STOLEN_128M: - stolen_size = MB(128); - break; - case SNB_GMCH_GMS_STOLEN_160M: - stolen_size = MB(160); - break; - case SNB_GMCH_GMS_STOLEN_192M: - stolen_size = MB(192); - break; - case SNB_GMCH_GMS_STOLEN_224M: - stolen_size = MB(224); - break; - case SNB_GMCH_GMS_STOLEN_256M: - stolen_size = MB(256); - break; - case SNB_GMCH_GMS_STOLEN_288M: - stolen_size = MB(288); - break; - case SNB_GMCH_GMS_STOLEN_320M: - stolen_size = MB(320); - break; - case SNB_GMCH_GMS_STOLEN_352M: - stolen_size = MB(352); - break; - case SNB_GMCH_GMS_STOLEN_384M: - stolen_size = MB(384); - break; - case SNB_GMCH_GMS_STOLEN_416M: - stolen_size = MB(416); - break; - case SNB_GMCH_GMS_STOLEN_448M: - stolen_size = MB(448); - break; - case SNB_GMCH_GMS_STOLEN_480M: - stolen_size = MB(480); - break; - case SNB_GMCH_GMS_STOLEN_512M: - stolen_size = MB(512); - break; - } } else { switch (gmch_ctrl & I855_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: @@ -556,33 +510,13 @@ static unsigned int i965_gtt_total_entries(void) static unsigned int intel_gtt_total_entries(void) { - int size; - if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) return i965_gtt_total_entries(); - else if (INTEL_GTT_GEN == 6) { - u16 snb_gmch_ctl; - - pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); - switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { - default: - case SNB_GTT_SIZE_0M: - printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); - size = MB(0); - break; - case SNB_GTT_SIZE_1M: - size = MB(1); - break; - case SNB_GTT_SIZE_2M: - size = MB(2); - break; - } - return size/4; - } else { + else { /* On previous hardware, the GTT size was just what was * required to map the aperture. */ - return intel_private.base.gtt_mappable_entries; + return intel_private.gtt_mappable_entries; } } @@ -622,7 +556,7 @@ static unsigned int intel_gtt_mappable_entries(void) static void intel_gtt_teardown_scratch_page(void) { set_pages_wb(intel_private.scratch_page, 1); - pci_unmap_page(intel_private.pcidev, intel_private.base.scratch_page_dma, + pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); put_page(intel_private.scratch_page); __free_page(intel_private.scratch_page); @@ -638,6 +572,40 @@ static void intel_gtt_cleanup(void) intel_gtt_teardown_scratch_page(); } +/* Certain Gen5 chipsets require require idling the GPU before + * unmapping anything from the GTT when VT-d is enabled. + */ +static inline int needs_ilk_vtd_wa(void) +{ +#ifdef CONFIG_INTEL_IOMMU + const unsigned short gpu_devid = intel_private.pcidev->device; + + /* Query intel_iommu to see if we need the workaround. Presumably that + * was loaded first. + */ + if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || + gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && + intel_iommu_gfx_mapped) + return 1; +#endif + return 0; +} + +static bool intel_gtt_can_wc(void) +{ + if (INTEL_GTT_GEN <= 2) + return false; + + if (INTEL_GTT_GEN >= 6) + return false; + + /* Reports of major corruption with ILK vt'd enabled */ + if (needs_ilk_vtd_wa()) + return false; + + return true; +} + static int intel_gtt_init(void) { u32 gma_addr; @@ -648,8 +616,8 @@ static int intel_gtt_init(void) if (ret != 0) return ret; - intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); - intel_private.base.gtt_total_entries = intel_gtt_total_entries(); + intel_private.gtt_mappable_entries = intel_gtt_mappable_entries(); + intel_private.gtt_total_entries = intel_gtt_total_entries(); /* save the PGETBL reg for resume */ intel_private.PGETBL_save = @@ -661,13 +629,13 @@ static int intel_gtt_init(void) dev_info(&intel_private.bridge_dev->dev, "detected gtt size: %dK total, %dK mappable\n", - intel_private.base.gtt_total_entries * 4, - intel_private.base.gtt_mappable_entries * 4); + intel_private.gtt_total_entries * 4, + intel_private.gtt_mappable_entries * 4); - gtt_map_size = intel_private.base.gtt_total_entries * 4; + gtt_map_size = intel_private.gtt_total_entries * 4; intel_private.gtt = NULL; - if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) + if (intel_gtt_can_wc()) intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, gtt_map_size); if (intel_private.gtt == NULL) @@ -678,13 +646,12 @@ static int intel_gtt_init(void) iounmap(intel_private.registers); return -ENOMEM; } - intel_private.base.gtt = intel_private.gtt; global_cache_flush(); /* FIXME: ? */ - intel_private.base.stolen_size = intel_gtt_stolen_size(); + intel_private.stolen_size = intel_gtt_stolen_size(); - intel_private.base.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; + intel_private.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; ret = intel_gtt_setup_scratch_page(); if (ret != 0) { @@ -699,7 +666,7 @@ static int intel_gtt_init(void) pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &gma_addr); - intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); + intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); return 0; } @@ -710,8 +677,7 @@ static int intel_fake_agp_fetch_size(void) unsigned int aper_size; int i; - aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) - / MB(1); + aper_size = (intel_private.gtt_mappable_entries << PAGE_SHIFT) / MB(1); for (i = 0; i < num_sizes; i++) { if (aper_size == intel_fake_agp_sizes[i].size) { @@ -778,9 +744,6 @@ bool intel_enable_gtt(void) { u8 __iomem *reg; - if (INTEL_GTT_GEN >= 6) - return true; - if (INTEL_GTT_GEN == 2) { u16 gmch_ctrl; @@ -858,7 +821,7 @@ static int intel_fake_agp_configure(void) return -EIO; intel_private.clear_fake_agp = true; - agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; + agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; return 0; } @@ -920,12 +883,9 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, { int ret = -EINVAL; - if (intel_private.base.do_idle_maps) - return -ENODEV; - if (intel_private.clear_fake_agp) { - int start = intel_private.base.stolen_size / PAGE_SIZE; - int end = intel_private.base.gtt_mappable_entries; + int start = intel_private.stolen_size / PAGE_SIZE; + int end = intel_private.gtt_mappable_entries; intel_gtt_clear_range(start, end - start); intel_private.clear_fake_agp = false; } @@ -936,7 +896,7 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, if (mem->page_count == 0) goto out; - if (pg_start + mem->page_count > intel_private.base.gtt_total_entries) + if (pg_start + mem->page_count > intel_private.gtt_total_entries) goto out_err; if (type != mem->type) @@ -948,7 +908,7 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, if (!mem->is_flushed) global_cache_flush(); - if (intel_private.base.needs_dmar) { + if (intel_private.needs_dmar) { struct sg_table st; ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st); @@ -974,7 +934,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) unsigned int i; for (i = first_entry; i < (first_entry + num_entries); i++) { - intel_private.driver->write_entry(intel_private.base.scratch_page_dma, + intel_private.driver->write_entry(intel_private.scratch_page_dma, i, 0); } readl(intel_private.gtt+i-1); @@ -987,12 +947,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, if (mem->page_count == 0) return 0; - if (intel_private.base.do_idle_maps) - return -ENODEV; - intel_gtt_clear_range(pg_start, mem->page_count); - if (intel_private.base.needs_dmar) { + if (intel_private.needs_dmar) { intel_gtt_unmap_memory(mem->sg_list, mem->num_sg); mem->sg_list = NULL; mem->num_sg = 0; @@ -1149,146 +1106,33 @@ static void i965_write_entry(dma_addr_t addr, writel(addr | pte_flags, intel_private.gtt + entry); } -static bool gen6_check_flags(unsigned int flags) -{ - return true; -} - -static void haswell_write_entry(dma_addr_t addr, unsigned int entry, - unsigned int flags) -{ - unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; - unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; - u32 pte_flags; - - if (type_mask == AGP_USER_MEMORY) - pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID; - else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { - pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } else { /* set 'normal'/'cached' to LLC by default */ - pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } - - /* gen6 has bit11-4 for physical addr bit39-32 */ - addr |= (addr >> 28) & 0xff0; - writel(addr | pte_flags, intel_private.gtt + entry); -} - -static void gen6_write_entry(dma_addr_t addr, unsigned int entry, - unsigned int flags) -{ - unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; - unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; - u32 pte_flags; - - if (type_mask == AGP_USER_MEMORY) - pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; - else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { - pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } else { /* set 'normal'/'cached' to LLC by default */ - pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } - - /* gen6 has bit11-4 for physical addr bit39-32 */ - addr |= (addr >> 28) & 0xff0; - writel(addr | pte_flags, intel_private.gtt + entry); -} - -static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, - unsigned int flags) -{ - unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; - unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; - u32 pte_flags; - - if (type_mask == AGP_USER_MEMORY) - pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; - else { - pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } - - /* gen6 has bit11-4 for physical addr bit39-32 */ - addr |= (addr >> 28) & 0xff0; - writel(addr | pte_flags, intel_private.gtt + entry); - - writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV); -} - -static void gen6_cleanup(void) -{ -} - -/* Certain Gen5 chipsets require require idling the GPU before - * unmapping anything from the GTT when VT-d is enabled. - */ -static inline int needs_idle_maps(void) -{ -#ifdef CONFIG_INTEL_IOMMU - const unsigned short gpu_devid = intel_private.pcidev->device; - - /* Query intel_iommu to see if we need the workaround. Presumably that - * was loaded first. - */ - if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || - gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && - intel_iommu_gfx_mapped) - return 1; -#endif - return 0; -} - static int i9xx_setup(void) { - u32 reg_addr; + u32 reg_addr, gtt_addr; int size = KB(512); pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); reg_addr &= 0xfff80000; - if (INTEL_GTT_GEN >= 7) - size = MB(2); - intel_private.registers = ioremap(reg_addr, size); if (!intel_private.registers) return -ENOMEM; - if (INTEL_GTT_GEN == 3) { - u32 gtt_addr; - + switch (INTEL_GTT_GEN) { + case 3: pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, >t_addr); intel_private.gtt_bus_addr = gtt_addr; - } else { - u32 gtt_offset; - - switch (INTEL_GTT_GEN) { - case 5: - case 6: - case 7: - gtt_offset = MB(2); - break; - case 4: - default: - gtt_offset = KB(512); - break; - } - intel_private.gtt_bus_addr = reg_addr + gtt_offset; + break; + case 5: + intel_private.gtt_bus_addr = reg_addr + MB(2); + break; + default: + intel_private.gtt_bus_addr = reg_addr + KB(512); + break; } - if (needs_idle_maps()) - intel_private.base.do_idle_maps = 1; - intel_i9xx_setup_flush(); return 0; @@ -1395,32 +1239,6 @@ static const struct intel_gtt_driver ironlake_gtt_driver = { .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, }; -static const struct intel_gtt_driver sandybridge_gtt_driver = { - .gen = 6, - .setup = i9xx_setup, - .cleanup = gen6_cleanup, - .write_entry = gen6_write_entry, - .dma_mask_size = 40, - .check_flags = gen6_check_flags, - .chipset_flush = i9xx_chipset_flush, -}; -static const struct intel_gtt_driver haswell_gtt_driver = { - .gen = 6, - .setup = i9xx_setup, - .cleanup = gen6_cleanup, - .write_entry = haswell_write_entry, - .dma_mask_size = 40, - .check_flags = gen6_check_flags, - .chipset_flush = i9xx_chipset_flush, -}; -static const struct intel_gtt_driver valleyview_gtt_driver = { - .gen = 7, - .setup = i9xx_setup, - .cleanup = gen6_cleanup, - .write_entry = valleyview_write_entry, - .dma_mask_size = 40, - .check_flags = gen6_check_flags, -}; /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of * driver and gmch_driver must be non-null, and find_gmch will determine @@ -1501,106 +1319,6 @@ static const struct intel_gtt_driver_description { "HD Graphics", &ironlake_gtt_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, "HD Graphics", &ironlake_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, - "Sandybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG, - "Ivybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG, - "Ivybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG, - "Ivybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG, - "Ivybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG, - "Ivybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG, - "Ivybridge", &sandybridge_gtt_driver }, - { PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG, - "ValleyView", &valleyview_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, - "Haswell", &haswell_gtt_driver }, - { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, - "Haswell", &haswell_gtt_driver }, { 0, NULL, NULL } }; @@ -1686,9 +1404,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, } EXPORT_SYMBOL(intel_gmch_probe); -const struct intel_gtt *intel_gtt_get(void) +void intel_gtt_get(size_t *gtt_total, size_t *stolen_size, + phys_addr_t *mappable_base, unsigned long *mappable_end) { - return &intel_private.base; + *gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT; + *stolen_size = intel_private.stolen_size; + *mappable_base = intel_private.gma_bus_addr; + *mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT; } EXPORT_SYMBOL(intel_gtt_get); diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index b9734a978186..62be3ec0da4b 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -332,8 +332,8 @@ static const struct agp_bridge_driver nvidia_driver = { .agp_type_to_mask_type = agp_generic_type_to_mask_type, }; -static int __devinit agp_nvidia_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_nvidia_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; @@ -388,7 +388,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_nvidia_remove(struct pci_dev *pdev) +static void agp_nvidia_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 3a5af2f9b015..05b8d0241bde 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -270,7 +270,7 @@ const struct agp_bridge_driver sgi_tioca_driver = { .num_aperture_sizes = 1, }; -static int __devinit agp_sgi_init(void) +static int agp_sgi_init(void) { unsigned int j; struct tioca_kernel *info; @@ -327,7 +327,7 @@ static int __devinit agp_sgi_init(void) return 0; } -static void __devexit agp_sgi_cleanup(void) +static void agp_sgi_cleanup(void) { kfree(sgi_tioca_agp_bridges); sgi_tioca_agp_bridges = NULL; diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 08704ae53956..79c838c434bc 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -17,8 +17,8 @@ #define PCI_DEVICE_ID_SI_662 0x0662 #define PCI_DEVICE_ID_SI_671 0x0671 -static bool __devinitdata agp_sis_force_delay = 0; -static int __devinitdata agp_sis_agp_spec = -1; +static bool agp_sis_force_delay = 0; +static int agp_sis_agp_spec = -1; static int sis_fetch_size(void) { @@ -148,13 +148,13 @@ static struct agp_bridge_driver sis_driver = { }; // chipsets that require the 'delay hack' -static int sis_broken_chipsets[] __devinitdata = { +static int sis_broken_chipsets[] = { PCI_DEVICE_ID_SI_648, PCI_DEVICE_ID_SI_746, 0 // terminator }; -static void __devinit sis_get_driver(struct agp_bridge_data *bridge) +static void sis_get_driver(struct agp_bridge_data *bridge) { int i; @@ -180,8 +180,7 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge) } -static int __devinit agp_sis_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_sis_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 cap_ptr; @@ -211,7 +210,7 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_sis_remove(struct pci_dev *pdev) +static void agp_sis_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index f02f9b07fd4c..9b163b49d976 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -445,8 +445,8 @@ static const struct agp_bridge_driver sworks_driver = { .agp_type_to_mask_type = agp_generic_type_to_mask_type, }; -static int __devinit agp_serverworks_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_serverworks_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_bridge_data *bridge; struct pci_dev *bridge_dev; @@ -518,7 +518,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_serverworks_remove(struct pci_dev *pdev) +static void agp_serverworks_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index a32c492baf5c..a56ee9bedd11 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -557,7 +557,7 @@ const struct agp_bridge_driver u3_agp_driver = { .needs_scratch_page = true, }; -static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { +static struct agp_device_ids uninorth_agp_device_ids[] = { { .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP, .chipset_name = "UniNorth", @@ -592,8 +592,8 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { }, }; -static int __devinit agp_uninorth_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_uninorth_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct agp_device_ids *devs = uninorth_agp_device_ids; struct agp_bridge_data *bridge; @@ -663,7 +663,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_uninorth_remove(struct pci_dev *pdev) +static void agp_uninorth_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 8bc384937401..74d3aa3773bf 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -224,7 +224,7 @@ static const struct agp_bridge_driver via_driver = { .agp_type_to_mask_type = agp_generic_type_to_mask_type, }; -static struct agp_device_ids via_agp_device_ids[] __devinitdata = +static struct agp_device_ids via_agp_device_ids[] = { { .device_id = PCI_DEVICE_ID_VIA_82C597_0, @@ -438,8 +438,7 @@ static void check_via_agp3 (struct agp_bridge_data *bridge) } -static int __devinit agp_via_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_device_ids *devs = via_agp_device_ids; struct agp_bridge_data *bridge; @@ -485,7 +484,7 @@ static int __devinit agp_via_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_via_remove(struct pci_dev *pdev) +static void agp_via_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 052797b32bd3..01a5ca7425d7 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -181,7 +181,7 @@ static int dsp56k_upload(u_char __user *bin, int len) static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file_inode(file); int dev = iminor(inode) & 0x0f; switch(dev) @@ -244,7 +244,7 @@ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file_inode(file); int dev = iminor(inode) & 0x0f; switch(dev) @@ -306,7 +306,7 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co static long dsp56k_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; + int dev = iminor(file_inode(file)) & 0x0f; void __user *argp = (void __user *)arg; switch(dev) @@ -408,7 +408,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd, #if 0 static unsigned int dsp56k_poll(struct file *file, poll_table *wait) { - int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; + int dev = iminor(file_inode(file)) & 0x0f; switch(dev) { diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 85156dd0caee..65a8d96c0e93 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -125,7 +125,7 @@ static char dtlk_write_tts(char); static ssize_t dtlk_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_path.dentry->d_inode); + unsigned int minor = iminor(file_inode(file)); char ch; int i = 0, retries; @@ -177,7 +177,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, } #endif - if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR) + if (iminor(file_inode(file)) != DTLK_MINOR) return -EINVAL; while (1) { diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index dfd7876f127c..e3f9a99b8522 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -816,7 +816,7 @@ static unsigned long __hpet_calibrate(struct hpets *hpetp) static unsigned long hpet_calibrate(struct hpets *hpetp) { - unsigned long ret = -1; + unsigned long ret = ~0UL; unsigned long tmp; /* @@ -1001,6 +1001,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) irqp = &res->data.extended_irq; for (i = 0; i < irqp->interrupt_count; i++) { + if (hdp->hd_nirqs >= HPET_MAX_TIMERS) + break; + irq = acpi_register_gsi(NULL, irqp->interrupts[i], irqp->triggering, irqp->polarity); if (irq < 0) @@ -1038,7 +1041,7 @@ static int hpet_acpi_add(struct acpi_device *device) return hpet_alloc(&data); } -static int hpet_acpi_remove(struct acpi_device *device, int type) +static int hpet_acpi_remove(struct acpi_device *device) { /* XXX need to unregister clocksource, dealloc mem, etc */ return -EINVAL; diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index fbd9b2b850ef..c5a0262251bc 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -127,12 +127,12 @@ config HW_RANDOM_VIA If unsure, say Y. config HW_RANDOM_IXP4XX - tristate "Intel IXP4xx NPU HW Random Number Generator support" + tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support" depends on HW_RANDOM && ARCH_IXP4XX default HW_RANDOM ---help--- - This driver provides kernel-side support for the Random - Number Generator hardware found on the Intel IXP4xx NPU. + This driver provides kernel-side support for the Pseudo-Random + Number Generator hardware found on the Intel IXP45x/46x NPU. To compile this driver as a module, choose M here: the module will be called ixp4xx-rng. @@ -216,7 +216,7 @@ config HW_RANDOM_MXC_RNGA config HW_RANDOM_NOMADIK tristate "ST-Ericsson Nomadik Random Number Generator support" - depends on HW_RANDOM && PLAT_NOMADIK + depends on HW_RANDOM && ARCH_NOMADIK ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on ST-Ericsson SoCs (8815 and 8500). diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 731c9046cf7b..7c73d4aca36b 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -98,7 +98,7 @@ err_enable: return ret; } -static int __devexit atmel_trng_remove(struct platform_device *pdev) +static int atmel_trng_remove(struct platform_device *pdev) { struct atmel_trng *trng = platform_get_drvdata(pdev); @@ -138,7 +138,7 @@ static const struct dev_pm_ops atmel_trng_pm_ops = { static struct platform_driver atmel_trng_driver = { .probe = atmel_trng_probe, - .remove = __devexit_p(atmel_trng_remove), + .remove = atmel_trng_remove, .driver = { .name = "atmel-trng", .owner = THIS_MODULE, diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index aec6a4277caa..f343b7d0dfa1 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -61,7 +61,7 @@ static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) return 4; } -static int __devinit bcm63xx_rng_probe(struct platform_device *pdev) +static int bcm63xx_rng_probe(struct platform_device *pdev) { struct resource *r; struct clk *clk; @@ -145,7 +145,7 @@ out: return ret; } -static int __devexit bcm63xx_rng_remove(struct platform_device *pdev) +static int bcm63xx_rng_remove(struct platform_device *pdev) { struct hwrng *rng = platform_get_drvdata(pdev); struct bcm63xx_rng_priv *priv = to_rng_priv(rng); @@ -161,7 +161,7 @@ static int __devexit bcm63xx_rng_remove(struct platform_device *pdev) static struct platform_driver bcm63xx_rng_driver = { .probe = bcm63xx_rng_probe, - .remove = __devexit_p(bcm63xx_rng_remove), + .remove = bcm63xx_rng_remove, .driver = { .name = "bcm63xx-rng", .owner = THIS_MODULE, diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1bafb40ec8a2..69ae5972713c 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -40,6 +40,7 @@ #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/delay.h> +#include <linux/slab.h> #include <asm/uaccess.h> @@ -52,8 +53,12 @@ static struct hwrng *current_rng; static LIST_HEAD(rng_list); static DEFINE_MUTEX(rng_mutex); static int data_avail; -static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] - __cacheline_aligned; +static u8 *rng_buffer; + +static size_t rng_buffer_size(void) +{ + return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; +} static inline int hwrng_init(struct hwrng *rng) { @@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, if (!data_avail) { bytes_read = rng_get_data(current_rng, rng_buffer, - sizeof(rng_buffer), + rng_buffer_size(), !(filp->f_flags & O_NONBLOCK)); if (bytes_read < 0) { err = bytes_read; @@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) mutex_lock(&rng_mutex); + /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ + err = -ENOMEM; + if (!rng_buffer) { + rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); + if (!rng_buffer) + goto out_unlock; + } + /* Must not register two RNGs with the same name. */ err = -EEXIST; list_for_each_entry(tmp, &rng_list, list) { diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index 232ba9ce579c..ac47631ab34f 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -101,9 +101,10 @@ static int exynos_read(struct hwrng *rng, void *buf, return 4; } -static int __devinit exynos_rng_probe(struct platform_device *pdev) +static int exynos_rng_probe(struct platform_device *pdev) { struct exynos_rng *exynos_rng; + struct resource *res; exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng), GFP_KERNEL); @@ -120,10 +121,10 @@ static int __devinit exynos_rng_probe(struct platform_device *pdev) return -ENOENT; } - exynos_rng->mem = devm_request_and_ioremap(&pdev->dev, - platform_get_resource(pdev, IORESOURCE_MEM, 0)); - if (!exynos_rng->mem) - return -EBUSY; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + exynos_rng->mem = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(exynos_rng->mem)) + return PTR_ERR(exynos_rng->mem); platform_set_drvdata(pdev, exynos_rng); @@ -134,7 +135,7 @@ static int __devinit exynos_rng_probe(struct platform_device *pdev) return hwrng_register(&exynos_rng->rng); } -static int __devexit exynos_rng_remove(struct platform_device *pdev) +static int exynos_rng_remove(struct platform_device *pdev) { struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); @@ -162,7 +163,7 @@ static int exynos_rng_runtime_resume(struct device *dev) } -UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend, +static UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend, exynos_rng_runtime_resume, NULL); static struct platform_driver exynos_rng_driver = { @@ -172,7 +173,7 @@ static struct platform_driver exynos_rng_driver = { .pm = &exynos_rng_pm_ops, }, .probe = exynos_rng_probe, - .remove = __devexit_p(exynos_rng_remove), + .remove = exynos_rng_remove, }; module_platform_driver(exynos_rng_driver); diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c index 263567f5f392..beec1627db3c 100644 --- a/drivers/char/hw_random/ixp4xx-rng.c +++ b/drivers/char/hw_random/ixp4xx-rng.c @@ -45,6 +45,9 @@ static int __init ixp4xx_rng_init(void) void __iomem * rng_base; int err; + if (!cpu_is_ixp46x()) /* includes IXP455 */ + return -ENOSYS; + rng_base = ioremap(0x70002100, 4); if (!rng_base) return -ENOMEM; @@ -68,5 +71,5 @@ module_init(ixp4xx_rng_init); module_exit(ixp4xx_rng_exit); MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); -MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx"); +MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index ebd48f0135da..20b962e1d832 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -25,7 +25,7 @@ #define DRV_MODULE_VERSION "0.2" #define DRV_MODULE_RELDATE "July 27, 2011" -static char version[] __devinitdata = +static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); @@ -611,7 +611,7 @@ static void n2rng_work(struct work_struct *work) schedule_delayed_work(&np->work, HZ * 2); } -static void __devinit n2rng_driver_version(void) +static void n2rng_driver_version(void) { static int n2rng_version_printed; @@ -620,7 +620,7 @@ static void __devinit n2rng_driver_version(void) } static const struct of_device_id n2rng_match[]; -static int __devinit n2rng_probe(struct platform_device *op) +static int n2rng_probe(struct platform_device *op) { const struct of_device_id *match; int multi_capable; @@ -719,7 +719,7 @@ out: return err; } -static int __devexit n2rng_remove(struct platform_device *op) +static int n2rng_remove(struct platform_device *op) { struct n2rng *np = dev_get_drvdata(&op->dev); @@ -767,7 +767,7 @@ static struct platform_driver n2rng_driver = { .of_match_table = n2rng_match, }, .probe = n2rng_probe, - .remove = __devexit_p(n2rng_remove), + .remove = n2rng_remove, }; module_platform_driver(n2rng_driver); diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c index 5c34c092af71..1eada566ca70 100644 --- a/drivers/char/hw_random/octeon-rng.c +++ b/drivers/char/hw_random/octeon-rng.c @@ -56,7 +56,7 @@ static int octeon_rng_data_read(struct hwrng *rng, u32 *data) return sizeof(u32); } -static int __devinit octeon_rng_probe(struct platform_device *pdev) +static int octeon_rng_probe(struct platform_device *pdev) { struct resource *res_ports; struct resource *res_result; diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index a5effd813abd..749dc16ca2cc 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -27,8 +27,6 @@ #include <asm/io.h> -#include <plat/cpu.h> - #define RNG_OUT_REG 0x00 /* Output register */ #define RNG_STAT_REG 0x04 /* Status register [0] = STAT_BUSY */ @@ -106,7 +104,7 @@ static struct hwrng omap_rng_ops = { .data_read = omap_rng_data_read, }; -static int __devinit omap_rng_probe(struct platform_device *pdev) +static int omap_rng_probe(struct platform_device *pdev) { struct omap_rng_private_data *priv; int ret; @@ -126,9 +124,9 @@ static int __devinit omap_rng_probe(struct platform_device *pdev) goto err_ioremap; } - priv->base = devm_request_and_ioremap(&pdev->dev, priv->mem_res); - if (!priv->base) { - ret = -ENOMEM; + priv->base = devm_ioremap_resource(&pdev->dev, priv->mem_res); + if (IS_ERR(priv->base)) { + ret = PTR_ERR(priv->base); goto err_ioremap; } dev_set_drvdata(&pdev->dev, priv); diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 3a632673aed5..c6df5b29af08 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c @@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = { .data_read = pasemi_rng_data_read, }; -static int __devinit rng_probe(struct platform_device *ofdev) +static int rng_probe(struct platform_device *ofdev) { void __iomem *rng_regs; struct device_node *rng_np = ofdev->dev.of_node; @@ -122,7 +122,7 @@ static int __devinit rng_probe(struct platform_device *ofdev) return err; } -static int __devexit rng_remove(struct platform_device *dev) +static int rng_remove(struct platform_device *dev) { void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c index 97bd891422c7..973b95113edf 100644 --- a/drivers/char/hw_random/picoxcell-rng.c +++ b/drivers/char/hw_random/picoxcell-rng.c @@ -151,7 +151,7 @@ err_enable: return ret; } -static int __devexit picoxcell_trng_remove(struct platform_device *pdev) +static int picoxcell_trng_remove(struct platform_device *pdev) { hwrng_unregister(&picoxcell_trng); clk_disable(rng_clk); @@ -181,7 +181,7 @@ static const struct dev_pm_ops picoxcell_trng_pm_ops = { static struct platform_driver picoxcell_trng_driver = { .probe = picoxcell_trng_probe, - .remove = __devexit_p(picoxcell_trng_remove), + .remove = picoxcell_trng_remove, .driver = { .name = "picoxcell-trng", .owner = THIS_MODULE, diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c index c51762c13031..732c330805fd 100644 --- a/drivers/char/hw_random/ppc4xx-rng.c +++ b/drivers/char/hw_random/ppc4xx-rng.c @@ -90,7 +90,7 @@ static struct hwrng ppc4xx_rng = { .data_read = ppc4xx_rng_data_read, }; -static int __devinit ppc4xx_rng_probe(struct platform_device *dev) +static int ppc4xx_rng_probe(struct platform_device *dev) { void __iomem *rng_regs; int err = 0; @@ -111,7 +111,7 @@ static int __devinit ppc4xx_rng_probe(struct platform_device *dev) return err; } -static int __devexit ppc4xx_rng_remove(struct platform_device *dev) +static int ppc4xx_rng_remove(struct platform_device *dev) { void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv; diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index f1a1618db1fb..849db199c02c 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -88,7 +88,7 @@ static struct hwrng timeriomem_rng_ops = { .priv = 0, }; -static int __devinit timeriomem_rng_probe(struct platform_device *pdev) +static int timeriomem_rng_probe(struct platform_device *pdev) { struct resource *res; int ret; @@ -130,7 +130,7 @@ failed: return ret; } -static int __devexit timeriomem_rng_remove(struct platform_device *pdev) +static int timeriomem_rng_remove(struct platform_device *pdev) { del_timer_sync(&timeriomem_rng_timer); hwrng_unregister(&timeriomem_rng_ops); @@ -146,7 +146,7 @@ static struct platform_driver timeriomem_rng_driver = { .owner = THIS_MODULE, }, .probe = timeriomem_rng_probe, - .remove = __devexit_p(timeriomem_rng_remove), + .remove = timeriomem_rng_remove, }; module_platform_driver(timeriomem_rng_driver); diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c index de473ef3882b..30991989d65b 100644 --- a/drivers/char/hw_random/tx4939-rng.c +++ b/drivers/char/hw_random/tx4939-rng.c @@ -7,6 +7,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#include <linux/err.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -115,9 +116,9 @@ static int __init tx4939_rng_probe(struct platform_device *dev) rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL); if (!rngdev) return -ENOMEM; - rngdev->base = devm_request_and_ioremap(&dev->dev, r); - if (!rngdev->base) - return -EBUSY; + rngdev->base = devm_ioremap_resource(&dev->dev, r); + if (IS_ERR(rngdev->base)) + return PTR_ERR(rngdev->base); rngdev->rng.name = dev_name(&dev->dev); rngdev->rng.data_present = tx4939_rng_data_present; diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 5708299507d0..6bf4d47324eb 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -92,14 +92,22 @@ static int probe_common(struct virtio_device *vdev) { int err; + if (vq) { + /* We only support one device for now */ + return -EBUSY; + } /* We expect a single virtqueue. */ vq = virtio_find_single_vq(vdev, random_recv_done, "input"); - if (IS_ERR(vq)) - return PTR_ERR(vq); + if (IS_ERR(vq)) { + err = PTR_ERR(vq); + vq = NULL; + return err; + } err = hwrng_register(&virtio_hwrng); if (err) { vdev->config->del_vqs(vdev); + vq = NULL; return err; } @@ -112,6 +120,7 @@ static void remove_common(struct virtio_device *vdev) busy = false; hwrng_unregister(&virtio_hwrng); vdev->config->del_vqs(vdev); + vq = NULL; } static int virtrng_probe(struct virtio_device *vdev) @@ -119,7 +128,7 @@ static int virtrng_probe(struct virtio_device *vdev) return probe_common(vdev); } -static void __devexit virtrng_remove(struct virtio_device *vdev) +static void virtrng_remove(struct virtio_device *vdev) { remove_common(vdev); } @@ -147,25 +156,14 @@ static struct virtio_driver virtio_rng_driver = { .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtrng_probe, - .remove = __devexit_p(virtrng_remove), + .remove = virtrng_remove, #ifdef CONFIG_PM .freeze = virtrng_freeze, .restore = virtrng_restore, #endif }; -static int __init init(void) -{ - return register_virtio_driver(&virtio_rng_driver); -} - -static void __exit fini(void) -{ - unregister_virtio_driver(&virtio_rng_driver); -} -module_init(init); -module_exit(fini); - +module_virtio_driver(virtio_rng_driver); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Virtio random number driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index a0c84bb30856..053201b062a4 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -3789,7 +3789,7 @@ static int handle_one_recv_msg(ipmi_smi_t intf, } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) { - /* It's an asyncronous event. */ + /* It's an asynchronous event. */ requeue = handle_read_event_rsp(intf, msg); } else { /* It's a response from the local BMC. */ diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 32a6c7e256bd..0ac9b45a585e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -155,7 +155,7 @@ enum si_stat_indexes { /* Number of watchdog pretimeouts. */ SI_STAT_watchdog_pretimeouts, - /* Number of asyncronous messages received. */ + /* Number of asynchronous messages received. */ SI_STAT_incoming_messages, @@ -1208,6 +1208,16 @@ static int smi_num; /* Used to sequence the SMIs */ #define DEFAULT_REGSPACING 1 #define DEFAULT_REGSIZE 1 +#ifdef CONFIG_ACPI +static bool si_tryacpi = 1; +#endif +#ifdef CONFIG_DMI +static bool si_trydmi = 1; +#endif +static bool si_tryplatform = 1; +#ifdef CONFIG_PCI +static bool si_trypci = 1; +#endif static bool si_trydefaults = 1; static char *si_type[SI_MAX_PARMS]; #define MAX_SI_TYPE_STR 30 @@ -1238,6 +1248,25 @@ MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See" " Documentation/IPMI.txt in the kernel sources for the" " gory details."); +#ifdef CONFIG_ACPI +module_param_named(tryacpi, si_tryacpi, bool, 0); +MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" + " default scan of the interfaces identified via ACPI"); +#endif +#ifdef CONFIG_DMI +module_param_named(trydmi, si_trydmi, bool, 0); +MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the" + " default scan of the interfaces identified via DMI"); +#endif +module_param_named(tryplatform, si_tryplatform, bool, 0); +MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" + " default scan of the interfaces identified via platform" + " interfaces like openfirmware"); +#ifdef CONFIG_PCI +module_param_named(trypci, si_trypci, bool, 0); +MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" + " default scan of the interfaces identified via pci"); +#endif module_param_named(trydefaults, si_trydefaults, bool, 0); MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the" " default scan of the KCS and SMIC interface at the standard" @@ -1836,7 +1865,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) return rv; } -static int __devinit hardcode_find_bmc(void) +static int hardcode_find_bmc(void) { int ret = -ENODEV; int i; @@ -2023,7 +2052,7 @@ struct SPMITable { s8 spmi_id[1]; /* A '\0' terminated array starts here. */ }; -static int __devinit try_init_spmi(struct SPMITable *spmi) +static int try_init_spmi(struct SPMITable *spmi) { struct smi_info *info; @@ -2106,7 +2135,7 @@ static int __devinit try_init_spmi(struct SPMITable *spmi) return 0; } -static void __devinit spmi_find_bmc(void) +static void spmi_find_bmc(void) { acpi_status status; struct SPMITable *spmi; @@ -2128,7 +2157,7 @@ static void __devinit spmi_find_bmc(void) } } -static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, +static int ipmi_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { struct acpi_device *acpi_dev; @@ -2228,7 +2257,7 @@ err_free: return -EINVAL; } -static void __devexit ipmi_pnp_remove(struct pnp_dev *dev) +static void ipmi_pnp_remove(struct pnp_dev *dev) { struct smi_info *info = pnp_get_drvdata(dev); @@ -2243,7 +2272,7 @@ static const struct pnp_device_id pnp_dev_table[] = { static struct pnp_driver ipmi_pnp_driver = { .name = DEVICE_NAME, .probe = ipmi_pnp_probe, - .remove = __devexit_p(ipmi_pnp_remove), + .remove = ipmi_pnp_remove, .id_table = pnp_dev_table, }; #endif @@ -2258,7 +2287,7 @@ struct dmi_ipmi_data { u8 slave_addr; }; -static int __devinit decode_dmi(const struct dmi_header *dm, +static int decode_dmi(const struct dmi_header *dm, struct dmi_ipmi_data *dmi) { const u8 *data = (const u8 *)dm; @@ -2320,7 +2349,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm, return 0; } -static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data) +static void try_init_dmi(struct dmi_ipmi_data *ipmi_data) { struct smi_info *info; @@ -2388,7 +2417,7 @@ static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data) kfree(info); } -static void __devinit dmi_find_bmc(void) +static void dmi_find_bmc(void) { const struct dmi_device *dev = NULL; struct dmi_ipmi_data data; @@ -2424,7 +2453,7 @@ static void ipmi_pci_cleanup(struct smi_info *info) pci_disable_device(pdev); } -static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info) +static int ipmi_pci_probe_regspacing(struct smi_info *info) { if (info->si_type == SI_KCS) { unsigned char status; @@ -2456,7 +2485,7 @@ static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info) return DEFAULT_REGSPACING; } -static int __devinit ipmi_pci_probe(struct pci_dev *pdev, +static int ipmi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rv; @@ -2529,7 +2558,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, return 0; } -static void __devexit ipmi_pci_remove(struct pci_dev *pdev) +static void ipmi_pci_remove(struct pci_dev *pdev) { struct smi_info *info = pci_get_drvdata(pdev); cleanup_one_si(info); @@ -2546,12 +2575,12 @@ static struct pci_driver ipmi_pci_driver = { .name = DEVICE_NAME, .id_table = ipmi_pci_devices, .probe = ipmi_pci_probe, - .remove = __devexit_p(ipmi_pci_remove), + .remove = ipmi_pci_remove, }; #endif /* CONFIG_PCI */ static struct of_device_id ipmi_match[]; -static int __devinit ipmi_probe(struct platform_device *dev) +static int ipmi_probe(struct platform_device *dev) { #ifdef CONFIG_OF const struct of_device_id *match; @@ -2635,7 +2664,7 @@ static int __devinit ipmi_probe(struct platform_device *dev) return 0; } -static int __devexit ipmi_remove(struct platform_device *dev) +static int ipmi_remove(struct platform_device *dev) { #ifdef CONFIG_OF cleanup_one_si(dev_get_drvdata(&dev->dev)); @@ -2661,7 +2690,7 @@ static struct platform_driver ipmi_driver = { .of_match_table = ipmi_match, }, .probe = ipmi_probe, - .remove = __devexit_p(ipmi_remove), + .remove = ipmi_remove, }; static int wait_for_msg_done(struct smi_info *smi_info) @@ -3047,7 +3076,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info) } } -static __devinitdata struct ipmi_default_vals +static struct ipmi_default_vals { int type; int port; @@ -3059,7 +3088,7 @@ static __devinitdata struct ipmi_default_vals { .port = 0 } }; -static void __devinit default_find_bmc(void) +static void default_find_bmc(void) { struct smi_info *info; int i; @@ -3359,7 +3388,7 @@ static int try_smi_init(struct smi_info *new_smi) return rv; } -static int __devinit init_ipmi_si(void) +static int init_ipmi_si(void) { int i; char *str; @@ -3371,13 +3400,15 @@ static int __devinit init_ipmi_si(void) return 0; initialized = 1; - rv = platform_driver_register(&ipmi_driver); - if (rv) { - printk(KERN_ERR PFX "Unable to register driver: %d\n", rv); - return rv; + if (si_tryplatform) { + rv = platform_driver_register(&ipmi_driver); + if (rv) { + printk(KERN_ERR PFX "Unable to register " + "driver: %d\n", rv); + return rv; + } } - /* Parse out the si_type string into its components. */ str = si_type_str; if (*str != '\0') { @@ -3400,24 +3431,31 @@ static int __devinit init_ipmi_si(void) return 0; #ifdef CONFIG_PCI - rv = pci_register_driver(&ipmi_pci_driver); - if (rv) - printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv); - else - pci_registered = 1; + if (si_trypci) { + rv = pci_register_driver(&ipmi_pci_driver); + if (rv) + printk(KERN_ERR PFX "Unable to register " + "PCI driver: %d\n", rv); + else + pci_registered = 1; + } #endif #ifdef CONFIG_ACPI - pnp_register_driver(&ipmi_pnp_driver); - pnp_registered = 1; + if (si_tryacpi) { + pnp_register_driver(&ipmi_pnp_driver); + pnp_registered = 1; + } #endif #ifdef CONFIG_DMI - dmi_find_bmc(); + if (si_trydmi) + dmi_find_bmc(); #endif #ifdef CONFIG_ACPI - spmi_find_bmc(); + if (si_tryacpi) + spmi_find_bmc(); #endif /* We prefer devices with interrupts, but in the case of a machine diff --git a/drivers/char/lp.c b/drivers/char/lp.c index a741e418b456..dafd9ac6428f 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -294,7 +294,7 @@ static int lp_wait_ready(int minor, int nonblock) static ssize_t lp_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - unsigned int minor = iminor(file->f_path.dentry->d_inode); + unsigned int minor = iminor(file_inode(file)); struct parport *port = lp_table[minor].dev->port; char *kbuf = lp_table[minor].lp_buffer; ssize_t retv = 0; @@ -413,7 +413,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { DEFINE_WAIT(wait); - unsigned int minor=iminor(file->f_path.dentry->d_inode); + unsigned int minor=iminor(file_inode(file)); struct parport *port = lp_table[minor].dev->port; ssize_t retval = 0; char *kbuf = lp_table[minor].lp_buffer; @@ -679,7 +679,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd, struct timeval par_timeout; int ret; - minor = iminor(file->f_path.dentry->d_inode); + minor = iminor(file_inode(file)); mutex_lock(&lp_mutex); switch (cmd) { case LPSETTIMEOUT: @@ -707,7 +707,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd, struct timeval par_timeout; int ret; - minor = iminor(file->f_path.dentry->d_inode); + minor = iminor(file_inode(file)); mutex_lock(&lp_mutex); switch (cmd) { case LPSETTIMEOUT: diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index f74e892711dd..e5d3e3f7a49b 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c @@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev) return 0; } -static const struct cx_device_id __devinitconst mbcs_id_table[] = { +static const struct cx_device_id mbcs_id_table[] = { { .part_num = MBCS_PART_NUM, .mfg_num = MBCS_MFG_NUM, diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 0537903c985b..2c644afbcdd4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -48,7 +48,7 @@ static inline unsigned long size_inside_page(unsigned long start, } #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE -static inline int valid_phys_addr_range(unsigned long addr, size_t count) +static inline int valid_phys_addr_range(phys_addr_t addr, size_t count) { return addr + count <= __pa(high_memory); } @@ -96,7 +96,7 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) static ssize_t read_mem(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; + phys_addr_t p = *ppos; ssize_t read, sz; char *ptr; @@ -153,7 +153,7 @@ static ssize_t read_mem(struct file *file, char __user *buf, static ssize_t write_mem(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; + phys_addr_t p = *ppos; ssize_t written, sz; unsigned long copied; void *ptr; @@ -226,7 +226,7 @@ int __weak phys_mem_access_prot_allowed(struct file *file, * */ #ifdef pgprot_noncached -static int uncached_access(struct file *file, unsigned long addr) +static int uncached_access(struct file *file, phys_addr_t addr) { #if defined(CONFIG_IA64) /* @@ -258,7 +258,7 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, pgprot_t vma_prot) { #ifdef pgprot_noncached - unsigned long offset = pfn << PAGE_SHIFT; + phys_addr_t offset = pfn << PAGE_SHIFT; if (uncached_access(file, offset)) return pgprot_noncached(vma_prot); @@ -399,7 +399,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf, { unsigned long p = *ppos; ssize_t low_count, read, sz; - char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ + char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ int err = 0; read = 0; @@ -527,7 +527,7 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, unsigned long p = *ppos; ssize_t wrote = 0; ssize_t virtr = 0; - char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ + char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ int err = 0; if (p < (unsigned long) high_memory) { @@ -595,7 +595,7 @@ static ssize_t write_port(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long i = *ppos; - const char __user * tmp = buf; + const char __user *tmp = buf; if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; @@ -708,7 +708,7 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) { loff_t ret; - mutex_lock(&file->f_path.dentry->d_inode->i_mutex); + mutex_lock(&file_inode(file)->i_mutex); switch (orig) { case SEEK_CUR: offset += file->f_pos; @@ -725,11 +725,11 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) default: ret = -EINVAL; } - mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); + mutex_unlock(&file_inode(file)->i_mutex); return ret; } -static int open_port(struct inode * inode, struct file * filp) +static int open_port(struct inode *inode, struct file *filp) { return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } @@ -898,7 +898,7 @@ static int __init chr_dev_init(void) continue; /* - * Create /dev/port? + * Create /dev/port? */ if ((minor == DEVPORT_MINOR) && !arch_has_dev_port()) continue; diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 522136d40843..190d4423653f 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -183,19 +183,12 @@ static const struct file_operations misc_fops = { int misc_register(struct miscdevice * misc) { - struct miscdevice *c; dev_t dev; int err = 0; INIT_LIST_HEAD(&misc->list); mutex_lock(&misc_mtx); - list_for_each_entry(c, &misc_list, list) { - if (c->minor == misc->minor) { - mutex_unlock(&misc_mtx); - return -EBUSY; - } - } if (misc->minor == MISC_DYNAMIC_MINOR) { int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); @@ -205,6 +198,15 @@ int misc_register(struct miscdevice * misc) } misc->minor = DYNAMIC_MINORS - i - 1; set_bit(i, misc_minors); + } else { + struct miscdevice *c; + + list_for_each_entry(c, &misc_list, list) { + if (c->minor == misc->minor) { + mutex_unlock(&misc_mtx); + return -EBUSY; + } + } } dev = MKDEV(MISC_MAJOR, misc->minor); diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c index 808d44e9a32a..b07b119ae57f 100644 --- a/drivers/char/nsc_gpio.c +++ b/drivers/char/nsc_gpio.c @@ -41,7 +41,7 @@ void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index) ssize_t nsc_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - unsigned m = iminor(file->f_path.dentry->d_inode); + unsigned m = iminor(file_inode(file)); struct nsc_gpio_ops *amp = file->private_data; struct device *dev = amp->dev; size_t i; @@ -104,7 +104,7 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data, ssize_t nsc_gpio_read(struct file *file, char __user * buf, size_t len, loff_t * ppos) { - unsigned m = iminor(file->f_path.dentry->d_inode); + unsigned m = iminor(file_inode(file)); int value; struct nsc_gpio_ops *amp = file->private_data; diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c index b304ec052501..3f79a9fb6b1b 100644 --- a/drivers/char/pc8736x_gpio.c +++ b/drivers/char/pc8736x_gpio.c @@ -345,8 +345,7 @@ static void __exit pc8736x_gpio_cleanup(void) unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT); release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE); - platform_device_del(pdev); - platform_device_put(pdev); + platform_device_unregister(pdev); } module_init(pc8736x_gpio_init); diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index 6614416a8623..2a166d56738a 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig @@ -7,7 +7,7 @@ menu "PCMCIA character devices" config SYNCLINK_CS tristate "SyncLink PC Card support" - depends on PCMCIA + depends on PCMCIA && TTY help Enable support for the SyncLink PC Card serial adapter, running asynchronous and HDLC communications up to 512Kbps. The port is @@ -45,7 +45,7 @@ config CARDMAN_4040 config IPWIRELESS tristate "IPWireless 3G UMTS PCMCIA card support" - depends on PCMCIA && NETDEVICES + depends on PCMCIA && NETDEVICES && TTY select PPP help This is a driver for 3G UMTS PCMCIA card from IPWireless company. In diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index a7584860e9a7..c115217c79ae 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1400,7 +1400,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct cm4000_dev *dev = filp->private_data; unsigned int iobase = dev->p_dev->resource[0]->start; - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file_inode(filp); struct pcmcia_device *link; int size; int rc; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 21721d25e388..5c5cc00ebb07 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -102,8 +102,7 @@ static MGSL_PARAMS default_params = { ASYNC_PARITY_NONE /* unsigned char parity; */ }; -typedef struct -{ +typedef struct { int count; unsigned char status; char data[1]; @@ -210,7 +209,7 @@ typedef struct _mgslpc_info { char testing_irq; unsigned int init_error; /* startup error (DIAGS) */ - char flag_buf[MAX_ASYNC_BUFFER_SIZE]; + char *flag_buf; bool drop_rts_on_tx_done; struct _input_signal_events input_signal_events; @@ -326,10 +325,10 @@ typedef struct _mgslpc_info { #define write_reg16(info, reg, val) outw((val), (info)->io_base + (reg)) #define set_reg_bits(info, reg, mask) \ - write_reg(info, (reg), \ + write_reg(info, (reg), \ (unsigned char) (read_reg(info, (reg)) | (mask))) #define clear_reg_bits(info, reg, mask) \ - write_reg(info, (reg), \ + write_reg(info, (reg), \ (unsigned char) (read_reg(info, (reg)) & ~(mask))) /* * interrupt enable/disable routines @@ -356,10 +355,10 @@ static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short } #define port_irq_disable(info, mask) \ - { info->pim_value |= (mask); write_reg(info, PIM, info->pim_value); } + { info->pim_value |= (mask); write_reg(info, PIM, info->pim_value); } #define port_irq_enable(info, mask) \ - { info->pim_value &= ~(mask); write_reg(info, PIM, info->pim_value); } + { info->pim_value &= ~(mask); write_reg(info, PIM, info->pim_value); } static void rx_start(MGSLPC_INFO *info); static void rx_stop(MGSLPC_INFO *info); @@ -397,7 +396,7 @@ static int adapter_test(MGSLPC_INFO *info); static int claim_resources(MGSLPC_INFO *info); static void release_resources(MGSLPC_INFO *info); -static void mgslpc_add_device(MGSLPC_INFO *info); +static int mgslpc_add_device(MGSLPC_INFO *info); static void mgslpc_remove_device(MGSLPC_INFO *info); static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty); @@ -514,47 +513,56 @@ static const struct tty_port_operations mgslpc_port_ops = { static int mgslpc_probe(struct pcmcia_device *link) { - MGSLPC_INFO *info; - int ret; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_attach\n"); - - info = kzalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); - if (!info) { - printk("Error can't allocate device instance data\n"); - return -ENOMEM; - } - - info->magic = MGSLPC_MAGIC; - tty_port_init(&info->port); - info->port.ops = &mgslpc_port_ops; - INIT_WORK(&info->task, bh_handler); - info->max_frame_size = 4096; - info->port.close_delay = 5*HZ/10; - info->port.closing_wait = 30*HZ; - init_waitqueue_head(&info->status_event_wait_q); - init_waitqueue_head(&info->event_wait_q); - spin_lock_init(&info->lock); - spin_lock_init(&info->netlock); - memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - info->idle_mode = HDLC_TXIDLE_FLAGS; - info->imra_value = 0xffff; - info->imrb_value = 0xffff; - info->pim_value = 0xff; - - info->p_dev = link; - link->priv = info; - - /* Initialize the struct pcmcia_device structure */ - - ret = mgslpc_config(link); - if (ret) - return ret; - - mgslpc_add_device(info); - - return 0; + MGSLPC_INFO *info; + int ret; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_attach\n"); + + info = kzalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); + if (!info) { + printk("Error can't allocate device instance data\n"); + return -ENOMEM; + } + + info->magic = MGSLPC_MAGIC; + tty_port_init(&info->port); + info->port.ops = &mgslpc_port_ops; + INIT_WORK(&info->task, bh_handler); + info->max_frame_size = 4096; + info->port.close_delay = 5*HZ/10; + info->port.closing_wait = 30*HZ; + init_waitqueue_head(&info->status_event_wait_q); + init_waitqueue_head(&info->event_wait_q); + spin_lock_init(&info->lock); + spin_lock_init(&info->netlock); + memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); + info->idle_mode = HDLC_TXIDLE_FLAGS; + info->imra_value = 0xffff; + info->imrb_value = 0xffff; + info->pim_value = 0xff; + + info->p_dev = link; + link->priv = info; + + /* Initialize the struct pcmcia_device structure */ + + ret = mgslpc_config(link); + if (ret != 0) + goto failed; + + ret = mgslpc_add_device(info); + if (ret != 0) + goto failed_release; + + return 0; + +failed_release: + mgslpc_release((u_long)link); +failed: + tty_port_destroy(&info->port); + kfree(info); + return ret; } /* Card has been inserted. @@ -567,35 +575,35 @@ static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data) static int mgslpc_config(struct pcmcia_device *link) { - MGSLPC_INFO *info = link->priv; - int ret; + MGSLPC_INFO *info = link->priv; + int ret; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_config(0x%p)\n", link); + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_config(0x%p)\n", link); - link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); - if (ret != 0) - goto failed; + ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); + if (ret != 0) + goto failed; - link->config_index = 8; - link->config_regs = PRESENT_OPTION; + link->config_index = 8; + link->config_regs = PRESENT_OPTION; - ret = pcmcia_request_irq(link, mgslpc_isr); - if (ret) - goto failed; - ret = pcmcia_enable_device(link); - if (ret) - goto failed; + ret = pcmcia_request_irq(link, mgslpc_isr); + if (ret) + goto failed; + ret = pcmcia_enable_device(link); + if (ret) + goto failed; - info->io_base = link->resource[0]->start; - info->irq_level = link->irq; - return 0; + info->io_base = link->resource[0]->start; + info->irq_level = link->irq; + return 0; failed: - mgslpc_release((u_long)link); - return -ENODEV; + mgslpc_release((u_long)link); + return -ENODEV; } /* Card has been removed. @@ -701,12 +709,12 @@ static void tx_pause(struct tty_struct *tty) if (mgslpc_paranoia_check(info, tty->name, "tx_pause")) return; if (debug_level >= DEBUG_LEVEL_INFO) - printk("tx_pause(%s)\n",info->device_name); + printk("tx_pause(%s)\n", info->device_name); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (info->tx_enabled) - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock, flags); } static void tx_release(struct tty_struct *tty) @@ -717,12 +725,12 @@ static void tx_release(struct tty_struct *tty) if (mgslpc_paranoia_check(info, tty->name, "tx_release")) return; if (debug_level >= DEBUG_LEVEL_INFO) - printk("tx_release(%s)\n",info->device_name); + printk("tx_release(%s)\n", info->device_name); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (!info->tx_enabled) - tx_start(info, tty); - spin_unlock_irqrestore(&info->lock,flags); + tx_start(info, tty); + spin_unlock_irqrestore(&info->lock, flags); } /* Return next bottom half action to perform. @@ -733,7 +741,7 @@ static int bh_action(MGSLPC_INFO *info) unsigned long flags; int rc = 0; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (info->pending_bh & BH_RECEIVE) { info->pending_bh &= ~BH_RECEIVE; @@ -752,7 +760,7 @@ static int bh_action(MGSLPC_INFO *info) info->bh_requested = false; } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return rc; } @@ -763,11 +771,8 @@ static void bh_handler(struct work_struct *work) struct tty_struct *tty; int action; - if (!info) - return; - if (debug_level >= DEBUG_LEVEL_BH) - printk( "%s(%d):bh_handler(%s) entry\n", + printk("%s(%d):bh_handler(%s) entry\n", __FILE__,__LINE__,info->device_name); info->bh_running = true; @@ -776,8 +781,8 @@ static void bh_handler(struct work_struct *work) while((action = bh_action(info)) != 0) { /* Process work item */ - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):bh_handler() work item action=%d\n", + if (debug_level >= DEBUG_LEVEL_BH) + printk("%s(%d):bh_handler() work item action=%d\n", __FILE__,__LINE__,action); switch (action) { @@ -800,7 +805,7 @@ static void bh_handler(struct work_struct *work) tty_kref_put(tty); if (debug_level >= DEBUG_LEVEL_BH) - printk( "%s(%d):bh_handler(%s) exit\n", + printk("%s(%d):bh_handler(%s) exit\n", __FILE__,__LINE__,info->device_name); } @@ -829,7 +834,7 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) RXBUF *buf = (RXBUF*)(info->rx_buf + (info->rx_put * info->rx_buf_size)); if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):rx_ready_hdlc(eom=%d)\n",__FILE__,__LINE__,eom); + printk("%s(%d):rx_ready_hdlc(eom=%d)\n", __FILE__, __LINE__, eom); if (!info->rx_enabled) return; @@ -845,7 +850,8 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) if (eom) { /* end of frame, get FIFO count from RBCL register */ - if (!(fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f))) + fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f); + if (fifo_count == 0) fifo_count = 32; } else fifo_count = 32; @@ -884,20 +890,13 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) issue_command(info, CHA, CMD_RXFIFO); } -static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) +static void rx_ready_async(MGSLPC_INFO *info, int tcd) { + struct tty_port *port = &info->port; unsigned char data, status, flag; int fifo_count; int work = 0; - struct mgsl_icount *icount = &info->icount; - - if (!tty) { - /* tty is not available anymore */ - issue_command(info, CHA, CMD_RXRESET); - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):rx_ready_async(tty=NULL)\n",__FILE__,__LINE__); - return; - } + struct mgsl_icount *icount = &info->icount; if (tcd) { /* early termination, get FIFO count from RBCL register */ @@ -911,7 +910,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) } else fifo_count = 32; - tty_buffer_request_room(tty, fifo_count); + tty_buffer_request_room(port, fifo_count); /* Flush received async data to receive data buffer. */ while (fifo_count) { data = read_reg(info, CHA + RXFIFO); @@ -942,7 +941,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) else if (status & BIT6) flag = TTY_FRAME; } - work += tty_insert_flip_char(tty, data, flag); + work += tty_insert_flip_char(port, data, flag); } issue_command(info, CHA, CMD_RXFIFO); @@ -955,7 +954,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) } if (work) - tty_flip_buffer_push(tty); + tty_flip_buffer_push(port); } @@ -1002,7 +1001,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) int c; if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):tx_ready(%s)\n", __FILE__,__LINE__,info->device_name); + printk("%s(%d):tx_ready(%s)\n", __FILE__, __LINE__, info->device_name); if (info->params.mode == MGSL_MODE_HDLC) { if (!info->tx_active) @@ -1215,7 +1214,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) if (info->params.mode == MGSL_MODE_HDLC) rx_ready_hdlc(info, isr & IRQ_RXEOM); else - rx_ready_async(info, isr & IRQ_RXEOM, tty); + rx_ready_async(info, isr & IRQ_RXEOM); } /* transmit IRQs */ @@ -1247,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) */ if (info->pending_bh && !info->bh_running && !info->bh_requested) { - if ( debug_level >= DEBUG_LEVEL_ISR ) + if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):%s queueing bh task.\n", __FILE__,__LINE__,info->device_name); schedule_work(&info->task); @@ -1271,7 +1270,7 @@ static int startup(MGSLPC_INFO * info, struct tty_struct *tty) int retval = 0; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name); + printk("%s(%d):startup(%s)\n", __FILE__, __LINE__, info->device_name); if (info->port.flags & ASYNC_INITIALIZED) return 0; @@ -1281,7 +1280,7 @@ static int startup(MGSLPC_INFO * info, struct tty_struct *tty) info->tx_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); if (!info->tx_buf) { printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", - __FILE__,__LINE__,info->device_name); + __FILE__, __LINE__, info->device_name); return -ENOMEM; } } @@ -1296,15 +1295,15 @@ static int startup(MGSLPC_INFO * info, struct tty_struct *tty) retval = claim_resources(info); /* perform existence check and diagnostics */ - if ( !retval ) + if (!retval) retval = adapter_test(info); - if ( retval ) { - if (capable(CAP_SYS_ADMIN) && tty) + if (retval) { + if (capable(CAP_SYS_ADMIN) && tty) set_bit(TTY_IO_ERROR, &tty->flags); release_resources(info); - return retval; - } + return retval; + } /* program hardware for current parameters */ mgslpc_change_params(info, tty); @@ -1328,7 +1327,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_shutdown(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); /* clear status wait queue because status changes */ /* can't happen after shutting down the hardware */ @@ -1342,7 +1341,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) info->tx_buf = NULL; } - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); rx_stop(info); tx_stop(info); @@ -1350,12 +1349,12 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); - if (!tty || tty->termios.c_cflag & HUPCL) { - info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + if (!tty || tty->termios.c_cflag & HUPCL) { + info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); set_signals(info); } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); release_resources(info); @@ -1369,7 +1368,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) { unsigned long flags; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); rx_stop(info); tx_stop(info); @@ -1394,7 +1393,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) rx_start(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); } /* Reconfigure adapter based on new parameters @@ -1409,16 +1408,16 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_change_params(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); cflag = tty->termios.c_cflag; - /* if B0 rate (hangup) specified then negate DTR and RTS */ - /* otherwise assert DTR and RTS */ - if (cflag & CBAUD) - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + /* if B0 rate (hangup) specified then negate RTS and DTR */ + /* otherwise assert RTS and DTR */ + if (cflag & CBAUD) + info->serial_signals |= SerialSignal_RTS | SerialSignal_DTR; else - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); /* byte size and parity */ @@ -1461,7 +1460,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) info->params.data_rate = tty_get_baud_rate(tty); } - if ( info->params.data_rate ) { + if (info->params.data_rate) { info->timeout = (32*HZ*bits_per_char) / info->params.data_rate; } @@ -1496,8 +1495,8 @@ static int mgslpc_put_char(struct tty_struct *tty, unsigned char ch) unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) { - printk( "%s(%d):mgslpc_put_char(%d) on %s\n", - __FILE__,__LINE__,ch,info->device_name); + printk("%s(%d):mgslpc_put_char(%d) on %s\n", + __FILE__, __LINE__, ch, info->device_name); } if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char")) @@ -1506,7 +1505,7 @@ static int mgslpc_put_char(struct tty_struct *tty, unsigned char ch) if (!info->tx_buf) return 0; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (info->params.mode == MGSL_MODE_ASYNC || !info->tx_active) { if (info->tx_count < TXBUFSIZE - 1) { @@ -1516,7 +1515,7 @@ static int mgslpc_put_char(struct tty_struct *tty, unsigned char ch) } } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 1; } @@ -1529,8 +1528,8 @@ static void mgslpc_flush_chars(struct tty_struct *tty) unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk( "%s(%d):mgslpc_flush_chars() entry on %s tx_count=%d\n", - __FILE__,__LINE__,info->device_name,info->tx_count); + printk("%s(%d):mgslpc_flush_chars() entry on %s tx_count=%d\n", + __FILE__, __LINE__, info->device_name, info->tx_count); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_chars")) return; @@ -1540,13 +1539,13 @@ static void mgslpc_flush_chars(struct tty_struct *tty) return; if (debug_level >= DEBUG_LEVEL_INFO) - printk( "%s(%d):mgslpc_flush_chars() entry on %s starting transmitter\n", - __FILE__,__LINE__,info->device_name); + printk("%s(%d):mgslpc_flush_chars() entry on %s starting transmitter\n", + __FILE__, __LINE__, info->device_name); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (!info->tx_active) - tx_start(info, tty); - spin_unlock_irqrestore(&info->lock,flags); + tx_start(info, tty); + spin_unlock_irqrestore(&info->lock, flags); } /* Send a block of data @@ -1567,8 +1566,8 @@ static int mgslpc_write(struct tty_struct * tty, unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk( "%s(%d):mgslpc_write(%s) count=%d\n", - __FILE__,__LINE__,info->device_name,count); + printk("%s(%d):mgslpc_write(%s) count=%d\n", + __FILE__, __LINE__, info->device_name, count); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") || !info->tx_buf) @@ -1594,26 +1593,26 @@ static int mgslpc_write(struct tty_struct * tty, memcpy(info->tx_buf + info->tx_put, buf, c); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); info->tx_put = (info->tx_put + c) & (TXBUFSIZE-1); info->tx_count += c; - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); buf += c; count -= c; ret += c; } start: - if (info->tx_count && !tty->stopped && !tty->hw_stopped) { - spin_lock_irqsave(&info->lock,flags); + if (info->tx_count && !tty->stopped && !tty->hw_stopped) { + spin_lock_irqsave(&info->lock, flags); if (!info->tx_active) - tx_start(info, tty); - spin_unlock_irqrestore(&info->lock,flags); - } + tx_start(info, tty); + spin_unlock_irqrestore(&info->lock, flags); + } cleanup: if (debug_level >= DEBUG_LEVEL_INFO) - printk( "%s(%d):mgslpc_write(%s) returning=%d\n", - __FILE__,__LINE__,info->device_name,ret); + printk("%s(%d):mgslpc_write(%s) returning=%d\n", + __FILE__, __LINE__, info->device_name, ret); return ret; } @@ -1641,7 +1640,7 @@ static int mgslpc_write_room(struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_write_room(%s)=%d\n", - __FILE__,__LINE__, info->device_name, ret); + __FILE__, __LINE__, info->device_name, ret); return ret; } @@ -1654,7 +1653,7 @@ static int mgslpc_chars_in_buffer(struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_chars_in_buffer(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_chars_in_buffer")) return 0; @@ -1666,7 +1665,7 @@ static int mgslpc_chars_in_buffer(struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_chars_in_buffer(%s)=%d\n", - __FILE__,__LINE__, info->device_name, rc); + __FILE__, __LINE__, info->device_name, rc); return rc; } @@ -1680,15 +1679,15 @@ static void mgslpc_flush_buffer(struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_flush_buffer(%s) entry\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_buffer")) return; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); info->tx_count = info->tx_put = info->tx_get = 0; del_timer(&info->tx_timer); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); @@ -1703,17 +1702,17 @@ static void mgslpc_send_xchar(struct tty_struct *tty, char ch) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_send_xchar(%s,%d)\n", - __FILE__,__LINE__, info->device_name, ch ); + __FILE__, __LINE__, info->device_name, ch); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_send_xchar")) return; info->x_char = ch; if (ch) { - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (!info->tx_enabled) - tx_start(info, tty); - spin_unlock_irqrestore(&info->lock,flags); + tx_start(info, tty); + spin_unlock_irqrestore(&info->lock, flags); } } @@ -1726,7 +1725,7 @@ static void mgslpc_throttle(struct tty_struct * tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_throttle(%s) entry\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_throttle")) return; @@ -1734,11 +1733,11 @@ static void mgslpc_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); + if (tty->termios.c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock, flags); info->serial_signals &= ~SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock, flags); } } @@ -1751,7 +1750,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_unthrottle(%s) entry\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_unthrottle")) return; @@ -1763,11 +1762,11 @@ static void mgslpc_unthrottle(struct tty_struct * tty) mgslpc_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); + if (tty->termios.c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock, flags); info->serial_signals |= SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock, flags); } } @@ -1805,33 +1804,33 @@ static int get_params(MGSLPC_INFO * info, MGSL_PARAMS __user *user_params) * * Arguments: * - * info pointer to device instance data - * new_params user buffer containing new serial params + * info pointer to device instance data + * new_params user buffer containing new serial params * * Returns: 0 if success, otherwise error code */ static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params, struct tty_struct *tty) { - unsigned long flags; + unsigned long flags; MGSL_PARAMS tmp_params; int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):set_params %s\n", __FILE__,__LINE__, - info->device_name ); + info->device_name); COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):set_params(%s) user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):set_params(%s) user buffer copy failed\n", + __FILE__, __LINE__, info->device_name); return -EFAULT; } - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); - mgslpc_change_params(info, tty); + mgslpc_change_params(info, tty); return 0; } @@ -1849,13 +1848,13 @@ static int get_txidle(MGSLPC_INFO * info, int __user *idle_mode) static int set_txidle(MGSLPC_INFO * info, int idle_mode) { - unsigned long flags; + unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_txidle(%s,%d)\n", info->device_name, idle_mode); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); info->idle_mode = idle_mode; tx_set_idle(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } @@ -1872,11 +1871,11 @@ static int get_interface(MGSLPC_INFO * info, int __user *if_mode) static int set_interface(MGSLPC_INFO * info, int if_mode) { - unsigned long flags; + unsigned long flags; unsigned char val; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_interface(%s,%d)\n", info->device_name, if_mode); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); info->if_mode = if_mode; val = read_reg(info, PVR) & 0x0f; @@ -1888,18 +1887,18 @@ static int set_interface(MGSLPC_INFO * info, int if_mode) } write_reg(info, PVR, val); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } static int set_txenable(MGSLPC_INFO * info, int enable, struct tty_struct *tty) { - unsigned long flags; + unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_txenable(%s,%d)\n", info->device_name, enable); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (enable) { if (!info->tx_enabled) tx_start(info, tty); @@ -1907,18 +1906,18 @@ static int set_txenable(MGSLPC_INFO * info, int enable, struct tty_struct *tty) if (info->tx_enabled) tx_stop(info); } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } static int tx_abort(MGSLPC_INFO * info) { - unsigned long flags; + unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("tx_abort(%s)\n", info->device_name); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (info->tx_active && info->tx_count && info->params.mode == MGSL_MODE_HDLC) { /* clear data count so FIFO is not filled on next IRQ. @@ -1927,18 +1926,18 @@ static int tx_abort(MGSLPC_INFO * info) info->tx_count = info->tx_put = info->tx_get = 0; info->tx_aborting = true; } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } static int set_rxenable(MGSLPC_INFO * info, int enable) { - unsigned long flags; + unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_rxenable(%s,%d)\n", info->device_name, enable); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (enable) { if (!info->rx_enabled) rx_start(info); @@ -1946,21 +1945,21 @@ static int set_rxenable(MGSLPC_INFO * info, int enable) if (info->rx_enabled) rx_stop(info); } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } /* wait for specified event to occur * - * Arguments: info pointer to device instance data - * mask pointer to bitmask of events to wait for - * Return Value: 0 if successful and bit mask updated with + * Arguments: info pointer to device instance data + * mask pointer to bitmask of events to wait for + * Return Value: 0 if successful and bit mask updated with * of events triggerred, - * otherwise error code + * otherwise error code */ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr) { - unsigned long flags; + unsigned long flags; int s; int rc=0; struct mgsl_icount cprev, cnow; @@ -1976,18 +1975,18 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr) if (debug_level >= DEBUG_LEVEL_INFO) printk("wait_events(%s,%d)\n", info->device_name, mask); - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); /* return immediately if state matches requested events */ get_signals(info); s = info->serial_signals; events = mask & ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + - ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + + ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); if (events) { - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); goto exit; } @@ -2002,7 +2001,7 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr) set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&info->event_wait_q, &wait); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); for(;;) { @@ -2013,11 +2012,11 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr) } /* get current irq counts */ - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); cnow = info->icount; newsigs = info->input_signal_events; set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); /* if no change, wait aborted for some reason */ if (newsigs.dsr_up == oldsigs.dsr_up && @@ -2056,10 +2055,10 @@ static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr) set_current_state(TASK_RUNNING); if (mask & MgslEvent_ExitHuntMode) { - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (!waitqueue_active(&info->event_wait_q)) irq_disable(info, CHA, IRQ_EXITHUNT); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); } exit: if (rc == 0) @@ -2069,17 +2068,17 @@ exit: static int modem_input_wait(MGSLPC_INFO *info,int arg) { - unsigned long flags; + unsigned long flags; int rc; struct mgsl_icount cprev, cnow; DECLARE_WAITQUEUE(wait, current); /* save current irq counts */ - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); cprev = info->icount; add_wait_queue(&info->status_event_wait_q, &wait); set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); for(;;) { schedule(); @@ -2089,10 +2088,10 @@ static int modem_input_wait(MGSLPC_INFO *info,int arg) } /* get new irq counts */ - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); cnow = info->icount; set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); /* if no change, wait aborted for some reason */ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && @@ -2123,11 +2122,11 @@ static int tiocmget(struct tty_struct *tty) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned int result; - unsigned long flags; + unsigned long flags; - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) + ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) + @@ -2138,7 +2137,7 @@ static int tiocmget(struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s tiocmget() value=%08X\n", - __FILE__,__LINE__, info->device_name, result ); + __FILE__, __LINE__, info->device_name, result); return result; } @@ -2148,11 +2147,11 @@ static int tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; - unsigned long flags; + unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s tiocmset(%x,%x)\n", - __FILE__,__LINE__,info->device_name, set, clear); + __FILE__, __LINE__, info->device_name, set, clear); if (set & TIOCM_RTS) info->serial_signals |= SerialSignal_RTS; @@ -2163,9 +2162,9 @@ static int tiocmset(struct tty_struct *tty, if (clear & TIOCM_DTR) info->serial_signals &= ~SerialSignal_DTR; - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock, flags); return 0; } @@ -2182,17 +2181,17 @@ static int mgslpc_break(struct tty_struct *tty, int break_state) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_break(%s,%d)\n", - __FILE__,__LINE__, info->device_name, break_state); + __FILE__, __LINE__, info->device_name, break_state); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break")) return -EINVAL; - spin_lock_irqsave(&info->lock,flags); - if (break_state == -1) + spin_lock_irqsave(&info->lock, flags); + if (break_state == -1) set_reg_bits(info, CHA+DAFO, BIT6); else clear_reg_bits(info, CHA+DAFO, BIT6); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } @@ -2203,9 +2202,9 @@ static int mgslpc_get_icount(struct tty_struct *tty, struct mgsl_icount cnow; /* kernel counter temps */ unsigned long flags; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); cnow = info->icount; - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); icount->cts = cnow.cts; icount->dsr = cnow.dsr; @@ -2226,9 +2225,9 @@ static int mgslpc_get_icount(struct tty_struct *tty, * * Arguments: * - * tty pointer to tty instance data - * cmd IOCTL command code - * arg command argument/context + * tty pointer to tty instance data + * cmd IOCTL command code + * arg command argument/context * * Return Value: 0 if success, otherwise error code */ @@ -2239,8 +2238,8 @@ static int mgslpc_ioctl(struct tty_struct *tty, void __user *argp = (void __user *)arg; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->device_name, cmd ); + printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__, __LINE__, + info->device_name, cmd); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_ioctl")) return -ENODEV; @@ -2286,8 +2285,8 @@ static int mgslpc_ioctl(struct tty_struct *tty, * * Arguments: * - * tty pointer to tty structure - * termios pointer to buffer to hold returned old termios + * tty pointer to tty structure + * termios pointer to buffer to hold returned old termios */ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { @@ -2295,8 +2294,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgslpc_set_termios %s\n", __FILE__,__LINE__, - tty->driver->name ); + printk("%s(%d):mgslpc_set_termios %s\n", __FILE__, __LINE__, + tty->driver->name); /* just return if nothing has changed */ if ((tty->termios.c_cflag == old_termios->c_cflag) @@ -2309,23 +2308,23 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term /* Handle transition to B0 status */ if (old_termios->c_cflag & CBAUD && !(tty->termios.c_cflag & CBAUD)) { - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); + spin_lock_irqsave(&info->lock, flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock, flags); } /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && tty->termios.c_cflag & CBAUD) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!(tty->termios.c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { info->serial_signals |= SerialSignal_RTS; - } - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + } + spin_lock_irqsave(&info->lock, flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock, flags); } /* Handle turning off CRTSCTS */ @@ -2346,15 +2345,15 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", - __FILE__,__LINE__, info->device_name, port->count); + __FILE__, __LINE__, info->device_name, port->count); WARN_ON(!port->count); if (tty_port_close_start(port, tty, filp) == 0) goto cleanup; - if (port->flags & ASYNC_INITIALIZED) - mgslpc_wait_until_sent(tty, info->timeout); + if (port->flags & ASYNC_INITIALIZED) + mgslpc_wait_until_sent(tty, info->timeout); mgslpc_flush_buffer(tty); @@ -2365,7 +2364,7 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp) tty_port_tty_set(port, NULL); cleanup: if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__, + printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__, __LINE__, tty->driver->name, port->count); } @@ -2376,12 +2375,12 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; unsigned long orig_jiffies, char_time; - if (!info ) + if (!info) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_wait_until_sent(%s) entry\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent")) return; @@ -2397,8 +2396,8 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) * Note: use tight timings here to satisfy the NIST-PCTS. */ - if ( info->params.data_rate ) { - char_time = info->timeout/(32 * 5); + if (info->params.data_rate) { + char_time = info->timeout/(32 * 5); if (!char_time) char_time++; } else @@ -2429,7 +2428,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) exit: if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_wait_until_sent(%s) exit\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); } /* Called by tty_hangup() when a hangup is signaled. @@ -2441,7 +2440,7 @@ static void mgslpc_hangup(struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_hangup(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_hangup")) return; @@ -2456,9 +2455,9 @@ static int carrier_raised(struct tty_port *port) MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); unsigned long flags; - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); if (info->serial_signals & SerialSignal_DCD) return 1; @@ -2470,13 +2469,13 @@ static void dtr_rts(struct tty_port *port, int onoff) MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); unsigned long flags; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (onoff) - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + info->serial_signals |= SerialSignal_RTS | SerialSignal_DTR; else - info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR; + info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); } @@ -2484,14 +2483,14 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) { MGSLPC_INFO *info; struct tty_port *port; - int retval, line; - unsigned long flags; + int retval, line; + unsigned long flags; /* verify range of specified line number */ line = tty->index; if (line >= mgslpc_device_count) { printk("%s(%d):mgslpc_open with invalid line #%d.\n", - __FILE__,__LINE__,line); + __FILE__, __LINE__, line); return -ENODEV; } @@ -2508,7 +2507,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", - __FILE__,__LINE__,tty->driver->name, port->count); + __FILE__, __LINE__, tty->driver->name, port->count); /* If port is closing, signal caller to try again */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){ @@ -2519,7 +2518,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) goto cleanup; } - tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; spin_lock_irqsave(&info->netlock, flags); if (info->netcount) { @@ -2543,13 +2542,13 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) if (retval) { if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):block_til_ready(%s) returned %d\n", - __FILE__,__LINE__, info->device_name, retval); + __FILE__, __LINE__, info->device_name, retval); goto cleanup; } if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_open(%s) success\n", - __FILE__,__LINE__, info->device_name); + __FILE__, __LINE__, info->device_name); retval = 0; cleanup: @@ -2569,9 +2568,9 @@ static inline void line_info(struct seq_file *m, MGSLPC_INFO *info) info->device_name, info->io_base, info->irq_level); /* output current serial signal states */ - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); stat_buf[0] = 0; stat_buf[1] = 0; @@ -2633,7 +2632,7 @@ static int mgslpc_proc_show(struct seq_file *m, void *v) seq_printf(m, "synclink driver:%s\n", driver_version); info = mgslpc_device_list; - while( info ) { + while (info) { line_info(m, info); info = info->next_device; } @@ -2672,6 +2671,14 @@ static int rx_alloc_buffers(MGSLPC_INFO *info) if (info->rx_buf == NULL) return -ENOMEM; + /* unused flag buffer to satisfy receive_buf calling interface */ + info->flag_buf = kzalloc(info->max_frame_size, GFP_KERNEL); + if (!info->flag_buf) { + kfree(info->rx_buf); + info->rx_buf = NULL; + return -ENOMEM; + } + rx_reset_buffers(info); return 0; } @@ -2680,12 +2687,14 @@ static void rx_free_buffers(MGSLPC_INFO *info) { kfree(info->rx_buf); info->rx_buf = NULL; + kfree(info->flag_buf); + info->flag_buf = NULL; } static int claim_resources(MGSLPC_INFO *info) { - if (rx_alloc_buffers(info) < 0 ) { - printk( "Can't allocate rx buffer %s\n", info->device_name); + if (rx_alloc_buffers(info) < 0) { + printk("Can't allocate rx buffer %s\n", info->device_name); release_resources(info); return -ENODEV; } @@ -2704,8 +2713,12 @@ static void release_resources(MGSLPC_INFO *info) * * Arguments: info pointer to device instance data */ -static void mgslpc_add_device(MGSLPC_INFO *info) +static int mgslpc_add_device(MGSLPC_INFO *info) { + MGSLPC_INFO *current_dev = NULL; + struct device *tty_dev; + int ret; + info->next_device = NULL; info->line = mgslpc_device_count; sprintf(info->device_name,"ttySLP%d",info->line); @@ -2720,8 +2733,8 @@ static void mgslpc_add_device(MGSLPC_INFO *info) if (!mgslpc_device_list) mgslpc_device_list = info; else { - MGSLPC_INFO *current_dev = mgslpc_device_list; - while( current_dev->next_device ) + current_dev = mgslpc_device_list; + while (current_dev->next_device) current_dev = current_dev->next_device; current_dev->next_device = info; } @@ -2731,14 +2744,34 @@ static void mgslpc_add_device(MGSLPC_INFO *info) else if (info->max_frame_size > 65535) info->max_frame_size = 65535; - printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n", + printk("SyncLink PC Card %s:IO=%04X IRQ=%d\n", info->device_name, info->io_base, info->irq_level); #if SYNCLINK_GENERIC_HDLC - hdlcdev_init(info); + ret = hdlcdev_init(info); + if (ret != 0) + goto failed; #endif - tty_port_register_device(&info->port, serial_driver, info->line, + + tty_dev = tty_port_register_device(&info->port, serial_driver, info->line, &info->p_dev->dev); + if (IS_ERR(tty_dev)) { + ret = PTR_ERR(tty_dev); +#if SYNCLINK_GENERIC_HDLC + hdlcdev_exit(info); +#endif + goto failed; + } + + return 0; + +failed: + if (current_dev) + current_dev->next_device = NULL; + else + mgslpc_device_list = NULL; + mgslpc_device_count--; + return ret; } static void mgslpc_remove_device(MGSLPC_INFO *remove_info) @@ -2757,6 +2790,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info) hdlcdev_exit(info); #endif release_resources(info); + tty_port_destroy(&info->port); kfree(info); mgslpc_device_count--; return; @@ -3259,7 +3293,7 @@ static void rx_stop(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):rx_stop(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); /* MODE:03 RAC Receiver Active, 0=inactive */ clear_reg_bits(info, CHA + MODE, BIT3); @@ -3272,7 +3306,7 @@ static void rx_start(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):rx_start(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); rx_reset_buffers(info); info->rx_enabled = false; @@ -3288,7 +3322,7 @@ static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):tx_start(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); if (info->tx_count) { /* If auto RTS enabled and RTS is inactive, then assert */ @@ -3326,7 +3360,7 @@ static void tx_stop(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):tx_stop(%s)\n", - __FILE__,__LINE__, info->device_name ); + __FILE__, __LINE__, info->device_name); del_timer(&info->tx_timer); @@ -3572,8 +3606,8 @@ static void get_signals(MGSLPC_INFO *info) { unsigned char status = 0; - /* preserve DTR and RTS */ - info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS; + /* preserve RTS and DTR */ + info->serial_signals &= SerialSignal_RTS | SerialSignal_DTR; if (read_reg(info, CHB + VSTR) & BIT7) info->serial_signals |= SerialSignal_DCD; @@ -3587,7 +3621,7 @@ static void get_signals(MGSLPC_INFO *info) info->serial_signals |= SerialSignal_DSR; } -/* Set the state of DTR and RTS based on contents of +/* Set the state of RTS and DTR based on contents of * serial_signals member of device extension. */ static void set_signals(MGSLPC_INFO *info) @@ -3678,7 +3712,7 @@ static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty) if (debug_level >= DEBUG_LEVEL_BH) printk("%s(%d):rx_get_frame(%s) status=%04X size=%d\n", - __FILE__,__LINE__,info->device_name,status,framesize); + __FILE__, __LINE__, info->device_name, status, framesize); if (debug_level >= DEBUG_LEVEL_DATA) trace_block(info, buf->data, framesize, 0); @@ -3706,13 +3740,13 @@ static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty) } } - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); buf->status = buf->count = 0; info->rx_frame_count--; info->rx_get++; if (info->rx_get >= info->rx_buf_count) info->rx_get = 0; - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return true; } @@ -3726,7 +3760,7 @@ static bool register_test(MGSLPC_INFO *info) bool rc = true; unsigned long flags; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); reset_device(info); for (i = 0; i < count; i++) { @@ -3739,7 +3773,7 @@ static bool register_test(MGSLPC_INFO *info) } } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return rc; } @@ -3748,7 +3782,7 @@ static bool irq_test(MGSLPC_INFO *info) unsigned long end_time; unsigned long flags; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); reset_device(info); info->testing_irq = true; @@ -3762,7 +3796,7 @@ static bool irq_test(MGSLPC_INFO *info) write_reg(info, CHA + TIMR, 0); /* 512 cycles */ issue_command(info, CHA, CMD_START_TIMER); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); end_time=100; while(end_time-- && !info->irq_occurred) { @@ -3771,9 +3805,9 @@ static bool irq_test(MGSLPC_INFO *info) info->testing_irq = false; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); reset_device(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return info->irq_occurred; } @@ -3782,21 +3816,21 @@ static int adapter_test(MGSLPC_INFO *info) { if (!register_test(info)) { info->init_error = DiagStatus_AddressFailure; - printk( "%s(%d):Register test failure for device %s Addr=%04X\n", - __FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) ); + printk("%s(%d):Register test failure for device %s Addr=%04X\n", + __FILE__, __LINE__, info->device_name, (unsigned short)(info->io_base)); return -ENODEV; } if (!irq_test(info)) { info->init_error = DiagStatus_IrqFailure; - printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n", - __FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) ); + printk("%s(%d):Interrupt test failure for device %s IRQ=%d\n", + __FILE__, __LINE__, info->device_name, (unsigned short)(info->irq_level)); return -ENODEV; } if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):device %s passed diagnostics\n", - __FILE__,__LINE__,info->device_name); + __FILE__, __LINE__, info->device_name); return 0; } @@ -3805,9 +3839,9 @@ static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) int i; int linecount; if (xmit) - printk("%s tx data:\n",info->device_name); + printk("%s tx data:\n", info->device_name); else - printk("%s rx data:\n",info->device_name); + printk("%s rx data:\n", info->device_name); while(count) { if (count > 16) @@ -3816,12 +3850,12 @@ static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) linecount = count; for(i=0;i<linecount;i++) - printk("%02X ",(unsigned char)data[i]); + printk("%02X ", (unsigned char)data[i]); for(;i<17;i++) printk(" "); for(i=0;i<linecount;i++) { if (data[i]>=040 && data[i]<=0176) - printk("%c",data[i]); + printk("%c", data[i]); else printk("."); } @@ -3840,18 +3874,18 @@ static void tx_timeout(unsigned long context) MGSLPC_INFO *info = (MGSLPC_INFO*)context; unsigned long flags; - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):tx_timeout(%s)\n", - __FILE__,__LINE__,info->device_name); - if(info->tx_active && - info->params.mode == MGSL_MODE_HDLC) { + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):tx_timeout(%s)\n", + __FILE__, __LINE__, info->device_name); + if (info->tx_active && + info->params.mode == MGSL_MODE_HDLC) { info->icount.txtimeout++; } - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); info->tx_active = false; info->tx_count = info->tx_put = info->tx_get = 0; - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); #if SYNCLINK_GENERIC_HDLC if (info->netcount) @@ -3933,7 +3967,7 @@ static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + printk(KERN_INFO "%s:hdlc_xmit(%s)\n", __FILE__, dev->name); /* stop sending until this frame completes */ netif_stop_queue(dev); @@ -3954,13 +3988,13 @@ static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, dev->trans_start = jiffies; /* start hardware transmitter if necessary */ - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); if (!info->tx_active) { struct tty_struct *tty = tty_port_tty_get(&info->port); - tx_start(info, tty); - tty_kref_put(tty); + tx_start(info, tty); + tty_kref_put(tty); } - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); return NETDEV_TX_OK; } @@ -3981,10 +4015,11 @@ static int hdlcdev_open(struct net_device *dev) unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + printk("%s:hdlcdev_open(%s)\n", __FILE__, dev->name); /* generic HDLC layer open processing */ - if ((rc = hdlc_open(dev))) + rc = hdlc_open(dev); + if (rc != 0) return rc; /* arbitrate between network and tty opens */ @@ -3999,15 +4034,16 @@ static int hdlcdev_open(struct net_device *dev) tty = tty_port_tty_get(&info->port); /* claim resources and init adapter */ - if ((rc = startup(info, tty)) != 0) { + rc = startup(info, tty); + if (rc != 0) { tty_kref_put(tty); spin_lock_irqsave(&info->netlock, flags); info->netcount=0; spin_unlock_irqrestore(&info->netlock, flags); return rc; } - /* assert DTR and RTS, apply hardware settings */ - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + /* assert RTS and DTR, apply hardware settings */ + info->serial_signals |= SerialSignal_RTS | SerialSignal_DTR; mgslpc_program_hw(info, tty); tty_kref_put(tty); @@ -4041,7 +4077,7 @@ static int hdlcdev_close(struct net_device *dev) unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); + printk("%s:hdlcdev_close(%s)\n", __FILE__, dev->name); netif_stop_queue(dev); @@ -4075,7 +4111,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); + printk("%s:hdlcdev_ioctl(%s)\n", __FILE__, dev->name); /* return error if TTY interface open */ if (info->port.count) @@ -4176,14 +4212,14 @@ static void hdlcdev_tx_timeout(struct net_device *dev) unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("hdlcdev_tx_timeout(%s)\n",dev->name); + printk("hdlcdev_tx_timeout(%s)\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; - spin_lock_irqsave(&info->lock,flags); + spin_lock_irqsave(&info->lock, flags); tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); + spin_unlock_irqrestore(&info->lock, flags); netif_wake_queue(dev); } @@ -4214,7 +4250,7 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) struct net_device *dev = info->netdev; if (debug_level >= DEBUG_LEVEL_INFO) - printk("hdlcdev_rx(%s)\n",dev->name); + printk("hdlcdev_rx(%s)\n", dev->name); if (skb == NULL) { printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); @@ -4257,8 +4293,9 @@ static int hdlcdev_init(MGSLPC_INFO *info) /* allocate and initialize network and HDLC layer objects */ - if (!(dev = alloc_hdlcdev(info))) { - printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + dev = alloc_hdlcdev(info); + if (dev == NULL) { + printk(KERN_ERR "%s:hdlc device allocation failure\n", __FILE__); return -ENOMEM; } @@ -4277,8 +4314,9 @@ static int hdlcdev_init(MGSLPC_INFO *info) hdlc->xmit = hdlcdev_xmit; /* register objects with HDLC layer */ - if ((rc = register_hdlc_device(dev))) { - printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + rc = register_hdlc_device(dev); + if (rc) { + printk(KERN_WARNING "%s:unable to register hdlc device\n", __FILE__); free_netdev(dev); return rc; } diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index d0d824ebf2c1..ae0b42b66e55 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -107,7 +107,7 @@ static inline void pp_enable_irq (struct pp_struct *pp) static ssize_t pp_read (struct file * file, char __user * buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_path.dentry->d_inode); + unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_read = 0; @@ -189,7 +189,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, static ssize_t pp_write (struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_path.dentry->d_inode); + unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_written = 0; @@ -251,12 +251,8 @@ static ssize_t pp_write (struct file * file, const char __user * buf, break; } - if (signal_pending (current)) { - if (!bytes_written) { - bytes_written = -EINTR; - } + if (signal_pending (current)) break; - } cond_resched(); } @@ -328,7 +324,7 @@ static enum ieee1284_phase init_phase (int mode) static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - unsigned int minor = iminor(file->f_path.dentry->d_inode); + unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; struct parport * port; void __user *argp = (void __user *)arg; diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c index 6abdde4da2b7..8cafa9ccd43f 100644 --- a/drivers/char/ps3flash.c +++ b/drivers/char/ps3flash.c @@ -312,7 +312,7 @@ static int ps3flash_flush(struct file *file, fl_owner_t id) static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file_inode(file); int err; mutex_lock(&inode->i_mutex); err = ps3flash_writeback(ps3flash_dev); @@ -363,7 +363,7 @@ static struct miscdevice ps3flash_misc = { .fops = &ps3flash_fops, }; -static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) +static int ps3flash_probe(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); struct ps3flash_private *priv; diff --git a/drivers/char/random.c b/drivers/char/random.c index b86eae9b77df..32a6c5764950 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -399,7 +399,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); static struct fasync_struct *fasync; -#if 0 static bool debug; module_param(debug, bool, 0644); #define DEBUG_ENT(fmt, arg...) do { \ @@ -410,9 +409,6 @@ module_param(debug, bool, 0644); blocking_pool.entropy_count,\ nonblocking_pool.entropy_count,\ ## arg); } while (0) -#else -#define DEBUG_ENT(fmt, arg...) do {} while (0) -#endif /********************************************************************** * @@ -437,6 +433,7 @@ struct entropy_store { int entropy_count; int entropy_total; unsigned int initialized:1; + bool last_data_init; __u8 last_data[EXTRACT_SIZE]; }; @@ -448,7 +445,7 @@ static struct entropy_store input_pool = { .poolinfo = &poolinfo_table[0], .name = "input", .limit = 1, - .lock = __SPIN_LOCK_UNLOCKED(&input_pool.lock), + .lock = __SPIN_LOCK_UNLOCKED(input_pool.lock), .pool = input_pool_data }; @@ -457,7 +454,7 @@ static struct entropy_store blocking_pool = { .name = "blocking", .limit = 1, .pull = &input_pool, - .lock = __SPIN_LOCK_UNLOCKED(&blocking_pool.lock), + .lock = __SPIN_LOCK_UNLOCKED(blocking_pool.lock), .pool = blocking_pool_data }; @@ -465,7 +462,7 @@ static struct entropy_store nonblocking_pool = { .poolinfo = &poolinfo_table[1], .name = "nonblocking", .pull = &input_pool, - .lock = __SPIN_LOCK_UNLOCKED(&nonblocking_pool.lock), + .lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock), .pool = nonblocking_pool_data }; @@ -829,7 +826,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) bytes = min_t(int, bytes, sizeof(tmp)); DEBUG_ENT("going to reseed %s with %d bits " - "(%d of %d requested)\n", + "(%zu of %d requested)\n", r->name, bytes * 8, nbytes * 8, r->entropy_count); bytes = extract_entropy(r->pull, tmp, bytes, @@ -855,12 +852,13 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, int reserved) { unsigned long flags; + int wakeup_write = 0; /* Hold lock while accounting */ spin_lock_irqsave(&r->lock, flags); BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); - DEBUG_ENT("trying to extract %d bits from %s\n", + DEBUG_ENT("trying to extract %zu bits from %s\n", nbytes * 8, r->name); /* Can we pull enough? */ @@ -876,17 +874,20 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, else r->entropy_count = reserved; - if (r->entropy_count < random_write_wakeup_thresh) { - wake_up_interruptible(&random_write_wait); - kill_fasync(&fasync, SIGIO, POLL_OUT); - } + if (r->entropy_count < random_write_wakeup_thresh) + wakeup_write = 1; } - DEBUG_ENT("debiting %d entropy credits from %s%s\n", + DEBUG_ENT("debiting %zu entropy credits from %s%s\n", nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); spin_unlock_irqrestore(&r->lock, flags); + if (wakeup_write) { + wake_up_interruptible(&random_write_wait); + kill_fasync(&fasync, SIGIO, POLL_OUT); + } + return nbytes; } @@ -957,6 +958,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; + /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ + if (fips_enabled && !r->last_data_init) + nbytes += EXTRACT_SIZE; + trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); @@ -967,6 +972,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, if (fips_enabled) { unsigned long flags; + + /* prime last_data value if need be, per fips 140-2 */ + if (!r->last_data_init) { + spin_lock_irqsave(&r->lock, flags); + memcpy(r->last_data, tmp, EXTRACT_SIZE); + r->last_data_init = true; + nbytes -= EXTRACT_SIZE; + spin_unlock_irqrestore(&r->lock, flags); + extract_buf(r, tmp); + } + spin_lock_irqsave(&r->lock, flags); if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) panic("Hardware RNG duplicated output!\n"); @@ -1086,6 +1102,7 @@ static void init_std_data(struct entropy_store *r) r->entropy_count = 0; r->entropy_total = 0; + r->last_data_init = false; mix_pool_bytes(r, &now, sizeof(now), NULL); for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { if (!arch_get_random_long(&rv)) @@ -1142,11 +1159,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) if (n > SEC_XFER_SIZE) n = SEC_XFER_SIZE; - DEBUG_ENT("reading %d bits\n", n*8); + DEBUG_ENT("reading %zu bits\n", n*8); n = extract_entropy_user(&blocking_pool, buf, n); - DEBUG_ENT("read got %d bits (%d still needed)\n", + if (n < 0) { + retval = n; + break; + } + + DEBUG_ENT("read got %zd bits (%zd still needed)\n", n*8, (nbytes-n)*8); if (n == 0) { @@ -1171,10 +1193,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) continue; } - if (n < 0) { - retval = n; - break; - } count += n; buf += n; nbytes -= n; diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 0bb207eaef2f..f3223aac4df1 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -80,7 +80,7 @@ static int raw_open(struct inode *inode, struct file *filp) filp->f_flags |= O_DIRECT; filp->f_mapping = bdev->bd_inode->i_mapping; if (++raw_devices[minor].inuse == 1) - filp->f_path.dentry->d_inode->i_mapping = + file_inode(filp)->i_mapping = bdev->bd_inode->i_mapping; filp->private_data = bdev; mutex_unlock(&raw_mutex); @@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, static const struct file_operations raw_fops = { .read = do_sync_read, - .aio_read = blkdev_aio_read, + .aio_read = generic_file_aio_read, .write = do_sync_write, .aio_write = blkdev_aio_write, .fsync = blkdev_fsync, diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 9b4f0116ff21..bf2349dbbf7f 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -938,7 +938,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, } if (ret > 0) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file_inode(file); inode->i_atime = current_fs_time(inode->i_sb); } @@ -1142,7 +1142,7 @@ static int sonypi_acpi_add(struct acpi_device *device) return 0; } -static int sonypi_acpi_remove(struct acpi_device *device, int type) +static int sonypi_acpi_remove(struct acpi_device *device) { sonypi_acpi_device = NULL; return 0; @@ -1164,7 +1164,7 @@ static struct acpi_driver sonypi_acpi_driver = { }; #endif -static int __devinit sonypi_create_input_devices(struct platform_device *pdev) +static int sonypi_create_input_devices(struct platform_device *pdev) { struct input_dev *jog_dev; struct input_dev *key_dev; @@ -1225,7 +1225,7 @@ static int __devinit sonypi_create_input_devices(struct platform_device *pdev) return error; } -static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, +static int sonypi_setup_ioports(struct sonypi_device *dev, const struct sonypi_ioport_list *ioport_list) { /* try to detect if sony-laptop is being used and thus @@ -1265,7 +1265,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, return -EBUSY; } -static int __devinit sonypi_setup_irq(struct sonypi_device *dev, +static int sonypi_setup_irq(struct sonypi_device *dev, const struct sonypi_irq_list *irq_list) { while (irq_list->irq) { @@ -1282,7 +1282,7 @@ static int __devinit sonypi_setup_irq(struct sonypi_device *dev, return -EBUSY; } -static void __devinit sonypi_display_info(void) +static void sonypi_display_info(void) { printk(KERN_INFO "sonypi: detected type%d model, " "verbose = %d, fnkeyinit = %s, camera = %s, " @@ -1304,7 +1304,7 @@ static void __devinit sonypi_display_info(void) sonypi_misc_device.minor); } -static int __devinit sonypi_probe(struct platform_device *dev) +static int sonypi_probe(struct platform_device *dev) { const struct sonypi_ioport_list *ioport_list; const struct sonypi_irq_list *irq_list; @@ -1428,7 +1428,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) return error; } -static int __devexit sonypi_remove(struct platform_device *dev) +static int sonypi_remove(struct platform_device *dev) { sonypi_disable(); @@ -1491,7 +1491,7 @@ static struct platform_driver sonypi_driver = { .pm = SONYPI_PM, }, .probe = sonypi_probe, - .remove = __devexit_p(sonypi_remove), + .remove = sonypi_remove, .shutdown = sonypi_shutdown, }; diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index ad264185eb10..47b9fdfcf083 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c @@ -164,7 +164,7 @@ static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t le unsigned int minor; char value; - minor = iminor(file->f_path.dentry->d_inode); + minor = iminor(file_inode(file)); switch (minor) { case 0: value = get_led(); @@ -200,7 +200,7 @@ static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data, int retval = 0; char c; - minor = iminor(file->f_path.dentry->d_inode); + minor = iminor(file_inode(file)); switch (minor) { case 0: type = TYPE_LED; @@ -284,7 +284,7 @@ static void tb0219_pci_irq_init(void) vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW); } -static int __devinit tb0219_probe(struct platform_device *dev) +static int tb0219_probe(struct platform_device *dev) { int retval; @@ -318,7 +318,7 @@ static int __devinit tb0219_probe(struct platform_device *dev) return 0; } -static int __devexit tb0219_remove(struct platform_device *dev) +static int tb0219_remove(struct platform_device *dev) { _machine_restart = old_machine_restart; @@ -334,7 +334,7 @@ static struct platform_device *tb0219_platform_device; static struct platform_driver tb0219_device_driver = { .probe = tb0219_probe, - .remove = __devexit_p(tb0219_remove), + .remove = tb0219_remove, .driver = { .name = "TB0219", .owner = THIS_MODULE, diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 915875e431d2..dbfd56446c31 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -75,10 +75,20 @@ config TCG_INFINEON config TCG_IBMVTPM tristate "IBM VTPM Interface" - depends on PPC64 + depends on PPC_PSERIES ---help--- If you have IBM virtual TPM (VTPM) support say Yes and it will be accessible from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_ibmvtpm. +config TCG_ST33_I2C + tristate "STMicroelectronics ST33 I2C TPM" + depends on I2C + depends on GPIOLIB + ---help--- + If you have a TPM security chip from STMicroelectronics working with + an I2C bus say Yes and it will be accessible from within Linux. + To compile this driver as a module, choose M here; the module will be + called tpm_stm_st33_i2c. + endif # TCG_TPM diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 5b3fc8bc6c13..a3736c97c65a 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_TCG_NSC) += tpm_nsc.o obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o +obj-$(CONFIG_TCG_ST33_I2C) += tpm_i2c_stm_st33.o diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 93211df52aab..0d2e82f95577 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -40,8 +40,9 @@ enum tpm_duration { }; #define TPM_MAX_ORDINAL 243 -#define TPM_MAX_PROTECTED_ORDINAL 12 -#define TPM_PROTECTED_ORDINAL_MASK 0xFF +#define TSC_MAX_ORDINAL 12 +#define TPM_PROTECTED_COMMAND 0x00 +#define TPM_CONNECTION_COMMAND 0x40 /* * Bug workaround - some TPM's don't flush the most @@ -65,21 +66,6 @@ static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); * values of the SHORT, MEDIUM, and LONG durations are retrieved * from the chip during initialization with a call to tpm_get_timeouts. */ -static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { - TPM_UNDEFINED, /* 0 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 5 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 10 */ - TPM_SHORT, -}; - static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { TPM_UNDEFINED, /* 0 */ TPM_UNDEFINED, @@ -351,14 +337,11 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, { int duration_idx = TPM_UNDEFINED; int duration = 0; + u8 category = (ordinal >> 24) & 0xFF; - if (ordinal < TPM_MAX_ORDINAL) + if ((category == TPM_PROTECTED_COMMAND && ordinal < TPM_MAX_ORDINAL) || + (category == TPM_CONNECTION_COMMAND && ordinal < TSC_MAX_ORDINAL)) duration_idx = tpm_ordinal_duration[ordinal]; - else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < - TPM_MAX_PROTECTED_ORDINAL) - duration_idx = - tpm_protected_ordinal_duration[ordinal & - TPM_PROTECTED_ORDINAL_MASK]; if (duration_idx != TPM_UNDEFINED) duration = chip->vendor.duration[duration_idx]; @@ -410,7 +393,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, chip->vendor.req_complete_val) goto out_recv; - if ((status == chip->vendor.req_canceled)) { + if (chip->vendor.req_canceled(chip, status)) { dev_err(chip->dev, "Operation Canceled\n"); rc = -ECANCELED; goto out; @@ -468,7 +451,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, return -EFAULT; err = be32_to_cpu(cmd->header.out.return_code); - if (err != 0) + if (err != 0 && desc) dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); return err; @@ -528,6 +511,25 @@ void tpm_gen_interrupt(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_gen_interrupt); +#define TPM_ORD_STARTUP cpu_to_be32(153) +#define TPM_ST_CLEAR cpu_to_be16(1) +#define TPM_ST_STATE cpu_to_be16(2) +#define TPM_ST_DEACTIVATED cpu_to_be16(3) +static const struct tpm_input_header tpm_startup_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(12), + .ordinal = TPM_ORD_STARTUP +}; + +static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) +{ + struct tpm_cmd_t start_cmd; + start_cmd.header.in = tpm_startup_header; + start_cmd.params.startup_in.startup_type = startup_type; + return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, + "attempting to start the TPM"); +} + int tpm_get_timeouts(struct tpm_chip *chip) { struct tpm_cmd_t tpm_cmd; @@ -541,11 +543,28 @@ int tpm_get_timeouts(struct tpm_chip *chip) tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); - rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the timeouts"); - if (rc) + if (rc == TPM_ERR_INVALID_POSTINIT) { + /* The TPM is not started, we are the first to talk to it. + Execute a startup command. */ + dev_info(chip->dev, "Issuing TPM_STARTUP"); + if (tpm_startup(chip, TPM_ST_CLEAR)) + return rc; + + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, + NULL); + } + if (rc) { + dev_err(chip->dev, + "A TPM error (%zd) occurred attempting to determine the timeouts\n", + rc); goto duration; + } if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) @@ -824,7 +843,7 @@ int tpm_do_selftest(struct tpm_chip *chip) { int rc; unsigned int loops; - unsigned int delay_msec = 1000; + unsigned int delay_msec = 100; unsigned long duration; struct tpm_cmd_t cmd; @@ -845,6 +864,14 @@ int tpm_do_selftest(struct tpm_chip *chip) cmd.header.in = pcrread_header; cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); + /* Some buggy TPMs will not respond to tpm_tis_ready() for + * around 300ms while the self test is ongoing, keep trying + * until the self test duration expires. */ + if (rc == -ETIME) { + dev_info(chip->dev, HW_ERR "TPM command timed out during continue self test"); + msleep(delay_msec); + continue; + } if (rc < TPM_HEADER_SIZE) return -EFAULT; @@ -1075,12 +1102,28 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, } EXPORT_SYMBOL_GPL(tpm_store_cancel); +static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, bool check_cancel, + bool *canceled) +{ + u8 status = chip->vendor.status(chip); + + *canceled = false; + if ((status & mask) == mask) + return true; + if (check_cancel && chip->vendor.req_canceled(chip, status)) { + *canceled = true; + return true; + } + return false; +} + int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - wait_queue_head_t *queue) + wait_queue_head_t *queue, bool check_cancel) { unsigned long stop; long rc; u8 status; + bool canceled = false; /* check current status */ status = chip->vendor.status(chip); @@ -1095,11 +1138,14 @@ again: if ((long)timeout <= 0) return -ETIME; rc = wait_event_interruptible_timeout(*queue, - ((chip->vendor.status(chip) - & mask) == mask), - timeout); - if (rc > 0) + wait_for_tpm_stat_cond(chip, mask, check_cancel, + &canceled), + timeout); + if (rc > 0) { + if (canceled) + return -ECANCELED; return 0; + } if (rc == -ERESTARTSYS && freezing(current)) { clear_thread_flag(TIF_SIGPENDING); goto again; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8ef7649a50aa..81b52015f669 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -47,6 +47,7 @@ enum tpm_addr { #define TPM_WARN_DOING_SELFTEST 0x802 #define TPM_ERR_DEACTIVATED 0x6 #define TPM_ERR_DISABLED 0x7 +#define TPM_ERR_INVALID_POSTINIT 38 #define TPM_HEADER_SIZE 10 extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, @@ -77,7 +78,7 @@ struct tpm_chip; struct tpm_vendor_specific { const u8 req_complete_mask; const u8 req_complete_val; - const u8 req_canceled; + bool (*req_canceled)(struct tpm_chip *chip, u8 status); void __iomem *iobase; /* ioremapped address */ unsigned long base; /* TPM base address */ @@ -100,13 +101,19 @@ struct tpm_vendor_specific { bool timeout_adjusted; unsigned long duration[3]; /* jiffies */ bool duration_adjusted; - void *data; + void *priv; wait_queue_head_t read_queue; wait_queue_head_t int_queue; + + u16 manufacturer_id; }; +#define TPM_VPRIV(c) (c)->vendor.priv + #define TPM_VID_INTEL 0x8086 +#define TPM_VID_WINBOND 0x1050 +#define TPM_VID_STM 0x104A struct tpm_chip { struct device *dev; /* Device stuff */ @@ -154,13 +161,13 @@ struct tpm_input_header { __be16 tag; __be32 length; __be32 ordinal; -}__attribute__((packed)); +} __packed; struct tpm_output_header { __be16 tag; __be32 length; __be32 return_code; -}__attribute__((packed)); +} __packed; struct stclear_flags_t { __be16 tag; @@ -169,14 +176,14 @@ struct stclear_flags_t { u8 physicalPresence; u8 physicalPresenceLock; u8 bGlobalLock; -}__attribute__((packed)); +} __packed; struct tpm_version_t { u8 Major; u8 Minor; u8 revMajor; u8 revMinor; -}__attribute__((packed)); +} __packed; struct tpm_version_1_2_t { __be16 tag; @@ -184,20 +191,20 @@ struct tpm_version_1_2_t { u8 Minor; u8 revMajor; u8 revMinor; -}__attribute__((packed)); +} __packed; struct timeout_t { __be32 a; __be32 b; __be32 c; __be32 d; -}__attribute__((packed)); +} __packed; struct duration_t { __be32 tpm_short; __be32 tpm_medium; __be32 tpm_long; -}__attribute__((packed)); +} __packed; struct permanent_flags_t { __be16 tag; @@ -221,7 +228,7 @@ struct permanent_flags_t { u8 tpmEstablished; u8 maintenanceDone; u8 disableFullDALogicInfo; -}__attribute__((packed)); +} __packed; typedef union { struct permanent_flags_t perm_flags; @@ -239,12 +246,12 @@ struct tpm_getcap_params_in { __be32 cap; __be32 subcap_size; __be32 subcap; -}__attribute__((packed)); +} __packed; struct tpm_getcap_params_out { __be32 cap_size; cap_t cap; -}__attribute__((packed)); +} __packed; struct tpm_readpubek_params_out { u8 algorithm[4]; @@ -255,7 +262,7 @@ struct tpm_readpubek_params_out { __be32 keysize; u8 modulus[256]; u8 checksum[20]; -}__attribute__((packed)); +} __packed; typedef union { struct tpm_input_header in; @@ -265,16 +272,16 @@ typedef union { #define TPM_DIGEST_SIZE 20 struct tpm_pcrread_out { u8 pcr_result[TPM_DIGEST_SIZE]; -}__attribute__((packed)); +} __packed; struct tpm_pcrread_in { __be32 pcr_idx; -}__attribute__((packed)); +} __packed; struct tpm_pcrextend_in { __be32 pcr_idx; u8 hash[TPM_DIGEST_SIZE]; -}__attribute__((packed)); +} __packed; /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 * bytes, but 128 is still a relatively large number of random bytes and @@ -285,11 +292,15 @@ struct tpm_pcrextend_in { struct tpm_getrandom_out { __be32 rng_data_len; u8 rng_data[TPM_MAX_RNG_DATA]; -}__attribute__((packed)); +} __packed; struct tpm_getrandom_in { __be32 num_bytes; -}__attribute__((packed)); +} __packed; + +struct tpm_startup_in { + __be16 startup_type; +} __packed; typedef union { struct tpm_getcap_params_out getcap_out; @@ -301,12 +312,13 @@ typedef union { struct tpm_pcrextend_in pcrextend_in; struct tpm_getrandom_in getrandom_in; struct tpm_getrandom_out getrandom_out; + struct tpm_startup_in startup_in; } tpm_cmd_params; struct tpm_cmd_t { tpm_cmd_header header; tpm_cmd_params params; -}__attribute__((packed)); +} __packed; ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); @@ -326,7 +338,7 @@ extern void tpm_remove_hardware(struct device *); extern int tpm_pm_suspend(struct device *); extern int tpm_pm_resume(struct device *); extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, - wait_queue_head_t *); + wait_queue_head_t *, bool); #ifdef CONFIG_ACPI extern int tpm_add_ppi(struct kobject *); diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c index 56051d0c97a2..64420b3396a2 100644 --- a/drivers/char/tpm/tpm_acpi.c +++ b/drivers/char/tpm/tpm_acpi.c @@ -33,13 +33,13 @@ struct acpi_tcpa { u16 platform_class; union { struct client_hdr { - u32 log_max_len __attribute__ ((packed)); - u64 log_start_addr __attribute__ ((packed)); + u32 log_max_len __packed; + u64 log_start_addr __packed; } client; struct server_hdr { u16 reserved; - u64 log_max_len __attribute__ ((packed)); - u64 log_start_addr __attribute__ ((packed)); + u64 log_max_len __packed; + u64 log_start_addr __packed; } server; }; }; diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 678d57019dc4..99d6820c611d 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -116,6 +116,11 @@ static u8 tpm_atml_status(struct tpm_chip *chip) return ioread8(chip->vendor.iobase + 1); } +static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status) +{ + return (status == ATML_STATUS_READY); +} + static const struct file_operations atmel_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -147,7 +152,7 @@ static const struct tpm_vendor_specific tpm_atmel = { .status = tpm_atml_status, .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, .req_complete_val = ATML_STATUS_DATA_AVAIL, - .req_canceled = ATML_STATUS_READY, + .req_canceled = tpm_atml_req_canceled, .attr_group = &atmel_attr_grp, .miscdev = { .fops = &atmel_ops, }, }; diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 5a831aec9d4b..8fe7ac3d095b 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -505,6 +505,11 @@ out_err: return rc; } +static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status) +{ + return (status == TPM_STS_COMMAND_READY); +} + static const struct file_operations tis_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -550,12 +555,12 @@ static struct tpm_vendor_specific tpm_tis_i2c = { .cancel = tpm_tis_i2c_ready, .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, - .req_canceled = TPM_STS_COMMAND_READY, + .req_canceled = tpm_tis_i2c_req_canceled, .attr_group = &tis_attr_grp, .miscdev.fops = &tis_ops, }; -static int __devinit tpm_tis_i2c_init(struct device *dev) +static int tpm_tis_i2c_init(struct device *dev) { u32 vendor; int rc = 0; @@ -632,7 +637,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = { MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); -static int __devinit tpm_tis_i2c_probe(struct i2c_client *client, +static int tpm_tis_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc; @@ -656,7 +661,7 @@ static int __devinit tpm_tis_i2c_probe(struct i2c_client *client, return rc; } -static int __devexit tpm_tis_i2c_remove(struct i2c_client *client) +static int tpm_tis_i2c_remove(struct i2c_client *client) { struct tpm_chip *chip = tpm_dev.chip; release_locality(chip, chip->vendor.locality, 1); diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c new file mode 100644 index 000000000000..1f5f71e14abe --- /dev/null +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c @@ -0,0 +1,887 @@ +/* + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 + * Copyright (C) 2009, 2010 STMicroelectronics + * + * 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) any 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * STMicroelectronics version 1.2.0, Copyright (C) 2010 + * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. + * This is free software, and you are welcome to redistribute it + * under certain conditions. + * + * @Author: Christophe RICARD tpmsupport@st.com + * + * @File: tpm_stm_st33_i2c.c + * + * @Synopsis: + * 09/15/2010: First shot driver tpm_tis driver for + lpc is used as model. + */ + +#include <linux/pci.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/wait.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/sysfs.h> +#include <linux/gpio.h> +#include <linux/sched.h> +#include <linux/uaccess.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/sched.h> + +#include "tpm.h" +#include "tpm_i2c_stm_st33.h" + +enum stm33zp24_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum stm33zp24_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +enum stm33zp24_int_flags { + TPM_GLOBAL_INT_ENABLE = 0x80, + TPM_INTF_CMD_READY_INT = 0x080, + TPM_INTF_FIFO_AVALAIBLE_INT = 0x040, + TPM_INTF_WAKE_UP_READY_INT = 0x020, + TPM_INTF_LOCALITY_CHANGE_INT = 0x004, + TPM_INTF_STS_VALID_INT = 0x002, + TPM_INTF_DATA_AVAIL_INT = 0x001, +}; + +enum tis_defaults { + TIS_SHORT_TIMEOUT = 750, + TIS_LONG_TIMEOUT = 2000, +}; + +/* + * write8_reg + * Send byte to the TIS register according to the ST33ZP24 I2C protocol. + * @param: tpm_register, the tpm tis register where the data should be written + * @param: tpm_data, the tpm_data to write inside the tpm_register + * @param: tpm_size, The length of the data + * @return: Returns negative errno, or else the number of bytes written. + */ +static int write8_reg(struct i2c_client *client, u8 tpm_register, + u8 *tpm_data, u16 tpm_size) +{ + struct st33zp24_platform_data *pin_infos; + + pin_infos = client->dev.platform_data; + + pin_infos->tpm_i2c_buffer[0][0] = tpm_register; + memcpy(&pin_infos->tpm_i2c_buffer[0][1], tpm_data, tpm_size); + return i2c_master_send(client, pin_infos->tpm_i2c_buffer[0], + tpm_size + 1); +} /* write8_reg() */ + +/* + * read8_reg + * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. + * @param: tpm_register, the tpm tis register where the data should be read + * @param: tpm_data, the TPM response + * @param: tpm_size, tpm TPM response size to read. + * @return: number of byte read successfully: should be one if success. + */ +static int read8_reg(struct i2c_client *client, u8 tpm_register, + u8 *tpm_data, int tpm_size) +{ + u8 status = 0; + u8 data; + + data = TPM_DUMMY_BYTE; + status = write8_reg(client, tpm_register, &data, 1); + if (status == 2) + status = i2c_master_recv(client, tpm_data, tpm_size); + return status; +} /* read8_reg() */ + +/* + * I2C_WRITE_DATA + * Send byte to the TIS register according to the ST33ZP24 I2C protocol. + * @param: client, the chip description + * @param: tpm_register, the tpm tis register where the data should be written + * @param: tpm_data, the tpm_data to write inside the tpm_register + * @param: tpm_size, The length of the data + * @return: number of byte written successfully: should be one if success. + */ +#define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \ + (write8_reg(client, tpm_register | \ + TPM_WRITE_DIRECTION, tpm_data, tpm_size)) + +/* + * I2C_READ_DATA + * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. + * @param: tpm, the chip description + * @param: tpm_register, the tpm tis register where the data should be read + * @param: tpm_data, the TPM response + * @param: tpm_size, tpm TPM response size to read. + * @return: number of byte read successfully: should be one if success. + */ +#define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \ + (read8_reg(client, tpm_register, tpm_data, tpm_size)) + +/* + * clear_interruption + * clear the TPM interrupt register. + * @param: tpm, the chip description + */ +static void clear_interruption(struct i2c_client *client) +{ + u8 interrupt; + I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1); + I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1); + I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1); +} /* clear_interruption() */ + +/* + * _wait_for_interrupt_serirq_timeout + * @param: tpm, the chip description + * @param: timeout, the timeout of the interrupt + * @return: the status of the interruption. + */ +static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip, + unsigned long timeout) +{ + long status; + struct i2c_client *client; + struct st33zp24_platform_data *pin_infos; + + client = (struct i2c_client *) TPM_VPRIV(chip); + pin_infos = client->dev.platform_data; + + status = wait_for_completion_interruptible_timeout( + &pin_infos->irq_detection, + timeout); + if (status > 0) + enable_irq(gpio_to_irq(pin_infos->io_serirq)); + gpio_direction_input(pin_infos->io_serirq); + + return status; +} /* wait_for_interrupt_serirq_timeout() */ + +static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition, + unsigned long timeout) +{ + int status = 2; + struct i2c_client *client; + + client = (struct i2c_client *) TPM_VPRIV(chip); + + status = _wait_for_interrupt_serirq_timeout(chip, timeout); + if (!status) { + status = -EBUSY; + } else{ + clear_interruption(client); + if (condition) + status = 1; + } + return status; +} + +/* + * tpm_stm_i2c_cancel, cancel is not implemented. + * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h + */ +static void tpm_stm_i2c_cancel(struct tpm_chip *chip) +{ + struct i2c_client *client; + u8 data; + + client = (struct i2c_client *) TPM_VPRIV(chip); + + data = TPM_STS_COMMAND_READY; + I2C_WRITE_DATA(client, TPM_STS, &data, 1); + if (chip->vendor.irq) + wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a); +} /* tpm_stm_i2c_cancel() */ + +/* + * tpm_stm_spi_status return the TPM_STS register + * @param: chip, the tpm chip description + * @return: the TPM_STS register value. + */ +static u8 tpm_stm_i2c_status(struct tpm_chip *chip) +{ + struct i2c_client *client; + u8 data; + client = (struct i2c_client *) TPM_VPRIV(chip); + + I2C_READ_DATA(client, TPM_STS, &data, 1); + return data; +} /* tpm_stm_i2c_status() */ + + +/* + * check_locality if the locality is active + * @param: chip, the tpm chip description + * @return: the active locality or -EACCESS. + */ +static int check_locality(struct tpm_chip *chip) +{ + struct i2c_client *client; + u8 data; + u8 status; + + client = (struct i2c_client *) TPM_VPRIV(chip); + + status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1); + if (status && (data & + (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == + (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) + return chip->vendor.locality; + + return -EACCES; + +} /* check_locality() */ + +/* + * request_locality request the TPM locality + * @param: chip, the chip description + * @return: the active locality or EACCESS. + */ +static int request_locality(struct tpm_chip *chip) +{ + unsigned long stop; + long rc; + struct i2c_client *client; + u8 data; + + client = (struct i2c_client *) TPM_VPRIV(chip); + + if (check_locality(chip) == chip->vendor.locality) + return chip->vendor.locality; + + data = TPM_ACCESS_REQUEST_USE; + rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); + if (rc < 0) + goto end; + + if (chip->vendor.irq) { + rc = wait_for_serirq_timeout(chip, (check_locality + (chip) >= 0), + chip->vendor.timeout_a); + if (rc > 0) + return chip->vendor.locality; + } else{ + stop = jiffies + chip->vendor.timeout_a; + do { + if (check_locality(chip) >= 0) + return chip->vendor.locality; + msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + } + rc = -EACCES; +end: + return rc; +} /* request_locality() */ + +/* + * release_locality release the active locality + * @param: chip, the tpm chip description. + */ +static void release_locality(struct tpm_chip *chip) +{ + struct i2c_client *client; + u8 data; + + client = (struct i2c_client *) TPM_VPRIV(chip); + data = TPM_ACCESS_ACTIVE_LOCALITY; + + I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); +} + +/* + * get_burstcount return the burstcount address 0x19 0x1A + * @param: chip, the chip description + * return: the burstcount. + */ +static int get_burstcount(struct tpm_chip *chip) +{ + unsigned long stop; + int burstcnt, status; + u8 tpm_reg, temp; + + struct i2c_client *client = (struct i2c_client *) TPM_VPRIV(chip); + + stop = jiffies + chip->vendor.timeout_d; + do { + tpm_reg = TPM_STS + 1; + status = I2C_READ_DATA(client, tpm_reg, &temp, 1); + if (status < 0) + goto end; + + tpm_reg = tpm_reg + 1; + burstcnt = temp; + status = I2C_READ_DATA(client, tpm_reg, &temp, 1); + if (status < 0) + goto end; + + burstcnt |= temp << 8; + if (burstcnt) + return burstcnt; + msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + +end: + return -EBUSY; +} /* get_burstcount() */ + +/* + * wait_for_stat wait for a TPM_STS value + * @param: chip, the tpm chip description + * @param: mask, the value mask to wait + * @param: timeout, the timeout + * @param: queue, the wait queue. + * @return: the tpm status, 0 if success, -ETIME if timeout is reached. + */ +static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + wait_queue_head_t *queue) +{ + unsigned long stop; + long rc; + u8 status; + + if (chip->vendor.irq) { + rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status + (chip) & mask) == + mask), timeout); + if (rc > 0) + return 0; + } else{ + stop = jiffies + timeout; + do { + msleep(TPM_TIMEOUT); + status = tpm_stm_i2c_status(chip); + if ((status & mask) == mask) + return 0; + } while (time_before(jiffies, stop)); + } + return -ETIME; +} /* wait_for_stat() */ + +/* + * recv_data receive data + * @param: chip, the tpm chip description + * @param: buf, the buffer where the data are received + * @param: count, the number of data to receive + * @return: the number of bytes read from TPM FIFO. + */ +static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) +{ + int size = 0, burstcnt, len; + struct i2c_client *client; + + client = (struct i2c_client *) TPM_VPRIV(chip); + + while (size < count && + wait_for_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->vendor.timeout_c, + &chip->vendor.read_queue) + == 0) { + burstcnt = get_burstcount(chip); + len = min_t(int, burstcnt, count - size); + I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len); + size += len; + } + return size; +} + +/* + * tpm_ioserirq_handler the serirq irq handler + * @param: irq, the tpm chip description + * @param: dev_id, the description of the chip + * @return: the status of the handler. + */ +static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) +{ + struct tpm_chip *chip = dev_id; + struct i2c_client *client; + struct st33zp24_platform_data *pin_infos; + + disable_irq_nosync(irq); + + client = (struct i2c_client *) TPM_VPRIV(chip); + pin_infos = client->dev.platform_data; + + complete(&pin_infos->irq_detection); + return IRQ_HANDLED; +} /* tpm_ioserirq_handler() */ + + +/* + * tpm_stm_i2c_send send TPM commands through the I2C bus. + * + * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h + * @param: buf, the buffer to send. + * @param: count, the number of bytes to send. + * @return: In case of success the number of bytes sent. + * In other case, a < 0 value describing the issue. + */ +static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, + size_t len) +{ + u32 status, + burstcnt = 0, i, size; + int ret; + u8 data; + struct i2c_client *client; + + if (chip == NULL) + return -EBUSY; + if (len < TPM_HEADER_SIZE) + return -EBUSY; + + client = (struct i2c_client *)TPM_VPRIV(chip); + + client->flags = 0; + + ret = request_locality(chip); + if (ret < 0) + return ret; + + status = tpm_stm_i2c_status(chip); + if ((status & TPM_STS_COMMAND_READY) == 0) { + tpm_stm_i2c_cancel(chip); + if (wait_for_stat + (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, + &chip->vendor.int_queue) < 0) { + ret = -ETIME; + goto out_err; + } + } + + for (i = 0 ; i < len - 1 ;) { + burstcnt = get_burstcount(chip); + size = min_t(int, len - i - 1, burstcnt); + ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); + if (ret < 0) + goto out_err; + + i += size; + } + + status = tpm_stm_i2c_status(chip); + if ((status & TPM_STS_DATA_EXPECT) == 0) { + ret = -EIO; + goto out_err; + } + + ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1); + if (ret < 0) + goto out_err; + + status = tpm_stm_i2c_status(chip); + if ((status & TPM_STS_DATA_EXPECT) != 0) { + ret = -EIO; + goto out_err; + } + + data = TPM_STS_GO; + I2C_WRITE_DATA(client, TPM_STS, &data, 1); + + return len; +out_err: + tpm_stm_i2c_cancel(chip); + release_locality(chip); + return ret; +} + +/* + * tpm_stm_i2c_recv received TPM response through the I2C bus. + * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h. + * @param: buf, the buffer to store datas. + * @param: count, the number of bytes to send. + * @return: In case of success the number of bytes received. + * In other case, a < 0 value describing the issue. + */ +static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, + size_t count) +{ + int size = 0; + int expected; + + if (chip == NULL) + return -EBUSY; + + if (count < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } + + size = recv_data(chip, buf, TPM_HEADER_SIZE); + if (size < TPM_HEADER_SIZE) { + dev_err(chip->dev, "Unable to read header\n"); + goto out; + } + + expected = be32_to_cpu(*(__be32 *) (buf + 2)); + if (expected > count) { + size = -EIO; + goto out; + } + + size += recv_data(chip, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (size < expected) { + dev_err(chip->dev, "Unable to read remainder of result\n"); + size = -ETIME; + goto out; + } + +out: + chip->vendor.cancel(chip); + release_locality(chip); + return size; +} + +static bool tpm_st33_i2c_req_canceled(struct tpm_chip *chip, u8 status) +{ + return (status == TPM_STS_COMMAND_READY); +} + +static const struct file_operations tpm_st33_i2c_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = tpm_read, + .write = tpm_write, + .open = tpm_open, + .release = tpm_release, +}; + +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); +static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); +static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); +static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); +static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); +static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); + +static struct attribute *stm_tpm_attrs[] = { + &dev_attr_pubek.attr, + &dev_attr_pcrs.attr, + &dev_attr_enabled.attr, + &dev_attr_active.attr, + &dev_attr_owned.attr, + &dev_attr_temp_deactivated.attr, + &dev_attr_caps.attr, + &dev_attr_cancel.attr, NULL, +}; + +static struct attribute_group stm_tpm_attr_grp = { + .attrs = stm_tpm_attrs +}; + +static struct tpm_vendor_specific st_i2c_tpm = { + .send = tpm_stm_i2c_send, + .recv = tpm_stm_i2c_recv, + .cancel = tpm_stm_i2c_cancel, + .status = tpm_stm_i2c_status, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_canceled = tpm_st33_i2c_req_canceled, + .attr_group = &stm_tpm_attr_grp, + .miscdev = {.fops = &tpm_st33_i2c_fops,}, +}; + +static int interrupts ; +module_param(interrupts, int, 0444); +MODULE_PARM_DESC(interrupts, "Enable interrupts"); + +static int power_mgt = 1; +module_param(power_mgt, int, 0444); +MODULE_PARM_DESC(power_mgt, "Power Management"); + +/* + * tpm_st33_i2c_probe initialize the TPM device + * @param: client, the i2c_client drescription (TPM I2C description). + * @param: id, the i2c_device_id struct. + * @return: 0 in case of success. + * -1 in other case. + */ +static int +tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err; + u8 intmask; + struct tpm_chip *chip; + struct st33zp24_platform_data *platform_data; + + if (client == NULL) { + pr_info("%s: i2c client is NULL. Device not accessible.\n", + __func__); + err = -ENODEV; + goto end; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_info(&client->dev, "client not i2c capable\n"); + err = -ENODEV; + goto end; + } + + chip = tpm_register_hardware(&client->dev, &st_i2c_tpm); + if (!chip) { + dev_info(&client->dev, "fail chip\n"); + err = -ENODEV; + goto end; + } + + platform_data = client->dev.platform_data; + + if (!platform_data) { + dev_info(&client->dev, "chip not available\n"); + err = -ENODEV; + goto _tpm_clean_answer; + } + + platform_data->tpm_i2c_buffer[0] = + kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); + if (platform_data->tpm_i2c_buffer[0] == NULL) { + err = -ENOMEM; + goto _tpm_clean_answer; + } + platform_data->tpm_i2c_buffer[1] = + kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); + if (platform_data->tpm_i2c_buffer[1] == NULL) { + err = -ENOMEM; + goto _tpm_clean_response1; + } + + TPM_VPRIV(chip) = client; + + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + + chip->vendor.locality = LOCALITY0; + + if (power_mgt) { + err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD"); + if (err) + goto _gpio_init1; + gpio_set_value(platform_data->io_lpcpd, 1); + } + + if (interrupts) { + init_completion(&platform_data->irq_detection); + if (request_locality(chip) != LOCALITY0) { + err = -ENODEV; + goto _tpm_clean_response2; + } + err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ"); + if (err) + goto _gpio_init2; + + clear_interruption(client); + err = request_irq(gpio_to_irq(platform_data->io_serirq), + &tpm_ioserirq_handler, + IRQF_TRIGGER_HIGH, + "TPM SERIRQ management", chip); + if (err < 0) { + dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", + gpio_to_irq(platform_data->io_serirq)); + goto _irq_set; + } + + err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1); + if (err < 0) + goto _irq_set; + + intmask |= TPM_INTF_CMD_READY_INT + | TPM_INTF_FIFO_AVALAIBLE_INT + | TPM_INTF_WAKE_UP_READY_INT + | TPM_INTF_LOCALITY_CHANGE_INT + | TPM_INTF_STS_VALID_INT + | TPM_INTF_DATA_AVAIL_INT; + + err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1); + if (err < 0) + goto _irq_set; + + intmask = TPM_GLOBAL_INT_ENABLE; + err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1); + if (err < 0) + goto _irq_set; + + err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1); + if (err < 0) + goto _irq_set; + + chip->vendor.irq = interrupts; + + tpm_gen_interrupt(chip); + } + + tpm_get_timeouts(chip); + + i2c_set_clientdata(client, chip); + + dev_info(chip->dev, "TPM I2C Initialized\n"); + return 0; +_irq_set: + free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip); +_gpio_init2: + if (interrupts) + gpio_free(platform_data->io_serirq); +_gpio_init1: + if (power_mgt) + gpio_free(platform_data->io_lpcpd); +_tpm_clean_response2: + kzfree(platform_data->tpm_i2c_buffer[1]); + platform_data->tpm_i2c_buffer[1] = NULL; +_tpm_clean_response1: + kzfree(platform_data->tpm_i2c_buffer[0]); + platform_data->tpm_i2c_buffer[0] = NULL; +_tpm_clean_answer: + tpm_remove_hardware(chip->dev); +end: + pr_info("TPM I2C initialisation fail\n"); + return err; +} + +/* + * tpm_st33_i2c_remove remove the TPM device + * @param: client, the i2c_client drescription (TPM I2C description). + clear_bit(0, &chip->is_open); + * @return: 0 in case of success. + */ +static int tpm_st33_i2c_remove(struct i2c_client *client) +{ + struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client); + struct st33zp24_platform_data *pin_infos = + ((struct i2c_client *) TPM_VPRIV(chip))->dev.platform_data; + + if (pin_infos != NULL) { + free_irq(pin_infos->io_serirq, chip); + + gpio_free(pin_infos->io_serirq); + gpio_free(pin_infos->io_lpcpd); + + tpm_remove_hardware(chip->dev); + + if (pin_infos->tpm_i2c_buffer[1] != NULL) { + kzfree(pin_infos->tpm_i2c_buffer[1]); + pin_infos->tpm_i2c_buffer[1] = NULL; + } + if (pin_infos->tpm_i2c_buffer[0] != NULL) { + kzfree(pin_infos->tpm_i2c_buffer[0]); + pin_infos->tpm_i2c_buffer[0] = NULL; + } + } + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +/* + * tpm_st33_i2c_pm_suspend suspend the TPM device + * Added: Work around when suspend and no tpm application is running, suspend + * may fail because chip->data_buffer is not set (only set in tpm_open in Linux + * TPM core) + * @param: client, the i2c_client drescription (TPM I2C description). + * @param: mesg, the power management message. + * @return: 0 in case of success. + */ +static int tpm_st33_i2c_pm_suspend(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct st33zp24_platform_data *pin_infos = dev->platform_data; + int ret = 0; + + if (power_mgt) + gpio_set_value(pin_infos->io_lpcpd, 0); + else{ + if (chip->data_buffer == NULL) + chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; + ret = tpm_pm_suspend(dev); + } + return ret; +} /* tpm_st33_i2c_suspend() */ + +/* + * tpm_st33_i2c_pm_resume resume the TPM device + * @param: client, the i2c_client drescription (TPM I2C description). + * @return: 0 in case of success. + */ +static int tpm_st33_i2c_pm_resume(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct st33zp24_platform_data *pin_infos = dev->platform_data; + + int ret = 0; + + if (power_mgt) { + gpio_set_value(pin_infos->io_lpcpd, 1); + ret = wait_for_serirq_timeout(chip, + (chip->vendor.status(chip) & + TPM_STS_VALID) == TPM_STS_VALID, + chip->vendor.timeout_b); + } else{ + if (chip->data_buffer == NULL) + chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; + ret = tpm_pm_resume(dev); + if (!ret) + tpm_do_selftest(chip); + } + return ret; +} /* tpm_st33_i2c_pm_resume() */ +#endif + +static const struct i2c_device_id tpm_st33_i2c_id[] = { + {TPM_ST33_I2C, 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id); +static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, tpm_st33_i2c_pm_resume); +static struct i2c_driver tpm_st33_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = TPM_ST33_I2C, + .pm = &tpm_st33_i2c_ops, + }, + .probe = tpm_st33_i2c_probe, + .remove = tpm_st33_i2c_remove, + .id_table = tpm_st33_i2c_id +}; + +module_i2c_driver(tpm_st33_i2c_driver); + +MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)"); +MODULE_DESCRIPTION("STM TPM I2C ST33 Driver"); +MODULE_VERSION("1.2.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.h b/drivers/char/tpm/tpm_i2c_stm_st33.h new file mode 100644 index 000000000000..439a43249aa6 --- /dev/null +++ b/drivers/char/tpm/tpm_i2c_stm_st33.h @@ -0,0 +1,61 @@ +/* + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 + * Copyright (C) 2009, 2010 STMicroelectronics + * + * 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) any 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * STMicroelectronics version 1.2.0, Copyright (C) 2010 + * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. + * This is free software, and you are welcome to redistribute it + * under certain conditions. + * + * @Author: Christophe RICARD tpmsupport@st.com + * + * @File: stm_st33_tpm_i2c.h + * + * @Date: 09/15/2010 + */ +#ifndef __STM_ST33_TPM_I2C_MAIN_H__ +#define __STM_ST33_TPM_I2C_MAIN_H__ + +#define TPM_ACCESS (0x0) +#define TPM_STS (0x18) +#define TPM_HASH_END (0x20) +#define TPM_DATA_FIFO (0x24) +#define TPM_HASH_DATA (0x24) +#define TPM_HASH_START (0x28) +#define TPM_INTF_CAPABILITY (0x14) +#define TPM_INT_STATUS (0x10) +#define TPM_INT_ENABLE (0x08) + +#define TPM_DUMMY_BYTE 0xAA +#define TPM_WRITE_DIRECTION 0x80 +#define TPM_HEADER_SIZE 10 +#define TPM_BUFSIZE 2048 + +#define LOCALITY0 0 + +#define TPM_ST33_I2C "st33zp24_i2c" + +struct st33zp24_platform_data { + int io_serirq; + int io_lpcpd; + struct i2c_client *client; + u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */ + struct completion irq_detection; + struct mutex lock; +}; + +#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */ diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index efc4ab36a9d6..56b07c35a13e 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c @@ -32,14 +32,12 @@ static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm"; -static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = { +static struct vio_device_id tpm_ibmvtpm_device_table[] = { { "IBM,vtpm", "IBM,vtpm"}, { "", "" } }; MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table); -DECLARE_WAIT_QUEUE_HEAD(wq); - /** * ibmvtpm_send_crq - Send a CRQ request * @vdev: vio device struct @@ -66,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); if (chip) - return (struct ibmvtpm_dev *)chip->vendor.data; + return (struct ibmvtpm_dev *)TPM_VPRIV(chip); return NULL; } @@ -83,30 +81,32 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) { struct ibmvtpm_dev *ibmvtpm; u16 len; + int sig; - ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); if (!ibmvtpm->rtce_buf) { dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); return 0; } - wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0); + sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0); + if (sig) + return -EINTR; + + len = ibmvtpm->res_len; - if (count < ibmvtpm->crq_res.len) { + if (count < len) { dev_err(ibmvtpm->dev, "Invalid size in recv: count=%ld, crq_size=%d\n", - count, ibmvtpm->crq_res.len); + count, len); return -EIO; } spin_lock(&ibmvtpm->rtce_lock); - memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len); - memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len); - ibmvtpm->crq_res.valid = 0; - ibmvtpm->crq_res.msg = 0; - len = ibmvtpm->crq_res.len; - ibmvtpm->crq_res.len = 0; + memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len); + memset(ibmvtpm->rtce_buf, 0, len); + ibmvtpm->res_len = 0; spin_unlock(&ibmvtpm->rtce_lock); return len; } @@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) u64 *word = (u64 *) &crq; int rc; - ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); if (!ibmvtpm->rtce_buf) { dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); @@ -267,13 +267,12 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm) * Return value: * 0 */ -static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev) +static int tpm_ibmvtpm_remove(struct vio_dev *vdev) { struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); int rc = 0; free_irq(vdev->irq, ibmvtpm); - tasklet_kill(&ibmvtpm->tasklet); do { if (rc) @@ -372,7 +371,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm) static int tpm_ibmvtpm_resume(struct device *dev) { struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); - unsigned long flags; int rc = 0; do { @@ -387,10 +385,11 @@ static int tpm_ibmvtpm_resume(struct device *dev) return rc; } - spin_lock_irqsave(&ibmvtpm->lock, flags); - vio_disable_interrupts(ibmvtpm->vdev); - tasklet_schedule(&ibmvtpm->tasklet); - spin_unlock_irqrestore(&ibmvtpm->lock, flags); + rc = vio_enable_interrupts(ibmvtpm->vdev); + if (rc) { + dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc); + return rc; + } rc = ibmvtpm_crq_send_init(ibmvtpm); if (rc) @@ -399,6 +398,11 @@ static int tpm_ibmvtpm_resume(struct device *dev) return rc; } +static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status) +{ + return (status == 0); +} + static const struct file_operations ibmvtpm_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -442,7 +446,7 @@ static const struct tpm_vendor_specific tpm_ibmvtpm = { .status = tpm_ibmvtpm_status, .req_complete_mask = 0, .req_complete_val = 0, - .req_canceled = 0, + .req_canceled = tpm_ibmvtpm_req_canceled, .attr_group = &ibmvtpm_attr_grp, .miscdev = { .fops = &ibmvtpm_ops, }, }; @@ -467,7 +471,7 @@ static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm) if (crq->valid & VTPM_MSG_RES) { if (++crq_q->index == crq_q->num_entry) crq_q->index = 0; - rmb(); + smp_rmb(); } else crq = NULL; return crq; @@ -535,11 +539,9 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, ibmvtpm->vtpm_version = crq->data; return; case VTPM_TPM_COMMAND_RES: - ibmvtpm->crq_res.valid = crq->valid; - ibmvtpm->crq_res.msg = crq->msg; - ibmvtpm->crq_res.len = crq->len; - ibmvtpm->crq_res.data = crq->data; - wake_up_interruptible(&wq); + /* len of the data in rtce buffer */ + ibmvtpm->res_len = crq->len; + wake_up_interruptible(&ibmvtpm->wq); return; default: return; @@ -559,38 +561,19 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance) { struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance; - unsigned long flags; - - spin_lock_irqsave(&ibmvtpm->lock, flags); - vio_disable_interrupts(ibmvtpm->vdev); - tasklet_schedule(&ibmvtpm->tasklet); - spin_unlock_irqrestore(&ibmvtpm->lock, flags); - - return IRQ_HANDLED; -} - -/** - * ibmvtpm_tasklet - Interrupt handler tasklet - * @data: ibm vtpm device struct - * - * Returns: - * Nothing - **/ -static void ibmvtpm_tasklet(void *data) -{ - struct ibmvtpm_dev *ibmvtpm = data; struct ibmvtpm_crq *crq; - unsigned long flags; - spin_lock_irqsave(&ibmvtpm->lock, flags); + /* while loop is needed for initial setup (get version and + * get rtce_size). There should be only one tpm request at any + * given time. + */ while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) { ibmvtpm_crq_process(crq, ibmvtpm); crq->valid = 0; - wmb(); + smp_wmb(); } - vio_enable_interrupts(ibmvtpm->vdev); - spin_unlock_irqrestore(&ibmvtpm->lock, flags); + return IRQ_HANDLED; } /** @@ -602,7 +585,7 @@ static void ibmvtpm_tasklet(void *data) * 0 - Success * Non-zero - Failure */ -static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, +static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, const struct vio_device_id *id) { struct ibmvtpm_dev *ibmvtpm; @@ -650,9 +633,6 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, goto reg_crq_cleanup; } - tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet, - (unsigned long)ibmvtpm); - rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0, tpm_ibmvtpm_driver_name, ibmvtpm); if (rc) { @@ -666,13 +646,14 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, goto init_irq_cleanup; } + init_waitqueue_head(&ibmvtpm->wq); + crq_q->index = 0; ibmvtpm->dev = dev; ibmvtpm->vdev = vio_dev; - chip->vendor.data = (void *)ibmvtpm; + TPM_VPRIV(chip) = (void *)ibmvtpm; - spin_lock_init(&ibmvtpm->lock); spin_lock_init(&ibmvtpm->rtce_lock); rc = ibmvtpm_crq_send_init(ibmvtpm); @@ -689,7 +670,6 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, return rc; init_irq_cleanup: - tasklet_kill(&ibmvtpm->tasklet); do { rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); } while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1)); diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h index 4296eb4b4d82..bd82a791f995 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.h +++ b/drivers/char/tpm/tpm_ibmvtpm.h @@ -38,13 +38,12 @@ struct ibmvtpm_dev { struct vio_dev *vdev; struct ibmvtpm_crq_queue crq_queue; dma_addr_t crq_dma_handle; - spinlock_t lock; - struct tasklet_struct tasklet; u32 rtce_size; void __iomem *rtce_buf; dma_addr_t rtce_dma_handle; spinlock_t rtce_lock; - struct ibmvtpm_crq crq_res; + wait_queue_head_t wq; + u16 res_len; u32 vtpm_version; }; diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 3251a44e8ceb..2b480c2960bb 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -415,7 +415,7 @@ static const struct pnp_device_id tpm_inf_pnp_tbl[] = { MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl); -static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, +static int tpm_inf_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { int rc = 0; @@ -594,7 +594,7 @@ err_last: return rc; } -static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) +static void tpm_inf_pnp_remove(struct pnp_dev *dev) { struct tpm_chip *chip = pnp_get_drvdata(dev); @@ -655,7 +655,7 @@ static struct pnp_driver tpm_inf_pnp_driver = { .probe = tpm_inf_pnp_probe, .suspend = tpm_inf_pnp_suspend, .resume = tpm_inf_pnp_resume, - .remove = __devexit_p(tpm_inf_pnp_remove) + .remove = tpm_inf_pnp_remove }; static int __init init_inf(void) diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 640c9a427b59..770c46f8eb30 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c @@ -227,6 +227,11 @@ static u8 tpm_nsc_status(struct tpm_chip *chip) return inb(chip->vendor.base + NSC_STATUS); } +static bool tpm_nsc_req_canceled(struct tpm_chip *chip, u8 status) +{ + return (status == NSC_STATUS_RDY); +} + static const struct file_operations nsc_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -258,7 +263,7 @@ static const struct tpm_vendor_specific tpm_nsc = { .status = tpm_nsc_status, .req_complete_mask = NSC_STATUS_OBF, .req_complete_val = NSC_STATUS_OBF, - .req_canceled = NSC_STATUS_RDY, + .req_canceled = tpm_nsc_req_canceled, .attr_group = &nsc_attr_grp, .miscdev = { .fops = &nsc_ops, }, }; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 6bdf2671254f..8a41b6be23a0 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -84,6 +84,9 @@ static int is_itpm(struct pnp_dev *dev) struct acpi_device *acpi = pnp_acpi_device(dev); struct acpi_hardware_id *id; + if (!acpi) + return 0; + list_for_each_entry(id, &acpi->pnp.ids, list) { if (!strcmp("INTC0102", id->id)) return 1; @@ -98,6 +101,22 @@ static inline int is_itpm(struct pnp_dev *dev) } #endif +/* Before we attempt to access the TPM we must see that the valid bit is set. + * The specification says that this bit is 0 at reset and remains 0 until the + * 'TPM has gone through its self test and initialization and has established + * correct values in the other bits.' */ +static int wait_startup(struct tpm_chip *chip, int l) +{ + unsigned long stop = jiffies + chip->vendor.timeout_a; + do { + if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & + TPM_ACCESS_VALID) + return 0; + msleep(TPM_TIMEOUT); + } while (time_before(jiffies, stop)); + return -1; +} + static int check_locality(struct tpm_chip *chip, int l) { if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & @@ -198,7 +217,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) wait_for_tpm_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.read_queue) + &chip->vendor.read_queue, true) == 0) { burstcnt = get_burstcount(chip); for (; burstcnt > 0 && size < count; burstcnt--) @@ -241,7 +260,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) } wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + &chip->vendor.int_queue, false); status = tpm_tis_status(chip); if (status & TPM_STS_DATA_AVAIL) { /* retry? */ dev_err(chip->dev, "Error left over data\n"); @@ -277,7 +296,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) tpm_tis_ready(chip); if (wait_for_tpm_stat (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, - &chip->vendor.int_queue) < 0) { + &chip->vendor.int_queue, false) < 0) { rc = -ETIME; goto out_err; } @@ -292,7 +311,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) } wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + &chip->vendor.int_queue, false); status = tpm_tis_status(chip); if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; @@ -304,7 +323,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) iowrite8(buf[count], chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + &chip->vendor.int_queue, false); status = tpm_tis_status(chip); if ((status & TPM_STS_DATA_EXPECT) != 0) { rc = -EIO; @@ -342,7 +361,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) if (wait_for_tpm_stat (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm_calc_ordinal_duration(chip, ordinal), - &chip->vendor.read_queue) < 0) { + &chip->vendor.read_queue, false) < 0) { rc = -ETIME; goto out_err; } @@ -374,7 +393,7 @@ static int probe_itpm(struct tpm_chip *chip) if (vendor != TPM_VID_INTEL) return 0; - itpm = 0; + itpm = false; rc = tpm_tis_send_data(chip, cmd_getticks, len); if (rc == 0) @@ -383,7 +402,7 @@ static int probe_itpm(struct tpm_chip *chip) tpm_tis_ready(chip); release_locality(chip, chip->vendor.locality, 0); - itpm = 1; + itpm = true; rc = tpm_tis_send_data(chip, cmd_getticks, len); if (rc == 0) { @@ -400,6 +419,19 @@ out: return rc; } +static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) +{ + switch (chip->vendor.manufacturer_id) { + case TPM_VID_WINBOND: + return ((status == TPM_STS_VALID) || + (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); + case TPM_VID_STM: + return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); + default: + return (status == TPM_STS_COMMAND_READY); + } +} + static const struct file_operations tis_ops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -445,7 +477,7 @@ static struct tpm_vendor_specific tpm_tis = { .cancel = tpm_tis_ready, .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, - .req_canceled = TPM_STS_COMMAND_READY, + .req_canceled = tpm_tis_req_canceled, .attr_group = &tis_attr_grp, .miscdev = { .fops = &tis_ops,}, @@ -502,7 +534,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) return IRQ_HANDLED; } -static bool interrupts = 1; +static bool interrupts = true; module_param(interrupts, bool, 0444); MODULE_PARM_DESC(interrupts, "Enable interrupts"); @@ -528,12 +560,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + if (wait_startup(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + if (request_locality(chip, 0) != 0) { rc = -ENODEV; goto out_err; } vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); + chip->vendor.manufacturer_id = vendor; dev_info(dev, "1.2 TPM (device-id 0x%X, rev-id %d)\n", @@ -545,7 +583,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, rc = -ENODEV; goto out_err; } - itpm = (probe == 0) ? 0 : 1; + itpm = !!probe; } if (itpm) @@ -729,7 +767,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) #endif #ifdef CONFIG_PNP -static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, +static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, const struct pnp_device_id *pnp_id) { resource_size_t start, len; @@ -741,10 +779,10 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, if (pnp_irq_valid(pnp_dev, 0)) irq = pnp_irq(pnp_dev, 0); else - interrupts = 0; + interrupts = false; if (is_itpm(pnp_dev)) - itpm = 1; + itpm = true; return tpm_tis_init(&pnp_dev->dev, start, len, irq); } @@ -769,7 +807,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) return ret; } -static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { +static struct pnp_device_id tpm_pnp_tbl[] = { {"PNP0C31", 0}, /* TPM */ {"ATM1200", 0}, /* Atmel */ {"IFX0102", 0}, /* Infineon */ @@ -783,7 +821,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { }; MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); -static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev) +static void tpm_tis_pnp_remove(struct pnp_dev *dev) { struct tpm_chip *chip = pnp_get_drvdata(dev); diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index af98f6d6509b..4945bd3d18d0 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -179,7 +179,6 @@ static int __init ttyprintk_init(void) { int ret = -ENOMEM; - tty_port_init(&tpk_port.port); tpk_port.port.ops = &null_ops; mutex_init(&tpk_port.port_write_mutex); @@ -190,6 +189,8 @@ static int __init ttyprintk_init(void) if (IS_ERR(ttyprintk_driver)) return PTR_ERR(ttyprintk_driver); + tty_port_init(&tpk_port.port); + ttyprintk_driver->driver_name = "ttyprintk"; ttyprintk_driver->name = "ttyprintk"; ttyprintk_driver->major = TTYAUX_MAJOR; @@ -211,6 +212,7 @@ static int __init ttyprintk_init(void) error: tty_unregister_driver(ttyprintk_driver); put_tty_driver(ttyprintk_driver); + tty_port_destroy(&tpk_port.port); ttyprintk_driver = NULL; return ret; } diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 8ab9c3d4bf13..e905d5f53051 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -37,8 +37,12 @@ #include <linux/wait.h> #include <linux/workqueue.h> #include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/kconfig.h> #include "../tty/hvc/hvc_console.h" +#define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC) + /* * This is a global struct for storing common data for all the devices * this driver handles. @@ -57,9 +61,6 @@ struct ports_driver_data { /* List of all the devices we're handling */ struct list_head portdevs; - /* Number of devices this driver is handling */ - unsigned int index; - /* * This is used to keep track of the number of hvc consoles * spawned by this driver. This number is given as the first @@ -111,6 +112,21 @@ struct port_buffer { size_t len; /* offset in the buf from which to consume data */ size_t offset; + + /* DMA address of buffer */ + dma_addr_t dma; + + /* Device we got DMA memory from */ + struct device *dev; + + /* List of pending dma buffers to free */ + struct list_head list; + + /* If sgpages == 0 then buf is used */ + unsigned int sgpages; + + /* sg is used if spages > 0. sg must be the last in is struct */ + struct scatterlist sg[0]; }; /* @@ -150,9 +166,6 @@ struct ports_device { /* Array of per-port IO virtqueues */ struct virtqueue **in_vqs, **out_vqs; - /* Used for numbering devices for sysfs and debugfs */ - unsigned int drv_index; - /* Major number for this device. Ports will be created as minors. */ int chr_major; }; @@ -325,6 +338,11 @@ static bool is_console_port(struct port *port) return false; } +static bool is_rproc_serial(const struct virtio_device *vdev) +{ + return is_rproc_enabled && vdev->id.device == VIRTIO_ID_RPROC_SERIAL; +} + static inline bool use_multiport(struct ports_device *portdev) { /* @@ -336,20 +354,110 @@ static inline bool use_multiport(struct ports_device *portdev) return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); } -static void free_buf(struct port_buffer *buf) +static DEFINE_SPINLOCK(dma_bufs_lock); +static LIST_HEAD(pending_free_dma_bufs); + +static void free_buf(struct port_buffer *buf, bool can_sleep) { - kfree(buf->buf); + unsigned int i; + + for (i = 0; i < buf->sgpages; i++) { + struct page *page = sg_page(&buf->sg[i]); + if (!page) + break; + put_page(page); + } + + if (!buf->dev) { + kfree(buf->buf); + } else if (is_rproc_enabled) { + unsigned long flags; + + /* dma_free_coherent requires interrupts to be enabled. */ + if (!can_sleep) { + /* queue up dma-buffers to be freed later */ + spin_lock_irqsave(&dma_bufs_lock, flags); + list_add_tail(&buf->list, &pending_free_dma_bufs); + spin_unlock_irqrestore(&dma_bufs_lock, flags); + return; + } + dma_free_coherent(buf->dev, buf->size, buf->buf, buf->dma); + + /* Release device refcnt and allow it to be freed */ + put_device(buf->dev); + } + kfree(buf); } -static struct port_buffer *alloc_buf(size_t buf_size) +static void reclaim_dma_bufs(void) +{ + unsigned long flags; + struct port_buffer *buf, *tmp; + LIST_HEAD(tmp_list); + + if (list_empty(&pending_free_dma_bufs)) + return; + + /* Create a copy of the pending_free_dma_bufs while holding the lock */ + spin_lock_irqsave(&dma_bufs_lock, flags); + list_cut_position(&tmp_list, &pending_free_dma_bufs, + pending_free_dma_bufs.prev); + spin_unlock_irqrestore(&dma_bufs_lock, flags); + + /* Release the dma buffers, without irqs enabled */ + list_for_each_entry_safe(buf, tmp, &tmp_list, list) { + list_del(&buf->list); + free_buf(buf, true); + } +} + +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size, + int pages) { struct port_buffer *buf; - buf = kmalloc(sizeof(*buf), GFP_KERNEL); + reclaim_dma_bufs(); + + /* + * Allocate buffer and the sg list. The sg list array is allocated + * directly after the port_buffer struct. + */ + buf = kmalloc(sizeof(*buf) + sizeof(struct scatterlist) * pages, + GFP_KERNEL); if (!buf) goto fail; - buf->buf = kzalloc(buf_size, GFP_KERNEL); + + buf->sgpages = pages; + if (pages > 0) { + buf->dev = NULL; + buf->buf = NULL; + return buf; + } + + if (is_rproc_serial(vq->vdev)) { + /* + * Allocate DMA memory from ancestor. When a virtio + * device is created by remoteproc, the DMA memory is + * associated with the grandparent device: + * vdev => rproc => platform-dev. + * The code here would have been less quirky if + * DMA_MEMORY_INCLUDES_CHILDREN had been supported + * in dma-coherent.c + */ + if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent) + goto free_buf; + buf->dev = vq->vdev->dev.parent->parent; + + /* Increase device refcnt to avoid freeing it */ + get_device(buf->dev); + buf->buf = dma_alloc_coherent(buf->dev, buf_size, &buf->dma, + GFP_KERNEL); + } else { + buf->dev = NULL; + buf->buf = kmalloc(buf_size, GFP_KERNEL); + } + if (!buf->buf) goto free_buf; buf->len = 0; @@ -396,6 +504,8 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC); virtqueue_kick(vq); + if (!ret) + ret = vq->num_free; return ret; } @@ -416,7 +526,7 @@ static void discard_port_data(struct port *port) port->stats.bytes_discarded += buf->len - buf->offset; if (add_inbuf(port->in_vq, buf) < 0) { err++; - free_buf(buf); + free_buf(buf, false); } port->inbuf = NULL; buf = get_inbuf(port); @@ -459,7 +569,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, vq = portdev->c_ovq; sg_init_one(sg, &cpkt, sizeof(cpkt)); - if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) { + if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) { virtqueue_kick(vq); while (!virtqueue_get_buf(vq, &len)) cpu_relax(); @@ -476,55 +586,29 @@ static ssize_t send_control_msg(struct port *port, unsigned int event, return 0; } -struct buffer_token { - union { - void *buf; - struct scatterlist *sg; - } u; - /* If sgpages == 0 then buf is used, else sg is used */ - unsigned int sgpages; -}; - -static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages) -{ - int i; - struct page *page; - - for (i = 0; i < nrpages; i++) { - page = sg_page(&sg[i]); - if (!page) - break; - put_page(page); - } - kfree(sg); -} /* Callers must take the port->outvq_lock */ static void reclaim_consumed_buffers(struct port *port) { - struct buffer_token *tok; + struct port_buffer *buf; unsigned int len; if (!port->portdev) { /* Device has been unplugged. vqs are already gone. */ return; } - while ((tok = virtqueue_get_buf(port->out_vq, &len))) { - if (tok->sgpages) - reclaim_sg_pages(tok->u.sg, tok->sgpages); - else - kfree(tok->u.buf); - kfree(tok); + while ((buf = virtqueue_get_buf(port->out_vq, &len))) { + free_buf(buf, false); port->outvq_full = false; } } static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, int nents, size_t in_count, - struct buffer_token *tok, bool nonblock) + void *data, bool nonblock) { struct virtqueue *out_vq; - ssize_t ret; + int err; unsigned long flags; unsigned int len; @@ -534,17 +618,17 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, reclaim_consumed_buffers(port); - ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC); + err = virtqueue_add_buf(out_vq, sg, nents, 0, data, GFP_ATOMIC); /* Tell Host to go! */ virtqueue_kick(out_vq); - if (ret < 0) { + if (err) { in_count = 0; goto done; } - if (ret == 0) + if (out_vq->num_free == 0) port->outvq_full = true; if (nonblock) @@ -572,37 +656,6 @@ done: return in_count; } -static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, - bool nonblock) -{ - struct scatterlist sg[1]; - struct buffer_token *tok; - - tok = kmalloc(sizeof(*tok), GFP_ATOMIC); - if (!tok) - return -ENOMEM; - tok->sgpages = 0; - tok->u.buf = in_buf; - - sg_init_one(sg, in_buf, in_count); - - return __send_to_port(port, sg, 1, in_count, tok, nonblock); -} - -static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents, - size_t in_count, bool nonblock) -{ - struct buffer_token *tok; - - tok = kmalloc(sizeof(*tok), GFP_ATOMIC); - if (!tok) - return -ENOMEM; - tok->sgpages = nents; - tok->u.sg = sg; - - return __send_to_port(port, sg, nents, in_count, tok, nonblock); -} - /* * Give out the data that's requested from the buffer that we have * queued up. @@ -748,9 +801,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, size_t count, loff_t *offp) { struct port *port; - char *buf; + struct port_buffer *buf; ssize_t ret; bool nonblock; + struct scatterlist sg[1]; /* Userspace could be out to fool us */ if (!count) @@ -766,11 +820,11 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, count = min((size_t)(32 * 1024), count); - buf = kmalloc(count, GFP_KERNEL); + buf = alloc_buf(port->out_vq, count, 0); if (!buf) return -ENOMEM; - ret = copy_from_user(buf, ubuf, count); + ret = copy_from_user(buf->buf, ubuf, count); if (ret) { ret = -EFAULT; goto free_buf; @@ -784,13 +838,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, * through to the host. */ nonblock = true; - ret = send_buf(port, buf, count, nonblock); + sg_init_one(sg, buf->buf, count); + ret = __send_to_port(port, sg, 1, count, buf, nonblock); if (nonblock && ret > 0) goto out; free_buf: - kfree(buf); + free_buf(buf, true); out: return ret; } @@ -856,6 +911,7 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, struct port *port = filp->private_data; struct sg_list sgl; ssize_t ret; + struct port_buffer *buf; struct splice_desc sd = { .total_len = len, .flags = flags, @@ -863,22 +919,34 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, .u.data = &sgl, }; + /* + * Rproc_serial does not yet support splice. To support splice + * pipe_to_sg() must allocate dma-buffers and copy content from + * regular pages to dma pages. And alloc_buf and free_buf must + * support allocating and freeing such a list of dma-buffers. + */ + if (is_rproc_serial(port->out_vq->vdev)) + return -EINVAL; + ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); if (ret < 0) return ret; + buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); + if (!buf) + return -ENOMEM; + sgl.n = 0; sgl.len = 0; sgl.size = pipe->nrbufs; - sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL); - if (unlikely(!sgl.sg)) - return -ENOMEM; - + sgl.sg = buf->sg; sg_init_table(sgl.sg, sgl.size); ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); if (likely(ret > 0)) - ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true); + ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); + if (unlikely(ret <= 0)) + free_buf(buf, true); return ret; } @@ -927,6 +995,7 @@ static int port_fops_release(struct inode *inode, struct file *filp) reclaim_consumed_buffers(port); spin_unlock_irq(&port->outvq_lock); + reclaim_dma_bufs(); /* * Locks aren't necessary here as a port can't be opened after * unplug, and if a port isn't unplugged, a kref would already @@ -1031,6 +1100,7 @@ static const struct file_operations port_fops = { static int put_chars(u32 vtermno, const char *buf, int count) { struct port *port; + struct scatterlist sg[1]; if (unlikely(early_put_chars)) return early_put_chars(vtermno, buf, count); @@ -1039,7 +1109,8 @@ static int put_chars(u32 vtermno, const char *buf, int count) if (!port) return -EPIPE; - return send_buf(port, (void *)buf, count, false); + sg_init_one(sg, buf, count); + return __send_to_port(port, sg, 1, count, (void *)buf, false); } /* @@ -1076,7 +1147,10 @@ static void resize_console(struct port *port) return; vdev = port->portdev->vdev; - if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) + + /* Don't test F_SIZE at all if we're rproc: not a valid feature! */ + if (!is_rproc_serial(vdev) && + virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) hvc_resize(port->cons.hvc, port->cons.ws); } @@ -1260,7 +1334,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) nr_added_bufs = 0; do { - buf = alloc_buf(PAGE_SIZE); + buf = alloc_buf(vq, PAGE_SIZE, 0); if (!buf) break; @@ -1268,7 +1342,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) ret = add_inbuf(vq, buf); if (ret < 0) { spin_unlock_irq(lock); - free_buf(buf); + free_buf(buf, true); break; } nr_added_bufs++; @@ -1335,7 +1409,7 @@ static int add_port(struct ports_device *portdev, u32 id) } port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, devt, port, "vport%up%u", - port->portdev->drv_index, id); + port->portdev->vdev->index, id); if (IS_ERR(port->dev)) { err = PTR_ERR(port->dev); dev_err(&port->portdev->vdev->dev, @@ -1356,10 +1430,18 @@ static int add_port(struct ports_device *portdev, u32 id) goto free_device; } - /* - * If we're not using multiport support, this has to be a console port - */ - if (!use_multiport(port->portdev)) { + if (is_rproc_serial(port->portdev->vdev)) + /* + * For rproc_serial assume remote processor is connected. + * rproc_serial does not want the console port, only + * the generic port implementation. + */ + port->host_connected = port->guest_connected = true; + else if (!use_multiport(port->portdev)) { + /* + * If we're not using multiport support, + * this has to be a console port. + */ err = init_port_console(port); if (err) goto free_inbufs; @@ -1382,7 +1464,7 @@ static int add_port(struct ports_device *portdev, u32 id) * inspect a port's state at any time */ sprintf(debugfs_name, "vport%up%u", - port->portdev->drv_index, id); + port->portdev->vdev->index, id); port->debugfs_file = debugfs_create_file(debugfs_name, 0444, pdrvdata.debugfs_dir, port, @@ -1392,7 +1474,7 @@ static int add_port(struct ports_device *portdev, u32 id) free_inbufs: while ((buf = virtqueue_detach_unused_buf(port->in_vq))) - free_buf(buf); + free_buf(buf, true); free_device: device_destroy(pdrvdata.class, port->dev->devt); free_cdev: @@ -1434,7 +1516,11 @@ static void remove_port_data(struct port *port) /* Remove buffers we queued up for the Host to send us data in. */ while ((buf = virtqueue_detach_unused_buf(port->in_vq))) - free_buf(buf); + free_buf(buf, true); + + /* Free pending buffers from the out-queue. */ + while ((buf = virtqueue_detach_unused_buf(port->out_vq))) + free_buf(buf, true); } /* @@ -1636,7 +1722,7 @@ static void control_work_handler(struct work_struct *work) if (add_inbuf(portdev->c_ivq, buf) < 0) { dev_warn(&portdev->vdev->dev, "Error adding buffer to queue\n"); - free_buf(buf); + free_buf(buf, false); } } spin_unlock(&portdev->cvq_lock); @@ -1832,10 +1918,10 @@ static void remove_controlq_data(struct ports_device *portdev) return; while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) - free_buf(buf); + free_buf(buf, true); while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) - free_buf(buf); + free_buf(buf, true); } /* @@ -1846,7 +1932,7 @@ static void remove_controlq_data(struct ports_device *portdev) * config space to see how many ports the host has spawned. We * initialize each port found. */ -static int __devinit virtcons_probe(struct virtio_device *vdev) +static int virtcons_probe(struct virtio_device *vdev) { struct ports_device *portdev; int err; @@ -1866,27 +1952,27 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) portdev->vdev = vdev; vdev->priv = portdev; - spin_lock_irq(&pdrvdata_lock); - portdev->drv_index = pdrvdata.index++; - spin_unlock_irq(&pdrvdata_lock); - portdev->chr_major = register_chrdev(0, "virtio-portsdev", &portdev_fops); if (portdev->chr_major < 0) { dev_err(&vdev->dev, "Error %d registering chrdev for device %u\n", - portdev->chr_major, portdev->drv_index); + portdev->chr_major, vdev->index); err = portdev->chr_major; goto free; } multiport = false; portdev->config.max_nr_ports = 1; - if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, - offsetof(struct virtio_console_config, - max_nr_ports), - &portdev->config.max_nr_ports) == 0) + + /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */ + if (!is_rproc_serial(vdev) && + virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, + offsetof(struct virtio_console_config, + max_nr_ports), + &portdev->config.max_nr_ports) == 0) { multiport = true; + } err = init_vqs(portdev); if (err < 0) { @@ -1966,7 +2052,8 @@ static void virtcons_remove(struct virtio_device *vdev) /* Disable interrupts for vqs */ vdev->config->reset(vdev); /* Finish up work that's lined up */ - cancel_work_sync(&portdev->control_work); + if (use_multiport(portdev)) + cancel_work_sync(&portdev->control_work); list_for_each_entry_safe(port, port2, &portdev->ports, list) unplug_port(port); @@ -1996,6 +2083,16 @@ static unsigned int features[] = { VIRTIO_CONSOLE_F_MULTIPORT, }; +static struct virtio_device_id rproc_serial_id_table[] = { +#if IS_ENABLED(CONFIG_REMOTEPROC) + { VIRTIO_ID_RPROC_SERIAL, VIRTIO_DEV_ANY_ID }, +#endif + { 0 }, +}; + +static unsigned int rproc_serial_features[] = { +}; + #ifdef CONFIG_PM static int virtcons_freeze(struct virtio_device *vdev) { @@ -2080,6 +2177,16 @@ static struct virtio_driver virtio_console = { #endif }; +static struct virtio_driver virtio_rproc_serial = { + .feature_table = rproc_serial_features, + .feature_table_size = ARRAY_SIZE(rproc_serial_features), + .driver.name = "virtio_rproc_serial", + .driver.owner = THIS_MODULE, + .id_table = rproc_serial_id_table, + .probe = virtcons_probe, + .remove = virtcons_remove, +}; + static int __init init(void) { int err; @@ -2104,7 +2211,15 @@ static int __init init(void) pr_err("Error %d registering virtio driver\n", err); goto free; } + err = register_virtio_driver(&virtio_rproc_serial); + if (err < 0) { + pr_err("Error %d registering virtio rproc serial driver\n", + err); + goto unregister; + } return 0; +unregister: + unregister_virtio_driver(&virtio_console); free: if (pdrvdata.debugfs_dir) debugfs_remove_recursive(pdrvdata.debugfs_dir); @@ -2114,7 +2229,10 @@ free: static void __exit fini(void) { + reclaim_dma_bufs(); + unregister_virtio_driver(&virtio_console); + unregister_virtio_driver(&virtio_rproc_serial); class_destroy(pdrvdata.class); if (pdrvdata.debugfs_dir) diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 2c5d15beea35..5224da5202d3 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -595,7 +595,7 @@ static const struct file_operations hwicap_fops = { .llseek = noop_llseek, }; -static int __devinit hwicap_setup(struct device *dev, int id, +static int hwicap_setup(struct device *dev, int id, const struct resource *regs_res, const struct hwicap_driver_config *config, const struct config_registers *config_regs) @@ -717,7 +717,7 @@ static struct hwicap_driver_config fifo_icap_config = { .reset = fifo_icap_reset, }; -static int __devexit hwicap_remove(struct device *dev) +static int hwicap_remove(struct device *dev) { struct hwicap_drvdata *drvdata; @@ -740,7 +740,7 @@ static int __devexit hwicap_remove(struct device *dev) } #ifdef CONFIG_OF -static int __devinit hwicap_of_probe(struct platform_device *op, +static int hwicap_of_probe(struct platform_device *op, const struct hwicap_driver_config *config) { struct resource res; @@ -785,8 +785,8 @@ static inline int hwicap_of_probe(struct platform_device *op, } #endif /* CONFIG_OF */ -static const struct of_device_id __devinitconst hwicap_of_match[]; -static int __devinit hwicap_drv_probe(struct platform_device *pdev) +static const struct of_device_id hwicap_of_match[]; +static int hwicap_drv_probe(struct platform_device *pdev) { const struct of_device_id *match; struct resource *res; @@ -822,14 +822,14 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev) &buffer_icap_config, regs); } -static int __devexit hwicap_drv_remove(struct platform_device *pdev) +static int hwicap_drv_remove(struct platform_device *pdev) { return hwicap_remove(&pdev->dev); } #ifdef CONFIG_OF /* Match table for device tree binding */ -static const struct of_device_id __devinitconst hwicap_of_match[] = { +static const struct of_device_id hwicap_of_match[] = { { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config}, {}, |