diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-05-08 21:29:27 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-05-08 21:29:27 -0400 |
commit | d585a021c0b10b0477d6b608c53e1feb8cde0507 (patch) | |
tree | 5ca059da1db7f15d4b29427644ad9c08270c885c /drivers/char | |
parent | 84e5b0d00f8f84c4ae226be131d4bebbcee88bd3 (diff) | |
parent | 091bf7624d1c90cec9e578a18529f615213ff847 (diff) |
Merge commit 'v2.6.30-rc5' into next
Diffstat (limited to 'drivers/char')
48 files changed, 1754 insertions, 978 deletions
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 52f4361eb6e4..d765afda9c2a 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -271,15 +271,15 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
271 | nb_order = (nb_order >> 1) & 7; | 271 | nb_order = (nb_order >> 1) & 7; |
272 | pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base); | 272 | pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base); |
273 | nb_aper = nb_base << 25; | 273 | nb_aper = nb_base << 25; |
274 | if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) { | ||
275 | return 0; | ||
276 | } | ||
277 | 274 | ||
278 | /* Northbridge seems to contain crap. Try the AGP bridge. */ | 275 | /* Northbridge seems to contain crap. Try the AGP bridge. */ |
279 | 276 | ||
280 | pci_read_config_word(agp, cap+0x14, &apsize); | 277 | pci_read_config_word(agp, cap+0x14, &apsize); |
281 | if (apsize == 0xffff) | 278 | if (apsize == 0xffff) { |
279 | if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) | ||
280 | return 0; | ||
282 | return -1; | 281 | return -1; |
282 | } | ||
283 | 283 | ||
284 | apsize &= 0xfff; | 284 | apsize &= 0xfff; |
285 | /* Some BIOS use weird encodings not in the AGPv3 table. */ | 285 | /* Some BIOS use weird encodings not in the AGPv3 table. */ |
@@ -301,6 +301,11 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
301 | order = nb_order; | 301 | order = nb_order; |
302 | } | 302 | } |
303 | 303 | ||
304 | if (nb_order >= order) { | ||
305 | if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) | ||
306 | return 0; | ||
307 | } | ||
308 | |||
304 | dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n", | 309 | dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n", |
305 | aper, 32 << order); | 310 | aper, 32 << order); |
306 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) | 311 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 10d6cbd7c05e..2224b762b7fb 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -1226,7 +1226,7 @@ int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *m | |||
1226 | int i, ret = -ENOMEM; | 1226 | int i, ret = -ENOMEM; |
1227 | 1227 | ||
1228 | for (i = 0; i < num_pages; i++) { | 1228 | for (i = 0; i < num_pages; i++) { |
1229 | page = alloc_page(GFP_KERNEL | GFP_DMA32); | 1229 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
1230 | /* agp_free_memory() needs gart address */ | 1230 | /* agp_free_memory() needs gart address */ |
1231 | if (page == NULL) | 1231 | if (page == NULL) |
1232 | goto out; | 1232 | goto out; |
@@ -1257,7 +1257,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | |||
1257 | { | 1257 | { |
1258 | struct page * page; | 1258 | struct page * page; |
1259 | 1259 | ||
1260 | page = alloc_page(GFP_KERNEL | GFP_DMA32); | 1260 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
1261 | if (page == NULL) | 1261 | if (page == NULL) |
1262 | return NULL; | 1262 | return NULL; |
1263 | 1263 | ||
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index c7714185f831..3686912427ba 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 | 26 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 |
27 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC | 27 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC |
28 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE | 28 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE |
29 | #define PCI_DEVICE_ID_INTEL_IGDGM_HB 0xA010 | ||
30 | #define PCI_DEVICE_ID_INTEL_IGDGM_IG 0xA011 | ||
31 | #define PCI_DEVICE_ID_INTEL_IGDG_HB 0xA000 | ||
32 | #define PCI_DEVICE_ID_INTEL_IGDG_IG 0xA001 | ||
29 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 | 33 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 |
30 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 | 34 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 |
31 | #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 | 35 | #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 |
@@ -60,7 +64,12 @@ | |||
60 | 64 | ||
61 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ | 65 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ |
62 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ | 66 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ |
63 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB) | 67 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ |
68 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ | ||
69 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) | ||
70 | |||
71 | #define IS_IGD (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ | ||
72 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) | ||
64 | 73 | ||
65 | #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ | 74 | #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ |
66 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ | 75 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ |
@@ -510,7 +519,7 @@ static void intel_i830_init_gtt_entries(void) | |||
510 | size = 512; | 519 | size = 512; |
511 | } | 520 | } |
512 | size += 4; /* add in BIOS popup space */ | 521 | size += 4; /* add in BIOS popup space */ |
513 | } else if (IS_G33) { | 522 | } else if (IS_G33 && !IS_IGD) { |
514 | /* G33's GTT size defined in gmch_ctrl */ | 523 | /* G33's GTT size defined in gmch_ctrl */ |
515 | switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { | 524 | switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { |
516 | case G33_PGETBL_SIZE_1M: | 525 | case G33_PGETBL_SIZE_1M: |
@@ -526,7 +535,7 @@ static void intel_i830_init_gtt_entries(void) | |||
526 | size = 512; | 535 | size = 512; |
527 | } | 536 | } |
528 | size += 4; | 537 | size += 4; |
529 | } else if (IS_G4X) { | 538 | } else if (IS_G4X || IS_IGD) { |
530 | /* On 4 series hardware, GTT stolen is separate from graphics | 539 | /* On 4 series hardware, GTT stolen is separate from graphics |
531 | * stolen, ignore it in stolen gtt entries counting. However, | 540 | * stolen, ignore it in stolen gtt entries counting. However, |
532 | * 4KB of the stolen memory doesn't get mapped to the GTT. | 541 | * 4KB of the stolen memory doesn't get mapped to the GTT. |
@@ -633,13 +642,15 @@ static void intel_i830_init_gtt_entries(void) | |||
633 | break; | 642 | break; |
634 | } | 643 | } |
635 | } | 644 | } |
636 | if (gtt_entries > 0) | 645 | if (gtt_entries > 0) { |
637 | dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", | 646 | dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", |
638 | gtt_entries / KB(1), local ? "local" : "stolen"); | 647 | gtt_entries / KB(1), local ? "local" : "stolen"); |
639 | else | 648 | gtt_entries /= KB(4); |
649 | } else { | ||
640 | dev_info(&agp_bridge->dev->dev, | 650 | dev_info(&agp_bridge->dev->dev, |
641 | "no pre-allocated video memory detected\n"); | 651 | "no pre-allocated video memory detected\n"); |
642 | gtt_entries /= KB(4); | 652 | gtt_entries = 0; |
653 | } | ||
643 | 654 | ||
644 | intel_private.gtt_entries = gtt_entries; | 655 | intel_private.gtt_entries = gtt_entries; |
645 | } | 656 | } |
@@ -2120,6 +2131,8 @@ static const struct intel_driver_description { | |||
2120 | { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M", | 2131 | { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M", |
2121 | &intel_845_driver, &intel_830_driver }, | 2132 | &intel_845_driver, &intel_830_driver }, |
2122 | { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL }, | 2133 | { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL }, |
2134 | { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854", | ||
2135 | &intel_845_driver, &intel_830_driver }, | ||
2123 | { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL }, | 2136 | { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL }, |
2124 | { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM", | 2137 | { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM", |
2125 | &intel_845_driver, &intel_830_driver }, | 2138 | &intel_845_driver, &intel_830_driver }, |
@@ -2159,6 +2172,10 @@ static const struct intel_driver_description { | |||
2159 | NULL, &intel_g33_driver }, | 2172 | NULL, &intel_g33_driver }, |
2160 | { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", | 2173 | { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", |
2161 | NULL, &intel_g33_driver }, | 2174 | NULL, &intel_g33_driver }, |
2175 | { PCI_DEVICE_ID_INTEL_IGDGM_HB, PCI_DEVICE_ID_INTEL_IGDGM_IG, 0, "IGD", | ||
2176 | NULL, &intel_g33_driver }, | ||
2177 | { PCI_DEVICE_ID_INTEL_IGDG_HB, PCI_DEVICE_ID_INTEL_IGDG_IG, 0, "IGD", | ||
2178 | NULL, &intel_g33_driver }, | ||
2162 | { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, | 2179 | { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, |
2163 | "Mobile Intel® GM45 Express", NULL, &intel_i965_driver }, | 2180 | "Mobile Intel® GM45 Express", NULL, &intel_i965_driver }, |
2164 | { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, | 2181 | { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, |
@@ -2340,6 +2357,7 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
2340 | ID(PCI_DEVICE_ID_INTEL_82845_HB), | 2357 | ID(PCI_DEVICE_ID_INTEL_82845_HB), |
2341 | ID(PCI_DEVICE_ID_INTEL_82845G_HB), | 2358 | ID(PCI_DEVICE_ID_INTEL_82845G_HB), |
2342 | ID(PCI_DEVICE_ID_INTEL_82850_HB), | 2359 | ID(PCI_DEVICE_ID_INTEL_82850_HB), |
2360 | ID(PCI_DEVICE_ID_INTEL_82854_HB), | ||
2343 | ID(PCI_DEVICE_ID_INTEL_82855PM_HB), | 2361 | ID(PCI_DEVICE_ID_INTEL_82855PM_HB), |
2344 | ID(PCI_DEVICE_ID_INTEL_82855GM_HB), | 2362 | ID(PCI_DEVICE_ID_INTEL_82855GM_HB), |
2345 | ID(PCI_DEVICE_ID_INTEL_82860_HB), | 2363 | ID(PCI_DEVICE_ID_INTEL_82860_HB), |
@@ -2353,6 +2371,8 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
2353 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), | 2371 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), |
2354 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), | 2372 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), |
2355 | ID(PCI_DEVICE_ID_INTEL_82945GME_HB), | 2373 | ID(PCI_DEVICE_ID_INTEL_82945GME_HB), |
2374 | ID(PCI_DEVICE_ID_INTEL_IGDGM_HB), | ||
2375 | ID(PCI_DEVICE_ID_INTEL_IGDG_HB), | ||
2356 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), | 2376 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), |
2357 | ID(PCI_DEVICE_ID_INTEL_82G35_HB), | 2377 | ID(PCI_DEVICE_ID_INTEL_82G35_HB), |
2358 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), | 2378 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), |
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index db60539bf67a..699e3422ad93 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c | |||
@@ -359,9 +359,16 @@ fail: | |||
359 | return error; | 359 | return error; |
360 | } | 360 | } |
361 | 361 | ||
362 | static struct device *next_device(struct klist_iter *i) { | 362 | static int |
363 | struct klist_node * n = klist_next(i); | 363 | find_quicksilver(struct device *dev, void *data) |
364 | return n ? container_of(n, struct device, knode_parent) : NULL; | 364 | { |
365 | struct parisc_device **lba = data; | ||
366 | struct parisc_device *padev = to_parisc_device(dev); | ||
367 | |||
368 | if (IS_QUICKSILVER(padev)) | ||
369 | *lba = padev; | ||
370 | |||
371 | return 0; | ||
365 | } | 372 | } |
366 | 373 | ||
367 | static int | 374 | static int |
@@ -372,8 +379,6 @@ parisc_agp_init(void) | |||
372 | int err = -1; | 379 | int err = -1; |
373 | struct parisc_device *sba = NULL, *lba = NULL; | 380 | struct parisc_device *sba = NULL, *lba = NULL; |
374 | struct lba_device *lbadev = NULL; | 381 | struct lba_device *lbadev = NULL; |
375 | struct device *dev = NULL; | ||
376 | struct klist_iter i; | ||
377 | 382 | ||
378 | if (!sba_list) | 383 | if (!sba_list) |
379 | goto out; | 384 | goto out; |
@@ -386,13 +391,7 @@ parisc_agp_init(void) | |||
386 | } | 391 | } |
387 | 392 | ||
388 | /* Now search our Pluto for our precious AGP device... */ | 393 | /* Now search our Pluto for our precious AGP device... */ |
389 | klist_iter_init(&sba->dev.klist_children, &i); | 394 | device_for_each_child(&sba->dev, &lba, find_quicksilver); |
390 | while ((dev = next_device(&i))) { | ||
391 | struct parisc_device *padev = to_parisc_device(dev); | ||
392 | if (IS_QUICKSILVER(padev)) | ||
393 | lba = padev; | ||
394 | } | ||
395 | klist_iter_exit(&i); | ||
396 | 395 | ||
397 | if (!lba) { | 396 | if (!lba) { |
398 | printk(KERN_INFO DRVPFX "No AGP devices found.\n"); | 397 | printk(KERN_INFO DRVPFX "No AGP devices found.\n"); |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index a58869ea8513..fd3ebd1be570 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -79,6 +79,7 @@ static char *serial_version = "4.30"; | |||
79 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
80 | #include <linux/ioport.h> | 80 | #include <linux/ioport.h> |
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | ||
82 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
83 | #include <linux/init.h> | 84 | #include <linux/init.h> |
84 | #include <linux/bitops.h> | 85 | #include <linux/bitops.h> |
@@ -1825,14 +1826,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp) | |||
1825 | * /proc fs routines.... | 1826 | * /proc fs routines.... |
1826 | */ | 1827 | */ |
1827 | 1828 | ||
1828 | static inline int line_info(char *buf, struct serial_state *state) | 1829 | static inline void line_info(struct seq_file *m, struct serial_state *state) |
1829 | { | 1830 | { |
1830 | struct async_struct *info = state->info, scr_info; | 1831 | struct async_struct *info = state->info, scr_info; |
1831 | char stat_buf[30], control, status; | 1832 | char stat_buf[30], control, status; |
1832 | int ret; | ||
1833 | unsigned long flags; | 1833 | unsigned long flags; |
1834 | 1834 | ||
1835 | ret = sprintf(buf, "%d: uart:amiga_builtin",state->line); | 1835 | seq_printf(m, "%d: uart:amiga_builtin",state->line); |
1836 | 1836 | ||
1837 | /* | 1837 | /* |
1838 | * Figure out the current RS-232 lines | 1838 | * Figure out the current RS-232 lines |
@@ -1864,55 +1864,49 @@ static inline int line_info(char *buf, struct serial_state *state) | |||
1864 | strcat(stat_buf, "|CD"); | 1864 | strcat(stat_buf, "|CD"); |
1865 | 1865 | ||
1866 | if (info->quot) { | 1866 | if (info->quot) { |
1867 | ret += sprintf(buf+ret, " baud:%d", | 1867 | seq_printf(m, " baud:%d", state->baud_base / info->quot); |
1868 | state->baud_base / info->quot); | ||
1869 | } | 1868 | } |
1870 | 1869 | ||
1871 | ret += sprintf(buf+ret, " tx:%d rx:%d", | 1870 | seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx); |
1872 | state->icount.tx, state->icount.rx); | ||
1873 | 1871 | ||
1874 | if (state->icount.frame) | 1872 | if (state->icount.frame) |
1875 | ret += sprintf(buf+ret, " fe:%d", state->icount.frame); | 1873 | seq_printf(m, " fe:%d", state->icount.frame); |
1876 | 1874 | ||
1877 | if (state->icount.parity) | 1875 | if (state->icount.parity) |
1878 | ret += sprintf(buf+ret, " pe:%d", state->icount.parity); | 1876 | seq_printf(m, " pe:%d", state->icount.parity); |
1879 | 1877 | ||
1880 | if (state->icount.brk) | 1878 | if (state->icount.brk) |
1881 | ret += sprintf(buf+ret, " brk:%d", state->icount.brk); | 1879 | seq_printf(m, " brk:%d", state->icount.brk); |
1882 | 1880 | ||
1883 | if (state->icount.overrun) | 1881 | if (state->icount.overrun) |
1884 | ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); | 1882 | seq_printf(m, " oe:%d", state->icount.overrun); |
1885 | 1883 | ||
1886 | /* | 1884 | /* |
1887 | * Last thing is the RS-232 status lines | 1885 | * Last thing is the RS-232 status lines |
1888 | */ | 1886 | */ |
1889 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1887 | seq_printf(m, " %s\n", stat_buf+1); |
1890 | return ret; | ||
1891 | } | 1888 | } |
1892 | 1889 | ||
1893 | static int rs_read_proc(char *page, char **start, off_t off, int count, | 1890 | static int rs_proc_show(struct seq_file *m, void *v) |
1894 | int *eof, void *data) | ||
1895 | { | 1891 | { |
1896 | int len = 0, l; | 1892 | seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); |
1897 | off_t begin = 0; | 1893 | line_info(m, &rs_table[0]); |
1898 | 1894 | return 0; | |
1899 | len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); | ||
1900 | l = line_info(page + len, &rs_table[0]); | ||
1901 | len += l; | ||
1902 | if (len+begin > off+count) | ||
1903 | goto done; | ||
1904 | if (len+begin < off) { | ||
1905 | begin += len; | ||
1906 | len = 0; | ||
1907 | } | ||
1908 | *eof = 1; | ||
1909 | done: | ||
1910 | if (off >= len+begin) | ||
1911 | return 0; | ||
1912 | *start = page + (off-begin); | ||
1913 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1914 | } | 1895 | } |
1915 | 1896 | ||
1897 | static int rs_proc_open(struct inode *inode, struct file *file) | ||
1898 | { | ||
1899 | return single_open(file, rs_proc_show, NULL); | ||
1900 | } | ||
1901 | |||
1902 | static const struct file_operations rs_proc_fops = { | ||
1903 | .owner = THIS_MODULE, | ||
1904 | .open = rs_proc_open, | ||
1905 | .read = seq_read, | ||
1906 | .llseek = seq_lseek, | ||
1907 | .release = single_release, | ||
1908 | }; | ||
1909 | |||
1916 | /* | 1910 | /* |
1917 | * --------------------------------------------------------------------- | 1911 | * --------------------------------------------------------------------- |
1918 | * rs_init() and friends | 1912 | * rs_init() and friends |
@@ -1951,9 +1945,9 @@ static const struct tty_operations serial_ops = { | |||
1951 | .break_ctl = rs_break, | 1945 | .break_ctl = rs_break, |
1952 | .send_xchar = rs_send_xchar, | 1946 | .send_xchar = rs_send_xchar, |
1953 | .wait_until_sent = rs_wait_until_sent, | 1947 | .wait_until_sent = rs_wait_until_sent, |
1954 | .read_proc = rs_read_proc, | ||
1955 | .tiocmget = rs_tiocmget, | 1948 | .tiocmget = rs_tiocmget, |
1956 | .tiocmset = rs_tiocmset, | 1949 | .tiocmset = rs_tiocmset, |
1950 | .proc_fops = &rs_proc_fops, | ||
1957 | }; | 1951 | }; |
1958 | 1952 | ||
1959 | /* | 1953 | /* |
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 05674febb0c6..73a0765344b6 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
@@ -75,6 +75,7 @@ MODULE_DEVICE_TABLE(pci, applicom_pci_tbl); | |||
75 | MODULE_AUTHOR("David Woodhouse & Applicom International"); | 75 | MODULE_AUTHOR("David Woodhouse & Applicom International"); |
76 | MODULE_DESCRIPTION("Driver for Applicom Profibus card"); | 76 | MODULE_DESCRIPTION("Driver for Applicom Profibus card"); |
77 | MODULE_LICENSE("GPL"); | 77 | MODULE_LICENSE("GPL"); |
78 | MODULE_ALIAS_MISCDEV(AC_MINOR); | ||
78 | 79 | ||
79 | MODULE_SUPPORTED_DEVICE("ac"); | 80 | MODULE_SUPPORTED_DEVICE("ac"); |
80 | 81 | ||
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index f6094ae0ef33..140ea10ecb88 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
@@ -140,7 +140,7 @@ static int bsr_open(struct inode * inode, struct file * filp) | |||
140 | return 0; | 140 | return 0; |
141 | } | 141 | } |
142 | 142 | ||
143 | const static struct file_operations bsr_fops = { | 143 | static const struct file_operations bsr_fops = { |
144 | .owner = THIS_MODULE, | 144 | .owner = THIS_MODULE, |
145 | .mmap = bsr_mmap, | 145 | .mmap = bsr_mmap, |
146 | .open = bsr_open, | 146 | .open = bsr_open, |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 6a59f72a9c21..1fdb9f657d8f 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -646,6 +646,7 @@ | |||
646 | #include <linux/spinlock.h> | 646 | #include <linux/spinlock.h> |
647 | #include <linux/bitops.h> | 647 | #include <linux/bitops.h> |
648 | #include <linux/firmware.h> | 648 | #include <linux/firmware.h> |
649 | #include <linux/device.h> | ||
649 | 650 | ||
650 | #include <asm/system.h> | 651 | #include <asm/system.h> |
651 | #include <linux/io.h> | 652 | #include <linux/io.h> |
@@ -657,6 +658,7 @@ | |||
657 | 658 | ||
658 | #include <linux/stat.h> | 659 | #include <linux/stat.h> |
659 | #include <linux/proc_fs.h> | 660 | #include <linux/proc_fs.h> |
661 | #include <linux/seq_file.h> | ||
660 | 662 | ||
661 | static void cy_throttle(struct tty_struct *tty); | 663 | static void cy_throttle(struct tty_struct *tty); |
662 | static void cy_send_xchar(struct tty_struct *tty, char ch); | 664 | static void cy_send_xchar(struct tty_struct *tty, char ch); |
@@ -868,8 +870,6 @@ static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); | |||
868 | static unsigned detect_isa_irq(void __iomem *); | 870 | static unsigned detect_isa_irq(void __iomem *); |
869 | #endif /* CONFIG_ISA */ | 871 | #endif /* CONFIG_ISA */ |
870 | 872 | ||
871 | static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *); | ||
872 | |||
873 | #ifndef CONFIG_CYZ_INTR | 873 | #ifndef CONFIG_CYZ_INTR |
874 | static void cyz_poll(unsigned long); | 874 | static void cyz_poll(unsigned long); |
875 | 875 | ||
@@ -5216,31 +5216,22 @@ static struct pci_driver cy_pci_driver = { | |||
5216 | }; | 5216 | }; |
5217 | #endif | 5217 | #endif |
5218 | 5218 | ||
5219 | static int | 5219 | static int cyclades_proc_show(struct seq_file *m, void *v) |
5220 | cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | ||
5221 | int *eof, void *data) | ||
5222 | { | 5220 | { |
5223 | struct cyclades_port *info; | 5221 | struct cyclades_port *info; |
5224 | unsigned int i, j; | 5222 | unsigned int i, j; |
5225 | int len = 0; | ||
5226 | off_t begin = 0; | ||
5227 | off_t pos = 0; | ||
5228 | int size; | ||
5229 | __u32 cur_jifs = jiffies; | 5223 | __u32 cur_jifs = jiffies; |
5230 | 5224 | ||
5231 | size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn " | 5225 | seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " |
5232 | "IdleIn Overruns Ldisc\n"); | 5226 | "IdleIn Overruns Ldisc\n"); |
5233 | 5227 | ||
5234 | pos += size; | ||
5235 | len += size; | ||
5236 | |||
5237 | /* Output one line for each known port */ | 5228 | /* Output one line for each known port */ |
5238 | for (i = 0; i < NR_CARDS; i++) | 5229 | for (i = 0; i < NR_CARDS; i++) |
5239 | for (j = 0; j < cy_card[i].nports; j++) { | 5230 | for (j = 0; j < cy_card[i].nports; j++) { |
5240 | info = &cy_card[i].ports[j]; | 5231 | info = &cy_card[i].ports[j]; |
5241 | 5232 | ||
5242 | if (info->port.count) | 5233 | if (info->port.count) |
5243 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5234 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5244 | "%10lu %8lu %9lu %6ld\n", info->line, | 5235 | "%10lu %8lu %9lu %6ld\n", info->line, |
5245 | (cur_jifs - info->idle_stats.in_use) / | 5236 | (cur_jifs - info->idle_stats.in_use) / |
5246 | HZ, info->idle_stats.xmit_bytes, | 5237 | HZ, info->idle_stats.xmit_bytes, |
@@ -5251,30 +5242,26 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5251 | /* FIXME: double check locking */ | 5242 | /* FIXME: double check locking */ |
5252 | (long)info->port.tty->ldisc.ops->num); | 5243 | (long)info->port.tty->ldisc.ops->num); |
5253 | else | 5244 | else |
5254 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5245 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5255 | "%10lu %8lu %9lu %6ld\n", | 5246 | "%10lu %8lu %9lu %6ld\n", |
5256 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); | 5247 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); |
5257 | len += size; | ||
5258 | pos = begin + len; | ||
5259 | |||
5260 | if (pos < offset) { | ||
5261 | len = 0; | ||
5262 | begin = pos; | ||
5263 | } | ||
5264 | if (pos > offset + length) | ||
5265 | goto done; | ||
5266 | } | 5248 | } |
5267 | *eof = 1; | 5249 | return 0; |
5268 | done: | 5250 | } |
5269 | *start = buf + (offset - begin); /* Start of wanted data */ | 5251 | |
5270 | len -= (offset - begin); /* Start slop */ | 5252 | static int cyclades_proc_open(struct inode *inode, struct file *file) |
5271 | if (len > length) | 5253 | { |
5272 | len = length; /* Ending slop */ | 5254 | return single_open(file, cyclades_proc_show, NULL); |
5273 | if (len < 0) | ||
5274 | len = 0; | ||
5275 | return len; | ||
5276 | } | 5255 | } |
5277 | 5256 | ||
5257 | static const struct file_operations cyclades_proc_fops = { | ||
5258 | .owner = THIS_MODULE, | ||
5259 | .open = cyclades_proc_open, | ||
5260 | .read = seq_read, | ||
5261 | .llseek = seq_lseek, | ||
5262 | .release = single_release, | ||
5263 | }; | ||
5264 | |||
5278 | /* The serial driver boot-time initialization code! | 5265 | /* The serial driver boot-time initialization code! |
5279 | Hardware I/O ports are mapped to character special devices on a | 5266 | Hardware I/O ports are mapped to character special devices on a |
5280 | first found, first allocated manner. That is, this code searches | 5267 | first found, first allocated manner. That is, this code searches |
@@ -5311,9 +5298,9 @@ static const struct tty_operations cy_ops = { | |||
5311 | .hangup = cy_hangup, | 5298 | .hangup = cy_hangup, |
5312 | .break_ctl = cy_break, | 5299 | .break_ctl = cy_break, |
5313 | .wait_until_sent = cy_wait_until_sent, | 5300 | .wait_until_sent = cy_wait_until_sent, |
5314 | .read_proc = cyclades_get_proc_info, | ||
5315 | .tiocmget = cy_tiocmget, | 5301 | .tiocmget = cy_tiocmget, |
5316 | .tiocmset = cy_tiocmset, | 5302 | .tiocmset = cy_tiocmset, |
5303 | .proc_fops = &cyclades_proc_fops, | ||
5317 | }; | 5304 | }; |
5318 | 5305 | ||
5319 | static int __init cy_init(void) | 5306 | static int __init cy_init(void) |
@@ -5422,3 +5409,4 @@ module_exit(cy_cleanup_module); | |||
5422 | 5409 | ||
5423 | MODULE_LICENSE("GPL"); | 5410 | MODULE_LICENSE("GPL"); |
5424 | MODULE_VERSION(CY_VERSION); | 5411 | MODULE_VERSION(CY_VERSION); |
5412 | MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); | ||
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 45ec263ec012..a5c59fc2b0ff 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -2258,7 +2258,7 @@ static int esp_open(struct tty_struct *tty, struct file *filp) | |||
2258 | * driver. | 2258 | * driver. |
2259 | */ | 2259 | */ |
2260 | 2260 | ||
2261 | static void show_serial_version(void) | 2261 | static void __init show_serial_version(void) |
2262 | { | 2262 | { |
2263 | printk(KERN_INFO "%s version %s (DMA %u)\n", | 2263 | printk(KERN_INFO "%s version %s (DMA %u)\n", |
2264 | serial_name, serial_version, dma); | 2264 | serial_name, serial_version, dma); |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 32b8bbf5003e..340ba4f9dc54 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -72,7 +72,7 @@ static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; | |||
72 | #ifdef CONFIG_IA64 | 72 | #ifdef CONFIG_IA64 |
73 | static void __iomem *hpet_mctr; | 73 | static void __iomem *hpet_mctr; |
74 | 74 | ||
75 | static cycle_t read_hpet(void) | 75 | static cycle_t read_hpet(struct clocksource *cs) |
76 | { | 76 | { |
77 | return (cycle_t)read_counter((void __iomem *)hpet_mctr); | 77 | return (cycle_t)read_counter((void __iomem *)hpet_mctr); |
78 | } | 78 | } |
@@ -713,7 +713,7 @@ static struct ctl_table_header *sysctl_header; | |||
713 | */ | 713 | */ |
714 | #define TICK_CALIBRATE (1000UL) | 714 | #define TICK_CALIBRATE (1000UL) |
715 | 715 | ||
716 | static unsigned long hpet_calibrate(struct hpets *hpetp) | 716 | static unsigned long __hpet_calibrate(struct hpets *hpetp) |
717 | { | 717 | { |
718 | struct hpet_timer __iomem *timer = NULL; | 718 | struct hpet_timer __iomem *timer = NULL; |
719 | unsigned long t, m, count, i, flags, start; | 719 | unsigned long t, m, count, i, flags, start; |
@@ -750,6 +750,26 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) | |||
750 | return (m - start) / i; | 750 | return (m - start) / i; |
751 | } | 751 | } |
752 | 752 | ||
753 | static unsigned long hpet_calibrate(struct hpets *hpetp) | ||
754 | { | ||
755 | unsigned long ret = -1; | ||
756 | unsigned long tmp; | ||
757 | |||
758 | /* | ||
759 | * Try to calibrate until return value becomes stable small value. | ||
760 | * If SMI interruption occurs in calibration loop, the return value | ||
761 | * will be big. This avoids its impact. | ||
762 | */ | ||
763 | for ( ; ; ) { | ||
764 | tmp = __hpet_calibrate(hpetp); | ||
765 | if (ret <= tmp) | ||
766 | break; | ||
767 | ret = tmp; | ||
768 | } | ||
769 | |||
770 | return ret; | ||
771 | } | ||
772 | |||
753 | int hpet_alloc(struct hpet_data *hdp) | 773 | int hpet_alloc(struct hpet_data *hdp) |
754 | { | 774 | { |
755 | u64 cap, mcfg; | 775 | u64 cap, mcfg; |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index a53496828b76..54481a887769 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -13,10 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <asm/ebcdic.h> | 15 | #include <asm/ebcdic.h> |
16 | #include <linux/ctype.h> | ||
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/mempool.h> | 19 | #include <linux/mempool.h> |
19 | #include <linux/module.h> | 20 | #include <linux/moduleparam.h> |
20 | #include <linux/tty.h> | 21 | #include <linux/tty.h> |
21 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
22 | #include <net/iucv/iucv.h> | 23 | #include <net/iucv/iucv.h> |
@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1; | |||
95 | /* Array of allocated hvc iucv tty lines... */ | 96 | /* Array of allocated hvc iucv tty lines... */ |
96 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; | 97 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; |
97 | #define IUCV_HVC_CON_IDX (0) | 98 | #define IUCV_HVC_CON_IDX (0) |
99 | /* List of z/VM user ID filter entries (struct iucv_vmid_filter) */ | ||
100 | #define MAX_VMID_FILTER (500) | ||
101 | static size_t hvc_iucv_filter_size; | ||
102 | static void *hvc_iucv_filter; | ||
103 | static const char *hvc_iucv_filter_string; | ||
104 | static DEFINE_RWLOCK(hvc_iucv_filter_lock); | ||
98 | 105 | ||
99 | /* Kmem cache and mempool for iucv_tty_buffer elements */ | 106 | /* Kmem cache and mempool for iucv_tty_buffer elements */ |
100 | static struct kmem_cache *hvc_iucv_buffer_cache; | 107 | static struct kmem_cache *hvc_iucv_buffer_cache; |
@@ -618,6 +625,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) | |||
618 | } | 625 | } |
619 | 626 | ||
620 | /** | 627 | /** |
628 | * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID | ||
629 | * @ipvmid: Originating z/VM user ID (right padded with blanks) | ||
630 | * | ||
631 | * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise | ||
632 | * non-zero. | ||
633 | */ | ||
634 | static int hvc_iucv_filter_connreq(u8 ipvmid[8]) | ||
635 | { | ||
636 | size_t i; | ||
637 | |||
638 | /* Note: default policy is ACCEPT if no filter is set */ | ||
639 | if (!hvc_iucv_filter_size) | ||
640 | return 0; | ||
641 | |||
642 | for (i = 0; i < hvc_iucv_filter_size; i++) | ||
643 | if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8)) | ||
644 | return 0; | ||
645 | return 1; | ||
646 | } | ||
647 | |||
648 | /** | ||
621 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. | 649 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. |
622 | * @path: Pending path (struct iucv_path) | 650 | * @path: Pending path (struct iucv_path) |
623 | * @ipvmid: z/VM system identifier of originator | 651 | * @ipvmid: z/VM system identifier of originator |
@@ -641,6 +669,7 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
641 | { | 669 | { |
642 | struct hvc_iucv_private *priv; | 670 | struct hvc_iucv_private *priv; |
643 | u8 nuser_data[16]; | 671 | u8 nuser_data[16]; |
672 | u8 vm_user_id[9]; | ||
644 | int i, rc; | 673 | int i, rc; |
645 | 674 | ||
646 | priv = NULL; | 675 | priv = NULL; |
@@ -653,6 +682,20 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
653 | if (!priv) | 682 | if (!priv) |
654 | return -ENODEV; | 683 | return -ENODEV; |
655 | 684 | ||
685 | /* Enforce that ipvmid is allowed to connect to us */ | ||
686 | read_lock(&hvc_iucv_filter_lock); | ||
687 | rc = hvc_iucv_filter_connreq(ipvmid); | ||
688 | read_unlock(&hvc_iucv_filter_lock); | ||
689 | if (rc) { | ||
690 | iucv_path_sever(path, ipuser); | ||
691 | iucv_path_free(path); | ||
692 | memcpy(vm_user_id, ipvmid, 8); | ||
693 | vm_user_id[8] = 0; | ||
694 | pr_info("A connection request from z/VM user ID %s " | ||
695 | "was refused\n", vm_user_id); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
656 | spin_lock(&priv->lock); | 699 | spin_lock(&priv->lock); |
657 | 700 | ||
658 | /* If the terminal is already connected or being severed, then sever | 701 | /* If the terminal is already connected or being severed, then sever |
@@ -877,6 +920,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) | |||
877 | } | 920 | } |
878 | 921 | ||
879 | /** | 922 | /** |
923 | * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID | ||
924 | * @filter: String containing a comma-separated list of z/VM user IDs | ||
925 | */ | ||
926 | static const char *hvc_iucv_parse_filter(const char *filter, char *dest) | ||
927 | { | ||
928 | const char *nextdelim, *residual; | ||
929 | size_t len; | ||
930 | |||
931 | nextdelim = strchr(filter, ','); | ||
932 | if (nextdelim) { | ||
933 | len = nextdelim - filter; | ||
934 | residual = nextdelim + 1; | ||
935 | } else { | ||
936 | len = strlen(filter); | ||
937 | residual = filter + len; | ||
938 | } | ||
939 | |||
940 | if (len == 0) | ||
941 | return ERR_PTR(-EINVAL); | ||
942 | |||
943 | /* check for '\n' (if called from sysfs) */ | ||
944 | if (filter[len - 1] == '\n') | ||
945 | len--; | ||
946 | |||
947 | if (len > 8) | ||
948 | return ERR_PTR(-EINVAL); | ||
949 | |||
950 | /* pad with blanks and save upper case version of user ID */ | ||
951 | memset(dest, ' ', 8); | ||
952 | while (len--) | ||
953 | dest[len] = toupper(filter[len]); | ||
954 | return residual; | ||
955 | } | ||
956 | |||
957 | /** | ||
958 | * hvc_iucv_setup_filter() - Set up z/VM user ID filter | ||
959 | * @filter: String consisting of a comma-separated list of z/VM user IDs | ||
960 | * | ||
961 | * The function parses the @filter string and creates an array containing | ||
962 | * the list of z/VM user ID filter entries. | ||
963 | * Return code 0 means success, -EINVAL if the filter is syntactically | ||
964 | * incorrect, -ENOMEM if there was not enough memory to allocate the | ||
965 | * filter list array, or -ENOSPC if too many z/VM user IDs have been specified. | ||
966 | */ | ||
967 | static int hvc_iucv_setup_filter(const char *val) | ||
968 | { | ||
969 | const char *residual; | ||
970 | int err; | ||
971 | size_t size, count; | ||
972 | void *array, *old_filter; | ||
973 | |||
974 | count = strlen(val); | ||
975 | if (count == 0 || (count == 1 && val[0] == '\n')) { | ||
976 | size = 0; | ||
977 | array = NULL; | ||
978 | goto out_replace_filter; /* clear filter */ | ||
979 | } | ||
980 | |||
981 | /* count user IDs in order to allocate sufficient memory */ | ||
982 | size = 1; | ||
983 | residual = val; | ||
984 | while ((residual = strchr(residual, ',')) != NULL) { | ||
985 | residual++; | ||
986 | size++; | ||
987 | } | ||
988 | |||
989 | /* check if the specified list exceeds the filter limit */ | ||
990 | if (size > MAX_VMID_FILTER) | ||
991 | return -ENOSPC; | ||
992 | |||
993 | array = kzalloc(size * 8, GFP_KERNEL); | ||
994 | if (!array) | ||
995 | return -ENOMEM; | ||
996 | |||
997 | count = size; | ||
998 | residual = val; | ||
999 | while (*residual && count) { | ||
1000 | residual = hvc_iucv_parse_filter(residual, | ||
1001 | array + ((size - count) * 8)); | ||
1002 | if (IS_ERR(residual)) { | ||
1003 | err = PTR_ERR(residual); | ||
1004 | kfree(array); | ||
1005 | goto out_err; | ||
1006 | } | ||
1007 | count--; | ||
1008 | } | ||
1009 | |||
1010 | out_replace_filter: | ||
1011 | write_lock_bh(&hvc_iucv_filter_lock); | ||
1012 | old_filter = hvc_iucv_filter; | ||
1013 | hvc_iucv_filter_size = size; | ||
1014 | hvc_iucv_filter = array; | ||
1015 | write_unlock_bh(&hvc_iucv_filter_lock); | ||
1016 | kfree(old_filter); | ||
1017 | |||
1018 | err = 0; | ||
1019 | out_err: | ||
1020 | return err; | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * param_set_vmidfilter() - Set z/VM user ID filter parameter | ||
1025 | * @val: String consisting of a comma-separated list of z/VM user IDs | ||
1026 | * @kp: Kernel parameter pointing to hvc_iucv_filter array | ||
1027 | * | ||
1028 | * The function sets up the z/VM user ID filter specified as comma-separated | ||
1029 | * list of user IDs in @val. | ||
1030 | * Note: If it is called early in the boot process, @val is stored and | ||
1031 | * parsed later in hvc_iucv_init(). | ||
1032 | */ | ||
1033 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | ||
1034 | { | ||
1035 | int rc; | ||
1036 | |||
1037 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
1038 | return -ENODEV; | ||
1039 | |||
1040 | if (!val) | ||
1041 | return -EINVAL; | ||
1042 | |||
1043 | rc = 0; | ||
1044 | if (slab_is_available()) | ||
1045 | rc = hvc_iucv_setup_filter(val); | ||
1046 | else | ||
1047 | hvc_iucv_filter_string = val; /* defer... */ | ||
1048 | return rc; | ||
1049 | } | ||
1050 | |||
1051 | /** | ||
1052 | * param_get_vmidfilter() - Get z/VM user ID filter | ||
1053 | * @buffer: Buffer to store z/VM user ID filter, | ||
1054 | * (buffer size assumption PAGE_SIZE) | ||
1055 | * @kp: Kernel parameter pointing to the hvc_iucv_filter array | ||
1056 | * | ||
1057 | * The function stores the filter as a comma-separated list of z/VM user IDs | ||
1058 | * in @buffer. Typically, sysfs routines call this function for attr show. | ||
1059 | */ | ||
1060 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | ||
1061 | { | ||
1062 | int rc; | ||
1063 | size_t index, len; | ||
1064 | void *start, *end; | ||
1065 | |||
1066 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
1067 | return -ENODEV; | ||
1068 | |||
1069 | rc = 0; | ||
1070 | read_lock_bh(&hvc_iucv_filter_lock); | ||
1071 | for (index = 0; index < hvc_iucv_filter_size; index++) { | ||
1072 | start = hvc_iucv_filter + (8 * index); | ||
1073 | end = memchr(start, ' ', 8); | ||
1074 | len = (end) ? end - start : 8; | ||
1075 | memcpy(buffer + rc, start, len); | ||
1076 | rc += len; | ||
1077 | buffer[rc++] = ','; | ||
1078 | } | ||
1079 | read_unlock_bh(&hvc_iucv_filter_lock); | ||
1080 | if (rc) | ||
1081 | buffer[--rc] = '\0'; /* replace last comma and update rc */ | ||
1082 | return rc; | ||
1083 | } | ||
1084 | |||
1085 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | ||
1086 | |||
1087 | /** | ||
880 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1088 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
881 | */ | 1089 | */ |
882 | static int __init hvc_iucv_init(void) | 1090 | static int __init hvc_iucv_init(void) |
@@ -884,24 +1092,53 @@ static int __init hvc_iucv_init(void) | |||
884 | int rc; | 1092 | int rc; |
885 | unsigned int i; | 1093 | unsigned int i; |
886 | 1094 | ||
1095 | if (!hvc_iucv_devices) | ||
1096 | return -ENODEV; | ||
1097 | |||
887 | if (!MACHINE_IS_VM) { | 1098 | if (!MACHINE_IS_VM) { |
888 | pr_info("The z/VM IUCV HVC device driver cannot " | 1099 | pr_notice("The z/VM IUCV HVC device driver cannot " |
889 | "be used without z/VM\n"); | 1100 | "be used without z/VM\n"); |
890 | return -ENODEV; | 1101 | rc = -ENODEV; |
1102 | goto out_error; | ||
891 | } | 1103 | } |
892 | 1104 | ||
893 | if (!hvc_iucv_devices) | 1105 | if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) { |
894 | return -ENODEV; | 1106 | pr_err("%lu is not a valid value for the hvc_iucv= " |
1107 | "kernel parameter\n", hvc_iucv_devices); | ||
1108 | rc = -EINVAL; | ||
1109 | goto out_error; | ||
1110 | } | ||
895 | 1111 | ||
896 | if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) | 1112 | /* parse hvc_iucv_allow string and create z/VM user ID filter list */ |
897 | return -EINVAL; | 1113 | if (hvc_iucv_filter_string) { |
1114 | rc = hvc_iucv_setup_filter(hvc_iucv_filter_string); | ||
1115 | switch (rc) { | ||
1116 | case 0: | ||
1117 | break; | ||
1118 | case -ENOMEM: | ||
1119 | pr_err("Allocating memory failed with " | ||
1120 | "reason code=%d\n", 3); | ||
1121 | goto out_error; | ||
1122 | case -EINVAL: | ||
1123 | pr_err("hvc_iucv_allow= does not specify a valid " | ||
1124 | "z/VM user ID list\n"); | ||
1125 | goto out_error; | ||
1126 | case -ENOSPC: | ||
1127 | pr_err("hvc_iucv_allow= specifies too many " | ||
1128 | "z/VM user IDs\n"); | ||
1129 | goto out_error; | ||
1130 | default: | ||
1131 | goto out_error; | ||
1132 | } | ||
1133 | } | ||
898 | 1134 | ||
899 | hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, | 1135 | hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, |
900 | sizeof(struct iucv_tty_buffer), | 1136 | sizeof(struct iucv_tty_buffer), |
901 | 0, 0, NULL); | 1137 | 0, 0, NULL); |
902 | if (!hvc_iucv_buffer_cache) { | 1138 | if (!hvc_iucv_buffer_cache) { |
903 | pr_err("Allocating memory failed with reason code=%d\n", 1); | 1139 | pr_err("Allocating memory failed with reason code=%d\n", 1); |
904 | return -ENOMEM; | 1140 | rc = -ENOMEM; |
1141 | goto out_error; | ||
905 | } | 1142 | } |
906 | 1143 | ||
907 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, | 1144 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, |
@@ -909,7 +1146,8 @@ static int __init hvc_iucv_init(void) | |||
909 | if (!hvc_iucv_mempool) { | 1146 | if (!hvc_iucv_mempool) { |
910 | pr_err("Allocating memory failed with reason code=%d\n", 2); | 1147 | pr_err("Allocating memory failed with reason code=%d\n", 2); |
911 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 1148 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
912 | return -ENOMEM; | 1149 | rc = -ENOMEM; |
1150 | goto out_error; | ||
913 | } | 1151 | } |
914 | 1152 | ||
915 | /* register the first terminal device as console | 1153 | /* register the first terminal device as console |
@@ -953,6 +1191,8 @@ out_error_hvc: | |||
953 | out_error_memory: | 1191 | out_error_memory: |
954 | mempool_destroy(hvc_iucv_mempool); | 1192 | mempool_destroy(hvc_iucv_mempool); |
955 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 1193 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
1194 | out_error: | ||
1195 | hvc_iucv_devices = 0; /* ensure that we do not provide any device */ | ||
956 | return rc; | 1196 | return rc; |
957 | } | 1197 | } |
958 | 1198 | ||
@@ -968,3 +1208,4 @@ static int __init hvc_iucv_config(char *val) | |||
968 | 1208 | ||
969 | device_initcall(hvc_iucv_init); | 1209 | device_initcall(hvc_iucv_init); |
970 | __setup("hvc_iucv=", hvc_iucv_config); | 1210 | __setup("hvc_iucv=", hvc_iucv_config); |
1211 | core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640); | ||
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 6e6eb445d374..c76bccf5354d 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -1139,15 +1139,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) | |||
1139 | hvcsd->tty = tty; | 1139 | hvcsd->tty = tty; |
1140 | tty->driver_data = hvcsd; | 1140 | tty->driver_data = hvcsd; |
1141 | 1141 | ||
1142 | /* | ||
1143 | * Set this driver to low latency so that we actually have a chance at | ||
1144 | * catching a throttled TTY after we flip_buffer_push. Otherwise the | ||
1145 | * flush_to_async may not execute until after the kernel_thread has | ||
1146 | * yielded and resumed the next flip_buffer_push resulting in data | ||
1147 | * loss. | ||
1148 | */ | ||
1149 | tty->low_latency = 1; | ||
1150 | |||
1151 | memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); | 1142 | memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); |
1152 | 1143 | ||
1153 | /* | 1144 | /* |
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 406f8742a260..2989056a9e39 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c | |||
@@ -810,7 +810,6 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) | |||
810 | hp = &hvsi_ports[line]; | 810 | hp = &hvsi_ports[line]; |
811 | 811 | ||
812 | tty->driver_data = hp; | 812 | tty->driver_data = hp; |
813 | tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */ | ||
814 | 813 | ||
815 | mb(); | 814 | mb(); |
816 | if (hp->state == HVSI_FSP_DIED) | 815 | if (hp->state == HVSI_FSP_DIED) |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8822eca58ffa..5fab6470f4b2 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -20,6 +20,20 @@ config HW_RANDOM | |||
20 | 20 | ||
21 | If unsure, say Y. | 21 | If unsure, say Y. |
22 | 22 | ||
23 | config HW_RANDOM_TIMERIOMEM | ||
24 | tristate "Timer IOMEM HW Random Number Generator support" | ||
25 | depends on HW_RANDOM && HAS_IOMEM | ||
26 | ---help--- | ||
27 | This driver provides kernel-side support for a generic Random | ||
28 | Number Generator used by reading a 'dumb' iomem address that | ||
29 | is to be read no faster than, for example, once a second; | ||
30 | the default FPGA bitstream on the TS-7800 has such functionality. | ||
31 | |||
32 | To compile this driver as a module, choose M here: the | ||
33 | module will be called timeriomem-rng. | ||
34 | |||
35 | If unsure, say Y. | ||
36 | |||
23 | config HW_RANDOM_INTEL | 37 | config HW_RANDOM_INTEL |
24 | tristate "Intel HW Random Number Generator support" | 38 | tristate "Intel HW Random Number Generator support" |
25 | depends on HW_RANDOM && (X86 || IA64) && PCI | 39 | depends on HW_RANDOM && (X86 || IA64) && PCI |
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b6effb7522c2..e81d21a5f28f 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_HW_RANDOM) += rng-core.o | 5 | obj-$(CONFIG_HW_RANDOM) += rng-core.o |
6 | rng-core-y := core.o | 6 | rng-core-y := core.o |
7 | obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o | ||
7 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o | 8 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o |
8 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o | 9 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o |
9 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o | 10 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o |
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index ba68a4671cb5..538313f9e7ac 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c | |||
@@ -102,7 +102,7 @@ static int __init omap_rng_probe(struct platform_device *pdev) | |||
102 | return -EBUSY; | 102 | return -EBUSY; |
103 | 103 | ||
104 | if (cpu_is_omap24xx()) { | 104 | if (cpu_is_omap24xx()) { |
105 | rng_ick = clk_get(&pdev->dev, "rng_ick"); | 105 | rng_ick = clk_get(&pdev->dev, "ick"); |
106 | if (IS_ERR(rng_ick)) { | 106 | if (IS_ERR(rng_ick)) { |
107 | dev_err(&pdev->dev, "Could not get rng_ick\n"); | 107 | dev_err(&pdev->dev, "Could not get rng_ick\n"); |
108 | ret = PTR_ERR(rng_ick); | 108 | ret = PTR_ERR(rng_ick); |
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c new file mode 100644 index 000000000000..dcd352ad0e7f --- /dev/null +++ b/drivers/char/hw_random/timeriomem-rng.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * drivers/char/hw_random/timeriomem-rng.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Alexander Clouter <alex@digriz.org.uk> | ||
5 | * | ||
6 | * Derived from drivers/char/hw_random/omap-rng.c | ||
7 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
8 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * Overview: | ||
15 | * This driver is useful for platforms that have an IO range that provides | ||
16 | * periodic random data from a single IO memory address. All the platform | ||
17 | * has to do is provide the address and 'wait time' that new data becomes | ||
18 | * available. | ||
19 | * | ||
20 | * TODO: add support for reading sizes other than 32bits and masking | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/hw_random.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/timeriomem-rng.h> | ||
29 | #include <linux/jiffies.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/timer.h> | ||
32 | #include <linux/completion.h> | ||
33 | |||
34 | static struct timeriomem_rng_data *timeriomem_rng_data; | ||
35 | |||
36 | static void timeriomem_rng_trigger(unsigned long); | ||
37 | static DEFINE_TIMER(timeriomem_rng_timer, timeriomem_rng_trigger, 0, 0); | ||
38 | |||
39 | /* | ||
40 | * have data return 1, however return 0 if we have nothing | ||
41 | */ | ||
42 | static int timeriomem_rng_data_present(struct hwrng *rng, int wait) | ||
43 | { | ||
44 | if (rng->priv == 0) | ||
45 | return 1; | ||
46 | |||
47 | if (!wait || timeriomem_rng_data->present) | ||
48 | return timeriomem_rng_data->present; | ||
49 | |||
50 | wait_for_completion(&timeriomem_rng_data->completion); | ||
51 | |||
52 | return 1; | ||
53 | } | ||
54 | |||
55 | static int timeriomem_rng_data_read(struct hwrng *rng, u32 *data) | ||
56 | { | ||
57 | unsigned long cur; | ||
58 | s32 delay; | ||
59 | |||
60 | *data = readl(timeriomem_rng_data->address); | ||
61 | |||
62 | if (rng->priv != 0) { | ||
63 | cur = jiffies; | ||
64 | |||
65 | delay = cur - timeriomem_rng_timer.expires; | ||
66 | delay = rng->priv - (delay % rng->priv); | ||
67 | |||
68 | timeriomem_rng_timer.expires = cur + delay; | ||
69 | timeriomem_rng_data->present = 0; | ||
70 | |||
71 | init_completion(&timeriomem_rng_data->completion); | ||
72 | add_timer(&timeriomem_rng_timer); | ||
73 | } | ||
74 | |||
75 | return 4; | ||
76 | } | ||
77 | |||
78 | static void timeriomem_rng_trigger(unsigned long dummy) | ||
79 | { | ||
80 | timeriomem_rng_data->present = 1; | ||
81 | complete(&timeriomem_rng_data->completion); | ||
82 | } | ||
83 | |||
84 | static struct hwrng timeriomem_rng_ops = { | ||
85 | .name = "timeriomem", | ||
86 | .data_present = timeriomem_rng_data_present, | ||
87 | .data_read = timeriomem_rng_data_read, | ||
88 | .priv = 0, | ||
89 | }; | ||
90 | |||
91 | static int __init timeriomem_rng_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | struct resource *res, *mem; | ||
94 | int ret; | ||
95 | |||
96 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
97 | |||
98 | if (!res) | ||
99 | return -ENOENT; | ||
100 | |||
101 | mem = request_mem_region(res->start, res->end - res->start + 1, | ||
102 | pdev->name); | ||
103 | if (mem == NULL) | ||
104 | return -EBUSY; | ||
105 | |||
106 | dev_set_drvdata(&pdev->dev, mem); | ||
107 | |||
108 | timeriomem_rng_data = pdev->dev.platform_data; | ||
109 | |||
110 | timeriomem_rng_data->address = ioremap(res->start, | ||
111 | res->end - res->start + 1); | ||
112 | if (!timeriomem_rng_data->address) { | ||
113 | ret = -ENOMEM; | ||
114 | goto err_ioremap; | ||
115 | } | ||
116 | |||
117 | if (timeriomem_rng_data->period != 0 | ||
118 | && usecs_to_jiffies(timeriomem_rng_data->period) > 0) { | ||
119 | timeriomem_rng_timer.expires = jiffies; | ||
120 | |||
121 | timeriomem_rng_ops.priv = usecs_to_jiffies( | ||
122 | timeriomem_rng_data->period); | ||
123 | } | ||
124 | timeriomem_rng_data->present = 1; | ||
125 | |||
126 | ret = hwrng_register(&timeriomem_rng_ops); | ||
127 | if (ret) | ||
128 | goto err_register; | ||
129 | |||
130 | dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n", | ||
131 | timeriomem_rng_data->address, | ||
132 | timeriomem_rng_data->period); | ||
133 | |||
134 | return 0; | ||
135 | |||
136 | err_register: | ||
137 | dev_err(&pdev->dev, "problem registering\n"); | ||
138 | iounmap(timeriomem_rng_data->address); | ||
139 | err_ioremap: | ||
140 | release_resource(mem); | ||
141 | |||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | static int __devexit timeriomem_rng_remove(struct platform_device *pdev) | ||
146 | { | ||
147 | struct resource *mem = dev_get_drvdata(&pdev->dev); | ||
148 | |||
149 | del_timer_sync(&timeriomem_rng_timer); | ||
150 | hwrng_unregister(&timeriomem_rng_ops); | ||
151 | |||
152 | iounmap(timeriomem_rng_data->address); | ||
153 | release_resource(mem); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct platform_driver timeriomem_rng_driver = { | ||
159 | .driver = { | ||
160 | .name = "timeriomem_rng", | ||
161 | .owner = THIS_MODULE, | ||
162 | }, | ||
163 | .probe = timeriomem_rng_probe, | ||
164 | .remove = __devexit_p(timeriomem_rng_remove), | ||
165 | }; | ||
166 | |||
167 | static int __init timeriomem_rng_init(void) | ||
168 | { | ||
169 | return platform_driver_register(&timeriomem_rng_driver); | ||
170 | } | ||
171 | |||
172 | static void __exit timeriomem_rng_exit(void) | ||
173 | { | ||
174 | platform_driver_unregister(&timeriomem_rng_driver); | ||
175 | } | ||
176 | |||
177 | module_init(timeriomem_rng_init); | ||
178 | module_exit(timeriomem_rng_exit); | ||
179 | |||
180 | MODULE_LICENSE("GPL"); | ||
181 | MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); | ||
182 | MODULE_DESCRIPTION("Timer IOMEM H/W RNG driver"); | ||
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index d0e563e4fc39..86e83f883139 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -37,9 +37,9 @@ static void random_recv_done(struct virtqueue *vq) | |||
37 | { | 37 | { |
38 | int len; | 38 | int len; |
39 | 39 | ||
40 | /* We never get spurious callbacks. */ | 40 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ |
41 | if (!vq->vq_ops->get_buf(vq, &len)) | 41 | if (!vq->vq_ops->get_buf(vq, &len)) |
42 | BUG(); | 42 | return; |
43 | 43 | ||
44 | data_left = len / sizeof(random_data[0]); | 44 | data_left = len / sizeof(random_data[0]); |
45 | complete(&have_data); | 45 | complete(&have_data); |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 70e0ebc30bd0..afd9247cf082 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -139,7 +139,7 @@ | |||
139 | #include <linux/seq_file.h> | 139 | #include <linux/seq_file.h> |
140 | 140 | ||
141 | static const struct file_operations ip2mem_proc_fops; | 141 | static const struct file_operations ip2mem_proc_fops; |
142 | static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); | 142 | static const struct file_operations ip2_proc_fops; |
143 | 143 | ||
144 | /********************/ | 144 | /********************/ |
145 | /* Type Definitions */ | 145 | /* Type Definitions */ |
@@ -446,9 +446,9 @@ static const struct tty_operations ip2_ops = { | |||
446 | .stop = ip2_stop, | 446 | .stop = ip2_stop, |
447 | .start = ip2_start, | 447 | .start = ip2_start, |
448 | .hangup = ip2_hangup, | 448 | .hangup = ip2_hangup, |
449 | .read_proc = ip2_read_proc, | ||
450 | .tiocmget = ip2_tiocmget, | 449 | .tiocmget = ip2_tiocmget, |
451 | .tiocmset = ip2_tiocmset, | 450 | .tiocmset = ip2_tiocmset, |
451 | .proc_fops = &ip2_proc_fops, | ||
452 | }; | 452 | }; |
453 | 453 | ||
454 | /******************************************************************************/ | 454 | /******************************************************************************/ |
@@ -3029,19 +3029,17 @@ static const struct file_operations ip2mem_proc_fops = { | |||
3029 | * different sources including ip2mkdev.c and a couple of other drivers. | 3029 | * different sources including ip2mkdev.c and a couple of other drivers. |
3030 | * The bugs are all mine. :-) =mhw= | 3030 | * The bugs are all mine. :-) =mhw= |
3031 | */ | 3031 | */ |
3032 | static int ip2_read_proc(char *page, char **start, off_t off, | 3032 | static int ip2_proc_show(struct seq_file *m, void *v) |
3033 | int count, int *eof, void *data) | ||
3034 | { | 3033 | { |
3035 | int i, j, box; | 3034 | int i, j, box; |
3036 | int len = 0; | ||
3037 | int boxes = 0; | 3035 | int boxes = 0; |
3038 | int ports = 0; | 3036 | int ports = 0; |
3039 | int tports = 0; | 3037 | int tports = 0; |
3040 | off_t begin = 0; | ||
3041 | i2eBordStrPtr pB; | 3038 | i2eBordStrPtr pB; |
3039 | char *sep; | ||
3042 | 3040 | ||
3043 | len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion ); | 3041 | seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); |
3044 | len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", | 3042 | seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", |
3045 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, | 3043 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, |
3046 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); | 3044 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); |
3047 | 3045 | ||
@@ -3053,7 +3051,8 @@ static int ip2_read_proc(char *page, char **start, off_t off, | |||
3053 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) | 3051 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) |
3054 | { | 3052 | { |
3055 | case POR_ID_FIIEX: | 3053 | case POR_ID_FIIEX: |
3056 | len += sprintf( page+len, "Board %d: EX ports=", i ); | 3054 | seq_printf(m, "Board %d: EX ports=", i); |
3055 | sep = ""; | ||
3057 | for( box = 0; box < ABS_MAX_BOXES; ++box ) | 3056 | for( box = 0; box < ABS_MAX_BOXES; ++box ) |
3058 | { | 3057 | { |
3059 | ports = 0; | 3058 | ports = 0; |
@@ -3065,79 +3064,74 @@ static int ip2_read_proc(char *page, char **start, off_t off, | |||
3065 | ++ports; | 3064 | ++ports; |
3066 | } | 3065 | } |
3067 | } | 3066 | } |
3068 | len += sprintf( page+len, "%d,", ports ); | 3067 | seq_printf(m, "%s%d", sep, ports); |
3068 | sep = ","; | ||
3069 | tports += ports; | 3069 | tports += ports; |
3070 | } | 3070 | } |
3071 | 3071 | seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); | |
3072 | --len; /* Backup over that last comma */ | ||
3073 | |||
3074 | len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 ); | ||
3075 | break; | 3072 | break; |
3076 | 3073 | ||
3077 | case POR_ID_II_4: | 3074 | case POR_ID_II_4: |
3078 | len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i ); | 3075 | seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); |
3079 | tports = ports = 4; | 3076 | tports = ports = 4; |
3080 | break; | 3077 | break; |
3081 | 3078 | ||
3082 | case POR_ID_II_8: | 3079 | case POR_ID_II_8: |
3083 | len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i ); | 3080 | seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); |
3084 | tports = ports = 8; | 3081 | tports = ports = 8; |
3085 | break; | 3082 | break; |
3086 | 3083 | ||
3087 | case POR_ID_II_8R: | 3084 | case POR_ID_II_8R: |
3088 | len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i ); | 3085 | seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); |
3089 | tports = ports = 8; | 3086 | tports = ports = 8; |
3090 | break; | 3087 | break; |
3091 | 3088 | ||
3092 | default: | 3089 | default: |
3093 | len += sprintf(page+len, "Board %d: unknown", i ); | 3090 | seq_printf(m, "Board %d: unknown", i); |
3094 | /* Don't try and probe for minor numbers */ | 3091 | /* Don't try and probe for minor numbers */ |
3095 | tports = ports = 0; | 3092 | tports = ports = 0; |
3096 | } | 3093 | } |
3097 | 3094 | ||
3098 | } else { | 3095 | } else { |
3099 | /* Don't try and probe for minor numbers */ | 3096 | /* Don't try and probe for minor numbers */ |
3100 | len += sprintf(page+len, "Board %d: vacant", i ); | 3097 | seq_printf(m, "Board %d: vacant", i); |
3101 | tports = ports = 0; | 3098 | tports = ports = 0; |
3102 | } | 3099 | } |
3103 | 3100 | ||
3104 | if( tports ) { | 3101 | if( tports ) { |
3105 | len += sprintf(page+len, " minors=" ); | 3102 | seq_puts(m, " minors="); |
3106 | 3103 | sep = ""; | |
3107 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 3104 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) |
3108 | { | 3105 | { |
3109 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | 3106 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) |
3110 | { | 3107 | { |
3111 | if ( pB->i2eChannelMap[box] & (1 << j) ) | 3108 | if ( pB->i2eChannelMap[box] & (1 << j) ) |
3112 | { | 3109 | { |
3113 | len += sprintf (page+len,"%d,", | 3110 | seq_printf(m, "%s%d", sep, |
3114 | j + ABS_BIGGEST_BOX * | 3111 | j + ABS_BIGGEST_BOX * |
3115 | (box+i*ABS_MAX_BOXES)); | 3112 | (box+i*ABS_MAX_BOXES)); |
3113 | sep = ","; | ||
3116 | } | 3114 | } |
3117 | } | 3115 | } |
3118 | } | 3116 | } |
3119 | |||
3120 | page[ len - 1 ] = '\n'; /* Overwrite that last comma */ | ||
3121 | } else { | ||
3122 | len += sprintf (page+len,"\n" ); | ||
3123 | } | ||
3124 | |||
3125 | if (len+begin > off+count) | ||
3126 | break; | ||
3127 | if (len+begin < off) { | ||
3128 | begin += len; | ||
3129 | len = 0; | ||
3130 | } | 3117 | } |
3118 | seq_putc(m, '\n'); | ||
3131 | } | 3119 | } |
3120 | return 0; | ||
3121 | } | ||
3132 | 3122 | ||
3133 | if (i >= IP2_MAX_BOARDS) | 3123 | static int ip2_proc_open(struct inode *inode, struct file *file) |
3134 | *eof = 1; | 3124 | { |
3135 | if (off >= len+begin) | 3125 | return single_open(file, ip2_proc_show, NULL); |
3136 | return 0; | 3126 | } |
3137 | 3127 | ||
3138 | *start = page + (off-begin); | 3128 | static const struct file_operations ip2_proc_fops = { |
3139 | return ((count < begin+len-off) ? count : begin+len-off); | 3129 | .owner = THIS_MODULE, |
3140 | } | 3130 | .open = ip2_proc_open, |
3131 | .read = seq_read, | ||
3132 | .llseek = seq_lseek, | ||
3133 | .release = single_release, | ||
3134 | }; | ||
3141 | 3135 | ||
3142 | /******************************************************************************/ | 3136 | /******************************************************************************/ |
3143 | /* Function: ip2trace() */ | 3137 | /* Function: ip2trace() */ |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 7a88dfd4427b..aa83a0865ec1 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -285,6 +285,11 @@ enum ipmi_stat_indexes { | |||
285 | /* Events that were received with the proper format. */ | 285 | /* Events that were received with the proper format. */ |
286 | IPMI_STAT_events, | 286 | IPMI_STAT_events, |
287 | 287 | ||
288 | /* Retransmissions on IPMB that failed. */ | ||
289 | IPMI_STAT_dropped_rexmit_ipmb_commands, | ||
290 | |||
291 | /* Retransmissions on LAN that failed. */ | ||
292 | IPMI_STAT_dropped_rexmit_lan_commands, | ||
288 | 293 | ||
289 | /* This *must* remain last, add new values above this. */ | 294 | /* This *must* remain last, add new values above this. */ |
290 | IPMI_NUM_STATS | 295 | IPMI_NUM_STATS |
@@ -445,6 +450,20 @@ static DEFINE_MUTEX(smi_watchers_mutex); | |||
445 | #define ipmi_get_stat(intf, stat) \ | 450 | #define ipmi_get_stat(intf, stat) \ |
446 | ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) | 451 | ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) |
447 | 452 | ||
453 | static int is_lan_addr(struct ipmi_addr *addr) | ||
454 | { | ||
455 | return addr->addr_type == IPMI_LAN_ADDR_TYPE; | ||
456 | } | ||
457 | |||
458 | static int is_ipmb_addr(struct ipmi_addr *addr) | ||
459 | { | ||
460 | return addr->addr_type == IPMI_IPMB_ADDR_TYPE; | ||
461 | } | ||
462 | |||
463 | static int is_ipmb_bcast_addr(struct ipmi_addr *addr) | ||
464 | { | ||
465 | return addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE; | ||
466 | } | ||
448 | 467 | ||
449 | static void free_recv_msg_list(struct list_head *q) | 468 | static void free_recv_msg_list(struct list_head *q) |
450 | { | 469 | { |
@@ -601,8 +620,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) | |||
601 | return (smi_addr1->lun == smi_addr2->lun); | 620 | return (smi_addr1->lun == smi_addr2->lun); |
602 | } | 621 | } |
603 | 622 | ||
604 | if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE) | 623 | if (is_ipmb_addr(addr1) || is_ipmb_bcast_addr(addr1)) { |
605 | || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { | ||
606 | struct ipmi_ipmb_addr *ipmb_addr1 | 624 | struct ipmi_ipmb_addr *ipmb_addr1 |
607 | = (struct ipmi_ipmb_addr *) addr1; | 625 | = (struct ipmi_ipmb_addr *) addr1; |
608 | struct ipmi_ipmb_addr *ipmb_addr2 | 626 | struct ipmi_ipmb_addr *ipmb_addr2 |
@@ -612,7 +630,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) | |||
612 | && (ipmb_addr1->lun == ipmb_addr2->lun)); | 630 | && (ipmb_addr1->lun == ipmb_addr2->lun)); |
613 | } | 631 | } |
614 | 632 | ||
615 | if (addr1->addr_type == IPMI_LAN_ADDR_TYPE) { | 633 | if (is_lan_addr(addr1)) { |
616 | struct ipmi_lan_addr *lan_addr1 | 634 | struct ipmi_lan_addr *lan_addr1 |
617 | = (struct ipmi_lan_addr *) addr1; | 635 | = (struct ipmi_lan_addr *) addr1; |
618 | struct ipmi_lan_addr *lan_addr2 | 636 | struct ipmi_lan_addr *lan_addr2 |
@@ -644,14 +662,13 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len) | |||
644 | || (addr->channel < 0)) | 662 | || (addr->channel < 0)) |
645 | return -EINVAL; | 663 | return -EINVAL; |
646 | 664 | ||
647 | if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) | 665 | if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) { |
648 | || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { | ||
649 | if (len < sizeof(struct ipmi_ipmb_addr)) | 666 | if (len < sizeof(struct ipmi_ipmb_addr)) |
650 | return -EINVAL; | 667 | return -EINVAL; |
651 | return 0; | 668 | return 0; |
652 | } | 669 | } |
653 | 670 | ||
654 | if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { | 671 | if (is_lan_addr(addr)) { |
655 | if (len < sizeof(struct ipmi_lan_addr)) | 672 | if (len < sizeof(struct ipmi_lan_addr)) |
656 | return -EINVAL; | 673 | return -EINVAL; |
657 | return 0; | 674 | return 0; |
@@ -1503,8 +1520,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1503 | memcpy(&(smi_msg->data[2]), msg->data, msg->data_len); | 1520 | memcpy(&(smi_msg->data[2]), msg->data, msg->data_len); |
1504 | smi_msg->data_size = msg->data_len + 2; | 1521 | smi_msg->data_size = msg->data_len + 2; |
1505 | ipmi_inc_stat(intf, sent_local_commands); | 1522 | ipmi_inc_stat(intf, sent_local_commands); |
1506 | } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) | 1523 | } else if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) { |
1507 | || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { | ||
1508 | struct ipmi_ipmb_addr *ipmb_addr; | 1524 | struct ipmi_ipmb_addr *ipmb_addr; |
1509 | unsigned char ipmb_seq; | 1525 | unsigned char ipmb_seq; |
1510 | long seqid; | 1526 | long seqid; |
@@ -1583,8 +1599,6 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1583 | 1599 | ||
1584 | spin_lock_irqsave(&(intf->seq_lock), flags); | 1600 | spin_lock_irqsave(&(intf->seq_lock), flags); |
1585 | 1601 | ||
1586 | ipmi_inc_stat(intf, sent_ipmb_commands); | ||
1587 | |||
1588 | /* | 1602 | /* |
1589 | * Create a sequence number with a 1 second | 1603 | * Create a sequence number with a 1 second |
1590 | * timeout and 4 retries. | 1604 | * timeout and 4 retries. |
@@ -1606,6 +1620,8 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1606 | goto out_err; | 1620 | goto out_err; |
1607 | } | 1621 | } |
1608 | 1622 | ||
1623 | ipmi_inc_stat(intf, sent_ipmb_commands); | ||
1624 | |||
1609 | /* | 1625 | /* |
1610 | * Store the sequence number in the message, | 1626 | * Store the sequence number in the message, |
1611 | * so that when the send message response | 1627 | * so that when the send message response |
@@ -1635,7 +1651,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1635 | */ | 1651 | */ |
1636 | spin_unlock_irqrestore(&(intf->seq_lock), flags); | 1652 | spin_unlock_irqrestore(&(intf->seq_lock), flags); |
1637 | } | 1653 | } |
1638 | } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { | 1654 | } else if (is_lan_addr(addr)) { |
1639 | struct ipmi_lan_addr *lan_addr; | 1655 | struct ipmi_lan_addr *lan_addr; |
1640 | unsigned char ipmb_seq; | 1656 | unsigned char ipmb_seq; |
1641 | long seqid; | 1657 | long seqid; |
@@ -1696,8 +1712,6 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1696 | 1712 | ||
1697 | spin_lock_irqsave(&(intf->seq_lock), flags); | 1713 | spin_lock_irqsave(&(intf->seq_lock), flags); |
1698 | 1714 | ||
1699 | ipmi_inc_stat(intf, sent_lan_commands); | ||
1700 | |||
1701 | /* | 1715 | /* |
1702 | * Create a sequence number with a 1 second | 1716 | * Create a sequence number with a 1 second |
1703 | * timeout and 4 retries. | 1717 | * timeout and 4 retries. |
@@ -1719,6 +1733,8 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1719 | goto out_err; | 1733 | goto out_err; |
1720 | } | 1734 | } |
1721 | 1735 | ||
1736 | ipmi_inc_stat(intf, sent_lan_commands); | ||
1737 | |||
1722 | /* | 1738 | /* |
1723 | * Store the sequence number in the message, | 1739 | * Store the sequence number in the message, |
1724 | * so that when the send message response | 1740 | * so that when the send message response |
@@ -1937,6 +1953,10 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
1937 | ipmi_get_stat(intf, invalid_events)); | 1953 | ipmi_get_stat(intf, invalid_events)); |
1938 | out += sprintf(out, "events: %u\n", | 1954 | out += sprintf(out, "events: %u\n", |
1939 | ipmi_get_stat(intf, events)); | 1955 | ipmi_get_stat(intf, events)); |
1956 | out += sprintf(out, "failed rexmit LAN msgs: %u\n", | ||
1957 | ipmi_get_stat(intf, dropped_rexmit_lan_commands)); | ||
1958 | out += sprintf(out, "failed rexmit IPMB msgs: %u\n", | ||
1959 | ipmi_get_stat(intf, dropped_rexmit_ipmb_commands)); | ||
1940 | 1960 | ||
1941 | return (out - ((char *) page)); | 1961 | return (out - ((char *) page)); |
1942 | } | 1962 | } |
@@ -1944,7 +1964,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
1944 | 1964 | ||
1945 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | 1965 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, |
1946 | read_proc_t *read_proc, | 1966 | read_proc_t *read_proc, |
1947 | void *data, struct module *owner) | 1967 | void *data) |
1948 | { | 1968 | { |
1949 | int rv = 0; | 1969 | int rv = 0; |
1950 | #ifdef CONFIG_PROC_FS | 1970 | #ifdef CONFIG_PROC_FS |
@@ -1970,7 +1990,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | |||
1970 | } else { | 1990 | } else { |
1971 | file->data = data; | 1991 | file->data = data; |
1972 | file->read_proc = read_proc; | 1992 | file->read_proc = read_proc; |
1973 | file->owner = owner; | ||
1974 | 1993 | ||
1975 | mutex_lock(&smi->proc_entry_lock); | 1994 | mutex_lock(&smi->proc_entry_lock); |
1976 | /* Stick it on the list. */ | 1995 | /* Stick it on the list. */ |
@@ -1993,23 +2012,21 @@ static int add_proc_entries(ipmi_smi_t smi, int num) | |||
1993 | smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); | 2012 | smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); |
1994 | if (!smi->proc_dir) | 2013 | if (!smi->proc_dir) |
1995 | rv = -ENOMEM; | 2014 | rv = -ENOMEM; |
1996 | else | ||
1997 | smi->proc_dir->owner = THIS_MODULE; | ||
1998 | 2015 | ||
1999 | if (rv == 0) | 2016 | if (rv == 0) |
2000 | rv = ipmi_smi_add_proc_entry(smi, "stats", | 2017 | rv = ipmi_smi_add_proc_entry(smi, "stats", |
2001 | stat_file_read_proc, | 2018 | stat_file_read_proc, |
2002 | smi, THIS_MODULE); | 2019 | smi); |
2003 | 2020 | ||
2004 | if (rv == 0) | 2021 | if (rv == 0) |
2005 | rv = ipmi_smi_add_proc_entry(smi, "ipmb", | 2022 | rv = ipmi_smi_add_proc_entry(smi, "ipmb", |
2006 | ipmb_file_read_proc, | 2023 | ipmb_file_read_proc, |
2007 | smi, THIS_MODULE); | 2024 | smi); |
2008 | 2025 | ||
2009 | if (rv == 0) | 2026 | if (rv == 0) |
2010 | rv = ipmi_smi_add_proc_entry(smi, "version", | 2027 | rv = ipmi_smi_add_proc_entry(smi, "version", |
2011 | version_file_read_proc, | 2028 | version_file_read_proc, |
2012 | smi, THIS_MODULE); | 2029 | smi); |
2013 | #endif /* CONFIG_PROC_FS */ | 2030 | #endif /* CONFIG_PROC_FS */ |
2014 | 2031 | ||
2015 | return rv; | 2032 | return rv; |
@@ -3267,6 +3284,114 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
3267 | return rv; | 3284 | return rv; |
3268 | } | 3285 | } |
3269 | 3286 | ||
3287 | /* | ||
3288 | * This routine will handle "Get Message" command responses with | ||
3289 | * channels that use an OEM Medium. The message format belongs to | ||
3290 | * the OEM. See IPMI 2.0 specification, Chapter 6 and | ||
3291 | * Chapter 22, sections 22.6 and 22.24 for more details. | ||
3292 | */ | ||
3293 | static int handle_oem_get_msg_cmd(ipmi_smi_t intf, | ||
3294 | struct ipmi_smi_msg *msg) | ||
3295 | { | ||
3296 | struct cmd_rcvr *rcvr; | ||
3297 | int rv = 0; | ||
3298 | unsigned char netfn; | ||
3299 | unsigned char cmd; | ||
3300 | unsigned char chan; | ||
3301 | ipmi_user_t user = NULL; | ||
3302 | struct ipmi_system_interface_addr *smi_addr; | ||
3303 | struct ipmi_recv_msg *recv_msg; | ||
3304 | |||
3305 | /* | ||
3306 | * We expect the OEM SW to perform error checking | ||
3307 | * so we just do some basic sanity checks | ||
3308 | */ | ||
3309 | if (msg->rsp_size < 4) { | ||
3310 | /* Message not big enough, just ignore it. */ | ||
3311 | ipmi_inc_stat(intf, invalid_commands); | ||
3312 | return 0; | ||
3313 | } | ||
3314 | |||
3315 | if (msg->rsp[2] != 0) { | ||
3316 | /* An error getting the response, just ignore it. */ | ||
3317 | return 0; | ||
3318 | } | ||
3319 | |||
3320 | /* | ||
3321 | * This is an OEM Message so the OEM needs to know how | ||
3322 | * handle the message. We do no interpretation. | ||
3323 | */ | ||
3324 | netfn = msg->rsp[0] >> 2; | ||
3325 | cmd = msg->rsp[1]; | ||
3326 | chan = msg->rsp[3] & 0xf; | ||
3327 | |||
3328 | rcu_read_lock(); | ||
3329 | rcvr = find_cmd_rcvr(intf, netfn, cmd, chan); | ||
3330 | if (rcvr) { | ||
3331 | user = rcvr->user; | ||
3332 | kref_get(&user->refcount); | ||
3333 | } else | ||
3334 | user = NULL; | ||
3335 | rcu_read_unlock(); | ||
3336 | |||
3337 | if (user == NULL) { | ||
3338 | /* We didn't find a user, just give up. */ | ||
3339 | ipmi_inc_stat(intf, unhandled_commands); | ||
3340 | |||
3341 | /* | ||
3342 | * Don't do anything with these messages, just allow | ||
3343 | * them to be freed. | ||
3344 | */ | ||
3345 | |||
3346 | rv = 0; | ||
3347 | } else { | ||
3348 | /* Deliver the message to the user. */ | ||
3349 | ipmi_inc_stat(intf, handled_commands); | ||
3350 | |||
3351 | recv_msg = ipmi_alloc_recv_msg(); | ||
3352 | if (!recv_msg) { | ||
3353 | /* | ||
3354 | * We couldn't allocate memory for the | ||
3355 | * message, so requeue it for handling | ||
3356 | * later. | ||
3357 | */ | ||
3358 | rv = 1; | ||
3359 | kref_put(&user->refcount, free_user); | ||
3360 | } else { | ||
3361 | /* | ||
3362 | * OEM Messages are expected to be delivered via | ||
3363 | * the system interface to SMS software. We might | ||
3364 | * need to visit this again depending on OEM | ||
3365 | * requirements | ||
3366 | */ | ||
3367 | smi_addr = ((struct ipmi_system_interface_addr *) | ||
3368 | &(recv_msg->addr)); | ||
3369 | smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; | ||
3370 | smi_addr->channel = IPMI_BMC_CHANNEL; | ||
3371 | smi_addr->lun = msg->rsp[0] & 3; | ||
3372 | |||
3373 | recv_msg->user = user; | ||
3374 | recv_msg->user_msg_data = NULL; | ||
3375 | recv_msg->recv_type = IPMI_OEM_RECV_TYPE; | ||
3376 | recv_msg->msg.netfn = msg->rsp[0] >> 2; | ||
3377 | recv_msg->msg.cmd = msg->rsp[1]; | ||
3378 | recv_msg->msg.data = recv_msg->msg_data; | ||
3379 | |||
3380 | /* | ||
3381 | * The message starts at byte 4 which follows the | ||
3382 | * the Channel Byte in the "GET MESSAGE" command | ||
3383 | */ | ||
3384 | recv_msg->msg.data_len = msg->rsp_size - 4; | ||
3385 | memcpy(recv_msg->msg_data, | ||
3386 | &(msg->rsp[4]), | ||
3387 | msg->rsp_size - 4); | ||
3388 | deliver_response(recv_msg); | ||
3389 | } | ||
3390 | } | ||
3391 | |||
3392 | return rv; | ||
3393 | } | ||
3394 | |||
3270 | static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, | 3395 | static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, |
3271 | struct ipmi_smi_msg *msg) | 3396 | struct ipmi_smi_msg *msg) |
3272 | { | 3397 | { |
@@ -3522,6 +3647,17 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
3522 | goto out; | 3647 | goto out; |
3523 | } | 3648 | } |
3524 | 3649 | ||
3650 | /* | ||
3651 | ** We need to make sure the channels have been initialized. | ||
3652 | ** The channel_handler routine will set the "curr_channel" | ||
3653 | ** equal to or greater than IPMI_MAX_CHANNELS when all the | ||
3654 | ** channels for this interface have been initialized. | ||
3655 | */ | ||
3656 | if (intf->curr_channel < IPMI_MAX_CHANNELS) { | ||
3657 | requeue = 1; /* Just put the message back for now */ | ||
3658 | goto out; | ||
3659 | } | ||
3660 | |||
3525 | switch (intf->channels[chan].medium) { | 3661 | switch (intf->channels[chan].medium) { |
3526 | case IPMI_CHANNEL_MEDIUM_IPMB: | 3662 | case IPMI_CHANNEL_MEDIUM_IPMB: |
3527 | if (msg->rsp[4] & 0x04) { | 3663 | if (msg->rsp[4] & 0x04) { |
@@ -3557,11 +3693,20 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
3557 | break; | 3693 | break; |
3558 | 3694 | ||
3559 | default: | 3695 | default: |
3560 | /* | 3696 | /* Check for OEM Channels. Clients had better |
3561 | * We don't handle the channel type, so just | 3697 | register for these commands. */ |
3562 | * free the message. | 3698 | if ((intf->channels[chan].medium |
3563 | */ | 3699 | >= IPMI_CHANNEL_MEDIUM_OEM_MIN) |
3564 | requeue = 0; | 3700 | && (intf->channels[chan].medium |
3701 | <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) { | ||
3702 | requeue = handle_oem_get_msg_cmd(intf, msg); | ||
3703 | } else { | ||
3704 | /* | ||
3705 | * We don't handle the channel type, so just | ||
3706 | * free the message. | ||
3707 | */ | ||
3708 | requeue = 0; | ||
3709 | } | ||
3565 | } | 3710 | } |
3566 | 3711 | ||
3567 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) | 3712 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) |
@@ -3733,7 +3878,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3733 | list_add_tail(&msg->link, timeouts); | 3878 | list_add_tail(&msg->link, timeouts); |
3734 | if (ent->broadcast) | 3879 | if (ent->broadcast) |
3735 | ipmi_inc_stat(intf, timed_out_ipmb_broadcasts); | 3880 | ipmi_inc_stat(intf, timed_out_ipmb_broadcasts); |
3736 | else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) | 3881 | else if (is_lan_addr(&ent->recv_msg->addr)) |
3737 | ipmi_inc_stat(intf, timed_out_lan_commands); | 3882 | ipmi_inc_stat(intf, timed_out_lan_commands); |
3738 | else | 3883 | else |
3739 | ipmi_inc_stat(intf, timed_out_ipmb_commands); | 3884 | ipmi_inc_stat(intf, timed_out_ipmb_commands); |
@@ -3747,15 +3892,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3747 | */ | 3892 | */ |
3748 | ent->timeout = MAX_MSG_TIMEOUT; | 3893 | ent->timeout = MAX_MSG_TIMEOUT; |
3749 | ent->retries_left--; | 3894 | ent->retries_left--; |
3750 | if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) | ||
3751 | ipmi_inc_stat(intf, retransmitted_lan_commands); | ||
3752 | else | ||
3753 | ipmi_inc_stat(intf, retransmitted_ipmb_commands); | ||
3754 | |||
3755 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, | 3895 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, |
3756 | ent->seqid); | 3896 | ent->seqid); |
3757 | if (!smi_msg) | 3897 | if (!smi_msg) { |
3898 | if (is_lan_addr(&ent->recv_msg->addr)) | ||
3899 | ipmi_inc_stat(intf, | ||
3900 | dropped_rexmit_lan_commands); | ||
3901 | else | ||
3902 | ipmi_inc_stat(intf, | ||
3903 | dropped_rexmit_ipmb_commands); | ||
3758 | return; | 3904 | return; |
3905 | } | ||
3759 | 3906 | ||
3760 | spin_unlock_irqrestore(&intf->seq_lock, *flags); | 3907 | spin_unlock_irqrestore(&intf->seq_lock, *flags); |
3761 | 3908 | ||
@@ -3767,10 +3914,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3767 | * resent. | 3914 | * resent. |
3768 | */ | 3915 | */ |
3769 | handlers = intf->handlers; | 3916 | handlers = intf->handlers; |
3770 | if (handlers) | 3917 | if (handlers) { |
3918 | if (is_lan_addr(&ent->recv_msg->addr)) | ||
3919 | ipmi_inc_stat(intf, | ||
3920 | retransmitted_lan_commands); | ||
3921 | else | ||
3922 | ipmi_inc_stat(intf, | ||
3923 | retransmitted_ipmb_commands); | ||
3924 | |||
3771 | intf->handlers->sender(intf->send_info, | 3925 | intf->handlers->sender(intf->send_info, |
3772 | smi_msg, 0); | 3926 | smi_msg, 0); |
3773 | else | 3927 | } else |
3774 | ipmi_free_smi_msg(smi_msg); | 3928 | ipmi_free_smi_msg(smi_msg); |
3775 | 3929 | ||
3776 | spin_lock_irqsave(&intf->seq_lock, *flags); | 3930 | spin_lock_irqsave(&intf->seq_lock, *flags); |
@@ -4265,7 +4419,6 @@ static int ipmi_init_msghandler(void) | |||
4265 | return -ENOMEM; | 4419 | return -ENOMEM; |
4266 | } | 4420 | } |
4267 | 4421 | ||
4268 | proc_ipmi_root->owner = THIS_MODULE; | ||
4269 | #endif /* CONFIG_PROC_FS */ | 4422 | #endif /* CONFIG_PROC_FS */ |
4270 | 4423 | ||
4271 | setup_timer(&ipmi_timer, ipmi_timeout, 0); | 4424 | setup_timer(&ipmi_timer, ipmi_timeout, 0); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3000135f2ead..259644646b82 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -82,12 +82,6 @@ | |||
82 | #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a | 82 | #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a |
83 | short timeout */ | 83 | short timeout */ |
84 | 84 | ||
85 | /* Bit for BMC global enables. */ | ||
86 | #define IPMI_BMC_RCV_MSG_INTR 0x01 | ||
87 | #define IPMI_BMC_EVT_MSG_INTR 0x02 | ||
88 | #define IPMI_BMC_EVT_MSG_BUFF 0x04 | ||
89 | #define IPMI_BMC_SYS_LOG 0x08 | ||
90 | |||
91 | enum si_intf_state { | 85 | enum si_intf_state { |
92 | SI_NORMAL, | 86 | SI_NORMAL, |
93 | SI_GETTING_FLAGS, | 87 | SI_GETTING_FLAGS, |
@@ -220,6 +214,9 @@ struct smi_info { | |||
220 | OEM2_DATA_AVAIL) | 214 | OEM2_DATA_AVAIL) |
221 | unsigned char msg_flags; | 215 | unsigned char msg_flags; |
222 | 216 | ||
217 | /* Does the BMC have an event buffer? */ | ||
218 | char has_event_buffer; | ||
219 | |||
223 | /* | 220 | /* |
224 | * If set to true, this will request events the next time the | 221 | * If set to true, this will request events the next time the |
225 | * state machine is idle. | 222 | * state machine is idle. |
@@ -968,7 +965,8 @@ static void request_events(void *send_info) | |||
968 | { | 965 | { |
969 | struct smi_info *smi_info = send_info; | 966 | struct smi_info *smi_info = send_info; |
970 | 967 | ||
971 | if (atomic_read(&smi_info->stop_operation)) | 968 | if (atomic_read(&smi_info->stop_operation) || |
969 | !smi_info->has_event_buffer) | ||
972 | return; | 970 | return; |
973 | 971 | ||
974 | atomic_set(&smi_info->req_events, 1); | 972 | atomic_set(&smi_info->req_events, 1); |
@@ -2407,26 +2405,9 @@ static struct of_platform_driver ipmi_of_platform_driver = { | |||
2407 | }; | 2405 | }; |
2408 | #endif /* CONFIG_PPC_OF */ | 2406 | #endif /* CONFIG_PPC_OF */ |
2409 | 2407 | ||
2410 | 2408 | static int wait_for_msg_done(struct smi_info *smi_info) | |
2411 | static int try_get_dev_id(struct smi_info *smi_info) | ||
2412 | { | 2409 | { |
2413 | unsigned char msg[2]; | ||
2414 | unsigned char *resp; | ||
2415 | unsigned long resp_len; | ||
2416 | enum si_sm_result smi_result; | 2410 | enum si_sm_result smi_result; |
2417 | int rv = 0; | ||
2418 | |||
2419 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | ||
2420 | if (!resp) | ||
2421 | return -ENOMEM; | ||
2422 | |||
2423 | /* | ||
2424 | * Do a Get Device ID command, since it comes back with some | ||
2425 | * useful info. | ||
2426 | */ | ||
2427 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
2428 | msg[1] = IPMI_GET_DEVICE_ID_CMD; | ||
2429 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); | ||
2430 | 2411 | ||
2431 | smi_result = smi_info->handlers->event(smi_info->si_sm, 0); | 2412 | smi_result = smi_info->handlers->event(smi_info->si_sm, 0); |
2432 | for (;;) { | 2413 | for (;;) { |
@@ -2441,16 +2422,39 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
2441 | } else | 2422 | } else |
2442 | break; | 2423 | break; |
2443 | } | 2424 | } |
2444 | if (smi_result == SI_SM_HOSED) { | 2425 | if (smi_result == SI_SM_HOSED) |
2445 | /* | 2426 | /* |
2446 | * We couldn't get the state machine to run, so whatever's at | 2427 | * We couldn't get the state machine to run, so whatever's at |
2447 | * the port is probably not an IPMI SMI interface. | 2428 | * the port is probably not an IPMI SMI interface. |
2448 | */ | 2429 | */ |
2449 | rv = -ENODEV; | 2430 | return -ENODEV; |
2431 | |||
2432 | return 0; | ||
2433 | } | ||
2434 | |||
2435 | static int try_get_dev_id(struct smi_info *smi_info) | ||
2436 | { | ||
2437 | unsigned char msg[2]; | ||
2438 | unsigned char *resp; | ||
2439 | unsigned long resp_len; | ||
2440 | int rv = 0; | ||
2441 | |||
2442 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | ||
2443 | if (!resp) | ||
2444 | return -ENOMEM; | ||
2445 | |||
2446 | /* | ||
2447 | * Do a Get Device ID command, since it comes back with some | ||
2448 | * useful info. | ||
2449 | */ | ||
2450 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
2451 | msg[1] = IPMI_GET_DEVICE_ID_CMD; | ||
2452 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); | ||
2453 | |||
2454 | rv = wait_for_msg_done(smi_info); | ||
2455 | if (rv) | ||
2450 | goto out; | 2456 | goto out; |
2451 | } | ||
2452 | 2457 | ||
2453 | /* Otherwise, we got some data. */ | ||
2454 | resp_len = smi_info->handlers->get_result(smi_info->si_sm, | 2458 | resp_len = smi_info->handlers->get_result(smi_info->si_sm, |
2455 | resp, IPMI_MAX_MSG_LENGTH); | 2459 | resp, IPMI_MAX_MSG_LENGTH); |
2456 | 2460 | ||
@@ -2462,6 +2466,88 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
2462 | return rv; | 2466 | return rv; |
2463 | } | 2467 | } |
2464 | 2468 | ||
2469 | static int try_enable_event_buffer(struct smi_info *smi_info) | ||
2470 | { | ||
2471 | unsigned char msg[3]; | ||
2472 | unsigned char *resp; | ||
2473 | unsigned long resp_len; | ||
2474 | int rv = 0; | ||
2475 | |||
2476 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | ||
2477 | if (!resp) | ||
2478 | return -ENOMEM; | ||
2479 | |||
2480 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
2481 | msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; | ||
2482 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); | ||
2483 | |||
2484 | rv = wait_for_msg_done(smi_info); | ||
2485 | if (rv) { | ||
2486 | printk(KERN_WARNING | ||
2487 | "ipmi_si: Error getting response from get global," | ||
2488 | " enables command, the event buffer is not" | ||
2489 | " enabled.\n"); | ||
2490 | goto out; | ||
2491 | } | ||
2492 | |||
2493 | resp_len = smi_info->handlers->get_result(smi_info->si_sm, | ||
2494 | resp, IPMI_MAX_MSG_LENGTH); | ||
2495 | |||
2496 | if (resp_len < 4 || | ||
2497 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || | ||
2498 | resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || | ||
2499 | resp[2] != 0) { | ||
2500 | printk(KERN_WARNING | ||
2501 | "ipmi_si: Invalid return from get global" | ||
2502 | " enables command, cannot enable the event" | ||
2503 | " buffer.\n"); | ||
2504 | rv = -EINVAL; | ||
2505 | goto out; | ||
2506 | } | ||
2507 | |||
2508 | if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) | ||
2509 | /* buffer is already enabled, nothing to do. */ | ||
2510 | goto out; | ||
2511 | |||
2512 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
2513 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | ||
2514 | msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF; | ||
2515 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3); | ||
2516 | |||
2517 | rv = wait_for_msg_done(smi_info); | ||
2518 | if (rv) { | ||
2519 | printk(KERN_WARNING | ||
2520 | "ipmi_si: Error getting response from set global," | ||
2521 | " enables command, the event buffer is not" | ||
2522 | " enabled.\n"); | ||
2523 | goto out; | ||
2524 | } | ||
2525 | |||
2526 | resp_len = smi_info->handlers->get_result(smi_info->si_sm, | ||
2527 | resp, IPMI_MAX_MSG_LENGTH); | ||
2528 | |||
2529 | if (resp_len < 3 || | ||
2530 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || | ||
2531 | resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { | ||
2532 | printk(KERN_WARNING | ||
2533 | "ipmi_si: Invalid return from get global," | ||
2534 | "enables command, not enable the event" | ||
2535 | " buffer.\n"); | ||
2536 | rv = -EINVAL; | ||
2537 | goto out; | ||
2538 | } | ||
2539 | |||
2540 | if (resp[2] != 0) | ||
2541 | /* | ||
2542 | * An error when setting the event buffer bit means | ||
2543 | * that the event buffer is not supported. | ||
2544 | */ | ||
2545 | rv = -ENOENT; | ||
2546 | out: | ||
2547 | kfree(resp); | ||
2548 | return rv; | ||
2549 | } | ||
2550 | |||
2465 | static int type_file_read_proc(char *page, char **start, off_t off, | 2551 | static int type_file_read_proc(char *page, char **start, off_t off, |
2466 | int count, int *eof, void *data) | 2552 | int count, int *eof, void *data) |
2467 | { | 2553 | { |
@@ -2847,6 +2933,10 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2847 | new_smi->intf_num = smi_num; | 2933 | new_smi->intf_num = smi_num; |
2848 | smi_num++; | 2934 | smi_num++; |
2849 | 2935 | ||
2936 | rv = try_enable_event_buffer(new_smi); | ||
2937 | if (rv == 0) | ||
2938 | new_smi->has_event_buffer = 1; | ||
2939 | |||
2850 | /* | 2940 | /* |
2851 | * Start clearing the flags before we enable interrupts or the | 2941 | * Start clearing the flags before we enable interrupts or the |
2852 | * timer to avoid racing with the timer. | 2942 | * timer to avoid racing with the timer. |
@@ -2863,7 +2953,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2863 | */ | 2953 | */ |
2864 | new_smi->pdev = platform_device_alloc("ipmi_si", | 2954 | new_smi->pdev = platform_device_alloc("ipmi_si", |
2865 | new_smi->intf_num); | 2955 | new_smi->intf_num); |
2866 | if (rv) { | 2956 | if (!new_smi->pdev) { |
2867 | printk(KERN_ERR | 2957 | printk(KERN_ERR |
2868 | "ipmi_si_intf:" | 2958 | "ipmi_si_intf:" |
2869 | " Unable to allocate platform device\n"); | 2959 | " Unable to allocate platform device\n"); |
@@ -2899,7 +2989,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2899 | 2989 | ||
2900 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", | 2990 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", |
2901 | type_file_read_proc, | 2991 | type_file_read_proc, |
2902 | new_smi, THIS_MODULE); | 2992 | new_smi); |
2903 | if (rv) { | 2993 | if (rv) { |
2904 | printk(KERN_ERR | 2994 | printk(KERN_ERR |
2905 | "ipmi_si: Unable to create proc entry: %d\n", | 2995 | "ipmi_si: Unable to create proc entry: %d\n", |
@@ -2909,7 +2999,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2909 | 2999 | ||
2910 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", | 3000 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", |
2911 | stat_file_read_proc, | 3001 | stat_file_read_proc, |
2912 | new_smi, THIS_MODULE); | 3002 | new_smi); |
2913 | if (rv) { | 3003 | if (rv) { |
2914 | printk(KERN_ERR | 3004 | printk(KERN_ERR |
2915 | "ipmi_si: Unable to create proc entry: %d\n", | 3005 | "ipmi_si: Unable to create proc entry: %d\n", |
@@ -2919,7 +3009,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2919 | 3009 | ||
2920 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", | 3010 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", |
2921 | param_read_proc, | 3011 | param_read_proc, |
2922 | new_smi, THIS_MODULE); | 3012 | new_smi); |
2923 | if (rv) { | 3013 | if (rv) { |
2924 | printk(KERN_ERR | 3014 | printk(KERN_ERR |
2925 | "ipmi_si: Unable to create proc entry: %d\n", | 3015 | "ipmi_si: Unable to create proc entry: %d\n", |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 24aa6e88e223..a59eac584d16 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -925,6 +925,7 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
925 | if (!card->count) | 925 | if (!card->count) |
926 | isicom_shutdown_board(card); | 926 | isicom_shutdown_board(card); |
927 | } | 927 | } |
928 | tty_kref_put(tty); | ||
928 | } | 929 | } |
929 | 930 | ||
930 | static void isicom_flush_buffer(struct tty_struct *tty) | 931 | static void isicom_flush_buffer(struct tty_struct *tty) |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 5c3dc6b8411c..fff19f7e29d2 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
25 | #include <linux/tty_flip.h> | 25 | #include <linux/tty_flip.h> |
26 | #include <linux/serial.h> | 26 | #include <linux/serial.h> |
27 | #include <linux/seq_file.h> | ||
27 | #include <linux/cdk.h> | 28 | #include <linux/cdk.h> |
28 | #include <linux/comstats.h> | 29 | #include <linux/comstats.h> |
29 | #include <linux/istallion.h> | 30 | #include <linux/istallion.h> |
@@ -613,7 +614,6 @@ static int stli_breakctl(struct tty_struct *tty, int state); | |||
613 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); | 614 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); |
614 | static void stli_sendxchar(struct tty_struct *tty, char ch); | 615 | static void stli_sendxchar(struct tty_struct *tty, char ch); |
615 | static void stli_hangup(struct tty_struct *tty); | 616 | static void stli_hangup(struct tty_struct *tty); |
616 | static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos); | ||
617 | 617 | ||
618 | static int stli_brdinit(struct stlibrd *brdp); | 618 | static int stli_brdinit(struct stlibrd *brdp); |
619 | static int stli_startbrd(struct stlibrd *brdp); | 619 | static int stli_startbrd(struct stlibrd *brdp); |
@@ -1893,20 +1893,10 @@ static void stli_sendxchar(struct tty_struct *tty, char ch) | |||
1893 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); | 1893 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); |
1894 | } | 1894 | } |
1895 | 1895 | ||
1896 | /*****************************************************************************/ | 1896 | static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr) |
1897 | |||
1898 | #define MAXLINE 80 | ||
1899 | |||
1900 | /* | ||
1901 | * Format info for a specified port. The line is deliberately limited | ||
1902 | * to 80 characters. (If it is too long it will be truncated, if too | ||
1903 | * short then padded with spaces). | ||
1904 | */ | ||
1905 | |||
1906 | static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos) | ||
1907 | { | 1897 | { |
1908 | char *sp, *uart; | 1898 | char *uart; |
1909 | int rc, cnt; | 1899 | int rc; |
1910 | 1900 | ||
1911 | rc = stli_portcmdstats(NULL, portp); | 1901 | rc = stli_portcmdstats(NULL, portp); |
1912 | 1902 | ||
@@ -1918,44 +1908,50 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1918 | default:uart = "CD1400"; break; | 1908 | default:uart = "CD1400"; break; |
1919 | } | 1909 | } |
1920 | } | 1910 | } |
1921 | 1911 | seq_printf(m, "%d: uart:%s ", portnr, uart); | |
1922 | sp = pos; | ||
1923 | sp += sprintf(sp, "%d: uart:%s ", portnr, uart); | ||
1924 | 1912 | ||
1925 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { | 1913 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { |
1926 | sp += sprintf(sp, "tx:%d rx:%d", (int) stli_comstats.txtotal, | 1914 | char sep; |
1915 | |||
1916 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | ||
1927 | (int) stli_comstats.rxtotal); | 1917 | (int) stli_comstats.rxtotal); |
1928 | 1918 | ||
1929 | if (stli_comstats.rxframing) | 1919 | if (stli_comstats.rxframing) |
1930 | sp += sprintf(sp, " fe:%d", | 1920 | seq_printf(m, " fe:%d", |
1931 | (int) stli_comstats.rxframing); | 1921 | (int) stli_comstats.rxframing); |
1932 | if (stli_comstats.rxparity) | 1922 | if (stli_comstats.rxparity) |
1933 | sp += sprintf(sp, " pe:%d", | 1923 | seq_printf(m, " pe:%d", |
1934 | (int) stli_comstats.rxparity); | 1924 | (int) stli_comstats.rxparity); |
1935 | if (stli_comstats.rxbreaks) | 1925 | if (stli_comstats.rxbreaks) |
1936 | sp += sprintf(sp, " brk:%d", | 1926 | seq_printf(m, " brk:%d", |
1937 | (int) stli_comstats.rxbreaks); | 1927 | (int) stli_comstats.rxbreaks); |
1938 | if (stli_comstats.rxoverrun) | 1928 | if (stli_comstats.rxoverrun) |
1939 | sp += sprintf(sp, " oe:%d", | 1929 | seq_printf(m, " oe:%d", |
1940 | (int) stli_comstats.rxoverrun); | 1930 | (int) stli_comstats.rxoverrun); |
1941 | 1931 | ||
1942 | cnt = sprintf(sp, "%s%s%s%s%s ", | 1932 | sep = ' '; |
1943 | (stli_comstats.signals & TIOCM_RTS) ? "|RTS" : "", | 1933 | if (stli_comstats.signals & TIOCM_RTS) { |
1944 | (stli_comstats.signals & TIOCM_CTS) ? "|CTS" : "", | 1934 | seq_printf(m, "%c%s", sep, "RTS"); |
1945 | (stli_comstats.signals & TIOCM_DTR) ? "|DTR" : "", | 1935 | sep = '|'; |
1946 | (stli_comstats.signals & TIOCM_CD) ? "|DCD" : "", | 1936 | } |
1947 | (stli_comstats.signals & TIOCM_DSR) ? "|DSR" : ""); | 1937 | if (stli_comstats.signals & TIOCM_CTS) { |
1948 | *sp = ' '; | 1938 | seq_printf(m, "%c%s", sep, "CTS"); |
1949 | sp += cnt; | 1939 | sep = '|'; |
1940 | } | ||
1941 | if (stli_comstats.signals & TIOCM_DTR) { | ||
1942 | seq_printf(m, "%c%s", sep, "DTR"); | ||
1943 | sep = '|'; | ||
1944 | } | ||
1945 | if (stli_comstats.signals & TIOCM_CD) { | ||
1946 | seq_printf(m, "%c%s", sep, "DCD"); | ||
1947 | sep = '|'; | ||
1948 | } | ||
1949 | if (stli_comstats.signals & TIOCM_DSR) { | ||
1950 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1951 | sep = '|'; | ||
1952 | } | ||
1950 | } | 1953 | } |
1951 | 1954 | seq_putc(m, '\n'); | |
1952 | for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++) | ||
1953 | *sp++ = ' '; | ||
1954 | if (cnt >= MAXLINE) | ||
1955 | pos[(MAXLINE - 2)] = '+'; | ||
1956 | pos[(MAXLINE - 1)] = '\n'; | ||
1957 | |||
1958 | return(MAXLINE); | ||
1959 | } | 1955 | } |
1960 | 1956 | ||
1961 | /*****************************************************************************/ | 1957 | /*****************************************************************************/ |
@@ -1964,26 +1960,15 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1964 | * Port info, read from the /proc file system. | 1960 | * Port info, read from the /proc file system. |
1965 | */ | 1961 | */ |
1966 | 1962 | ||
1967 | static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) | 1963 | static int stli_proc_show(struct seq_file *m, void *v) |
1968 | { | 1964 | { |
1969 | struct stlibrd *brdp; | 1965 | struct stlibrd *brdp; |
1970 | struct stliport *portp; | 1966 | struct stliport *portp; |
1971 | unsigned int brdnr, portnr, totalport; | 1967 | unsigned int brdnr, portnr, totalport; |
1972 | int curoff, maxoff; | ||
1973 | char *pos; | ||
1974 | 1968 | ||
1975 | pos = page; | ||
1976 | totalport = 0; | 1969 | totalport = 0; |
1977 | curoff = 0; | 1970 | |
1978 | 1971 | seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion); | |
1979 | if (off == 0) { | ||
1980 | pos += sprintf(pos, "%s: version %s", stli_drvtitle, | ||
1981 | stli_drvversion); | ||
1982 | while (pos < (page + MAXLINE - 1)) | ||
1983 | *pos++ = ' '; | ||
1984 | *pos++ = '\n'; | ||
1985 | } | ||
1986 | curoff = MAXLINE; | ||
1987 | 1972 | ||
1988 | /* | 1973 | /* |
1989 | * We scan through for each board, panel and port. The offset is | 1974 | * We scan through for each board, panel and port. The offset is |
@@ -1996,33 +1981,31 @@ static int stli_readproc(char *page, char **start, off_t off, int count, int *eo | |||
1996 | if (brdp->state == 0) | 1981 | if (brdp->state == 0) |
1997 | continue; | 1982 | continue; |
1998 | 1983 | ||
1999 | maxoff = curoff + (brdp->nrports * MAXLINE); | ||
2000 | if (off >= maxoff) { | ||
2001 | curoff = maxoff; | ||
2002 | continue; | ||
2003 | } | ||
2004 | |||
2005 | totalport = brdnr * STL_MAXPORTS; | 1984 | totalport = brdnr * STL_MAXPORTS; |
2006 | for (portnr = 0; (portnr < brdp->nrports); portnr++, | 1985 | for (portnr = 0; (portnr < brdp->nrports); portnr++, |
2007 | totalport++) { | 1986 | totalport++) { |
2008 | portp = brdp->ports[portnr]; | 1987 | portp = brdp->ports[portnr]; |
2009 | if (portp == NULL) | 1988 | if (portp == NULL) |
2010 | continue; | 1989 | continue; |
2011 | if (off >= (curoff += MAXLINE)) | 1990 | stli_portinfo(m, brdp, portp, totalport); |
2012 | continue; | ||
2013 | if ((pos - page + MAXLINE) > count) | ||
2014 | goto stli_readdone; | ||
2015 | pos += stli_portinfo(brdp, portp, totalport, pos); | ||
2016 | } | 1991 | } |
2017 | } | 1992 | } |
1993 | return 0; | ||
1994 | } | ||
2018 | 1995 | ||
2019 | *eof = 1; | 1996 | static int stli_proc_open(struct inode *inode, struct file *file) |
2020 | 1997 | { | |
2021 | stli_readdone: | 1998 | return single_open(file, stli_proc_show, NULL); |
2022 | *start = page; | ||
2023 | return(pos - page); | ||
2024 | } | 1999 | } |
2025 | 2000 | ||
2001 | static const struct file_operations stli_proc_fops = { | ||
2002 | .owner = THIS_MODULE, | ||
2003 | .open = stli_proc_open, | ||
2004 | .read = seq_read, | ||
2005 | .llseek = seq_lseek, | ||
2006 | .release = single_release, | ||
2007 | }; | ||
2008 | |||
2026 | /*****************************************************************************/ | 2009 | /*****************************************************************************/ |
2027 | 2010 | ||
2028 | /* | 2011 | /* |
@@ -4427,9 +4410,9 @@ static const struct tty_operations stli_ops = { | |||
4427 | .break_ctl = stli_breakctl, | 4410 | .break_ctl = stli_breakctl, |
4428 | .wait_until_sent = stli_waituntilsent, | 4411 | .wait_until_sent = stli_waituntilsent, |
4429 | .send_xchar = stli_sendxchar, | 4412 | .send_xchar = stli_sendxchar, |
4430 | .read_proc = stli_readproc, | ||
4431 | .tiocmget = stli_tiocmget, | 4413 | .tiocmget = stli_tiocmget, |
4432 | .tiocmset = stli_tiocmset, | 4414 | .tiocmset = stli_tiocmset, |
4415 | .proc_fops = &stli_proc_fops, | ||
4433 | }; | 4416 | }; |
4434 | 4417 | ||
4435 | static const struct tty_port_operations stli_port_ops = { | 4418 | static const struct tty_port_operations stli_port_ops = { |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 3586b3b3df3f..8f05c38c2f06 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -301,33 +301,7 @@ static inline int private_mapping_ok(struct vm_area_struct *vma) | |||
301 | } | 301 | } |
302 | #endif | 302 | #endif |
303 | 303 | ||
304 | void __attribute__((weak)) | ||
305 | map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot) | ||
306 | { | ||
307 | /* nothing. architectures can override. */ | ||
308 | } | ||
309 | |||
310 | void __attribute__((weak)) | ||
311 | unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot) | ||
312 | { | ||
313 | /* nothing. architectures can override. */ | ||
314 | } | ||
315 | |||
316 | static void mmap_mem_open(struct vm_area_struct *vma) | ||
317 | { | ||
318 | map_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start, | ||
319 | vma->vm_page_prot); | ||
320 | } | ||
321 | |||
322 | static void mmap_mem_close(struct vm_area_struct *vma) | ||
323 | { | ||
324 | unmap_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start, | ||
325 | vma->vm_page_prot); | ||
326 | } | ||
327 | |||
328 | static struct vm_operations_struct mmap_mem_ops = { | 304 | static struct vm_operations_struct mmap_mem_ops = { |
329 | .open = mmap_mem_open, | ||
330 | .close = mmap_mem_close, | ||
331 | #ifdef CONFIG_HAVE_IOREMAP_PROT | 305 | #ifdef CONFIG_HAVE_IOREMAP_PROT |
332 | .access = generic_access_phys | 306 | .access = generic_access_phys |
333 | #endif | 307 | #endif |
@@ -362,7 +336,6 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) | |||
362 | vma->vm_pgoff, | 336 | vma->vm_pgoff, |
363 | size, | 337 | size, |
364 | vma->vm_page_prot)) { | 338 | vma->vm_page_prot)) { |
365 | unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot); | ||
366 | return -EAGAIN; | 339 | return -EAGAIN; |
367 | } | 340 | } |
368 | return 0; | 341 | return 0; |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 8b0da97d5293..4a4cab73d0be 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -1486,11 +1486,11 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1486 | } | 1486 | } |
1487 | 1487 | ||
1488 | if (!handle) /* nothing else to do */ | 1488 | if (!handle) /* nothing else to do */ |
1489 | return 0; | 1489 | goto put; |
1490 | 1490 | ||
1491 | intr = readw(ip); /* port irq status */ | 1491 | intr = readw(ip); /* port irq status */ |
1492 | if (intr == 0) | 1492 | if (intr == 0) |
1493 | return 0; | 1493 | goto put; |
1494 | 1494 | ||
1495 | writew(0, ip); /* ACK port */ | 1495 | writew(0, ip); /* ACK port */ |
1496 | ofsAddr = p->tableAddr; | 1496 | ofsAddr = p->tableAddr; |
@@ -1499,16 +1499,17 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1499 | ofsAddr + HostStat); | 1499 | ofsAddr + HostStat); |
1500 | 1500 | ||
1501 | if (!inited) | 1501 | if (!inited) |
1502 | return 0; | 1502 | goto put; |
1503 | 1503 | ||
1504 | if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ | 1504 | if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ |
1505 | tty_insert_flip_char(tty, 0, TTY_BREAK); | 1505 | tty_insert_flip_char(tty, 0, TTY_BREAK); |
1506 | tty_schedule_flip(tty); | 1506 | tty_schedule_flip(tty); |
1507 | } | 1507 | } |
1508 | tty_kref_put(tty); | ||
1509 | 1508 | ||
1510 | if (intr & IntrLine) | 1509 | if (intr & IntrLine) |
1511 | moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); | 1510 | moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); |
1511 | put: | ||
1512 | tty_kref_put(tty); | ||
1512 | 1513 | ||
1513 | return 0; | 1514 | return 0; |
1514 | } | 1515 | } |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 402c9f217f83..a420e8d437dd 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -820,7 +820,6 @@ static void mxser_check_modem_status(struct tty_struct *tty, | |||
820 | wake_up_interruptible(&port->port.open_wait); | 820 | wake_up_interruptible(&port->port.open_wait); |
821 | } | 821 | } |
822 | 822 | ||
823 | tty = tty_port_tty_get(&port->port); | ||
824 | if (port->port.flags & ASYNC_CTS_FLOW) { | 823 | if (port->port.flags & ASYNC_CTS_FLOW) { |
825 | if (tty->hw_stopped) { | 824 | if (tty->hw_stopped) { |
826 | if (status & UART_MSR_CTS) { | 825 | if (status & UART_MSR_CTS) { |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index dc073e167abc..19d79fc54461 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/ptrace.h> | 51 | #include <linux/ptrace.h> |
52 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
53 | #include <linux/mm.h> | 53 | #include <linux/mm.h> |
54 | #include <linux/seq_file.h> | ||
54 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
55 | #include <linux/netdevice.h> | 56 | #include <linux/netdevice.h> |
56 | #include <linux/vmalloc.h> | 57 | #include <linux/vmalloc.h> |
@@ -2619,13 +2620,12 @@ cleanup: | |||
2619 | * /proc fs routines.... | 2620 | * /proc fs routines.... |
2620 | */ | 2621 | */ |
2621 | 2622 | ||
2622 | static inline int line_info(char *buf, MGSLPC_INFO *info) | 2623 | static inline void line_info(struct seq_file *m, MGSLPC_INFO *info) |
2623 | { | 2624 | { |
2624 | char stat_buf[30]; | 2625 | char stat_buf[30]; |
2625 | int ret; | ||
2626 | unsigned long flags; | 2626 | unsigned long flags; |
2627 | 2627 | ||
2628 | ret = sprintf(buf, "%s:io:%04X irq:%d", | 2628 | seq_printf(m, "%s:io:%04X irq:%d", |
2629 | info->device_name, info->io_base, info->irq_level); | 2629 | info->device_name, info->io_base, info->irq_level); |
2630 | 2630 | ||
2631 | /* output current serial signal states */ | 2631 | /* output current serial signal states */ |
@@ -2649,75 +2649,70 @@ static inline int line_info(char *buf, MGSLPC_INFO *info) | |||
2649 | strcat(stat_buf, "|RI"); | 2649 | strcat(stat_buf, "|RI"); |
2650 | 2650 | ||
2651 | if (info->params.mode == MGSL_MODE_HDLC) { | 2651 | if (info->params.mode == MGSL_MODE_HDLC) { |
2652 | ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", | 2652 | seq_printf(m, " HDLC txok:%d rxok:%d", |
2653 | info->icount.txok, info->icount.rxok); | 2653 | info->icount.txok, info->icount.rxok); |
2654 | if (info->icount.txunder) | 2654 | if (info->icount.txunder) |
2655 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 2655 | seq_printf(m, " txunder:%d", info->icount.txunder); |
2656 | if (info->icount.txabort) | 2656 | if (info->icount.txabort) |
2657 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 2657 | seq_printf(m, " txabort:%d", info->icount.txabort); |
2658 | if (info->icount.rxshort) | 2658 | if (info->icount.rxshort) |
2659 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 2659 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
2660 | if (info->icount.rxlong) | 2660 | if (info->icount.rxlong) |
2661 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 2661 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
2662 | if (info->icount.rxover) | 2662 | if (info->icount.rxover) |
2663 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 2663 | seq_printf(m, " rxover:%d", info->icount.rxover); |
2664 | if (info->icount.rxcrc) | 2664 | if (info->icount.rxcrc) |
2665 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 2665 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
2666 | } else { | 2666 | } else { |
2667 | ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", | 2667 | seq_printf(m, " ASYNC tx:%d rx:%d", |
2668 | info->icount.tx, info->icount.rx); | 2668 | info->icount.tx, info->icount.rx); |
2669 | if (info->icount.frame) | 2669 | if (info->icount.frame) |
2670 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 2670 | seq_printf(m, " fe:%d", info->icount.frame); |
2671 | if (info->icount.parity) | 2671 | if (info->icount.parity) |
2672 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 2672 | seq_printf(m, " pe:%d", info->icount.parity); |
2673 | if (info->icount.brk) | 2673 | if (info->icount.brk) |
2674 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 2674 | seq_printf(m, " brk:%d", info->icount.brk); |
2675 | if (info->icount.overrun) | 2675 | if (info->icount.overrun) |
2676 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 2676 | seq_printf(m, " oe:%d", info->icount.overrun); |
2677 | } | 2677 | } |
2678 | 2678 | ||
2679 | /* Append serial signal status to end */ | 2679 | /* Append serial signal status to end */ |
2680 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 2680 | seq_printf(m, " %s\n", stat_buf+1); |
2681 | 2681 | ||
2682 | ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 2682 | seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
2683 | info->tx_active,info->bh_requested,info->bh_running, | 2683 | info->tx_active,info->bh_requested,info->bh_running, |
2684 | info->pending_bh); | 2684 | info->pending_bh); |
2685 | |||
2686 | return ret; | ||
2687 | } | 2685 | } |
2688 | 2686 | ||
2689 | /* Called to print information about devices | 2687 | /* Called to print information about devices |
2690 | */ | 2688 | */ |
2691 | static int mgslpc_read_proc(char *page, char **start, off_t off, int count, | 2689 | static int mgslpc_proc_show(struct seq_file *m, void *v) |
2692 | int *eof, void *data) | ||
2693 | { | 2690 | { |
2694 | int len = 0, l; | ||
2695 | off_t begin = 0; | ||
2696 | MGSLPC_INFO *info; | 2691 | MGSLPC_INFO *info; |
2697 | 2692 | ||
2698 | len += sprintf(page, "synclink driver:%s\n", driver_version); | 2693 | seq_printf(m, "synclink driver:%s\n", driver_version); |
2699 | 2694 | ||
2700 | info = mgslpc_device_list; | 2695 | info = mgslpc_device_list; |
2701 | while( info ) { | 2696 | while( info ) { |
2702 | l = line_info(page + len, info); | 2697 | line_info(m, info); |
2703 | len += l; | ||
2704 | if (len+begin > off+count) | ||
2705 | goto done; | ||
2706 | if (len+begin < off) { | ||
2707 | begin += len; | ||
2708 | len = 0; | ||
2709 | } | ||
2710 | info = info->next_device; | 2698 | info = info->next_device; |
2711 | } | 2699 | } |
2700 | return 0; | ||
2701 | } | ||
2712 | 2702 | ||
2713 | *eof = 1; | 2703 | static int mgslpc_proc_open(struct inode *inode, struct file *file) |
2714 | done: | 2704 | { |
2715 | if (off >= len+begin) | 2705 | return single_open(file, mgslpc_proc_show, NULL); |
2716 | return 0; | ||
2717 | *start = page + (off-begin); | ||
2718 | return ((count < begin+len-off) ? count : begin+len-off); | ||
2719 | } | 2706 | } |
2720 | 2707 | ||
2708 | static const struct file_operations mgslpc_proc_fops = { | ||
2709 | .owner = THIS_MODULE, | ||
2710 | .open = mgslpc_proc_open, | ||
2711 | .read = seq_read, | ||
2712 | .llseek = seq_lseek, | ||
2713 | .release = single_release, | ||
2714 | }; | ||
2715 | |||
2721 | static int rx_alloc_buffers(MGSLPC_INFO *info) | 2716 | static int rx_alloc_buffers(MGSLPC_INFO *info) |
2722 | { | 2717 | { |
2723 | /* each buffer has header and data */ | 2718 | /* each buffer has header and data */ |
@@ -2861,13 +2856,13 @@ static const struct tty_operations mgslpc_ops = { | |||
2861 | .send_xchar = mgslpc_send_xchar, | 2856 | .send_xchar = mgslpc_send_xchar, |
2862 | .break_ctl = mgslpc_break, | 2857 | .break_ctl = mgslpc_break, |
2863 | .wait_until_sent = mgslpc_wait_until_sent, | 2858 | .wait_until_sent = mgslpc_wait_until_sent, |
2864 | .read_proc = mgslpc_read_proc, | ||
2865 | .set_termios = mgslpc_set_termios, | 2859 | .set_termios = mgslpc_set_termios, |
2866 | .stop = tx_pause, | 2860 | .stop = tx_pause, |
2867 | .start = tx_release, | 2861 | .start = tx_release, |
2868 | .hangup = mgslpc_hangup, | 2862 | .hangup = mgslpc_hangup, |
2869 | .tiocmget = tiocmget, | 2863 | .tiocmget = tiocmget, |
2870 | .tiocmset = tiocmset, | 2864 | .tiocmset = tiocmset, |
2865 | .proc_fops = &mgslpc_proc_fops, | ||
2871 | }; | 2866 | }; |
2872 | 2867 | ||
2873 | static void synclink_cs_cleanup(void) | 2868 | static void synclink_cs_cleanup(void) |
@@ -4311,10 +4306,17 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) | |||
4311 | dev->stats.rx_bytes += size; | 4306 | dev->stats.rx_bytes += size; |
4312 | 4307 | ||
4313 | netif_rx(skb); | 4308 | netif_rx(skb); |
4314 | |||
4315 | dev->last_rx = jiffies; | ||
4316 | } | 4309 | } |
4317 | 4310 | ||
4311 | static const struct net_device_ops hdlcdev_ops = { | ||
4312 | .ndo_open = hdlcdev_open, | ||
4313 | .ndo_stop = hdlcdev_close, | ||
4314 | .ndo_change_mtu = hdlc_change_mtu, | ||
4315 | .ndo_start_xmit = hdlc_start_xmit, | ||
4316 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
4317 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
4318 | }; | ||
4319 | |||
4318 | /** | 4320 | /** |
4319 | * called by device driver when adding device instance | 4321 | * called by device driver when adding device instance |
4320 | * do generic HDLC initialization | 4322 | * do generic HDLC initialization |
@@ -4341,11 +4343,8 @@ static int hdlcdev_init(MGSLPC_INFO *info) | |||
4341 | dev->irq = info->irq_level; | 4343 | dev->irq = info->irq_level; |
4342 | 4344 | ||
4343 | /* network layer callbacks and settings */ | 4345 | /* network layer callbacks and settings */ |
4344 | dev->do_ioctl = hdlcdev_ioctl; | 4346 | dev->netdev_ops = &hdlcdev_ops; |
4345 | dev->open = hdlcdev_open; | 4347 | dev->watchdog_timeo = 10 * HZ; |
4346 | dev->stop = hdlcdev_close; | ||
4347 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
4348 | dev->watchdog_timeo = 10*HZ; | ||
4349 | dev->tx_queue_len = 50; | 4348 | dev->tx_queue_len = 50; |
4350 | 4349 | ||
4351 | /* generic HDLC layer callbacks and settings */ | 4350 | /* generic HDLC layer callbacks and settings */ |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 7c13581ca9cd..b2ced39d76b2 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -241,6 +241,10 @@ | |||
241 | #include <linux/percpu.h> | 241 | #include <linux/percpu.h> |
242 | #include <linux/cryptohash.h> | 242 | #include <linux/cryptohash.h> |
243 | 243 | ||
244 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
245 | # include <linux/irq.h> | ||
246 | #endif | ||
247 | |||
244 | #include <asm/processor.h> | 248 | #include <asm/processor.h> |
245 | #include <asm/uaccess.h> | 249 | #include <asm/uaccess.h> |
246 | #include <asm/irq.h> | 250 | #include <asm/irq.h> |
@@ -558,7 +562,7 @@ struct timer_rand_state { | |||
558 | unsigned dont_count_entropy:1; | 562 | unsigned dont_count_entropy:1; |
559 | }; | 563 | }; |
560 | 564 | ||
561 | #ifndef CONFIG_SPARSE_IRQ | 565 | #ifndef CONFIG_GENERIC_HARDIRQS |
562 | 566 | ||
563 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; | 567 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; |
564 | 568 | ||
@@ -1484,7 +1488,8 @@ static void rekey_seq_generator(struct work_struct *work) | |||
1484 | keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS; | 1488 | keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS; |
1485 | smp_wmb(); | 1489 | smp_wmb(); |
1486 | ip_cnt++; | 1490 | ip_cnt++; |
1487 | schedule_delayed_work(&rekey_work, REKEY_INTERVAL); | 1491 | schedule_delayed_work(&rekey_work, |
1492 | round_jiffies_relative(REKEY_INTERVAL)); | ||
1488 | } | 1493 | } |
1489 | 1494 | ||
1490 | static inline struct keydata *get_keyptr(void) | 1495 | static inline struct keydata *get_keyptr(void) |
@@ -1660,15 +1665,20 @@ EXPORT_SYMBOL(secure_dccp_sequence_number); | |||
1660 | * value is not cryptographically secure but for several uses the cost of | 1665 | * value is not cryptographically secure but for several uses the cost of |
1661 | * depleting entropy is too high | 1666 | * depleting entropy is too high |
1662 | */ | 1667 | */ |
1668 | DEFINE_PER_CPU(__u32 [4], get_random_int_hash); | ||
1663 | unsigned int get_random_int(void) | 1669 | unsigned int get_random_int(void) |
1664 | { | 1670 | { |
1665 | /* | 1671 | struct keydata *keyptr; |
1666 | * Use IP's RNG. It suits our purpose perfectly: it re-keys itself | 1672 | __u32 *hash = get_cpu_var(get_random_int_hash); |
1667 | * every second, from the entropy pool (and thus creates a limited | 1673 | int ret; |
1668 | * drain on it), and uses halfMD4Transform within the second. We | 1674 | |
1669 | * also mix it with jiffies and the PID: | 1675 | keyptr = get_keyptr(); |
1670 | */ | 1676 | hash[0] += current->pid + jiffies + get_cycles() + (int)(long)&ret; |
1671 | return secure_ip_id((__force __be32)(current->pid + jiffies)); | 1677 | |
1678 | ret = half_md4_transform(hash, keyptr->secret); | ||
1679 | put_cpu_var(get_random_int_hash); | ||
1680 | |||
1681 | return ret; | ||
1672 | } | 1682 | } |
1673 | 1683 | ||
1674 | /* | 1684 | /* |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 96adf28a17e4..20d90e6a6e50 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -90,6 +90,7 @@ out1: | |||
90 | blkdev_put(bdev, filp->f_mode); | 90 | blkdev_put(bdev, filp->f_mode); |
91 | out: | 91 | out: |
92 | mutex_unlock(&raw_mutex); | 92 | mutex_unlock(&raw_mutex); |
93 | unlock_kernel(); | ||
93 | return err; | 94 | return err; |
94 | } | 95 | } |
95 | 96 | ||
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 2e8a6eed34be..ce81da5b2da9 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
@@ -333,7 +333,7 @@ void rio_copy_to_card(void *from, void __iomem *to, int len) | |||
333 | 333 | ||
334 | int rio_minor(struct tty_struct *tty) | 334 | int rio_minor(struct tty_struct *tty) |
335 | { | 335 | { |
336 | return tty->index + (tty->driver == rio_driver) ? 0 : 256; | 336 | return tty->index + ((tty->driver == rio_driver) ? 0 : 256); |
337 | } | 337 | } |
338 | 338 | ||
339 | static int rio_set_real_termios(void *ptr) | 339 | static int rio_set_real_termios(void *ptr) |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 9af8d74875bc..217660451237 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/spinlock.h> | 50 | #include <linux/spinlock.h> |
51 | #include <linux/device.h> | ||
51 | 52 | ||
52 | #include <linux/uaccess.h> | 53 | #include <linux/uaccess.h> |
53 | 54 | ||
@@ -1524,6 +1525,7 @@ module_param(iobase2, int, 0); | |||
1524 | module_param(iobase3, int, 0); | 1525 | module_param(iobase3, int, 0); |
1525 | 1526 | ||
1526 | MODULE_LICENSE("GPL"); | 1527 | MODULE_LICENSE("GPL"); |
1528 | MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR); | ||
1527 | #endif /* MODULE */ | 1529 | #endif /* MODULE */ |
1528 | 1530 | ||
1529 | /* | 1531 | /* |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index f4374437a033..fd3dced97776 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -888,12 +888,7 @@ found: | |||
888 | 888 | ||
889 | static int sonypi_misc_fasync(int fd, struct file *filp, int on) | 889 | static int sonypi_misc_fasync(int fd, struct file *filp, int on) |
890 | { | 890 | { |
891 | int retval; | 891 | return fasync_helper(fd, filp, on, &sonypi_device.fifo_async); |
892 | |||
893 | retval = fasync_helper(fd, filp, on, &sonypi_device.fifo_async); | ||
894 | if (retval < 0) | ||
895 | return retval; | ||
896 | return 0; | ||
897 | } | 892 | } |
898 | 893 | ||
899 | static int sonypi_misc_release(struct inode *inode, struct file *file) | 894 | static int sonypi_misc_release(struct inode *inode, struct file *file) |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 3c67c3d83de9..e72be4190a44 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -2365,3 +2365,4 @@ module_init(specialix_init_module); | |||
2365 | module_exit(specialix_exit_module); | 2365 | module_exit(specialix_exit_module); |
2366 | 2366 | ||
2367 | MODULE_LICENSE("GPL"); | 2367 | MODULE_LICENSE("GPL"); |
2368 | MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR); | ||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index e1e0dd89ac9a..2ad813a801dc 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/tty.h> | 32 | #include <linux/tty.h> |
33 | #include <linux/tty_flip.h> | 33 | #include <linux/tty_flip.h> |
34 | #include <linux/serial.h> | 34 | #include <linux/serial.h> |
35 | #include <linux/seq_file.h> | ||
35 | #include <linux/cd1400.h> | 36 | #include <linux/cd1400.h> |
36 | #include <linux/sc26198.h> | 37 | #include <linux/sc26198.h> |
37 | #include <linux/comstats.h> | 38 | #include <linux/comstats.h> |
@@ -1379,52 +1380,47 @@ static void stl_sendxchar(struct tty_struct *tty, char ch) | |||
1379 | stl_putchar(tty, ch); | 1380 | stl_putchar(tty, ch); |
1380 | } | 1381 | } |
1381 | 1382 | ||
1382 | /*****************************************************************************/ | 1383 | static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr) |
1383 | |||
1384 | #define MAXLINE 80 | ||
1385 | |||
1386 | /* | ||
1387 | * Format info for a specified port. The line is deliberately limited | ||
1388 | * to 80 characters. (If it is too long it will be truncated, if too | ||
1389 | * short then padded with spaces). | ||
1390 | */ | ||
1391 | |||
1392 | static int stl_portinfo(struct stlport *portp, int portnr, char *pos) | ||
1393 | { | 1384 | { |
1394 | char *sp; | 1385 | int sigs; |
1395 | int sigs, cnt; | 1386 | char sep; |
1396 | 1387 | ||
1397 | sp = pos; | 1388 | seq_printf(m, "%d: uart:%s tx:%d rx:%d", |
1398 | sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d", | ||
1399 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", | 1389 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", |
1400 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); | 1390 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); |
1401 | 1391 | ||
1402 | if (portp->stats.rxframing) | 1392 | if (portp->stats.rxframing) |
1403 | sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing); | 1393 | seq_printf(m, " fe:%d", (int) portp->stats.rxframing); |
1404 | if (portp->stats.rxparity) | 1394 | if (portp->stats.rxparity) |
1405 | sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity); | 1395 | seq_printf(m, " pe:%d", (int) portp->stats.rxparity); |
1406 | if (portp->stats.rxbreaks) | 1396 | if (portp->stats.rxbreaks) |
1407 | sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks); | 1397 | seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks); |
1408 | if (portp->stats.rxoverrun) | 1398 | if (portp->stats.rxoverrun) |
1409 | sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun); | 1399 | seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun); |
1410 | 1400 | ||
1411 | sigs = stl_getsignals(portp); | 1401 | sigs = stl_getsignals(portp); |
1412 | cnt = sprintf(sp, "%s%s%s%s%s ", | 1402 | sep = ' '; |
1413 | (sigs & TIOCM_RTS) ? "|RTS" : "", | 1403 | if (sigs & TIOCM_RTS) { |
1414 | (sigs & TIOCM_CTS) ? "|CTS" : "", | 1404 | seq_printf(m, "%c%s", sep, "RTS"); |
1415 | (sigs & TIOCM_DTR) ? "|DTR" : "", | 1405 | sep = '|'; |
1416 | (sigs & TIOCM_CD) ? "|DCD" : "", | 1406 | } |
1417 | (sigs & TIOCM_DSR) ? "|DSR" : ""); | 1407 | if (sigs & TIOCM_CTS) { |
1418 | *sp = ' '; | 1408 | seq_printf(m, "%c%s", sep, "CTS"); |
1419 | sp += cnt; | 1409 | sep = '|'; |
1420 | 1410 | } | |
1421 | for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++) | 1411 | if (sigs & TIOCM_DTR) { |
1422 | *sp++ = ' '; | 1412 | seq_printf(m, "%c%s", sep, "DTR"); |
1423 | if (cnt >= MAXLINE) | 1413 | sep = '|'; |
1424 | pos[(MAXLINE - 2)] = '+'; | 1414 | } |
1425 | pos[(MAXLINE - 1)] = '\n'; | 1415 | if (sigs & TIOCM_CD) { |
1426 | 1416 | seq_printf(m, "%c%s", sep, "DCD"); | |
1427 | return MAXLINE; | 1417 | sep = '|'; |
1418 | } | ||
1419 | if (sigs & TIOCM_DSR) { | ||
1420 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1421 | sep = '|'; | ||
1422 | } | ||
1423 | seq_putc(m, '\n'); | ||
1428 | } | 1424 | } |
1429 | 1425 | ||
1430 | /*****************************************************************************/ | 1426 | /*****************************************************************************/ |
@@ -1433,30 +1429,17 @@ static int stl_portinfo(struct stlport *portp, int portnr, char *pos) | |||
1433 | * Port info, read from the /proc file system. | 1429 | * Port info, read from the /proc file system. |
1434 | */ | 1430 | */ |
1435 | 1431 | ||
1436 | static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) | 1432 | static int stl_proc_show(struct seq_file *m, void *v) |
1437 | { | 1433 | { |
1438 | struct stlbrd *brdp; | 1434 | struct stlbrd *brdp; |
1439 | struct stlpanel *panelp; | 1435 | struct stlpanel *panelp; |
1440 | struct stlport *portp; | 1436 | struct stlport *portp; |
1441 | unsigned int brdnr, panelnr, portnr; | 1437 | unsigned int brdnr, panelnr, portnr; |
1442 | int totalport, curoff, maxoff; | 1438 | int totalport; |
1443 | char *pos; | ||
1444 | 1439 | ||
1445 | pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p," | ||
1446 | "data=%p\n", page, start, off, count, eof, data); | ||
1447 | |||
1448 | pos = page; | ||
1449 | totalport = 0; | 1440 | totalport = 0; |
1450 | curoff = 0; | 1441 | |
1451 | 1442 | seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion); | |
1452 | if (off == 0) { | ||
1453 | pos += sprintf(pos, "%s: version %s", stl_drvtitle, | ||
1454 | stl_drvversion); | ||
1455 | while (pos < (page + MAXLINE - 1)) | ||
1456 | *pos++ = ' '; | ||
1457 | *pos++ = '\n'; | ||
1458 | } | ||
1459 | curoff = MAXLINE; | ||
1460 | 1443 | ||
1461 | /* | 1444 | /* |
1462 | * We scan through for each board, panel and port. The offset is | 1445 | * We scan through for each board, panel and port. The offset is |
@@ -1469,46 +1452,37 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof | |||
1469 | if (brdp->state == 0) | 1452 | if (brdp->state == 0) |
1470 | continue; | 1453 | continue; |
1471 | 1454 | ||
1472 | maxoff = curoff + (brdp->nrports * MAXLINE); | ||
1473 | if (off >= maxoff) { | ||
1474 | curoff = maxoff; | ||
1475 | continue; | ||
1476 | } | ||
1477 | |||
1478 | totalport = brdnr * STL_MAXPORTS; | 1455 | totalport = brdnr * STL_MAXPORTS; |
1479 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { | 1456 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { |
1480 | panelp = brdp->panels[panelnr]; | 1457 | panelp = brdp->panels[panelnr]; |
1481 | if (panelp == NULL) | 1458 | if (panelp == NULL) |
1482 | continue; | 1459 | continue; |
1483 | 1460 | ||
1484 | maxoff = curoff + (panelp->nrports * MAXLINE); | ||
1485 | if (off >= maxoff) { | ||
1486 | curoff = maxoff; | ||
1487 | totalport += panelp->nrports; | ||
1488 | continue; | ||
1489 | } | ||
1490 | |||
1491 | for (portnr = 0; portnr < panelp->nrports; portnr++, | 1461 | for (portnr = 0; portnr < panelp->nrports; portnr++, |
1492 | totalport++) { | 1462 | totalport++) { |
1493 | portp = panelp->ports[portnr]; | 1463 | portp = panelp->ports[portnr]; |
1494 | if (portp == NULL) | 1464 | if (portp == NULL) |
1495 | continue; | 1465 | continue; |
1496 | if (off >= (curoff += MAXLINE)) | 1466 | stl_portinfo(m, portp, totalport); |
1497 | continue; | ||
1498 | if ((pos - page + MAXLINE) > count) | ||
1499 | goto stl_readdone; | ||
1500 | pos += stl_portinfo(portp, totalport, pos); | ||
1501 | } | 1467 | } |
1502 | } | 1468 | } |
1503 | } | 1469 | } |
1470 | return 0; | ||
1471 | } | ||
1504 | 1472 | ||
1505 | *eof = 1; | 1473 | static int stl_proc_open(struct inode *inode, struct file *file) |
1506 | 1474 | { | |
1507 | stl_readdone: | 1475 | return single_open(file, stl_proc_show, NULL); |
1508 | *start = page; | ||
1509 | return pos - page; | ||
1510 | } | 1476 | } |
1511 | 1477 | ||
1478 | static const struct file_operations stl_proc_fops = { | ||
1479 | .owner = THIS_MODULE, | ||
1480 | .open = stl_proc_open, | ||
1481 | .read = seq_read, | ||
1482 | .llseek = seq_lseek, | ||
1483 | .release = single_release, | ||
1484 | }; | ||
1485 | |||
1512 | /*****************************************************************************/ | 1486 | /*****************************************************************************/ |
1513 | 1487 | ||
1514 | /* | 1488 | /* |
@@ -2566,9 +2540,9 @@ static const struct tty_operations stl_ops = { | |||
2566 | .break_ctl = stl_breakctl, | 2540 | .break_ctl = stl_breakctl, |
2567 | .wait_until_sent = stl_waituntilsent, | 2541 | .wait_until_sent = stl_waituntilsent, |
2568 | .send_xchar = stl_sendxchar, | 2542 | .send_xchar = stl_sendxchar, |
2569 | .read_proc = stl_readproc, | ||
2570 | .tiocmget = stl_tiocmget, | 2543 | .tiocmget = stl_tiocmget, |
2571 | .tiocmset = stl_tiocmset, | 2544 | .tiocmset = stl_tiocmset, |
2545 | .proc_fops = &stl_proc_fops, | ||
2572 | }; | 2546 | }; |
2573 | 2547 | ||
2574 | static const struct tty_port_operations stl_port_ops = { | 2548 | static const struct tty_port_operations stl_port_ops = { |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index b8063d4cad32..afd0b26ca056 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
80 | #include <linux/ioport.h> | 80 | #include <linux/ioport.h> |
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | ||
82 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
83 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
84 | #include <linux/netdevice.h> | 85 | #include <linux/netdevice.h> |
@@ -3459,18 +3460,17 @@ cleanup: | |||
3459 | * /proc fs routines.... | 3460 | * /proc fs routines.... |
3460 | */ | 3461 | */ |
3461 | 3462 | ||
3462 | static inline int line_info(char *buf, struct mgsl_struct *info) | 3463 | static inline void line_info(struct seq_file *m, struct mgsl_struct *info) |
3463 | { | 3464 | { |
3464 | char stat_buf[30]; | 3465 | char stat_buf[30]; |
3465 | int ret; | ||
3466 | unsigned long flags; | 3466 | unsigned long flags; |
3467 | 3467 | ||
3468 | if (info->bus_type == MGSL_BUS_TYPE_PCI) { | 3468 | if (info->bus_type == MGSL_BUS_TYPE_PCI) { |
3469 | ret = sprintf(buf, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", | 3469 | seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", |
3470 | info->device_name, info->io_base, info->irq_level, | 3470 | info->device_name, info->io_base, info->irq_level, |
3471 | info->phys_memory_base, info->phys_lcr_base); | 3471 | info->phys_memory_base, info->phys_lcr_base); |
3472 | } else { | 3472 | } else { |
3473 | ret = sprintf(buf, "%s:(E)ISA io:%04X irq:%d dma:%d", | 3473 | seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", |
3474 | info->device_name, info->io_base, | 3474 | info->device_name, info->io_base, |
3475 | info->irq_level, info->dma_level); | 3475 | info->irq_level, info->dma_level); |
3476 | } | 3476 | } |
@@ -3497,37 +3497,37 @@ static inline int line_info(char *buf, struct mgsl_struct *info) | |||
3497 | 3497 | ||
3498 | if (info->params.mode == MGSL_MODE_HDLC || | 3498 | if (info->params.mode == MGSL_MODE_HDLC || |
3499 | info->params.mode == MGSL_MODE_RAW ) { | 3499 | info->params.mode == MGSL_MODE_RAW ) { |
3500 | ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", | 3500 | seq_printf(m, " HDLC txok:%d rxok:%d", |
3501 | info->icount.txok, info->icount.rxok); | 3501 | info->icount.txok, info->icount.rxok); |
3502 | if (info->icount.txunder) | 3502 | if (info->icount.txunder) |
3503 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 3503 | seq_printf(m, " txunder:%d", info->icount.txunder); |
3504 | if (info->icount.txabort) | 3504 | if (info->icount.txabort) |
3505 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 3505 | seq_printf(m, " txabort:%d", info->icount.txabort); |
3506 | if (info->icount.rxshort) | 3506 | if (info->icount.rxshort) |
3507 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 3507 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
3508 | if (info->icount.rxlong) | 3508 | if (info->icount.rxlong) |
3509 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 3509 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
3510 | if (info->icount.rxover) | 3510 | if (info->icount.rxover) |
3511 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 3511 | seq_printf(m, " rxover:%d", info->icount.rxover); |
3512 | if (info->icount.rxcrc) | 3512 | if (info->icount.rxcrc) |
3513 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 3513 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
3514 | } else { | 3514 | } else { |
3515 | ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", | 3515 | seq_printf(m, " ASYNC tx:%d rx:%d", |
3516 | info->icount.tx, info->icount.rx); | 3516 | info->icount.tx, info->icount.rx); |
3517 | if (info->icount.frame) | 3517 | if (info->icount.frame) |
3518 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 3518 | seq_printf(m, " fe:%d", info->icount.frame); |
3519 | if (info->icount.parity) | 3519 | if (info->icount.parity) |
3520 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 3520 | seq_printf(m, " pe:%d", info->icount.parity); |
3521 | if (info->icount.brk) | 3521 | if (info->icount.brk) |
3522 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 3522 | seq_printf(m, " brk:%d", info->icount.brk); |
3523 | if (info->icount.overrun) | 3523 | if (info->icount.overrun) |
3524 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 3524 | seq_printf(m, " oe:%d", info->icount.overrun); |
3525 | } | 3525 | } |
3526 | 3526 | ||
3527 | /* Append serial signal status to end */ | 3527 | /* Append serial signal status to end */ |
3528 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 3528 | seq_printf(m, " %s\n", stat_buf+1); |
3529 | 3529 | ||
3530 | ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 3530 | seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
3531 | info->tx_active,info->bh_requested,info->bh_running, | 3531 | info->tx_active,info->bh_requested,info->bh_running, |
3532 | info->pending_bh); | 3532 | info->pending_bh); |
3533 | 3533 | ||
@@ -3544,60 +3544,40 @@ static inline int line_info(char *buf, struct mgsl_struct *info) | |||
3544 | u16 Tmr = usc_InReg( info, TMR ); | 3544 | u16 Tmr = usc_InReg( info, TMR ); |
3545 | u16 Tccr = usc_InReg( info, TCCR ); | 3545 | u16 Tccr = usc_InReg( info, TCCR ); |
3546 | u16 Ccar = inw( info->io_base + CCAR ); | 3546 | u16 Ccar = inw( info->io_base + CCAR ); |
3547 | ret += sprintf(buf+ret, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" | 3547 | seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" |
3548 | "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", | 3548 | "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", |
3549 | Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); | 3549 | Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); |
3550 | } | 3550 | } |
3551 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 3551 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
3552 | 3552 | } | |
3553 | return ret; | ||
3554 | |||
3555 | } /* end of line_info() */ | ||
3556 | 3553 | ||
3557 | /* mgsl_read_proc() | 3554 | /* Called to print information about devices */ |
3558 | * | 3555 | static int mgsl_proc_show(struct seq_file *m, void *v) |
3559 | * Called to print information about devices | ||
3560 | * | ||
3561 | * Arguments: | ||
3562 | * page page of memory to hold returned info | ||
3563 | * start | ||
3564 | * off | ||
3565 | * count | ||
3566 | * eof | ||
3567 | * data | ||
3568 | * | ||
3569 | * Return Value: | ||
3570 | */ | ||
3571 | static int mgsl_read_proc(char *page, char **start, off_t off, int count, | ||
3572 | int *eof, void *data) | ||
3573 | { | 3556 | { |
3574 | int len = 0, l; | ||
3575 | off_t begin = 0; | ||
3576 | struct mgsl_struct *info; | 3557 | struct mgsl_struct *info; |
3577 | 3558 | ||
3578 | len += sprintf(page, "synclink driver:%s\n", driver_version); | 3559 | seq_printf(m, "synclink driver:%s\n", driver_version); |
3579 | 3560 | ||
3580 | info = mgsl_device_list; | 3561 | info = mgsl_device_list; |
3581 | while( info ) { | 3562 | while( info ) { |
3582 | l = line_info(page + len, info); | 3563 | line_info(m, info); |
3583 | len += l; | ||
3584 | if (len+begin > off+count) | ||
3585 | goto done; | ||
3586 | if (len+begin < off) { | ||
3587 | begin += len; | ||
3588 | len = 0; | ||
3589 | } | ||
3590 | info = info->next_device; | 3564 | info = info->next_device; |
3591 | } | 3565 | } |
3566 | return 0; | ||
3567 | } | ||
3592 | 3568 | ||
3593 | *eof = 1; | 3569 | static int mgsl_proc_open(struct inode *inode, struct file *file) |
3594 | done: | 3570 | { |
3595 | if (off >= len+begin) | 3571 | return single_open(file, mgsl_proc_show, NULL); |
3596 | return 0; | 3572 | } |
3597 | *start = page + (off-begin); | 3573 | |
3598 | return ((count < begin+len-off) ? count : begin+len-off); | 3574 | static const struct file_operations mgsl_proc_fops = { |
3599 | 3575 | .owner = THIS_MODULE, | |
3600 | } /* end of mgsl_read_proc() */ | 3576 | .open = mgsl_proc_open, |
3577 | .read = seq_read, | ||
3578 | .llseek = seq_lseek, | ||
3579 | .release = single_release, | ||
3580 | }; | ||
3601 | 3581 | ||
3602 | /* mgsl_allocate_dma_buffers() | 3582 | /* mgsl_allocate_dma_buffers() |
3603 | * | 3583 | * |
@@ -4335,13 +4315,13 @@ static const struct tty_operations mgsl_ops = { | |||
4335 | .send_xchar = mgsl_send_xchar, | 4315 | .send_xchar = mgsl_send_xchar, |
4336 | .break_ctl = mgsl_break, | 4316 | .break_ctl = mgsl_break, |
4337 | .wait_until_sent = mgsl_wait_until_sent, | 4317 | .wait_until_sent = mgsl_wait_until_sent, |
4338 | .read_proc = mgsl_read_proc, | ||
4339 | .set_termios = mgsl_set_termios, | 4318 | .set_termios = mgsl_set_termios, |
4340 | .stop = mgsl_stop, | 4319 | .stop = mgsl_stop, |
4341 | .start = mgsl_start, | 4320 | .start = mgsl_start, |
4342 | .hangup = mgsl_hangup, | 4321 | .hangup = mgsl_hangup, |
4343 | .tiocmget = tiocmget, | 4322 | .tiocmget = tiocmget, |
4344 | .tiocmset = tiocmset, | 4323 | .tiocmset = tiocmset, |
4324 | .proc_fops = &mgsl_proc_fops, | ||
4345 | }; | 4325 | }; |
4346 | 4326 | ||
4347 | /* | 4327 | /* |
@@ -8007,10 +7987,17 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) | |||
8007 | dev->stats.rx_bytes += size; | 7987 | dev->stats.rx_bytes += size; |
8008 | 7988 | ||
8009 | netif_rx(skb); | 7989 | netif_rx(skb); |
8010 | |||
8011 | dev->last_rx = jiffies; | ||
8012 | } | 7990 | } |
8013 | 7991 | ||
7992 | static const struct net_device_ops hdlcdev_ops = { | ||
7993 | .ndo_open = hdlcdev_open, | ||
7994 | .ndo_stop = hdlcdev_close, | ||
7995 | .ndo_change_mtu = hdlc_change_mtu, | ||
7996 | .ndo_start_xmit = hdlc_start_xmit, | ||
7997 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
7998 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
7999 | }; | ||
8000 | |||
8014 | /** | 8001 | /** |
8015 | * called by device driver when adding device instance | 8002 | * called by device driver when adding device instance |
8016 | * do generic HDLC initialization | 8003 | * do generic HDLC initialization |
@@ -8038,11 +8025,8 @@ static int hdlcdev_init(struct mgsl_struct *info) | |||
8038 | dev->dma = info->dma_level; | 8025 | dev->dma = info->dma_level; |
8039 | 8026 | ||
8040 | /* network layer callbacks and settings */ | 8027 | /* network layer callbacks and settings */ |
8041 | dev->do_ioctl = hdlcdev_ioctl; | 8028 | dev->netdev_ops = &hdlcdev_ops; |
8042 | dev->open = hdlcdev_open; | 8029 | dev->watchdog_timeo = 10 * HZ; |
8043 | dev->stop = hdlcdev_close; | ||
8044 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
8045 | dev->watchdog_timeo = 10*HZ; | ||
8046 | dev->tx_queue_len = 50; | 8030 | dev->tx_queue_len = 50; |
8047 | 8031 | ||
8048 | /* generic HDLC layer callbacks and settings */ | 8032 | /* generic HDLC layer callbacks and settings */ |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index f329f459817c..5e256494686a 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <linux/ptrace.h> | 60 | #include <linux/ptrace.h> |
61 | #include <linux/ioport.h> | 61 | #include <linux/ioport.h> |
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | ||
63 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
64 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
65 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
@@ -154,7 +155,6 @@ static void tx_hold(struct tty_struct *tty); | |||
154 | static void tx_release(struct tty_struct *tty); | 155 | static void tx_release(struct tty_struct *tty); |
155 | 156 | ||
156 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | 157 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); |
157 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
158 | static int chars_in_buffer(struct tty_struct *tty); | 158 | static int chars_in_buffer(struct tty_struct *tty); |
159 | static void throttle(struct tty_struct * tty); | 159 | static void throttle(struct tty_struct * tty); |
160 | static void unthrottle(struct tty_struct * tty); | 160 | static void unthrottle(struct tty_struct * tty); |
@@ -298,6 +298,7 @@ struct slgt_info { | |||
298 | 298 | ||
299 | unsigned int rbuf_fill_level; | 299 | unsigned int rbuf_fill_level; |
300 | unsigned int if_mode; | 300 | unsigned int if_mode; |
301 | unsigned int base_clock; | ||
301 | 302 | ||
302 | /* device status */ | 303 | /* device status */ |
303 | 304 | ||
@@ -1156,22 +1157,26 @@ static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *ne | |||
1156 | return -EFAULT; | 1157 | return -EFAULT; |
1157 | 1158 | ||
1158 | spin_lock(&info->lock); | 1159 | spin_lock(&info->lock); |
1159 | info->params.mode = tmp_params.mode; | 1160 | if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) { |
1160 | info->params.loopback = tmp_params.loopback; | 1161 | info->base_clock = tmp_params.clock_speed; |
1161 | info->params.flags = tmp_params.flags; | 1162 | } else { |
1162 | info->params.encoding = tmp_params.encoding; | 1163 | info->params.mode = tmp_params.mode; |
1163 | info->params.clock_speed = tmp_params.clock_speed; | 1164 | info->params.loopback = tmp_params.loopback; |
1164 | info->params.addr_filter = tmp_params.addr_filter; | 1165 | info->params.flags = tmp_params.flags; |
1165 | info->params.crc_type = tmp_params.crc_type; | 1166 | info->params.encoding = tmp_params.encoding; |
1166 | info->params.preamble_length = tmp_params.preamble_length; | 1167 | info->params.clock_speed = tmp_params.clock_speed; |
1167 | info->params.preamble = tmp_params.preamble; | 1168 | info->params.addr_filter = tmp_params.addr_filter; |
1168 | info->params.data_rate = tmp_params.data_rate; | 1169 | info->params.crc_type = tmp_params.crc_type; |
1169 | info->params.data_bits = tmp_params.data_bits; | 1170 | info->params.preamble_length = tmp_params.preamble_length; |
1170 | info->params.stop_bits = tmp_params.stop_bits; | 1171 | info->params.preamble = tmp_params.preamble; |
1171 | info->params.parity = tmp_params.parity; | 1172 | info->params.data_rate = tmp_params.data_rate; |
1173 | info->params.data_bits = tmp_params.data_bits; | ||
1174 | info->params.stop_bits = tmp_params.stop_bits; | ||
1175 | info->params.parity = tmp_params.parity; | ||
1176 | } | ||
1172 | spin_unlock(&info->lock); | 1177 | spin_unlock(&info->lock); |
1173 | 1178 | ||
1174 | change_params(info); | 1179 | program_hw(info); |
1175 | 1180 | ||
1176 | return 0; | 1181 | return 0; |
1177 | } | 1182 | } |
@@ -1229,13 +1234,12 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, | |||
1229 | /* | 1234 | /* |
1230 | * proc fs support | 1235 | * proc fs support |
1231 | */ | 1236 | */ |
1232 | static inline int line_info(char *buf, struct slgt_info *info) | 1237 | static inline void line_info(struct seq_file *m, struct slgt_info *info) |
1233 | { | 1238 | { |
1234 | char stat_buf[30]; | 1239 | char stat_buf[30]; |
1235 | int ret; | ||
1236 | unsigned long flags; | 1240 | unsigned long flags; |
1237 | 1241 | ||
1238 | ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", | 1242 | seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", |
1239 | info->device_name, info->phys_reg_addr, | 1243 | info->device_name, info->phys_reg_addr, |
1240 | info->irq_level, info->max_frame_size); | 1244 | info->irq_level, info->max_frame_size); |
1241 | 1245 | ||
@@ -1260,75 +1264,70 @@ static inline int line_info(char *buf, struct slgt_info *info) | |||
1260 | strcat(stat_buf, "|RI"); | 1264 | strcat(stat_buf, "|RI"); |
1261 | 1265 | ||
1262 | if (info->params.mode != MGSL_MODE_ASYNC) { | 1266 | if (info->params.mode != MGSL_MODE_ASYNC) { |
1263 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | 1267 | seq_printf(m, "\tHDLC txok:%d rxok:%d", |
1264 | info->icount.txok, info->icount.rxok); | 1268 | info->icount.txok, info->icount.rxok); |
1265 | if (info->icount.txunder) | 1269 | if (info->icount.txunder) |
1266 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 1270 | seq_printf(m, " txunder:%d", info->icount.txunder); |
1267 | if (info->icount.txabort) | 1271 | if (info->icount.txabort) |
1268 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 1272 | seq_printf(m, " txabort:%d", info->icount.txabort); |
1269 | if (info->icount.rxshort) | 1273 | if (info->icount.rxshort) |
1270 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 1274 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
1271 | if (info->icount.rxlong) | 1275 | if (info->icount.rxlong) |
1272 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 1276 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
1273 | if (info->icount.rxover) | 1277 | if (info->icount.rxover) |
1274 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 1278 | seq_printf(m, " rxover:%d", info->icount.rxover); |
1275 | if (info->icount.rxcrc) | 1279 | if (info->icount.rxcrc) |
1276 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 1280 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
1277 | } else { | 1281 | } else { |
1278 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | 1282 | seq_printf(m, "\tASYNC tx:%d rx:%d", |
1279 | info->icount.tx, info->icount.rx); | 1283 | info->icount.tx, info->icount.rx); |
1280 | if (info->icount.frame) | 1284 | if (info->icount.frame) |
1281 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 1285 | seq_printf(m, " fe:%d", info->icount.frame); |
1282 | if (info->icount.parity) | 1286 | if (info->icount.parity) |
1283 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 1287 | seq_printf(m, " pe:%d", info->icount.parity); |
1284 | if (info->icount.brk) | 1288 | if (info->icount.brk) |
1285 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 1289 | seq_printf(m, " brk:%d", info->icount.brk); |
1286 | if (info->icount.overrun) | 1290 | if (info->icount.overrun) |
1287 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 1291 | seq_printf(m, " oe:%d", info->icount.overrun); |
1288 | } | 1292 | } |
1289 | 1293 | ||
1290 | /* Append serial signal status to end */ | 1294 | /* Append serial signal status to end */ |
1291 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1295 | seq_printf(m, " %s\n", stat_buf+1); |
1292 | 1296 | ||
1293 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 1297 | seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
1294 | info->tx_active,info->bh_requested,info->bh_running, | 1298 | info->tx_active,info->bh_requested,info->bh_running, |
1295 | info->pending_bh); | 1299 | info->pending_bh); |
1296 | |||
1297 | return ret; | ||
1298 | } | 1300 | } |
1299 | 1301 | ||
1300 | /* Called to print information about devices | 1302 | /* Called to print information about devices |
1301 | */ | 1303 | */ |
1302 | static int read_proc(char *page, char **start, off_t off, int count, | 1304 | static int synclink_gt_proc_show(struct seq_file *m, void *v) |
1303 | int *eof, void *data) | ||
1304 | { | 1305 | { |
1305 | int len = 0, l; | ||
1306 | off_t begin = 0; | ||
1307 | struct slgt_info *info; | 1306 | struct slgt_info *info; |
1308 | 1307 | ||
1309 | len += sprintf(page, "synclink_gt driver\n"); | 1308 | seq_puts(m, "synclink_gt driver\n"); |
1310 | 1309 | ||
1311 | info = slgt_device_list; | 1310 | info = slgt_device_list; |
1312 | while( info ) { | 1311 | while( info ) { |
1313 | l = line_info(page + len, info); | 1312 | line_info(m, info); |
1314 | len += l; | ||
1315 | if (len+begin > off+count) | ||
1316 | goto done; | ||
1317 | if (len+begin < off) { | ||
1318 | begin += len; | ||
1319 | len = 0; | ||
1320 | } | ||
1321 | info = info->next_device; | 1313 | info = info->next_device; |
1322 | } | 1314 | } |
1315 | return 0; | ||
1316 | } | ||
1323 | 1317 | ||
1324 | *eof = 1; | 1318 | static int synclink_gt_proc_open(struct inode *inode, struct file *file) |
1325 | done: | 1319 | { |
1326 | if (off >= len+begin) | 1320 | return single_open(file, synclink_gt_proc_show, NULL); |
1327 | return 0; | ||
1328 | *start = page + (off-begin); | ||
1329 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1330 | } | 1321 | } |
1331 | 1322 | ||
1323 | static const struct file_operations synclink_gt_proc_fops = { | ||
1324 | .owner = THIS_MODULE, | ||
1325 | .open = synclink_gt_proc_open, | ||
1326 | .read = seq_read, | ||
1327 | .llseek = seq_lseek, | ||
1328 | .release = single_release, | ||
1329 | }; | ||
1330 | |||
1332 | /* | 1331 | /* |
1333 | * return count of bytes in transmit buffer | 1332 | * return count of bytes in transmit buffer |
1334 | */ | 1333 | */ |
@@ -1763,10 +1762,17 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) | |||
1763 | dev->stats.rx_bytes += size; | 1762 | dev->stats.rx_bytes += size; |
1764 | 1763 | ||
1765 | netif_rx(skb); | 1764 | netif_rx(skb); |
1766 | |||
1767 | dev->last_rx = jiffies; | ||
1768 | } | 1765 | } |
1769 | 1766 | ||
1767 | static const struct net_device_ops hdlcdev_ops = { | ||
1768 | .ndo_open = hdlcdev_open, | ||
1769 | .ndo_stop = hdlcdev_close, | ||
1770 | .ndo_change_mtu = hdlc_change_mtu, | ||
1771 | .ndo_start_xmit = hdlc_start_xmit, | ||
1772 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
1773 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
1774 | }; | ||
1775 | |||
1770 | /** | 1776 | /** |
1771 | * called by device driver when adding device instance | 1777 | * called by device driver when adding device instance |
1772 | * do generic HDLC initialization | 1778 | * do generic HDLC initialization |
@@ -1794,11 +1800,8 @@ static int hdlcdev_init(struct slgt_info *info) | |||
1794 | dev->irq = info->irq_level; | 1800 | dev->irq = info->irq_level; |
1795 | 1801 | ||
1796 | /* network layer callbacks and settings */ | 1802 | /* network layer callbacks and settings */ |
1797 | dev->do_ioctl = hdlcdev_ioctl; | 1803 | dev->netdev_ops = &hdlcdev_ops; |
1798 | dev->open = hdlcdev_open; | 1804 | dev->watchdog_timeo = 10 * HZ; |
1799 | dev->stop = hdlcdev_close; | ||
1800 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
1801 | dev->watchdog_timeo = 10*HZ; | ||
1802 | dev->tx_queue_len = 50; | 1805 | dev->tx_queue_len = 50; |
1803 | 1806 | ||
1804 | /* generic HDLC layer callbacks and settings */ | 1807 | /* generic HDLC layer callbacks and settings */ |
@@ -2561,10 +2564,13 @@ static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params) | |||
2561 | return -EFAULT; | 2564 | return -EFAULT; |
2562 | 2565 | ||
2563 | spin_lock_irqsave(&info->lock, flags); | 2566 | spin_lock_irqsave(&info->lock, flags); |
2564 | memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS)); | 2567 | if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) |
2568 | info->base_clock = tmp_params.clock_speed; | ||
2569 | else | ||
2570 | memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS)); | ||
2565 | spin_unlock_irqrestore(&info->lock, flags); | 2571 | spin_unlock_irqrestore(&info->lock, flags); |
2566 | 2572 | ||
2567 | change_params(info); | 2573 | program_hw(info); |
2568 | 2574 | ||
2569 | return 0; | 2575 | return 0; |
2570 | } | 2576 | } |
@@ -3434,6 +3440,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3434 | info->magic = MGSL_MAGIC; | 3440 | info->magic = MGSL_MAGIC; |
3435 | INIT_WORK(&info->task, bh_handler); | 3441 | INIT_WORK(&info->task, bh_handler); |
3436 | info->max_frame_size = 4096; | 3442 | info->max_frame_size = 4096; |
3443 | info->base_clock = 14745600; | ||
3437 | info->rbuf_fill_level = DMABUFSIZE; | 3444 | info->rbuf_fill_level = DMABUFSIZE; |
3438 | info->port.close_delay = 5*HZ/10; | 3445 | info->port.close_delay = 5*HZ/10; |
3439 | info->port.closing_wait = 30*HZ; | 3446 | info->port.closing_wait = 30*HZ; |
@@ -3558,13 +3565,13 @@ static const struct tty_operations ops = { | |||
3558 | .send_xchar = send_xchar, | 3565 | .send_xchar = send_xchar, |
3559 | .break_ctl = set_break, | 3566 | .break_ctl = set_break, |
3560 | .wait_until_sent = wait_until_sent, | 3567 | .wait_until_sent = wait_until_sent, |
3561 | .read_proc = read_proc, | ||
3562 | .set_termios = set_termios, | 3568 | .set_termios = set_termios, |
3563 | .stop = tx_hold, | 3569 | .stop = tx_hold, |
3564 | .start = tx_release, | 3570 | .start = tx_release, |
3565 | .hangup = hangup, | 3571 | .hangup = hangup, |
3566 | .tiocmget = tiocmget, | 3572 | .tiocmget = tiocmget, |
3567 | .tiocmset = tiocmset, | 3573 | .tiocmset = tiocmset, |
3574 | .proc_fops = &synclink_gt_proc_fops, | ||
3568 | }; | 3575 | }; |
3569 | 3576 | ||
3570 | static void slgt_cleanup(void) | 3577 | static void slgt_cleanup(void) |
@@ -3781,7 +3788,7 @@ static void enable_loopback(struct slgt_info *info) | |||
3781 | static void set_rate(struct slgt_info *info, u32 rate) | 3788 | static void set_rate(struct slgt_info *info, u32 rate) |
3782 | { | 3789 | { |
3783 | unsigned int div; | 3790 | unsigned int div; |
3784 | static unsigned int osc = 14745600; | 3791 | unsigned int osc = info->base_clock; |
3785 | 3792 | ||
3786 | /* div = osc/rate - 1 | 3793 | /* div = osc/rate - 1 |
3787 | * | 3794 | * |
@@ -4085,18 +4092,27 @@ static void async_mode(struct slgt_info *info) | |||
4085 | * 06 CTS IRQ enable | 4092 | * 06 CTS IRQ enable |
4086 | * 05 DCD IRQ enable | 4093 | * 05 DCD IRQ enable |
4087 | * 04 RI IRQ enable | 4094 | * 04 RI IRQ enable |
4088 | * 03 reserved, must be zero | 4095 | * 03 0=16x sampling, 1=8x sampling |
4089 | * 02 1=txd->rxd internal loopback enable | 4096 | * 02 1=txd->rxd internal loopback enable |
4090 | * 01 reserved, must be zero | 4097 | * 01 reserved, must be zero |
4091 | * 00 1=master IRQ enable | 4098 | * 00 1=master IRQ enable |
4092 | */ | 4099 | */ |
4093 | val = BIT15 + BIT14 + BIT0; | 4100 | val = BIT15 + BIT14 + BIT0; |
4101 | /* JCR[8] : 1 = x8 async mode feature available */ | ||
4102 | if ((rd_reg32(info, JCR) & BIT8) && info->params.data_rate && | ||
4103 | ((info->base_clock < (info->params.data_rate * 16)) || | ||
4104 | (info->base_clock % (info->params.data_rate * 16)))) { | ||
4105 | /* use 8x sampling */ | ||
4106 | val |= BIT3; | ||
4107 | set_rate(info, info->params.data_rate * 8); | ||
4108 | } else { | ||
4109 | /* use 16x sampling */ | ||
4110 | set_rate(info, info->params.data_rate * 16); | ||
4111 | } | ||
4094 | wr_reg16(info, SCR, val); | 4112 | wr_reg16(info, SCR, val); |
4095 | 4113 | ||
4096 | slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER); | 4114 | slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER); |
4097 | 4115 | ||
4098 | set_rate(info, info->params.data_rate * 16); | ||
4099 | |||
4100 | if (info->params.loopback) | 4116 | if (info->params.loopback) |
4101 | enable_loopback(info); | 4117 | enable_loopback(info); |
4102 | } | 4118 | } |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 7b0c5b2dd263..26de60efe4b2 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/ptrace.h> | 50 | #include <linux/ptrace.h> |
51 | #include <linux/ioport.h> | 51 | #include <linux/ioport.h> |
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/seq_file.h> | ||
53 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
54 | #include <linux/netdevice.h> | 55 | #include <linux/netdevice.h> |
55 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
@@ -520,7 +521,6 @@ static void tx_hold(struct tty_struct *tty); | |||
520 | static void tx_release(struct tty_struct *tty); | 521 | static void tx_release(struct tty_struct *tty); |
521 | 522 | ||
522 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | 523 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); |
523 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
524 | static int chars_in_buffer(struct tty_struct *tty); | 524 | static int chars_in_buffer(struct tty_struct *tty); |
525 | static void throttle(struct tty_struct * tty); | 525 | static void throttle(struct tty_struct * tty); |
526 | static void unthrottle(struct tty_struct * tty); | 526 | static void unthrottle(struct tty_struct * tty); |
@@ -1354,13 +1354,12 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1354 | * /proc fs routines.... | 1354 | * /proc fs routines.... |
1355 | */ | 1355 | */ |
1356 | 1356 | ||
1357 | static inline int line_info(char *buf, SLMP_INFO *info) | 1357 | static inline void line_info(struct seq_file *m, SLMP_INFO *info) |
1358 | { | 1358 | { |
1359 | char stat_buf[30]; | 1359 | char stat_buf[30]; |
1360 | int ret; | ||
1361 | unsigned long flags; | 1360 | unsigned long flags; |
1362 | 1361 | ||
1363 | ret = sprintf(buf, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" | 1362 | seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" |
1364 | "\tIRQ=%d MaxFrameSize=%u\n", | 1363 | "\tIRQ=%d MaxFrameSize=%u\n", |
1365 | info->device_name, | 1364 | info->device_name, |
1366 | info->phys_sca_base, | 1365 | info->phys_sca_base, |
@@ -1391,75 +1390,70 @@ static inline int line_info(char *buf, SLMP_INFO *info) | |||
1391 | strcat(stat_buf, "|RI"); | 1390 | strcat(stat_buf, "|RI"); |
1392 | 1391 | ||
1393 | if (info->params.mode == MGSL_MODE_HDLC) { | 1392 | if (info->params.mode == MGSL_MODE_HDLC) { |
1394 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | 1393 | seq_printf(m, "\tHDLC txok:%d rxok:%d", |
1395 | info->icount.txok, info->icount.rxok); | 1394 | info->icount.txok, info->icount.rxok); |
1396 | if (info->icount.txunder) | 1395 | if (info->icount.txunder) |
1397 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 1396 | seq_printf(m, " txunder:%d", info->icount.txunder); |
1398 | if (info->icount.txabort) | 1397 | if (info->icount.txabort) |
1399 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 1398 | seq_printf(m, " txabort:%d", info->icount.txabort); |
1400 | if (info->icount.rxshort) | 1399 | if (info->icount.rxshort) |
1401 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 1400 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
1402 | if (info->icount.rxlong) | 1401 | if (info->icount.rxlong) |
1403 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 1402 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
1404 | if (info->icount.rxover) | 1403 | if (info->icount.rxover) |
1405 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 1404 | seq_printf(m, " rxover:%d", info->icount.rxover); |
1406 | if (info->icount.rxcrc) | 1405 | if (info->icount.rxcrc) |
1407 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); | 1406 | seq_printf(m, " rxlong:%d", info->icount.rxcrc); |
1408 | } else { | 1407 | } else { |
1409 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | 1408 | seq_printf(m, "\tASYNC tx:%d rx:%d", |
1410 | info->icount.tx, info->icount.rx); | 1409 | info->icount.tx, info->icount.rx); |
1411 | if (info->icount.frame) | 1410 | if (info->icount.frame) |
1412 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 1411 | seq_printf(m, " fe:%d", info->icount.frame); |
1413 | if (info->icount.parity) | 1412 | if (info->icount.parity) |
1414 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 1413 | seq_printf(m, " pe:%d", info->icount.parity); |
1415 | if (info->icount.brk) | 1414 | if (info->icount.brk) |
1416 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 1415 | seq_printf(m, " brk:%d", info->icount.brk); |
1417 | if (info->icount.overrun) | 1416 | if (info->icount.overrun) |
1418 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 1417 | seq_printf(m, " oe:%d", info->icount.overrun); |
1419 | } | 1418 | } |
1420 | 1419 | ||
1421 | /* Append serial signal status to end */ | 1420 | /* Append serial signal status to end */ |
1422 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1421 | seq_printf(m, " %s\n", stat_buf+1); |
1423 | 1422 | ||
1424 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 1423 | seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
1425 | info->tx_active,info->bh_requested,info->bh_running, | 1424 | info->tx_active,info->bh_requested,info->bh_running, |
1426 | info->pending_bh); | 1425 | info->pending_bh); |
1427 | |||
1428 | return ret; | ||
1429 | } | 1426 | } |
1430 | 1427 | ||
1431 | /* Called to print information about devices | 1428 | /* Called to print information about devices |
1432 | */ | 1429 | */ |
1433 | static int read_proc(char *page, char **start, off_t off, int count, | 1430 | static int synclinkmp_proc_show(struct seq_file *m, void *v) |
1434 | int *eof, void *data) | ||
1435 | { | 1431 | { |
1436 | int len = 0, l; | ||
1437 | off_t begin = 0; | ||
1438 | SLMP_INFO *info; | 1432 | SLMP_INFO *info; |
1439 | 1433 | ||
1440 | len += sprintf(page, "synclinkmp driver:%s\n", driver_version); | 1434 | seq_printf(m, "synclinkmp driver:%s\n", driver_version); |
1441 | 1435 | ||
1442 | info = synclinkmp_device_list; | 1436 | info = synclinkmp_device_list; |
1443 | while( info ) { | 1437 | while( info ) { |
1444 | l = line_info(page + len, info); | 1438 | line_info(m, info); |
1445 | len += l; | ||
1446 | if (len+begin > off+count) | ||
1447 | goto done; | ||
1448 | if (len+begin < off) { | ||
1449 | begin += len; | ||
1450 | len = 0; | ||
1451 | } | ||
1452 | info = info->next_device; | 1439 | info = info->next_device; |
1453 | } | 1440 | } |
1441 | return 0; | ||
1442 | } | ||
1454 | 1443 | ||
1455 | *eof = 1; | 1444 | static int synclinkmp_proc_open(struct inode *inode, struct file *file) |
1456 | done: | 1445 | { |
1457 | if (off >= len+begin) | 1446 | return single_open(file, synclinkmp_proc_show, NULL); |
1458 | return 0; | ||
1459 | *start = page + (off-begin); | ||
1460 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1461 | } | 1447 | } |
1462 | 1448 | ||
1449 | static const struct file_operations synclinkmp_proc_fops = { | ||
1450 | .owner = THIS_MODULE, | ||
1451 | .open = synclinkmp_proc_open, | ||
1452 | .read = seq_read, | ||
1453 | .llseek = seq_lseek, | ||
1454 | .release = single_release, | ||
1455 | }; | ||
1456 | |||
1463 | /* Return the count of bytes in transmit buffer | 1457 | /* Return the count of bytes in transmit buffer |
1464 | */ | 1458 | */ |
1465 | static int chars_in_buffer(struct tty_struct *tty) | 1459 | static int chars_in_buffer(struct tty_struct *tty) |
@@ -1907,10 +1901,17 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) | |||
1907 | dev->stats.rx_bytes += size; | 1901 | dev->stats.rx_bytes += size; |
1908 | 1902 | ||
1909 | netif_rx(skb); | 1903 | netif_rx(skb); |
1910 | |||
1911 | dev->last_rx = jiffies; | ||
1912 | } | 1904 | } |
1913 | 1905 | ||
1906 | static const struct net_device_ops hdlcdev_ops = { | ||
1907 | .ndo_open = hdlcdev_open, | ||
1908 | .ndo_stop = hdlcdev_close, | ||
1909 | .ndo_change_mtu = hdlc_change_mtu, | ||
1910 | .ndo_start_xmit = hdlc_start_xmit, | ||
1911 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
1912 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
1913 | }; | ||
1914 | |||
1914 | /** | 1915 | /** |
1915 | * called by device driver when adding device instance | 1916 | * called by device driver when adding device instance |
1916 | * do generic HDLC initialization | 1917 | * do generic HDLC initialization |
@@ -1938,11 +1939,8 @@ static int hdlcdev_init(SLMP_INFO *info) | |||
1938 | dev->irq = info->irq_level; | 1939 | dev->irq = info->irq_level; |
1939 | 1940 | ||
1940 | /* network layer callbacks and settings */ | 1941 | /* network layer callbacks and settings */ |
1941 | dev->do_ioctl = hdlcdev_ioctl; | 1942 | dev->netdev_ops = &hdlcdev_ops; |
1942 | dev->open = hdlcdev_open; | 1943 | dev->watchdog_timeo = 10 * HZ; |
1943 | dev->stop = hdlcdev_close; | ||
1944 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
1945 | dev->watchdog_timeo = 10*HZ; | ||
1946 | dev->tx_queue_len = 50; | 1944 | dev->tx_queue_len = 50; |
1947 | 1945 | ||
1948 | /* generic HDLC layer callbacks and settings */ | 1946 | /* generic HDLC layer callbacks and settings */ |
@@ -3901,13 +3899,13 @@ static const struct tty_operations ops = { | |||
3901 | .send_xchar = send_xchar, | 3899 | .send_xchar = send_xchar, |
3902 | .break_ctl = set_break, | 3900 | .break_ctl = set_break, |
3903 | .wait_until_sent = wait_until_sent, | 3901 | .wait_until_sent = wait_until_sent, |
3904 | .read_proc = read_proc, | ||
3905 | .set_termios = set_termios, | 3902 | .set_termios = set_termios, |
3906 | .stop = tx_hold, | 3903 | .stop = tx_hold, |
3907 | .start = tx_release, | 3904 | .start = tx_release, |
3908 | .hangup = hangup, | 3905 | .hangup = hangup, |
3909 | .tiocmget = tiocmget, | 3906 | .tiocmget = tiocmget, |
3910 | .tiocmset = tiocmset, | 3907 | .tiocmset = tiocmset, |
3908 | .proc_fops = &synclinkmp_proc_fops, | ||
3911 | }; | 3909 | }; |
3912 | 3910 | ||
3913 | 3911 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 33a9351c896d..b0a6a3e51924 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/vt_kern.h> | 35 | #include <linux/vt_kern.h> |
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | #include <linux/kexec.h> | 37 | #include <linux/kexec.h> |
38 | #include <linux/irq.h> | ||
39 | #include <linux/hrtimer.h> | 38 | #include <linux/hrtimer.h> |
40 | #include <linux/oom.h> | 39 | #include <linux/oom.h> |
41 | 40 | ||
@@ -283,7 +282,7 @@ static void sysrq_ftrace_dump(int key, struct tty_struct *tty) | |||
283 | } | 282 | } |
284 | static struct sysrq_key_op sysrq_ftrace_dump_op = { | 283 | static struct sysrq_key_op sysrq_ftrace_dump_op = { |
285 | .handler = sysrq_ftrace_dump, | 284 | .handler = sysrq_ftrace_dump, |
286 | .help_msg = "dumpZ-ftrace-buffer", | 285 | .help_msg = "dump-ftrace-buffer(Z)", |
287 | .action_msg = "Dump ftrace buffer", | 286 | .action_msg = "Dump ftrace buffer", |
288 | .enable_mask = SYSRQ_ENABLE_DUMP, | 287 | .enable_mask = SYSRQ_ENABLE_DUMP, |
289 | }; | 288 | }; |
@@ -346,6 +345,19 @@ static struct sysrq_key_op sysrq_moom_op = { | |||
346 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | 345 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
347 | }; | 346 | }; |
348 | 347 | ||
348 | #ifdef CONFIG_BLOCK | ||
349 | static void sysrq_handle_thaw(int key, struct tty_struct *tty) | ||
350 | { | ||
351 | emergency_thaw_all(); | ||
352 | } | ||
353 | static struct sysrq_key_op sysrq_thaw_op = { | ||
354 | .handler = sysrq_handle_thaw, | ||
355 | .help_msg = "thaw-filesystems(J)", | ||
356 | .action_msg = "Emergency Thaw of all frozen filesystems", | ||
357 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | ||
358 | }; | ||
359 | #endif | ||
360 | |||
349 | static void sysrq_handle_kill(int key, struct tty_struct *tty) | 361 | static void sysrq_handle_kill(int key, struct tty_struct *tty) |
350 | { | 362 | { |
351 | send_sig_all(SIGKILL); | 363 | send_sig_all(SIGKILL); |
@@ -396,9 +408,13 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
396 | &sysrq_moom_op, /* f */ | 408 | &sysrq_moom_op, /* f */ |
397 | /* g: May be registered by ppc for kgdb */ | 409 | /* g: May be registered by ppc for kgdb */ |
398 | NULL, /* g */ | 410 | NULL, /* g */ |
399 | NULL, /* h */ | 411 | NULL, /* h - reserved for help */ |
400 | &sysrq_kill_op, /* i */ | 412 | &sysrq_kill_op, /* i */ |
413 | #ifdef CONFIG_BLOCK | ||
414 | &sysrq_thaw_op, /* j */ | ||
415 | #else | ||
401 | NULL, /* j */ | 416 | NULL, /* j */ |
417 | #endif | ||
402 | &sysrq_SAK_op, /* k */ | 418 | &sysrq_SAK_op, /* k */ |
403 | #ifdef CONFIG_SMP | 419 | #ifdef CONFIG_SMP |
404 | &sysrq_showallcpus_op, /* l */ | 420 | &sysrq_showallcpus_op, /* l */ |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9c47dc48c9fd..ccdd828adcef 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -429,134 +429,148 @@ out: | |||
429 | #define TPM_DIGEST_SIZE 20 | 429 | #define TPM_DIGEST_SIZE 20 |
430 | #define TPM_ERROR_SIZE 10 | 430 | #define TPM_ERROR_SIZE 10 |
431 | #define TPM_RET_CODE_IDX 6 | 431 | #define TPM_RET_CODE_IDX 6 |
432 | #define TPM_GET_CAP_RET_SIZE_IDX 10 | ||
433 | #define TPM_GET_CAP_RET_UINT32_1_IDX 14 | ||
434 | #define TPM_GET_CAP_RET_UINT32_2_IDX 18 | ||
435 | #define TPM_GET_CAP_RET_UINT32_3_IDX 22 | ||
436 | #define TPM_GET_CAP_RET_UINT32_4_IDX 26 | ||
437 | #define TPM_GET_CAP_PERM_DISABLE_IDX 16 | ||
438 | #define TPM_GET_CAP_PERM_INACTIVE_IDX 18 | ||
439 | #define TPM_GET_CAP_RET_BOOL_1_IDX 14 | ||
440 | #define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 | ||
441 | |||
442 | #define TPM_CAP_IDX 13 | ||
443 | #define TPM_CAP_SUBCAP_IDX 21 | ||
444 | 432 | ||
445 | enum tpm_capabilities { | 433 | enum tpm_capabilities { |
446 | TPM_CAP_FLAG = 4, | 434 | TPM_CAP_FLAG = cpu_to_be32(4), |
447 | TPM_CAP_PROP = 5, | 435 | TPM_CAP_PROP = cpu_to_be32(5), |
436 | CAP_VERSION_1_1 = cpu_to_be32(0x06), | ||
437 | CAP_VERSION_1_2 = cpu_to_be32(0x1A) | ||
448 | }; | 438 | }; |
449 | 439 | ||
450 | enum tpm_sub_capabilities { | 440 | enum tpm_sub_capabilities { |
451 | TPM_CAP_PROP_PCR = 0x1, | 441 | TPM_CAP_PROP_PCR = cpu_to_be32(0x101), |
452 | TPM_CAP_PROP_MANUFACTURER = 0x3, | 442 | TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), |
453 | TPM_CAP_FLAG_PERM = 0x8, | 443 | TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), |
454 | TPM_CAP_FLAG_VOL = 0x9, | 444 | TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), |
455 | TPM_CAP_PROP_OWNER = 0x11, | 445 | TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), |
456 | TPM_CAP_PROP_TIS_TIMEOUT = 0x15, | 446 | TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), |
457 | TPM_CAP_PROP_TIS_DURATION = 0x20, | 447 | TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), |
458 | }; | ||
459 | 448 | ||
460 | /* | ||
461 | * This is a semi generic GetCapability command for use | ||
462 | * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG | ||
463 | * and their associated sub_capabilities. | ||
464 | */ | ||
465 | |||
466 | static const u8 tpm_cap[] = { | ||
467 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
468 | 0, 0, 0, 22, /* length */ | ||
469 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | ||
470 | 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ | ||
471 | 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ | ||
472 | 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ | ||
473 | }; | 449 | }; |
474 | 450 | ||
475 | static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, | 451 | static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, |
476 | char *desc) | 452 | int len, const char *desc) |
477 | { | 453 | { |
478 | int err; | 454 | int err; |
479 | 455 | ||
480 | len = tpm_transmit(chip, data, len); | 456 | len = tpm_transmit(chip,(u8 *) cmd, len); |
481 | if (len < 0) | 457 | if (len < 0) |
482 | return len; | 458 | return len; |
483 | if (len == TPM_ERROR_SIZE) { | 459 | if (len == TPM_ERROR_SIZE) { |
484 | err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); | 460 | err = be32_to_cpu(cmd->header.out.return_code); |
485 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | 461 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); |
486 | return err; | 462 | return err; |
487 | } | 463 | } |
488 | return 0; | 464 | return 0; |
489 | } | 465 | } |
490 | 466 | ||
467 | #define TPM_INTERNAL_RESULT_SIZE 200 | ||
468 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) | ||
469 | #define TPM_ORD_GET_CAP cpu_to_be32(101) | ||
470 | |||
471 | static const struct tpm_input_header tpm_getcap_header = { | ||
472 | .tag = TPM_TAG_RQU_COMMAND, | ||
473 | .length = cpu_to_be32(22), | ||
474 | .ordinal = TPM_ORD_GET_CAP | ||
475 | }; | ||
476 | |||
477 | ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, | ||
478 | const char *desc) | ||
479 | { | ||
480 | struct tpm_cmd_t tpm_cmd; | ||
481 | int rc; | ||
482 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
483 | |||
484 | tpm_cmd.header.in = tpm_getcap_header; | ||
485 | if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { | ||
486 | tpm_cmd.params.getcap_in.cap = subcap_id; | ||
487 | /*subcap field not necessary */ | ||
488 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); | ||
489 | tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); | ||
490 | } else { | ||
491 | if (subcap_id == TPM_CAP_FLAG_PERM || | ||
492 | subcap_id == TPM_CAP_FLAG_VOL) | ||
493 | tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG; | ||
494 | else | ||
495 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | ||
496 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | ||
497 | tpm_cmd.params.getcap_in.subcap = subcap_id; | ||
498 | } | ||
499 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); | ||
500 | if (!rc) | ||
501 | *cap = tpm_cmd.params.getcap_out.cap; | ||
502 | return rc; | ||
503 | } | ||
504 | |||
491 | void tpm_gen_interrupt(struct tpm_chip *chip) | 505 | void tpm_gen_interrupt(struct tpm_chip *chip) |
492 | { | 506 | { |
493 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | 507 | struct tpm_cmd_t tpm_cmd; |
494 | ssize_t rc; | 508 | ssize_t rc; |
495 | 509 | ||
496 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 510 | tpm_cmd.header.in = tpm_getcap_header; |
497 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 511 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
498 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | 512 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
513 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | ||
499 | 514 | ||
500 | rc = transmit_cmd(chip, data, sizeof(data), | 515 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
501 | "attempting to determine the timeouts"); | 516 | "attempting to determine the timeouts"); |
502 | } | 517 | } |
503 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 518 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
504 | 519 | ||
505 | void tpm_get_timeouts(struct tpm_chip *chip) | 520 | void tpm_get_timeouts(struct tpm_chip *chip) |
506 | { | 521 | { |
507 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | 522 | struct tpm_cmd_t tpm_cmd; |
523 | struct timeout_t *timeout_cap; | ||
524 | struct duration_t *duration_cap; | ||
508 | ssize_t rc; | 525 | ssize_t rc; |
509 | u32 timeout; | 526 | u32 timeout; |
510 | 527 | ||
511 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 528 | tpm_cmd.header.in = tpm_getcap_header; |
512 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 529 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
513 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | 530 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
531 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | ||
514 | 532 | ||
515 | rc = transmit_cmd(chip, data, sizeof(data), | 533 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
516 | "attempting to determine the timeouts"); | 534 | "attempting to determine the timeouts"); |
517 | if (rc) | 535 | if (rc) |
518 | goto duration; | 536 | goto duration; |
519 | 537 | ||
520 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | 538 | if (be32_to_cpu(tpm_cmd.header.out.length) |
521 | != 4 * sizeof(u32)) | 539 | != 4 * sizeof(u32)) |
522 | goto duration; | 540 | goto duration; |
523 | 541 | ||
542 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; | ||
524 | /* Don't overwrite default if value is 0 */ | 543 | /* Don't overwrite default if value is 0 */ |
525 | timeout = | 544 | timeout = be32_to_cpu(timeout_cap->a); |
526 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); | ||
527 | if (timeout) | 545 | if (timeout) |
528 | chip->vendor.timeout_a = usecs_to_jiffies(timeout); | 546 | chip->vendor.timeout_a = usecs_to_jiffies(timeout); |
529 | timeout = | 547 | timeout = be32_to_cpu(timeout_cap->b); |
530 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); | ||
531 | if (timeout) | 548 | if (timeout) |
532 | chip->vendor.timeout_b = usecs_to_jiffies(timeout); | 549 | chip->vendor.timeout_b = usecs_to_jiffies(timeout); |
533 | timeout = | 550 | timeout = be32_to_cpu(timeout_cap->c); |
534 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); | ||
535 | if (timeout) | 551 | if (timeout) |
536 | chip->vendor.timeout_c = usecs_to_jiffies(timeout); | 552 | chip->vendor.timeout_c = usecs_to_jiffies(timeout); |
537 | timeout = | 553 | timeout = be32_to_cpu(timeout_cap->d); |
538 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); | ||
539 | if (timeout) | 554 | if (timeout) |
540 | chip->vendor.timeout_d = usecs_to_jiffies(timeout); | 555 | chip->vendor.timeout_d = usecs_to_jiffies(timeout); |
541 | 556 | ||
542 | duration: | 557 | duration: |
543 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 558 | tpm_cmd.header.in = tpm_getcap_header; |
544 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 559 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
545 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; | 560 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
561 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; | ||
546 | 562 | ||
547 | rc = transmit_cmd(chip, data, sizeof(data), | 563 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
548 | "attempting to determine the durations"); | 564 | "attempting to determine the durations"); |
549 | if (rc) | 565 | if (rc) |
550 | return; | 566 | return; |
551 | 567 | ||
552 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | 568 | if (be32_to_cpu(tpm_cmd.header.out.return_code) |
553 | != 3 * sizeof(u32)) | 569 | != 3 * sizeof(u32)) |
554 | return; | 570 | return; |
555 | 571 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; | |
556 | chip->vendor.duration[TPM_SHORT] = | 572 | chip->vendor.duration[TPM_SHORT] = |
557 | usecs_to_jiffies(be32_to_cpu | 573 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); |
558 | (*((__be32 *) (data + | ||
559 | TPM_GET_CAP_RET_UINT32_1_IDX)))); | ||
560 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above | 574 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above |
561 | * value wrong and apparently reports msecs rather than usecs. So we | 575 | * value wrong and apparently reports msecs rather than usecs. So we |
562 | * fix up the resulting too-small TPM_SHORT value to make things work. | 576 | * fix up the resulting too-small TPM_SHORT value to make things work. |
@@ -565,13 +579,9 @@ duration: | |||
565 | chip->vendor.duration[TPM_SHORT] = HZ; | 579 | chip->vendor.duration[TPM_SHORT] = HZ; |
566 | 580 | ||
567 | chip->vendor.duration[TPM_MEDIUM] = | 581 | chip->vendor.duration[TPM_MEDIUM] = |
568 | usecs_to_jiffies(be32_to_cpu | 582 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); |
569 | (*((__be32 *) (data + | ||
570 | TPM_GET_CAP_RET_UINT32_2_IDX)))); | ||
571 | chip->vendor.duration[TPM_LONG] = | 583 | chip->vendor.duration[TPM_LONG] = |
572 | usecs_to_jiffies(be32_to_cpu | 584 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); |
573 | (*((__be32 *) (data + | ||
574 | TPM_GET_CAP_RET_UINT32_3_IDX)))); | ||
575 | } | 585 | } |
576 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | 586 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); |
577 | 587 | ||
@@ -587,36 +597,18 @@ void tpm_continue_selftest(struct tpm_chip *chip) | |||
587 | } | 597 | } |
588 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | 598 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); |
589 | 599 | ||
590 | #define TPM_INTERNAL_RESULT_SIZE 200 | ||
591 | |||
592 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 600 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
593 | char *buf) | 601 | char *buf) |
594 | { | 602 | { |
595 | u8 *data; | 603 | cap_t cap; |
596 | ssize_t rc; | 604 | ssize_t rc; |
597 | 605 | ||
598 | struct tpm_chip *chip = dev_get_drvdata(dev); | 606 | rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, |
599 | if (chip == NULL) | 607 | "attempting to determine the permanent enabled state"); |
600 | return -ENODEV; | 608 | if (rc) |
601 | |||
602 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
603 | if (!data) | ||
604 | return -ENOMEM; | ||
605 | |||
606 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
607 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
608 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
609 | |||
610 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
611 | "attemtping to determine the permanent enabled state"); | ||
612 | if (rc) { | ||
613 | kfree(data); | ||
614 | return 0; | 609 | return 0; |
615 | } | ||
616 | |||
617 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | ||
618 | 610 | ||
619 | kfree(data); | 611 | rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); |
620 | return rc; | 612 | return rc; |
621 | } | 613 | } |
622 | EXPORT_SYMBOL_GPL(tpm_show_enabled); | 614 | EXPORT_SYMBOL_GPL(tpm_show_enabled); |
@@ -624,31 +616,15 @@ EXPORT_SYMBOL_GPL(tpm_show_enabled); | |||
624 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, | 616 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, |
625 | char *buf) | 617 | char *buf) |
626 | { | 618 | { |
627 | u8 *data; | 619 | cap_t cap; |
628 | ssize_t rc; | 620 | ssize_t rc; |
629 | 621 | ||
630 | struct tpm_chip *chip = dev_get_drvdata(dev); | 622 | rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, |
631 | if (chip == NULL) | 623 | "attempting to determine the permanent active state"); |
632 | return -ENODEV; | 624 | if (rc) |
633 | |||
634 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
635 | if (!data) | ||
636 | return -ENOMEM; | ||
637 | |||
638 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
639 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
640 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
641 | |||
642 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
643 | "attemtping to determine the permanent active state"); | ||
644 | if (rc) { | ||
645 | kfree(data); | ||
646 | return 0; | 625 | return 0; |
647 | } | ||
648 | 626 | ||
649 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | 627 | rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); |
650 | |||
651 | kfree(data); | ||
652 | return rc; | 628 | return rc; |
653 | } | 629 | } |
654 | EXPORT_SYMBOL_GPL(tpm_show_active); | 630 | EXPORT_SYMBOL_GPL(tpm_show_active); |
@@ -656,31 +632,15 @@ EXPORT_SYMBOL_GPL(tpm_show_active); | |||
656 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, | 632 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, |
657 | char *buf) | 633 | char *buf) |
658 | { | 634 | { |
659 | u8 *data; | 635 | cap_t cap; |
660 | ssize_t rc; | 636 | ssize_t rc; |
661 | 637 | ||
662 | struct tpm_chip *chip = dev_get_drvdata(dev); | 638 | rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, |
663 | if (chip == NULL) | 639 | "attempting to determine the owner state"); |
664 | return -ENODEV; | 640 | if (rc) |
665 | |||
666 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
667 | if (!data) | ||
668 | return -ENOMEM; | ||
669 | |||
670 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
671 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
672 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; | ||
673 | |||
674 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
675 | "attempting to determine the owner state"); | ||
676 | if (rc) { | ||
677 | kfree(data); | ||
678 | return 0; | 641 | return 0; |
679 | } | ||
680 | |||
681 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | ||
682 | 642 | ||
683 | kfree(data); | 643 | rc = sprintf(buf, "%d\n", cap.owned); |
684 | return rc; | 644 | return rc; |
685 | } | 645 | } |
686 | EXPORT_SYMBOL_GPL(tpm_show_owned); | 646 | EXPORT_SYMBOL_GPL(tpm_show_owned); |
@@ -688,116 +648,180 @@ EXPORT_SYMBOL_GPL(tpm_show_owned); | |||
688 | ssize_t tpm_show_temp_deactivated(struct device * dev, | 648 | ssize_t tpm_show_temp_deactivated(struct device * dev, |
689 | struct device_attribute * attr, char *buf) | 649 | struct device_attribute * attr, char *buf) |
690 | { | 650 | { |
691 | u8 *data; | 651 | cap_t cap; |
692 | ssize_t rc; | 652 | ssize_t rc; |
693 | 653 | ||
694 | struct tpm_chip *chip = dev_get_drvdata(dev); | 654 | rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, |
695 | if (chip == NULL) | 655 | "attempting to determine the temporary state"); |
696 | return -ENODEV; | 656 | if (rc) |
657 | return 0; | ||
697 | 658 | ||
698 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | 659 | rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); |
699 | if (!data) | 660 | return rc; |
700 | return -ENOMEM; | 661 | } |
662 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | ||
701 | 663 | ||
702 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 664 | /* |
703 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 665 | * tpm_chip_find_get - return tpm_chip for given chip number |
704 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; | 666 | */ |
667 | static struct tpm_chip *tpm_chip_find_get(int chip_num) | ||
668 | { | ||
669 | struct tpm_chip *pos, *chip = NULL; | ||
705 | 670 | ||
706 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | 671 | rcu_read_lock(); |
707 | "attempting to determine the temporary state"); | 672 | list_for_each_entry_rcu(pos, &tpm_chip_list, list) { |
708 | if (rc) { | 673 | if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) |
709 | kfree(data); | 674 | continue; |
710 | return 0; | 675 | |
676 | if (try_module_get(pos->dev->driver->owner)) { | ||
677 | chip = pos; | ||
678 | break; | ||
679 | } | ||
711 | } | 680 | } |
681 | rcu_read_unlock(); | ||
682 | return chip; | ||
683 | } | ||
712 | 684 | ||
713 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | 685 | #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) |
686 | #define READ_PCR_RESULT_SIZE 30 | ||
687 | static struct tpm_input_header pcrread_header = { | ||
688 | .tag = TPM_TAG_RQU_COMMAND, | ||
689 | .length = cpu_to_be32(14), | ||
690 | .ordinal = TPM_ORDINAL_PCRREAD | ||
691 | }; | ||
714 | 692 | ||
715 | kfree(data); | 693 | int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
694 | { | ||
695 | int rc; | ||
696 | struct tpm_cmd_t cmd; | ||
697 | |||
698 | cmd.header.in = pcrread_header; | ||
699 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); | ||
700 | BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); | ||
701 | rc = transmit_cmd(chip, &cmd, cmd.header.in.length, | ||
702 | "attempting to read a pcr value"); | ||
703 | |||
704 | if (rc == 0) | ||
705 | memcpy(res_buf, cmd.params.pcrread_out.pcr_result, | ||
706 | TPM_DIGEST_SIZE); | ||
716 | return rc; | 707 | return rc; |
717 | } | 708 | } |
718 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | ||
719 | 709 | ||
720 | static const u8 pcrread[] = { | 710 | /** |
721 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 711 | * tpm_pcr_read - read a pcr value |
722 | 0, 0, 0, 14, /* length */ | 712 | * @chip_num: tpm idx # or ANY |
723 | 0, 0, 0, 21, /* TPM_ORD_PcrRead */ | 713 | * @pcr_idx: pcr idx to retrieve |
724 | 0, 0, 0, 0 /* PCR index */ | 714 | * @res_buf: TPM_PCR value |
715 | * size of res_buf is 20 bytes (or NULL if you don't care) | ||
716 | * | ||
717 | * The TPM driver should be built-in, but for whatever reason it | ||
718 | * isn't, protect against the chip disappearing, by incrementing | ||
719 | * the module usage count. | ||
720 | */ | ||
721 | int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) | ||
722 | { | ||
723 | struct tpm_chip *chip; | ||
724 | int rc; | ||
725 | |||
726 | chip = tpm_chip_find_get(chip_num); | ||
727 | if (chip == NULL) | ||
728 | return -ENODEV; | ||
729 | rc = __tpm_pcr_read(chip, pcr_idx, res_buf); | ||
730 | module_put(chip->dev->driver->owner); | ||
731 | return rc; | ||
732 | } | ||
733 | EXPORT_SYMBOL_GPL(tpm_pcr_read); | ||
734 | |||
735 | /** | ||
736 | * tpm_pcr_extend - extend pcr value with hash | ||
737 | * @chip_num: tpm idx # or AN& | ||
738 | * @pcr_idx: pcr idx to extend | ||
739 | * @hash: hash value used to extend pcr value | ||
740 | * | ||
741 | * The TPM driver should be built-in, but for whatever reason it | ||
742 | * isn't, protect against the chip disappearing, by incrementing | ||
743 | * the module usage count. | ||
744 | */ | ||
745 | #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) | ||
746 | #define EXTEND_PCR_SIZE 34 | ||
747 | static struct tpm_input_header pcrextend_header = { | ||
748 | .tag = TPM_TAG_RQU_COMMAND, | ||
749 | .length = cpu_to_be32(34), | ||
750 | .ordinal = TPM_ORD_PCR_EXTEND | ||
725 | }; | 751 | }; |
726 | 752 | ||
753 | int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | ||
754 | { | ||
755 | struct tpm_cmd_t cmd; | ||
756 | int rc; | ||
757 | struct tpm_chip *chip; | ||
758 | |||
759 | chip = tpm_chip_find_get(chip_num); | ||
760 | if (chip == NULL) | ||
761 | return -ENODEV; | ||
762 | |||
763 | cmd.header.in = pcrextend_header; | ||
764 | BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); | ||
765 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | ||
766 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); | ||
767 | rc = transmit_cmd(chip, &cmd, cmd.header.in.length, | ||
768 | "attempting extend a PCR value"); | ||
769 | |||
770 | module_put(chip->dev->driver->owner); | ||
771 | return rc; | ||
772 | } | ||
773 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); | ||
774 | |||
727 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | 775 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
728 | char *buf) | 776 | char *buf) |
729 | { | 777 | { |
730 | u8 *data; | 778 | cap_t cap; |
779 | u8 digest[TPM_DIGEST_SIZE]; | ||
731 | ssize_t rc; | 780 | ssize_t rc; |
732 | int i, j, num_pcrs; | 781 | int i, j, num_pcrs; |
733 | __be32 index; | ||
734 | char *str = buf; | 782 | char *str = buf; |
735 | |||
736 | struct tpm_chip *chip = dev_get_drvdata(dev); | 783 | struct tpm_chip *chip = dev_get_drvdata(dev); |
737 | if (chip == NULL) | ||
738 | return -ENODEV; | ||
739 | 784 | ||
740 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | 785 | rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, |
741 | if (!data) | ||
742 | return -ENOMEM; | ||
743 | |||
744 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
745 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
746 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; | ||
747 | |||
748 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
749 | "attempting to determine the number of PCRS"); | 786 | "attempting to determine the number of PCRS"); |
750 | if (rc) { | 787 | if (rc) |
751 | kfree(data); | ||
752 | return 0; | 788 | return 0; |
753 | } | ||
754 | 789 | ||
755 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); | 790 | num_pcrs = be32_to_cpu(cap.num_pcrs); |
756 | for (i = 0; i < num_pcrs; i++) { | 791 | for (i = 0; i < num_pcrs; i++) { |
757 | memcpy(data, pcrread, sizeof(pcrread)); | 792 | rc = __tpm_pcr_read(chip, i, digest); |
758 | index = cpu_to_be32(i); | ||
759 | memcpy(data + 10, &index, 4); | ||
760 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
761 | "attempting to read a PCR"); | ||
762 | if (rc) | 793 | if (rc) |
763 | goto out; | 794 | break; |
764 | str += sprintf(str, "PCR-%02d: ", i); | 795 | str += sprintf(str, "PCR-%02d: ", i); |
765 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | 796 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
766 | str += sprintf(str, "%02X ", *(data + 10 + j)); | 797 | str += sprintf(str, "%02X ", digest[j]); |
767 | str += sprintf(str, "\n"); | 798 | str += sprintf(str, "\n"); |
768 | } | 799 | } |
769 | out: | ||
770 | kfree(data); | ||
771 | return str - buf; | 800 | return str - buf; |
772 | } | 801 | } |
773 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); | 802 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); |
774 | 803 | ||
775 | #define READ_PUBEK_RESULT_SIZE 314 | 804 | #define READ_PUBEK_RESULT_SIZE 314 |
776 | static const u8 readpubek[] = { | 805 | #define TPM_ORD_READPUBEK cpu_to_be32(124) |
777 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 806 | struct tpm_input_header tpm_readpubek_header = { |
778 | 0, 0, 0, 30, /* length */ | 807 | .tag = TPM_TAG_RQU_COMMAND, |
779 | 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ | 808 | .length = cpu_to_be32(30), |
809 | .ordinal = TPM_ORD_READPUBEK | ||
780 | }; | 810 | }; |
781 | 811 | ||
782 | ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | 812 | ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, |
783 | char *buf) | 813 | char *buf) |
784 | { | 814 | { |
785 | u8 *data; | 815 | u8 *data; |
816 | struct tpm_cmd_t tpm_cmd; | ||
786 | ssize_t err; | 817 | ssize_t err; |
787 | int i, rc; | 818 | int i, rc; |
788 | char *str = buf; | 819 | char *str = buf; |
789 | 820 | ||
790 | struct tpm_chip *chip = dev_get_drvdata(dev); | 821 | struct tpm_chip *chip = dev_get_drvdata(dev); |
791 | if (chip == NULL) | ||
792 | return -ENODEV; | ||
793 | 822 | ||
794 | data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); | 823 | tpm_cmd.header.in = tpm_readpubek_header; |
795 | if (!data) | 824 | err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, |
796 | return -ENOMEM; | ||
797 | |||
798 | memcpy(data, readpubek, sizeof(readpubek)); | ||
799 | |||
800 | err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, | ||
801 | "attempting to read the PUBEK"); | 825 | "attempting to read the PUBEK"); |
802 | if (err) | 826 | if (err) |
803 | goto out; | 827 | goto out; |
@@ -812,7 +836,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
812 | 256 byte modulus | 836 | 256 byte modulus |
813 | ignore checksum 20 bytes | 837 | ignore checksum 20 bytes |
814 | */ | 838 | */ |
815 | 839 | data = tpm_cmd.params.readpubek_out_buffer; | |
816 | str += | 840 | str += |
817 | sprintf(str, | 841 | sprintf(str, |
818 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" | 842 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" |
@@ -832,65 +856,33 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
832 | } | 856 | } |
833 | out: | 857 | out: |
834 | rc = str - buf; | 858 | rc = str - buf; |
835 | kfree(data); | ||
836 | return rc; | 859 | return rc; |
837 | } | 860 | } |
838 | EXPORT_SYMBOL_GPL(tpm_show_pubek); | 861 | EXPORT_SYMBOL_GPL(tpm_show_pubek); |
839 | 862 | ||
840 | #define CAP_VERSION_1_1 6 | ||
841 | #define CAP_VERSION_1_2 0x1A | ||
842 | #define CAP_VERSION_IDX 13 | ||
843 | static const u8 cap_version[] = { | ||
844 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
845 | 0, 0, 0, 18, /* length */ | ||
846 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | ||
847 | 0, 0, 0, 0, | ||
848 | 0, 0, 0, 0 | ||
849 | }; | ||
850 | 863 | ||
851 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | 864 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
852 | char *buf) | 865 | char *buf) |
853 | { | 866 | { |
854 | u8 *data; | 867 | cap_t cap; |
855 | ssize_t rc; | 868 | ssize_t rc; |
856 | char *str = buf; | 869 | char *str = buf; |
857 | 870 | ||
858 | struct tpm_chip *chip = dev_get_drvdata(dev); | 871 | rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, |
859 | if (chip == NULL) | ||
860 | return -ENODEV; | ||
861 | |||
862 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
863 | if (!data) | ||
864 | return -ENOMEM; | ||
865 | |||
866 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
867 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
868 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
869 | |||
870 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
871 | "attempting to determine the manufacturer"); | 872 | "attempting to determine the manufacturer"); |
872 | if (rc) { | 873 | if (rc) |
873 | kfree(data); | ||
874 | return 0; | 874 | return 0; |
875 | } | ||
876 | |||
877 | str += sprintf(str, "Manufacturer: 0x%x\n", | 875 | str += sprintf(str, "Manufacturer: 0x%x\n", |
878 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | 876 | be32_to_cpu(cap.manufacturer_id)); |
879 | 877 | ||
880 | memcpy(data, cap_version, sizeof(cap_version)); | 878 | rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, |
881 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; | 879 | "attempting to determine the 1.1 version"); |
882 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
883 | "attempting to determine the 1.1 version"); | ||
884 | if (rc) | 880 | if (rc) |
885 | goto out; | 881 | return 0; |
886 | |||
887 | str += sprintf(str, | 882 | str += sprintf(str, |
888 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | 883 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
889 | (int) data[14], (int) data[15], (int) data[16], | 884 | cap.tpm_version.Major, cap.tpm_version.Minor, |
890 | (int) data[17]); | 885 | cap.tpm_version.revMajor, cap.tpm_version.revMinor); |
891 | |||
892 | out: | ||
893 | kfree(data); | ||
894 | return str - buf; | 886 | return str - buf; |
895 | } | 887 | } |
896 | EXPORT_SYMBOL_GPL(tpm_show_caps); | 888 | EXPORT_SYMBOL_GPL(tpm_show_caps); |
@@ -898,51 +890,25 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); | |||
898 | ssize_t tpm_show_caps_1_2(struct device * dev, | 890 | ssize_t tpm_show_caps_1_2(struct device * dev, |
899 | struct device_attribute * attr, char *buf) | 891 | struct device_attribute * attr, char *buf) |
900 | { | 892 | { |
901 | u8 *data; | 893 | cap_t cap; |
902 | ssize_t len; | 894 | ssize_t rc; |
903 | char *str = buf; | 895 | char *str = buf; |
904 | 896 | ||
905 | struct tpm_chip *chip = dev_get_drvdata(dev); | 897 | rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, |
906 | if (chip == NULL) | 898 | "attempting to determine the manufacturer"); |
907 | return -ENODEV; | 899 | if (rc) |
908 | |||
909 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
910 | if (!data) | ||
911 | return -ENOMEM; | ||
912 | |||
913 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
914 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
915 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
916 | |||
917 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); | ||
918 | if (len <= TPM_ERROR_SIZE) { | ||
919 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | ||
920 | "attempting to determine the manufacturer\n", | ||
921 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
922 | kfree(data); | ||
923 | return 0; | 900 | return 0; |
924 | } | ||
925 | |||
926 | str += sprintf(str, "Manufacturer: 0x%x\n", | 901 | str += sprintf(str, "Manufacturer: 0x%x\n", |
927 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | 902 | be32_to_cpu(cap.manufacturer_id)); |
928 | 903 | rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, | |
929 | memcpy(data, cap_version, sizeof(cap_version)); | 904 | "attempting to determine the 1.2 version"); |
930 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; | 905 | if (rc) |
931 | 906 | return 0; | |
932 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); | ||
933 | if (len <= TPM_ERROR_SIZE) { | ||
934 | dev_err(chip->dev, "A TPM error (%d) occurred " | ||
935 | "attempting to determine the 1.2 version\n", | ||
936 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
937 | goto out; | ||
938 | } | ||
939 | str += sprintf(str, | 907 | str += sprintf(str, |
940 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | 908 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
941 | (int) data[16], (int) data[17], (int) data[18], | 909 | cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor, |
942 | (int) data[19]); | 910 | cap.tpm_version_1_2.revMajor, |
943 | 911 | cap.tpm_version_1_2.revMinor); | |
944 | out: | ||
945 | kfree(data); | ||
946 | return str - buf; | 912 | return str - buf; |
947 | } | 913 | } |
948 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | 914 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e30df4a4388..8e00b4ddd083 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/miscdevice.h> | 26 | #include <linux/miscdevice.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/tpm.h> | ||
29 | 30 | ||
30 | enum tpm_timeout { | 31 | enum tpm_timeout { |
31 | TPM_TIMEOUT = 5, /* msecs */ | 32 | TPM_TIMEOUT = 5, /* msecs */ |
@@ -123,6 +124,147 @@ static inline void tpm_write_index(int base, int index, int value) | |||
123 | outb(index, base); | 124 | outb(index, base); |
124 | outb(value & 0xFF, base+1); | 125 | outb(value & 0xFF, base+1); |
125 | } | 126 | } |
127 | struct tpm_input_header { | ||
128 | __be16 tag; | ||
129 | __be32 length; | ||
130 | __be32 ordinal; | ||
131 | }__attribute__((packed)); | ||
132 | |||
133 | struct tpm_output_header { | ||
134 | __be16 tag; | ||
135 | __be32 length; | ||
136 | __be32 return_code; | ||
137 | }__attribute__((packed)); | ||
138 | |||
139 | struct stclear_flags_t { | ||
140 | __be16 tag; | ||
141 | u8 deactivated; | ||
142 | u8 disableForceClear; | ||
143 | u8 physicalPresence; | ||
144 | u8 physicalPresenceLock; | ||
145 | u8 bGlobalLock; | ||
146 | }__attribute__((packed)); | ||
147 | |||
148 | struct tpm_version_t { | ||
149 | u8 Major; | ||
150 | u8 Minor; | ||
151 | u8 revMajor; | ||
152 | u8 revMinor; | ||
153 | }__attribute__((packed)); | ||
154 | |||
155 | struct tpm_version_1_2_t { | ||
156 | __be16 tag; | ||
157 | u8 Major; | ||
158 | u8 Minor; | ||
159 | u8 revMajor; | ||
160 | u8 revMinor; | ||
161 | }__attribute__((packed)); | ||
162 | |||
163 | struct timeout_t { | ||
164 | __be32 a; | ||
165 | __be32 b; | ||
166 | __be32 c; | ||
167 | __be32 d; | ||
168 | }__attribute__((packed)); | ||
169 | |||
170 | struct duration_t { | ||
171 | __be32 tpm_short; | ||
172 | __be32 tpm_medium; | ||
173 | __be32 tpm_long; | ||
174 | }__attribute__((packed)); | ||
175 | |||
176 | struct permanent_flags_t { | ||
177 | __be16 tag; | ||
178 | u8 disable; | ||
179 | u8 ownership; | ||
180 | u8 deactivated; | ||
181 | u8 readPubek; | ||
182 | u8 disableOwnerClear; | ||
183 | u8 allowMaintenance; | ||
184 | u8 physicalPresenceLifetimeLock; | ||
185 | u8 physicalPresenceHWEnable; | ||
186 | u8 physicalPresenceCMDEnable; | ||
187 | u8 CEKPUsed; | ||
188 | u8 TPMpost; | ||
189 | u8 TPMpostLock; | ||
190 | u8 FIPS; | ||
191 | u8 operator; | ||
192 | u8 enableRevokeEK; | ||
193 | u8 nvLocked; | ||
194 | u8 readSRKPub; | ||
195 | u8 tpmEstablished; | ||
196 | u8 maintenanceDone; | ||
197 | u8 disableFullDALogicInfo; | ||
198 | }__attribute__((packed)); | ||
199 | |||
200 | typedef union { | ||
201 | struct permanent_flags_t perm_flags; | ||
202 | struct stclear_flags_t stclear_flags; | ||
203 | bool owned; | ||
204 | __be32 num_pcrs; | ||
205 | struct tpm_version_t tpm_version; | ||
206 | struct tpm_version_1_2_t tpm_version_1_2; | ||
207 | __be32 manufacturer_id; | ||
208 | struct timeout_t timeout; | ||
209 | struct duration_t duration; | ||
210 | } cap_t; | ||
211 | |||
212 | struct tpm_getcap_params_in { | ||
213 | __be32 cap; | ||
214 | __be32 subcap_size; | ||
215 | __be32 subcap; | ||
216 | }__attribute__((packed)); | ||
217 | |||
218 | struct tpm_getcap_params_out { | ||
219 | __be32 cap_size; | ||
220 | cap_t cap; | ||
221 | }__attribute__((packed)); | ||
222 | |||
223 | struct tpm_readpubek_params_out { | ||
224 | u8 algorithm[4]; | ||
225 | u8 encscheme[2]; | ||
226 | u8 sigscheme[2]; | ||
227 | u8 parameters[12]; /*assuming RSA*/ | ||
228 | __be32 keysize; | ||
229 | u8 modulus[256]; | ||
230 | u8 checksum[20]; | ||
231 | }__attribute__((packed)); | ||
232 | |||
233 | typedef union { | ||
234 | struct tpm_input_header in; | ||
235 | struct tpm_output_header out; | ||
236 | } tpm_cmd_header; | ||
237 | |||
238 | #define TPM_DIGEST_SIZE 20 | ||
239 | struct tpm_pcrread_out { | ||
240 | u8 pcr_result[TPM_DIGEST_SIZE]; | ||
241 | }__attribute__((packed)); | ||
242 | |||
243 | struct tpm_pcrread_in { | ||
244 | __be32 pcr_idx; | ||
245 | }__attribute__((packed)); | ||
246 | |||
247 | struct tpm_pcrextend_in { | ||
248 | __be32 pcr_idx; | ||
249 | u8 hash[TPM_DIGEST_SIZE]; | ||
250 | }__attribute__((packed)); | ||
251 | |||
252 | typedef union { | ||
253 | struct tpm_getcap_params_out getcap_out; | ||
254 | struct tpm_readpubek_params_out readpubek_out; | ||
255 | u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; | ||
256 | struct tpm_getcap_params_in getcap_in; | ||
257 | struct tpm_pcrread_in pcrread_in; | ||
258 | struct tpm_pcrread_out pcrread_out; | ||
259 | struct tpm_pcrextend_in pcrextend_in; | ||
260 | } tpm_cmd_params; | ||
261 | |||
262 | struct tpm_cmd_t { | ||
263 | tpm_cmd_header header; | ||
264 | tpm_cmd_params params; | ||
265 | }__attribute__((packed)); | ||
266 | |||
267 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | ||
126 | 268 | ||
127 | extern void tpm_get_timeouts(struct tpm_chip *); | 269 | extern void tpm_get_timeouts(struct tpm_chip *); |
128 | extern void tpm_gen_interrupt(struct tpm_chip *); | 270 | extern void tpm_gen_interrupt(struct tpm_chip *); |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index d0e7926eb486..c64a1bc65349 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -168,12 +168,22 @@ static void atml_plat_remove(void) | |||
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | static struct device_driver atml_drv = { | 171 | static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg) |
172 | .name = "tpm_atmel", | 172 | { |
173 | .bus = &platform_bus_type, | 173 | return tpm_pm_suspend(&dev->dev, msg); |
174 | .owner = THIS_MODULE, | 174 | } |
175 | .suspend = tpm_pm_suspend, | 175 | |
176 | .resume = tpm_pm_resume, | 176 | static int tpm_atml_resume(struct platform_device *dev) |
177 | { | ||
178 | return tpm_pm_resume(&dev->dev); | ||
179 | } | ||
180 | static struct platform_driver atml_drv = { | ||
181 | .driver = { | ||
182 | .name = "tpm_atmel", | ||
183 | .owner = THIS_MODULE, | ||
184 | }, | ||
185 | .suspend = tpm_atml_suspend, | ||
186 | .resume = tpm_atml_resume, | ||
177 | }; | 187 | }; |
178 | 188 | ||
179 | static int __init init_atmel(void) | 189 | static int __init init_atmel(void) |
@@ -184,7 +194,7 @@ static int __init init_atmel(void) | |||
184 | unsigned long base; | 194 | unsigned long base; |
185 | struct tpm_chip *chip; | 195 | struct tpm_chip *chip; |
186 | 196 | ||
187 | rc = driver_register(&atml_drv); | 197 | rc = platform_driver_register(&atml_drv); |
188 | if (rc) | 198 | if (rc) |
189 | return rc; | 199 | return rc; |
190 | 200 | ||
@@ -223,13 +233,13 @@ err_rel_reg: | |||
223 | atmel_release_region(base, | 233 | atmel_release_region(base, |
224 | region_size); | 234 | region_size); |
225 | err_unreg_drv: | 235 | err_unreg_drv: |
226 | driver_unregister(&atml_drv); | 236 | platform_driver_unregister(&atml_drv); |
227 | return rc; | 237 | return rc; |
228 | } | 238 | } |
229 | 239 | ||
230 | static void __exit cleanup_atmel(void) | 240 | static void __exit cleanup_atmel(void) |
231 | { | 241 | { |
232 | driver_unregister(&atml_drv); | 242 | platform_driver_unregister(&atml_drv); |
233 | atml_plat_remove(); | 243 | atml_plat_remove(); |
234 | } | 244 | } |
235 | 245 | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 717af7ad1bdf..aec1931608aa 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -654,12 +654,22 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | |||
654 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 654 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
655 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 655 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
656 | 656 | ||
657 | static struct device_driver tis_drv = { | 657 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) |
658 | .name = "tpm_tis", | 658 | { |
659 | .bus = &platform_bus_type, | 659 | return tpm_pm_suspend(&dev->dev, msg); |
660 | .owner = THIS_MODULE, | 660 | } |
661 | .suspend = tpm_pm_suspend, | 661 | |
662 | .resume = tpm_pm_resume, | 662 | static int tpm_tis_resume(struct platform_device *dev) |
663 | { | ||
664 | return tpm_pm_resume(&dev->dev); | ||
665 | } | ||
666 | static struct platform_driver tis_drv = { | ||
667 | .driver = { | ||
668 | .name = "tpm_tis", | ||
669 | .owner = THIS_MODULE, | ||
670 | }, | ||
671 | .suspend = tpm_tis_suspend, | ||
672 | .resume = tpm_tis_resume, | ||
663 | }; | 673 | }; |
664 | 674 | ||
665 | static struct platform_device *pdev; | 675 | static struct platform_device *pdev; |
@@ -672,14 +682,14 @@ static int __init init_tis(void) | |||
672 | int rc; | 682 | int rc; |
673 | 683 | ||
674 | if (force) { | 684 | if (force) { |
675 | rc = driver_register(&tis_drv); | 685 | rc = platform_driver_register(&tis_drv); |
676 | if (rc < 0) | 686 | if (rc < 0) |
677 | return rc; | 687 | return rc; |
678 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | 688 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) |
679 | return PTR_ERR(pdev); | 689 | return PTR_ERR(pdev); |
680 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | 690 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { |
681 | platform_device_unregister(pdev); | 691 | platform_device_unregister(pdev); |
682 | driver_unregister(&tis_drv); | 692 | platform_driver_unregister(&tis_drv); |
683 | } | 693 | } |
684 | return rc; | 694 | return rc; |
685 | } | 695 | } |
@@ -711,7 +721,7 @@ static void __exit cleanup_tis(void) | |||
711 | 721 | ||
712 | if (force) { | 722 | if (force) { |
713 | platform_device_unregister(pdev); | 723 | platform_device_unregister(pdev); |
714 | driver_unregister(&tis_drv); | 724 | platform_driver_unregister(&tis_drv); |
715 | } else | 725 | } else |
716 | pnp_unregister_driver(&tis_pnp_driver); | 726 | pnp_unregister_driver(&tis_pnp_driver); |
717 | } | 727 | } |
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 34ab6d798f81..55ba6f142883 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
@@ -10,8 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/audit.h> | 12 | #include <linux/audit.h> |
13 | #include <linux/file.h> | ||
14 | #include <linux/fdtable.h> | ||
15 | #include <linux/tty.h> | 13 | #include <linux/tty.h> |
16 | 14 | ||
17 | struct tty_audit_buf { | 15 | struct tty_audit_buf { |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bc84e125c6bc..66b99a2049e3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -464,7 +464,7 @@ void tty_wakeup(struct tty_struct *tty) | |||
464 | tty_ldisc_deref(ld); | 464 | tty_ldisc_deref(ld); |
465 | } | 465 | } |
466 | } | 466 | } |
467 | wake_up_interruptible(&tty->write_wait); | 467 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
468 | } | 468 | } |
469 | 469 | ||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 470 | EXPORT_SYMBOL_GPL(tty_wakeup); |
@@ -587,8 +587,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
587 | * FIXME: Once we trust the LDISC code better we can wait here for | 587 | * FIXME: Once we trust the LDISC code better we can wait here for |
588 | * ldisc completion and fix the driver call race | 588 | * ldisc completion and fix the driver call race |
589 | */ | 589 | */ |
590 | wake_up_interruptible(&tty->write_wait); | 590 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
591 | wake_up_interruptible(&tty->read_wait); | 591 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
592 | /* | 592 | /* |
593 | * Shutdown the current line discipline, and reset it to | 593 | * Shutdown the current line discipline, and reset it to |
594 | * N_TTY. | 594 | * N_TTY. |
@@ -879,7 +879,7 @@ void stop_tty(struct tty_struct *tty) | |||
879 | if (tty->link && tty->link->packet) { | 879 | if (tty->link && tty->link->packet) { |
880 | tty->ctrl_status &= ~TIOCPKT_START; | 880 | tty->ctrl_status &= ~TIOCPKT_START; |
881 | tty->ctrl_status |= TIOCPKT_STOP; | 881 | tty->ctrl_status |= TIOCPKT_STOP; |
882 | wake_up_interruptible(&tty->link->read_wait); | 882 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); |
883 | } | 883 | } |
884 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 884 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
885 | if (tty->ops->stop) | 885 | if (tty->ops->stop) |
@@ -913,7 +913,7 @@ void start_tty(struct tty_struct *tty) | |||
913 | if (tty->link && tty->link->packet) { | 913 | if (tty->link && tty->link->packet) { |
914 | tty->ctrl_status &= ~TIOCPKT_STOP; | 914 | tty->ctrl_status &= ~TIOCPKT_STOP; |
915 | tty->ctrl_status |= TIOCPKT_START; | 915 | tty->ctrl_status |= TIOCPKT_START; |
916 | wake_up_interruptible(&tty->link->read_wait); | 916 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); |
917 | } | 917 | } |
918 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 918 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
919 | if (tty->ops->start) | 919 | if (tty->ops->start) |
@@ -970,7 +970,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
970 | void tty_write_unlock(struct tty_struct *tty) | 970 | void tty_write_unlock(struct tty_struct *tty) |
971 | { | 971 | { |
972 | mutex_unlock(&tty->atomic_write_lock); | 972 | mutex_unlock(&tty->atomic_write_lock); |
973 | wake_up_interruptible(&tty->write_wait); | 973 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
974 | } | 974 | } |
975 | 975 | ||
976 | int tty_write_lock(struct tty_struct *tty, int ndelay) | 976 | int tty_write_lock(struct tty_struct *tty, int ndelay) |
@@ -1623,21 +1623,21 @@ void tty_release_dev(struct file *filp) | |||
1623 | 1623 | ||
1624 | if (tty_closing) { | 1624 | if (tty_closing) { |
1625 | if (waitqueue_active(&tty->read_wait)) { | 1625 | if (waitqueue_active(&tty->read_wait)) { |
1626 | wake_up(&tty->read_wait); | 1626 | wake_up_poll(&tty->read_wait, POLLIN); |
1627 | do_sleep++; | 1627 | do_sleep++; |
1628 | } | 1628 | } |
1629 | if (waitqueue_active(&tty->write_wait)) { | 1629 | if (waitqueue_active(&tty->write_wait)) { |
1630 | wake_up(&tty->write_wait); | 1630 | wake_up_poll(&tty->write_wait, POLLOUT); |
1631 | do_sleep++; | 1631 | do_sleep++; |
1632 | } | 1632 | } |
1633 | } | 1633 | } |
1634 | if (o_tty_closing) { | 1634 | if (o_tty_closing) { |
1635 | if (waitqueue_active(&o_tty->read_wait)) { | 1635 | if (waitqueue_active(&o_tty->read_wait)) { |
1636 | wake_up(&o_tty->read_wait); | 1636 | wake_up_poll(&o_tty->read_wait, POLLIN); |
1637 | do_sleep++; | 1637 | do_sleep++; |
1638 | } | 1638 | } |
1639 | if (waitqueue_active(&o_tty->write_wait)) { | 1639 | if (waitqueue_active(&o_tty->write_wait)) { |
1640 | wake_up(&o_tty->write_wait); | 1640 | wake_up_poll(&o_tty->write_wait, POLLOUT); |
1641 | do_sleep++; | 1641 | do_sleep++; |
1642 | } | 1642 | } |
1643 | } | 1643 | } |
@@ -1758,7 +1758,7 @@ static int __tty_open(struct inode *inode, struct file *filp) | |||
1758 | struct tty_driver *driver; | 1758 | struct tty_driver *driver; |
1759 | int index; | 1759 | int index; |
1760 | dev_t device = inode->i_rdev; | 1760 | dev_t device = inode->i_rdev; |
1761 | unsigned short saved_flags = filp->f_flags; | 1761 | unsigned saved_flags = filp->f_flags; |
1762 | 1762 | ||
1763 | nonseekable_open(inode, filp); | 1763 | nonseekable_open(inode, filp); |
1764 | 1764 | ||
@@ -2162,13 +2162,12 @@ static int fionbio(struct file *file, int __user *p) | |||
2162 | if (get_user(nonblock, p)) | 2162 | if (get_user(nonblock, p)) |
2163 | return -EFAULT; | 2163 | return -EFAULT; |
2164 | 2164 | ||
2165 | /* file->f_flags is still BKL protected in the fs layer - vomit */ | 2165 | spin_lock(&file->f_lock); |
2166 | lock_kernel(); | ||
2167 | if (nonblock) | 2166 | if (nonblock) |
2168 | file->f_flags |= O_NONBLOCK; | 2167 | file->f_flags |= O_NONBLOCK; |
2169 | else | 2168 | else |
2170 | file->f_flags &= ~O_NONBLOCK; | 2169 | file->f_flags &= ~O_NONBLOCK; |
2171 | unlock_kernel(); | 2170 | spin_unlock(&file->f_lock); |
2172 | return 0; | 2171 | return 0; |
2173 | } | 2172 | } |
2174 | 2173 | ||
@@ -2682,7 +2681,7 @@ void __do_SAK(struct tty_struct *tty) | |||
2682 | /* Kill the entire session */ | 2681 | /* Kill the entire session */ |
2683 | do_each_pid_task(session, PIDTYPE_SID, p) { | 2682 | do_each_pid_task(session, PIDTYPE_SID, p) { |
2684 | printk(KERN_NOTICE "SAK: killed process %d" | 2683 | printk(KERN_NOTICE "SAK: killed process %d" |
2685 | " (%s): task_session_nr(p)==tty->session\n", | 2684 | " (%s): task_session(p)==tty->session\n", |
2686 | task_pid_nr(p), p->comm); | 2685 | task_pid_nr(p), p->comm); |
2687 | send_sig(SIGKILL, p, 1); | 2686 | send_sig(SIGKILL, p, 1); |
2688 | } while_each_pid_task(session, PIDTYPE_SID, p); | 2687 | } while_each_pid_task(session, PIDTYPE_SID, p); |
@@ -2692,7 +2691,7 @@ void __do_SAK(struct tty_struct *tty) | |||
2692 | do_each_thread(g, p) { | 2691 | do_each_thread(g, p) { |
2693 | if (p->signal->tty == tty) { | 2692 | if (p->signal->tty == tty) { |
2694 | printk(KERN_NOTICE "SAK: killed process %d" | 2693 | printk(KERN_NOTICE "SAK: killed process %d" |
2695 | " (%s): task_session_nr(p)==tty->session\n", | 2694 | " (%s): task_session(p)==tty->session\n", |
2696 | task_pid_nr(p), p->comm); | 2695 | task_pid_nr(p), p->comm); |
2697 | send_sig(SIGKILL, p, 1); | 2696 | send_sig(SIGKILL, p, 1); |
2698 | continue; | 2697 | continue; |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 7a84b406a952..f78f5b0127a8 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/tty_flip.h> | 10 | #include <linux/tty_flip.h> |
11 | #include <linux/devpts_fs.h> | 11 | #include <linux/devpts_fs.h> |
12 | #include <linux/file.h> | 12 | #include <linux/file.h> |
13 | #include <linux/fdtable.h> | ||
14 | #include <linux/console.h> | 13 | #include <linux/console.h> |
15 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
16 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 4f3b3f95fc42..d94d25c12aa8 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -479,18 +479,18 @@ static const struct file_operations vcs_fops = { | |||
479 | 479 | ||
480 | static struct class *vc_class; | 480 | static struct class *vc_class; |
481 | 481 | ||
482 | void vcs_make_sysfs(struct tty_struct *tty) | 482 | void vcs_make_sysfs(int index) |
483 | { | 483 | { |
484 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL, | 484 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, |
485 | "vcs%u", tty->index + 1); | 485 | "vcs%u", index + 1); |
486 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL, | 486 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, |
487 | "vcsa%u", tty->index + 1); | 487 | "vcsa%u", index + 1); |
488 | } | 488 | } |
489 | 489 | ||
490 | void vcs_remove_sysfs(struct tty_struct *tty) | 490 | void vcs_remove_sysfs(int index) |
491 | { | 491 | { |
492 | device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); | 492 | device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1)); |
493 | device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); | 493 | device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129)); |
494 | } | 494 | } |
495 | 495 | ||
496 | int __init vcs_init(void) | 496 | int __init vcs_init(void) |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7900bd63b36d..08151d4de489 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -778,6 +778,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
778 | } | 778 | } |
779 | vc->vc_kmalloced = 1; | 779 | vc->vc_kmalloced = 1; |
780 | vc_init(vc, vc->vc_rows, vc->vc_cols, 1); | 780 | vc_init(vc, vc->vc_rows, vc->vc_cols, 1); |
781 | vcs_make_sysfs(currcons); | ||
781 | atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); | 782 | atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); |
782 | } | 783 | } |
783 | return 0; | 784 | return 0; |
@@ -987,7 +988,9 @@ void vc_deallocate(unsigned int currcons) | |||
987 | if (vc_cons_allocated(currcons)) { | 988 | if (vc_cons_allocated(currcons)) { |
988 | struct vc_data *vc = vc_cons[currcons].d; | 989 | struct vc_data *vc = vc_cons[currcons].d; |
989 | struct vt_notifier_param param = { .vc = vc }; | 990 | struct vt_notifier_param param = { .vc = vc }; |
991 | |||
990 | atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); | 992 | atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); |
993 | vcs_remove_sysfs(currcons); | ||
991 | vc->vc_sw->con_deinit(vc); | 994 | vc->vc_sw->con_deinit(vc); |
992 | put_pid(vc->vt_pid); | 995 | put_pid(vc->vt_pid); |
993 | module_put(vc->vc_sw->owner); | 996 | module_put(vc->vc_sw->owner); |
@@ -2271,7 +2274,7 @@ rescan_last_byte: | |||
2271 | continue; /* nothing to display */ | 2274 | continue; /* nothing to display */ |
2272 | } | 2275 | } |
2273 | /* Glyph not found */ | 2276 | /* Glyph not found */ |
2274 | if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) { | 2277 | if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { |
2275 | /* In legacy mode use the glyph we get by a 1:1 mapping. | 2278 | /* In legacy mode use the glyph we get by a 1:1 mapping. |
2276 | This would make absolutely no sense with Unicode in mind, | 2279 | This would make absolutely no sense with Unicode in mind, |
2277 | but do this for ASCII characters since a font may lack | 2280 | but do this for ASCII characters since a font may lack |
@@ -2775,7 +2778,6 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2775 | tty->termios->c_iflag |= IUTF8; | 2778 | tty->termios->c_iflag |= IUTF8; |
2776 | else | 2779 | else |
2777 | tty->termios->c_iflag &= ~IUTF8; | 2780 | tty->termios->c_iflag &= ~IUTF8; |
2778 | vcs_make_sysfs(tty); | ||
2779 | release_console_sem(); | 2781 | release_console_sem(); |
2780 | return ret; | 2782 | return ret; |
2781 | } | 2783 | } |
@@ -2795,7 +2797,6 @@ static void con_shutdown(struct tty_struct *tty) | |||
2795 | BUG_ON(vc == NULL); | 2797 | BUG_ON(vc == NULL); |
2796 | acquire_console_sem(); | 2798 | acquire_console_sem(); |
2797 | vc->vc_tty = NULL; | 2799 | vc->vc_tty = NULL; |
2798 | vcs_remove_sysfs(tty); | ||
2799 | release_console_sem(); | 2800 | release_console_sem(); |
2800 | tty_shutdown(tty); | 2801 | tty_shutdown(tty); |
2801 | } | 2802 | } |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index a2dee0eb6dad..e6ce632a393e 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -400,6 +400,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
400 | case KIOCSOUND: | 400 | case KIOCSOUND: |
401 | if (!perm) | 401 | if (!perm) |
402 | goto eperm; | 402 | goto eperm; |
403 | /* FIXME: This is an old broken API but we need to keep it | ||
404 | supported and somehow separate the historic advertised | ||
405 | tick rate from any real one */ | ||
403 | if (arg) | 406 | if (arg) |
404 | arg = CLOCK_TICK_RATE / arg; | 407 | arg = CLOCK_TICK_RATE / arg; |
405 | kd_mksound(arg, 0); | 408 | kd_mksound(arg, 0); |
@@ -417,6 +420,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
417 | */ | 420 | */ |
418 | ticks = HZ * ((arg >> 16) & 0xffff) / 1000; | 421 | ticks = HZ * ((arg >> 16) & 0xffff) / 1000; |
419 | count = ticks ? (arg & 0xffff) : 0; | 422 | count = ticks ? (arg & 0xffff) : 0; |
423 | /* FIXME: This is an old broken API but we need to keep it | ||
424 | supported and somehow separate the historic advertised | ||
425 | tick rate from any real one */ | ||
420 | if (count) | 426 | if (count) |
421 | count = CLOCK_TICK_RATE / count; | 427 | count = CLOCK_TICK_RATE / count; |
422 | kd_mksound(count, ticks); | 428 | kd_mksound(count, ticks); |